<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Gnana-Shishir-Kumar</title>
    <description>The latest articles on DEV Community by Gnana-Shishir-Kumar (@gnanashishirkumar).</description>
    <link>https://dev.to/gnanashishirkumar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3834151%2Ffe00064a-a98a-4a10-9961-c1d8bdededa3.png</url>
      <title>DEV Community: Gnana-Shishir-Kumar</title>
      <link>https://dev.to/gnanashishirkumar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gnanashishirkumar"/>
    <language>en</language>
    <item>
      <title>EndoSeg: What We Built, What We Didn't, and Why the Overlay Lies a Little</title>
      <dc:creator>Gnana-Shishir-Kumar</dc:creator>
      <pubDate>Wed, 15 Jul 2026 22:24:13 +0000</pubDate>
      <link>https://dev.to/gnanashishirkumar/endoseg-what-we-built-what-we-didnt-and-why-the-overlay-lies-a-little-35h9</link>
      <guid>https://dev.to/gnanashishirkumar/endoseg-what-we-built-what-we-didnt-and-why-the-overlay-lies-a-little-35h9</guid>
      <description>&lt;p&gt;EndoSeg was built for the Nebius Serverless AI Builders Challenge &lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://nebius.com/serverless-ai-builders-challenge?utm_medium=email&amp;amp;amp%3B_hsenc=p2ANqtz-8F3gVU2ZJGtSR9rHFP1eDX7DZyMtnzXwr9pSlfPTmNw_e8eUtq7t-CtYFwXadbLdE11QPFHXid2XKN33cto6_D8lsZ0T88mDv0Q5VwYY5Fdc89rZ4&amp;amp;amp%3B_hsmi=137555492&amp;amp;amp%3Butm_content=137555492&amp;amp;amp%3Butm_source=hs_email" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.nebius.com%2Fassets%2Ff8b33d8b-e015-483a-b934-85a1df36f861%2Ftest-share-5.jpg%3Fcache-buster%3D2026-05-19T07%3A37%3A55.265Z" height="400" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://nebius.com/serverless-ai-builders-challenge?utm_medium=email&amp;amp;amp%3B_hsenc=p2ANqtz-8F3gVU2ZJGtSR9rHFP1eDX7DZyMtnzXwr9pSlfPTmNw_e8eUtq7t-CtYFwXadbLdE11QPFHXid2XKN33cto6_D8lsZ0T88mDv0Q5VwYY5Fdc89rZ4&amp;amp;amp%3B_hsmi=137555492&amp;amp;amp%3Butm_content=137555492&amp;amp;amp%3Butm_source=hs_email" rel="noopener noreferrer" class="c-link"&gt;
            Nebius Serverless AI Builders Challenge
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fnebius.com%2Ffavicon%2Ffavicon-96x96.png" width="96" height="96"&gt;
          nebius.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Team
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shishir&lt;/strong&gt; — &lt;a href="https://www.linkedin.com/in/shishircj/" rel="noopener noreferrer"&gt;[LinkedIn]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Je Sai Kailash Pulipati&lt;/strong&gt; — &lt;a href="https://www.linkedin.com/in/je-pulipati/" rel="noopener noreferrer"&gt;[LinkedIn]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maya Orzach&lt;/strong&gt; — &lt;a href="https://www.linkedin.com/in/mayaorzach/" rel="noopener noreferrer"&gt;[LinkedIn]&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What We Built
&lt;/h2&gt;

&lt;p&gt;An estimated 1 in 10 women of reproductive age has endometriosis. The average time from first symptoms to diagnosis is still measured in &lt;strong&gt;years&lt;/strong&gt;, and ultrasound is one of the few tools that can catch it early — if someone reviews the scan carefully. Most segmentation tools that try to help either run in a cloud you have to trust with a patient's pelvic ultrasound, or ship a black-box "AI diagnosis" that overstates what a pixel mask can actually tell you.&lt;/p&gt;

