Mila Gates
A growing-up site for my daughter.

the project
Mila Gatesis a private family site for my daughter — a growing-up timeline of photos, milestones, and written memories, captured month by month. The front door is a calm, mobile-friendly blog. The interesting part is what's behind it.
The whole site is wrapped in an agentic AI surface. I can ask — or speak — in plain English: “Find the photos from her first birthday,” “Pull up the post about her first steps,” “What did I write about the trip to Galveston?” The model searches the memory corpus, returns the right entry, and cites the source post.
what makes it agentic
The chatbot isn't a sidekick — it's the navigation layer. Under the hood, every blog post is ingested into an OpenAI Vector Store, and the chat surface uses OpenAI ChatKit with File Search (RAG) turned on. Ask a natural-language question, the model retrieves the matching posts, and the response stream includes citations back to the original entries.
Every blog post also has a TTS endpoint (/api/blog/[slug]/audio) that streams a voiced version of the entry. Family members who don't want to read can listen.
the stack
- Next.js 15 App Router + React 19 — server components for the blog tier, route handlers under
src/app/api/**for the AI + TTS endpoints. - Supabase for auth and content — Postgres + Row Level Security, a whitelisted-email auth flow so only family can see the protected segment.
- OpenAI ChatKit embedded widget — exchanges a workflow ID for a per-session client secret via
/api/chatkit/session, then renders the chat bottom-right. The workflow itself lives in OpenAI Agent Builder. - OpenAI Vector Store + File Search — the RAG tier. The chat stream attaches
tools: [{ type: "file_search", vector_store_ids: [...] }]when a store ID is configured. Citations come back in theevent: doneSSE payload. - Edge-runtime streaming — the legacy
/api/chat-streamroute runs on the edge with SSE for low-latency token streaming and proper cancellation handling. - Bootstrap 5 + SCSS for the front-end shell. Deployed on Vercel with Analytics.
architecture in one paragraph
Posts live in Supabase. Posts are ingested into an OpenAI Vector Store. ChatKit renders a widget that talks to a session route, which mints a per-session client secret from the OpenAI workflow. When a family member asks a question, the workflow agent uses File Search to retrieve the relevant posts from the vector store, generates an answer streamed back token-by-token, and returns citations on completion. Voice playback of any post is a separate route that streams audio from the TTS endpoint. Auth is whitelist-based via Supabase RLS, so the protected segment is invisible to anyone outside the family allowlist.
why i built it
I have a daughter. I take a lot of photos. The phone's camera roll is a terrible memory system — chronological, unsearchable, and useless if you ever want to find the one moment. Mila Gates is the “I build for the people I love” piece. It's also the project where I get to feel good about agentic AI: a tool whose job is to help me remember.
what this demonstrates
- Modern AI primitives in production. ChatKit, Vector Store, File Search, edge streaming, SSE with citations — wired end-to-end, deployed, in use.
- Full-stack ownership. Auth, RLS, server components, edge handlers, RAG ingestion, TTS, embedded widget — all of it.
- Pragmatic auth. Supabase + email allowlist instead of building a full identity stack. Right tool, right scope.
- Agentic UX done quietly.The chat surface isn't a gimmick — it's the navigation. No forms to fill, no filters to click. Just ask.