Mila is a blog dedicated to my daughter to capture her life memories month to month.
- Next.js App Router + React 19
- Supabase Auth & Database (Postgres, RLS)
- Role‑based protected routes:
(protected)and(public)segments - Responsive UI with Bootstrap 5 + SCSS
- AI chatbot streaming from OpenAI (ChatKit embed built but currently parked)
- TTS for blog posts via
/api/blog/[slug]/audio - Vercel Analytics, ready for CI/CD
- Node.js 22.x (matches
package.jsonengines,.nvmrc,.node-version) - npm / pnpm / yarn
- Supabase project and keys
- OpenAI API key
git clone https://github.com/stozo04/mila-nextjs.git
cd mila-nextjs
npm install # or pnpm/yarn
cp .env.example .env.local # fill in values
npm run devNEXT_PUBLIC_SUPABASE_URL="" # Supabase project URL (from dashboard > Settings > API) NEXT_PUBLIC_SUPABASE_ANON_KEY="" # Supabase anon/public key (used in client/browser) SUPABASE_SERVICE_ROLE_KEY="" # Supabase service role key (server-side only, keep secret!)
OPENAI_API_KEY="" # Your OpenAI secret key OPENAI_VECTOR_STORE_ID="" # Optional: OpenAI Vector Store ID for File Search OPENAI_MODEL="" # Optional: override the default model (e.g., gpt-4.1, gpt-4o-mini) OPENAI_CHATKIT_WORKFLOW_ID="" # Workflow ID from OpenAI Agent Builder for ChatKit
SITE_URL="" # Used for backend or deployment config (sometimes Netlify/Vercel) NEXT_PUBLIC_SITE_URL="" # Base URL for auth callbacks (e.g., https://yourapp.com)
NEXT_PUBLIC_ALLOWED_EMAIL="" # Legacy setting; not an enforced allowlist NEXT_PUBLIC_ADMIN_EMAIL="" # Email for admin account (grants elevated privileges)
- Live widget:
src/components/Shared/Chatbot/OpenAIChatBot.tsx- Mounted in
src/app/layout.tsxand pinned bottom-right — this is what users see - Streams from
/api/chat-streamover SSE
- Mounted in
- ChatKit embed (built, currently parked):
src/components/Shared/Chatbot/ChatKitWidget.tsx- Commented out in
src/app/layout.tsxalong with its import; nothing renders it - Would exchange a client secret via
/api/chatkit/session
- Commented out in
- ChatKit session API:
src/app/api/chatkit/session/route.ts- Exchanges the workflow (
OPENAI_CHATKIT_WORKFLOW_ID) for a ChatKit client secret - Guards on missing env vars and surfaces OpenAI API errors
- Exchanges the workflow (
- Streaming API:
src/app/api/chat-stream/route.ts- Node.js runtime, uses OpenAI Responses API streaming
- File Search tool is included if
OPENAI_VECTOR_STORE_IDis set - Emits SSE: token chunks (default),
event: donewith{ conversationId, sources }, andevent: error
src/
app/ # App Router
api/ # Route handlers
blog/[slug]/audio/route.ts
chat-stream/route.ts
components/ # Reusable React components
lib/ # Client & server helpers
styles/ # SCSS & global CSS
docs/ # Long‑form docs, assets
npm run dev: Start dev servernpm run build: Production buildnpm run start: Start built appnpm run lint: Shared agent synchronization check, then ESLint
- 400 Missing
tools[0].vector_store_ids: EnsureOPENAI_VECTOR_STORE_IDis set and the ID exists in your OpenAI project. - Vector store not found: Verify the ID and that your OpenAI API key has access to that project.
- Streaming works but no citations: Confirm your vector store has files and that File Search is enabled (env var set).
Built by Steven Gates.