&lt;p&gt;We built &lt;strong&gt;EndoSeg&lt;/strong&gt; — a gynecological ultrasound segmentation tool that fine-tunes a lesion segmenter on &lt;strong&gt;Nebius Serverless GPU Jobs&lt;/strong&gt;, exports it to ONNX, and then runs inference &lt;strong&gt;entirely in the browser&lt;/strong&gt;. The scan never leaves the device unless the user explicitly opts in to a cloud comparison.&lt;/p&gt;

&lt;p&gt;Just as important: We are shipping this with an honest account of what the model does and doesn't know. It segments lesion-like pixels. It does not diagnose endometriosis. That distinction is the whole point of this writeup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔬 &lt;strong&gt;Browser-side lesion segmentation&lt;/strong&gt; — ONNX Runtime Web (WebGPU → WASM fallback) runs the fine-tuned U-Net locally in a Web Worker, so a scan can be reviewed with zero data leaving the device&lt;/li&gt;
&lt;li&gt;☁️ &lt;strong&gt;Optional cloud compare&lt;/strong&gt; — a Nebius Serverless Endpoint serves the same model behind a token-hiding proxy, so a user can voluntarily check local vs. cloud mask agreement&lt;/li&gt;
&lt;li&gt;⚙️ &lt;strong&gt;Full training pipeline on Nebius Jobs&lt;/strong&gt; — three chained GPU/CPU jobs (preprocess → fine-tune → ONNX export + parity check) trained on the MMOTU ultrasound dataset&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;Transparent metrics, not vibes&lt;/strong&gt; — reported Dice/IoU on val and test splits, plus per-sample variance, instead of a single flattering aggregate number&lt;/li&gt;
&lt;li&gt;🚫 &lt;strong&gt;No overclaiming by design&lt;/strong&gt; — the UI cannot output "endometrioma," "chocolate cyst," or any disease probability from the network, because the model was never trained to produce one&lt;/li&gt;
&lt;li&gt;🩺 &lt;strong&gt;Explicit scope disclaimer&lt;/strong&gt; — research/education only, not a medical device, does not replace clinician review&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvsviw3o2cwv5hhj58eqy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvsviw3o2cwv5hhj58eqy.png" alt=" " width="800" height="623"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Show Me the Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Gnana-Shishir-Kumar/nebius-challenge" rel="noopener noreferrer"&gt;https://github.com/Gnana-Shishir-Kumar/nebius-challenge&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How We Used Nebius
&lt;/h2&gt;

&lt;p&gt;Nebius Serverless isn't a side detail here — it's the entire training and (optional) serving path. Here's the full pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MMOTU ultrasound dataset (1,469 frames)
        ↓
  Nebius Job N1 — preprocess (CPU)
  binarizes 8 MMOTU class masks → single lesion/background mask
        ↓
  Nebius Job N2 — U-Net fine-tune (GPU, Dice + BCE loss, 50 epochs)
        ↓
  Nebius Job N3 — ONNX export + parity check
        ↓
  Static browser app (ONNX Runtime Web)
  ├── Default path: local inference in a Web Worker (WebGPU → WASM)
  └── Opt-in path: Nebius Serverless Endpoint + token-hiding proxy
                   ("Compare to cloud" button)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Nebius services used:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Serverless Jobs&lt;/strong&gt; — the core of the training pipeline. Job N1 binarizes MMOTU's 8 tumor-type class masks down to a single foreground/background mask (the PRD scoped this as binary lesion segmentation, not tumor-type classification). Job N2 fine-tunes a U-Net on GPU with a combined Dice + BCE loss over 50 epochs. Job N3 exports the trained weights to ONNX and runs a parity check between the PyTorch and ONNX outputs before anything ships to the browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Serverless Endpoint&lt;/strong&gt; — powers the optional "Compare to cloud" feature. Rather than exposing raw model access, requests go through a token-hiding proxy, so the browser app never holds a credential capable of hitting Nebius directly. This is used purely for a local-vs-cloud mask agreement check, not as the primary inference path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GPU compute for fine-tuning&lt;/strong&gt; — the U-Net training run (Job N2) is the one step that actually needs a GPU; everything downstream (preprocess, export, browser inference) runs on CPU or client hardware, which kept the compute footprint deliberately small.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why browser-side inference matters
