Your conversations, alive.
Lumen is a living board that listens to your conversations — meetings, brainstorms, voice notes — and visualizes the extracted ideas, questions, and patterns as a growing constellation of glowing orbs on a dreamy, dark canvas. The board never resets. It accumulates. And overnight, it finds the connections you missed.
This repo implements the full PRD (prd-lumen.md): the living canvas, ambient
listening + AI extraction, multi-participant real-time, pattern analysis,
sharing, and payments.
The entire pipeline can run at $0 until you have traction:
| Layer | Choice | Cost | Notes |
|---|---|---|---|
| Speech-to-text | Web Speech API (browser) | $0 | Default. No key, no server. Chrome/Edge/Safari. |
| LLM extraction + patterns | Groq (Llama 3.3 70B) | $0 | OpenAI-compatible free tier. Swap to OpenAI/OpenRouter/Cerebras via env. |
| Embeddings | local keyword vectors (in-process) | $0 | Optional dense embeddings via Gemini/OpenAI/Jina. |
| Backend / real-time DB | Convex free tier | $0 | Live queries, actions, crons, presence. |
| Auth | Clerk (free to 50k MAU) | $0 | Web + mobile-ready. |
| Hosting | Vercel free tier | $0 | |
| Payments | Stripe | % only | Charges nothing until revenue. |
The LLM / STT / embedding layers are provider-agnostic — change one env var and one base URL, never rewrite code.
npm install
npm run devOpen http://localhost:3000 → Enter the living demo.
The demo board runs the entire Phase 1 canvas experience — 40 themed orbs, force-directed clustering, glow/breathing, pan/zoom, tap-to-expand, focus / save / dismiss / connect, and a "simulate listening" mode that spawns orbs in real time — with no Clerk, Convex, or API keys required. The visual IS the product; this is the "prove the magic" gate from the PRD, and it's runnable now.
Scripts:
| Command | What it does |
|---|---|
npm run dev |
Next.js dev server |
npm run build / npm run start |
Production build / serve |
npm run typecheck |
tsc --noEmit |
npm run convex |
convex dev — link a deployment + regenerate types |
The app auto-detects whether services are configured: if NEXT_PUBLIC_CONVEX_URL
and NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY are present it runs in live mode
(real boards, auth, AI pipeline); otherwise it runs in demo mode.
npx convex dev # log in, create a deployment, push schema + functionsThis writes NEXT_PUBLIC_CONVEX_URL to .env.local, generates the real typed
convex/_generated/ (the committed stubs are overwritten), and links the
deployment. Keep npx convex dev running while developing.
- Create a Clerk app; copy the publishable key and secret key into
.env.local(NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,CLERK_SECRET_KEY). - Create a Clerk JWT Template named
convex(Convex's applicationID). - Set the issuer URL as
CLERK_ISSUER(used byconvex/auth.config.js) and runnpx convex env set CLERK_ISSUER <url>.
The extraction / embedding / pattern code runs inside Convex actions, so these live in Convex's environment:
npx convex env set LLM_PROVIDER groq
npx convex env set LLM_BASE_URL https://api.groq.com/openai/v1
npx convex env set LLM_MODEL llama-3.3-70b-versatile
npx convex env set LLM_API_KEY <your free Groq key>Groq keys are free at https://console.groq.com. STT defaults to the browser's
Web Speech API (no key). Embeddings default to local (no key). See
.env.local.example for every option.
Create Pro/Team prices in the Stripe dashboard, then set both the server price
ids + NEXT_PUBLIC_STRIPE_PRICE_* in .env.local, plus STRIPE_SECRET_KEY and
STRIPE_WEBHOOK_SECRET on Vercel. Register the webhook at
https://<your-app>/api/... — actually the webhook lives on Convex:
https://<deployment>.convex.site/stripe/webhook (see convex/http.ts).
- Push the repo to GitHub and import it in Vercel (framework auto-detected).
- Add the
.env.localvariables as Vercel environment variables. - Set
NEXT_PUBLIC_CONVEX_URLto your production Convex deployment URL. - Deploy. Run
npx convex deploy(orconvex dev --prod) to push the backend to production.
Browser (Next.js 14 PWA)
└─ Living Canvas: <canvas> particles + d3-force + DOM orbs + SVG lines
│ Web Speech API ──► transcript chunks
▼
Convex (real-time backend)
├─ queries/mutations: boards · orbs · sessions · presence · patterns · reports
├─ actions: ai.extract (LLM) · ai.embeddings · ai.patterns (LLM)
├─ crons: presence reap · retention · weekly patterns + reports
└─ http: /stripe/webhook · /health ← also the iOS API surface
The canvas is purely presentational — it takes orbs/patterns as props and
emits intents. The same <LivingCanvas> powers the dummy demo and the live
Convex board (DemoBoard vs LiveBoard).
The architecture is iOS-ready by design:
- Convex is the single source of truth. The iOS app uses the official Convex Swift SDK for the same live queries + mutations — it sees the board grow in real time, identically to web.
- Clerk authenticates iOS (Clerk's RN/iOS SDK), issuing the same JWT template.
convex/http.tsexposes HTTP endpoints (/health,/stripe/webhook) for REST-only integrations and webhooks — not the primary iOS path, but available.- The schema (
convex/schema.ts) and orb types (src/lib/types.ts) are the shared contract.
To build the companion: pod install the Convex Swift SDK, point it at the same
deployment URL, subscribe to api.orbs.list / api.patterns.list, and render.
lumen/
├─ convex/ # real-time backend (Convex)
│ ├─ schema.ts # single source of truth (web + iOS)
│ ├─ boards.ts orbs.ts sessions.ts presence.ts patterns.ts reports.ts sharing.ts
│ ├─ users.ts stripe.ts http.ts crons.ts
│ ├─ ai/ extraction.ts embeddings.ts patterns.ts sweeps.ts llm.ts prompts.ts
│ └─ _generated/ # stubs; regenerated by `npx convex dev`
├─ src/
│ ├─ app/ # Next.js App Router pages
│ │ ├─ page.tsx # landing
│ │ ├─ b/[boardId]/ # the board (demo or live)
│ │ ├─ s/[token]/ # read-only guest view
│ │ ├─ dashboard onboarding upgrade
│ ├─ components/
│ │ ├─ canvas/ # LivingCanvas, force sim, pan/zoom, particles, lines
│ │ ├─ orbs/ # Orb, OrbCard
│ │ ├─ board/ # BoardChrome, DemoBoard, LiveBoard, GuestBoard, share, pattern toast
│ │ └─ listening/ # consent, controller, banner
│ ├─ hooks/ # useWebSpeech
│ └─ lib/ # types, orb styling, dummy data, snapshot, runtime
└─ prd-lumen.md # the full product spec
- Demo mode is the default until Convex + Clerk are configured. Every page degrades gracefully (no auth walls, no crashes).
convex/_generated/contains loose stubs so the project compiles before a deployment is linked.npx convex devoverwrites them with the real, fully-typed function tree.- Audio is never stored — only transcribed text passes through the pipeline, and only extracted orbs are persisted (PRD FR-3.4).
- Free-tier limits (1 board, 3 hrs/week listening, 7-day retention, no patterns)
are enforced in
convex/lib/limits.tsand surfaced in-app.
Built from prd-lumen.md — the Living Board edition.