Upload documents, explore parsed content, and ask questions about your knowledge — powered by the Knowhere API.
-
Copy the environment template:
cp .env.local.example .env.local
-
Fill in your API keys in
.env.local:AI_GATEWAY_API_KEY— your Vercel AI Gateway key for chat (optionalCHAT_MODELoverride)KNOWHERE_API_KEY— optional development override that skips Dashboard auth and calls Knowhere directlyNEXT_PUBLIC_POSTHOG_KEY— PostHog Project API key for front-end event trackingNEXT_PUBLIC_POSTHOG_HOST— PostHog ingestion host (defaulthttps://us.i.posthog.com)
-
Install dependencies and run:
pnpm install pnpm dev
Notebook sends these product analytics events when PostHog is configured:
notebook_upload_button_clickednotebook_document_upload_completed(uploaded_count,file_types,total_size_bytes)notebook_assistant_question_submitted(selected_sources_count,message_length)notebook_dashboard_link_clicked
Notebook also calls PostHog identify for authenticated users and reset for
guest sessions so insights can be grouped by user.
- In PostHog, create/select a project.
- Copy the project API key and ingestion host.
- Set these values in
.env.local:NEXT_PUBLIC_POSTHOG_KEY=phc_your_project_api_key NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
- Restart
pnpm dev(ornpm run dev), then trigger a few actions in Notebook. - Open PostHog
Eventsand filter by the event names above to verify ingestion.
Create four Trends insights in PostHog:
- Upload button clicks: count of
notebook_upload_button_clicked - Uploaded documents:
sum(uploaded_count)onnotebook_document_upload_completed - Avg sources per question:
avg(selected_sources_count)onnotebook_assistant_question_submitted - Users opening dashboard:
Unique usersonnotebook_dashboard_link_clicked
Pin those four insights to a Notebook Tracking dashboard for team reporting.
GA4 field and event alignment guidance lives in docs/ga4-alignment.md.
- Framework: Next.js 16 with App Router and Server Components
- AI: Vercel AI SDK + Vercel AI Gateway
- Knowledge: Knowhere Node.js SDK for document parsing and retrieval
- UI: shadcn/ui + Tailwind CSS 4
- Icons: Lucide
The CI workflow runs lint, typecheck, tests, and build on pull requests targeting
main and staging.
After changes are merged to main, the release workflow creates a date-based
GitHub Release with a source archive and build metadata.
Notebook treats Dashboard as the auth source of truth. Server-side auth calls
forward the incoming session cookie to Dashboard oRPC endpoints, including
/api/orpc/users/getCurrentUser and /api/orpc/users/issueServiceJwt.
For local development, setting server-side KNOWHERE_API_KEY switches Notebook
into API-key mode. In that mode the app uses a deterministic local development
user, skips Dashboard redirects and JWT issuance, and passes the configured key
directly to the Knowhere SDK. Leave it unset for production and normal
Dashboard-authenticated staging flows.
Dashboard chooses its oRPC handler by request shape and Content-Type.
When using Effect's HttpClientRequest.bodyText, pass
"application/json" as the body content type. Setting the header before
bodyText("{}") is not enough because bodyText overwrites it with
text/plain. If that happens, Dashboard can return a successful OpenAPI-shaped
response instead of the RPC envelope, and Notebook will log a 200
schema mismatch followed by no valid session.
Use setEmptyJsonBody from src/integrations/dashboard/orpc-request.ts for empty
Dashboard oRPC POST bodies.
src/
├── app/ # Next.js App Router pages and route handlers
├── components/ # React components and shadcn/ui primitives
├── domains/ # Product domains: chat, chunks, sources, workspace
├── infrastructure/ # Owned platform concerns: auth and database access
├── integrations/ # External systems: Dashboard and Knowhere
└── lib/ # Small cross-cutting utilities