&lt;/h2&gt;

&lt;p&gt;Most medical-image tools in this space — and most prior segmentation entries in Nebius's own healthcare track — treat the cloud as the default: upload an image, get a mask back. That's a reasonable pattern for most imaging, but pelvic ultrasound is different — it's a category of data people are understandably wary of sending anywhere.&lt;/p&gt;

&lt;p&gt;EndoSeg flips the default:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The model weights are fetched once and cached; every subsequent inference happens locally in a Web Worker&lt;/li&gt;
&lt;li&gt;Images never touch a server unless the user explicitly clicks "Compare to cloud"&lt;/li&gt;
&lt;li&gt;The Nebius Endpoint exists as an &lt;em&gt;opt-in verification step&lt;/em&gt;, not a requirement to use the tool&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the structural differentiator versus prior bio/healthcare-track winners I looked at before building: privacy isn't a footnote, it's the architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honesty problem this solves
&lt;/h2&gt;

&lt;p&gt;Here's the harder thing I want to be upfront about, because it's more important than the architecture: &lt;strong&gt;it would have been easy to make EndoSeg look like it does more than it does.&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What the UI could show&lt;/th&gt;
&lt;th&gt;What the model actually outputs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Teal overlay, Dice score, agreement %, "max probability"&lt;/td&gt;
&lt;td&gt;A per-pixel lesion-vs-background mask&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Endometrioma / Chocolate Cyst" style labels&lt;/td&gt;
&lt;td&gt;Nothing from the network — this would be a JS shape heuristic, not a classifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud vs. local "agreement"&lt;/td&gt;
&lt;td&gt;Mask overlap between two segmenters, not diagnostic truth&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There is no code path in EndoSeg that computes P(endometriosis), healthy vs. diseased, or endometrioma vs. other-cyst from learned class labels. MMOTU's 8 class IDs are discarded at preprocessing (&lt;code&gt;mask &amp;gt; 0&lt;/code&gt;). If a healthy ovary scan still produces a finding-like overlay, that's expected behavior of a &lt;em&gt;segmenter&lt;/em&gt;, not a bug in a &lt;em&gt;diagnostic tool&lt;/em&gt; — because it was never built to be the latter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Numbers that we stand behind&lt;/strong&gt;, trained on MMOTU (1,469 frames), 50 epochs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Split&lt;/th&gt;
&lt;th&gt;Dice&lt;/th&gt;
&lt;th&gt;IoU&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Val (best @ epoch 33)&lt;/td&gt;
&lt;td&gt;0.764&lt;/td&gt;
&lt;td&gt;0.670&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test&lt;/td&gt;
&lt;td&gt;0.755&lt;/td&gt;
&lt;td&gt;0.655&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Caveats that matter: per-sample Dice on held-out test images ranged from 0.02 to 0.97 — medium/large lesions segment well, small/thin ones sometimes get a confident but wrong "typical blob." Aggregate Dice hides that spread. Also, this MMOTU mirror has no recoverable patient IDs, so the split is stratified by file, not strictly patient-disjoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data sources
&lt;/h2&gt;

