Inspiration
We've all been there — a great idea strikes mid-commute, during a workout, or while staring at a whiteboard. By the time you open a note-taking app and navigate to the right document, the thought is gone or diluted. We wanted to remove that friction entirely: capture anything (voice, image, or text) and have it automatically land in exactly the right place — your Notion page, Google Doc, or Slack channel — without you having to decide where it goes.
What it does
NoteRoute lets you say it, snap it, or type it — and routes the content to the right destination automatically.
- Record a voice note → transcribed via AWS Transcribe, embedded, semantically matched to your best-fit slot (a Notion page, Google Doc, Slack channel, etc.), then delivered there
- Snap a photo → Claude Vision extracts text or describes the image, then the same routing pipeline runs
- Type a note → same pipeline, no transcription step
Supported integrations: Notion, Google Docs/Drive, Slack, Todoist, Trello. Available on ***web* (Next.js). Coming soon to iOS/Android (Expo)
How we built it
Four services, each with a clear responsibility:
| Service | Stack |
|---|---|
| Backend | FastAPI + MongoDB (Beanie) + Firebase Auth |
| LangGraph microservice | Python, LangGraph pipeline (transcribe → embed → search → rank → confirm → deliver) |
| Mobile | Expo / React Native, Zustand |
| Web | Next.js 15, Tailwind, shadcn/ui |
The pipeline runs as a LangGraph state machine. Input arrives (audio, image, or text), branches to the correct entry node, gets embedded with AWS Bedrock, then vector-searched against the user's pinned slots stored in Pinecone Vectors. The top match is confirmed and the note is delivered via the provider's API. The entire pipeline streams status updates to the client over SSE.
OAuth for Google, Slack, Todoist, and Trello is handled with a unified callback pattern — web vs. mobile is distinguished by a ?platform=web flag so callbacks redirect to the right place (deep link vs. /oauth/callback page).
Both services are deployed on Railway via Dockerfile.
Challenges we ran into
- Railway inter-service networking: containers can't resolve their own project's public
.up.railway.appdomains from within Railway. We had to switch all intra-project calls to.railway.internalprivate hostnames, which wasn't obvious from the docs. - PORT binding: Railway injects
$PORTdynamically. Using exec-formCMDin Dockerfile prevents shell variable expansion, causing Railway's proxy to 502. Switching to shell-formCMDand pinningPORTexplicitly in Railway Variables fixed it. - Todoist API deprecations: REST v2 and Sync v9 both returned 410 Gone. We had to discover and migrate to their undocumented v1 API during the hackathon.
- Image OCR routing: integrating a new entry node into the LangGraph graph without breaking existing audio/text routing required careful conditional edge design.
- OAuth state across platforms: keeping web and mobile OAuth flows using the same backend callback endpoint without separate routes required encoding platform context into the OAuth
stateparameter.
Accomplishments that we're proud of
- A single LangGraph pipeline handles audio, image, and text inputs with branching at the graph level — no duplicate logic
- Five OAuth integrations with a unified pattern that required adding just one file and a handful of
elifbranches per new provider - Streaming SSE status updates from deep inside a LangGraph node all the way to a React Native screen and a Next.js page, with identical UX on both
- The web app is fully feature-parity with mobile (record, image capture, source management, OAuth) built with the same backend
What we learned
- LangGraph is well-suited to pipelines with conditional branching and shared state, but graph topology needs to be planned upfront — retrofitting new entry points is painful
- Railway's networking model (public vs. private domains) is not well-documented; internal service communication must use private networking explicitly
- Building two frontends (mobile + web) in parallel against one backend forces cleaner API design — every ambiguity in the contract surfaces immediately
- Claude Vision is remarkably capable as a first-pass OCR and content extraction layer without any fine-tuning
What's next for NoteRoute: Say it. Snap it. Route it.
- Smart routing confidence scores — show the user why a slot was chosen and let them correct it to improve future routing
- More integrations — Linear, GitHub Issues, Obsidian, email (via SMTP)
- Scheduled digests — batch voice notes captured throughout the day and deliver a summarized digest to a chosen slot at a set time
- On-device processing — run a lightweight embedding model locally so routing works offline and notes sync when connectivity returns
- Team workspaces — shared slot libraries so a team can collectively route notes into a shared Notion workspace or Slack channel
Built With
- amazon-web-services
- fastapi
- firebase
- langgraph
- mongodb
- nextjs
- nova
- python
- typescript
- zustand
Log in or sign up for Devpost to join the conversation.