&lt;p&gt;Trained and evaluated on the &lt;strong&gt;MMOTU&lt;/strong&gt; (Multi-Modality Ovarian Tumor Ultrasound) public dataset, 1,469 annotated frames across 8 original tumor-type classes, collapsed to a binary lesion mask for this MVP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Training/serving infra:&lt;/strong&gt; Nebius Serverless Jobs (preprocess, fine-tune, export), Nebius Serverless Endpoint (optional cloud compare)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model:&lt;/strong&gt; U-Net, Dice + BCE loss, exported to ONNX&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inference:&lt;/strong&gt; ONNX Runtime Web, WebGPU with WASM fallback, running in a Web Worker&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; Static browser app, no server-side dependency for the default path&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dataset:&lt;/strong&gt; MMOTU (ultrasound, 8-class → binarized to lesion/background)&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Research/education only. EndoSeg is not a medical device.&lt;/strong&gt; It does not diagnose endometriosis, score disease risk, or replace imaging review by a clinician.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>onnx</category>
      <category>nebiusserverlesschallenge</category>
      <category>healthcare</category>
    </item>
    <item>
      <title>EZRide Intel — I Built an AI Assistant for Boston's Hidden Free Bus Using Notion MCP</title>
      <dc:creator>Gnana-Shishir-Kumar</dc:creator>
      <pubDate>Sun, 29 Mar 2026 22:57:36 +0000</pubDate>
      <link>https://dev.to/gnanashishirkumar/ezride-intel-i-built-an-ai-assistant-for-bostons-hidden-free-bus-using-notion-mcp-27af</link>
      <guid>https://dev.to/gnanashishirkumar/ezride-intel-i-built-an-ai-assistant-for-bostons-hidden-free-bus-using-notion-mcp-27af</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/notion-2026-03-04"&gt;Notion MCP Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Most people in Boston and Cambridge have no idea that a completely free public shuttle has been running since 2002 — no fare, no ID, no registration. It connects North Station in Boston all the way to Cambridgeport via Kendall Square and MIT, and it's open to &lt;strong&gt;everyone&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It's called EZRide. And almost nobody knows it exists.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;EZRide Intel&lt;/strong&gt; — an AI-powered transit assistant that makes this hidden public resource discoverable, with &lt;strong&gt;Notion as the sole database layer&lt;/strong&gt;. No PostgreSQL, no Firebase, no JSON files at runtime. Every read, every write, every analytics query goes through Notion MCP.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it does:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🚌 &lt;strong&gt;AI Transit Assistant&lt;/strong&gt; — answers questions about routes, stops, schedules, and fares using data served live from Notion&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;Ridership Analytics Dashboard&lt;/strong&gt; — historical ridership analysis from 2015-2025 with Chart.js visualizations, all data sourced from a Notion Analytics database&lt;/li&gt;
&lt;li&gt;⚠️ &lt;strong&gt;Live Alert Management&lt;/strong&gt; — active stop closures shown in the sidebar, resolvable with one click that updates Notion in real time via &lt;code&gt;pages.update&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;🗺️ &lt;strong&gt;Trip Planner&lt;/strong&gt; — saves formatted trip plans directly to Notion as rich pages using &lt;code&gt;blocks.children.append&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;Notion Global Search&lt;/strong&gt; — searches across all EZRide databases simultaneously using the Notion &lt;code&gt;search&lt;/code&gt; API&lt;/li&gt;
&lt;li&gt;🕐 &lt;strong&gt;Recent Searches&lt;/strong&gt; — sidebar shows live questions pulled from the Notion Query Log DB, updated after every chat interaction&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Video Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://youtu.be/LBt1OOiA-vg" rel="noopener noreferrer"&gt;https://youtu.be/LBt1OOiA-vg&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Show Me the Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Gnana-Shishir-Kumar/ezride-intel" rel="noopener noreferrer"&gt;https://github.com/Gnana-Shishir-Kumar/ezride-intel&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Used Notion MCP
&lt;/h2&gt;

&lt;p&gt;Notion MCP is not a side integration in this project — &lt;strong&gt;it is the entire data layer&lt;/strong&gt;. Here's the full architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Charles River TMA data (charlesrivertma.org)
        ↓
   ingest.py (one-time seed script)
        ↓
  Notion Workspace (5 databases via MCP)
  ├── Routes DB      — 4 service patterns with stops, times, directions
  ├── Stops DB       — 16 stops with neighborhoods and service notes  
  ├── Alerts DB      — active stop closures, resolvable via pages.update
  ├── Query Log DB   — every user question + AI answer + timestamp
  └── Analytics DB   — ridership data 2015-2025 (11 years)
        ↕
   agent.py — reads all 5 DBs → Gemini generates answer → logs back to Notion
        ↓
   Flask web app (localhost:5000)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Notion MCP tools used:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;databases.query&lt;/code&gt;&lt;/strong&gt; — the core of the RAG pipeline. Every user question triggers live queries to Routes, Stops, Alerts, and Analytics databases. The results become Gemini's context window — so the AI's knowledge comes entirely from Notion at runtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;pages.create&lt;/code&gt;&lt;/strong&gt; — used in two ways: the ingest script seeds all 16 stops, 4 routes, 2 alerts, and 11 years of analytics into Notion on setup. Then at runtime, every user question is logged as a new page in the Query Log DB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;pages.update&lt;/code&gt;&lt;/strong&gt; — powers the human-in-the-loop alert resolution. When a transit alert is resolved, clicking "Mark Resolved" in the UI calls &lt;code&gt;pages.update&lt;/code&gt; to change the Status property from Active → Resolved in Notion live. No page refresh needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;blocks.children.append&lt;/code&gt;&lt;/strong&gt; — the Trip Planner creates a full rich Notion page with headings, callout blocks, and bulleted stop lists when a user saves a trip plan. The page appears instantly in their Notion workspace.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;search&lt;/code&gt;&lt;/strong&gt; — the global search bar queries across all EZRide databases simultaneously using Notion's search API, returning matching stops, routes, and analytics records.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Notion as the database matters
&lt;/h3&gt;

&lt;p&gt;Most projects use Notion as a UI layer on top of a "real" database. In EZRide Intel, Notion &lt;strong&gt;is&lt;/strong&gt; the database. There is no fallback. If you disconnect the Notion integration, the AI has no context, the dashboard has no data, and the query log has nowhere to write.&lt;/p&gt;

&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Non-technical users can edit stop data, add alerts, or update schedules directly in Notion — no code changes needed&lt;/li&gt;
&lt;li&gt;The Query Log becomes a living analytics dashboard in Notion itself — you can see what people are asking in real time&lt;/li&gt;
&lt;li&gt;Alerts can be managed by a transit operator directly in Notion, and the web app reflects changes instantly&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The civic problem this solves
&lt;/h3&gt;

&lt;p&gt;EZRide averaged 500,000 passengers per year before COVID — yet Cambridge city councillors have said publicly that even bus drivers don't know the routes are open to the public. People get turned away at the door. The awareness gap is real.&lt;/p&gt;

&lt;p&gt;EZRide Intel makes the service discoverable through natural language. Ask it anything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;"Is EZRide really free?"&lt;/em&gt; → Yes, 100% free, no ID required&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;"What stops are near MIT?"&lt;/em&gt; → Main/Vassar and Vassar/Mass Ave for weekdays&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;"How did COVID affect ridership?"&lt;/em&gt; → Annual riders dropped from 508,000 in 2019 to 142,000 in 2020 — a 72% decline&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;"Are there any current stop closures?"&lt;/em&gt; → Broadway/Galileo closed Mon-Fri, use Kendall Square (71 Ames St)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Data sources
&lt;/h3&gt;

&lt;p&gt;All route, stop, and schedule data sourced from the &lt;a href="https://charlesrivertma.org" rel="noopener noreferrer"&gt;Charles River TMA official site&lt;/a&gt;. Historical ridership anchor points from official statements: 2012 daily average of 2,500 riders and pre-COVID annual ridership of ~500,000 sourced from &lt;a href="https://mass.streetsblog.org/2025/06/02/ezride-in-cambridge-expands-schedule-with-frequent-service-midday-and-weekend-trips/" rel="noopener noreferrer"&gt;Streetsblog Massachusetts&lt;/a&gt; and Wikipedia. Intermediate years reconstructed as realistic synthetic data following known trends.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: Python + Flask&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI&lt;/strong&gt;: Google Gemini 2.5 Flash via &lt;code&gt;google-generativeai&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database&lt;/strong&gt;: Notion (via &lt;code&gt;notion-client&lt;/code&gt; Python SDK)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: Vanilla HTML/CSS/JavaScript + Chart.js&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data ingestion&lt;/strong&gt;: Custom Python seed script (&lt;code&gt;ingest.py&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pattern&lt;/strong&gt;: RAG (Retrieval Augmented Generation) — Notion data as context window&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>ai</category>
      <category>notionchallenge</category>
      <category>mcp</category>
    </item>
  </channel>
</rss>
