AI-powered meeting-minutes & compliance-report platform for French works-council bodies CSE · CSSCT · AG · CSEE · QVCT
MMeet turns a raw meeting recording or transcript into an audit-ready, legally-formatted compliance report — the kind French works-council bodies (CSE, CSSCT, AG, CSEE, QVCT) are required to produce after every session — in minutes instead of hours of manual drafting.
Upload a recording → real Deepgram transcription → a single tier-aware LLM call produces one structured JSON report → that same object drives three consistent surfaces: a client-facing compliance preview, an internal analytics dashboard for the compliance team, and a formatted PDF ready for signature and dispatch.
This isn't a UI mockup wired to fake data. Auth, the job pipeline, file uploads, transcription, AI generation, and PDF export are all real, working, server-verified end to end — see What's Real.
Client journey
- Guided 5-step flow: meeting context → source upload → AI-generated compliance preview → tiered quote request → live dashboard
- Real-time compliance preview e-book (speaker analysis, key figures, risk findings) generated from the actual uploaded transcript
- Three pricing tiers (Essential / Scope / Premium) with genuinely different prompt depth, not just a cosmetic label
Admin / compliance-team console
- Job queue with per-status kanban-style folders, from intake through dispatch
- Report Analyzer — a full compliance dashboard (score ring, risk gauge, filterable findings table, category tabs) driven by the same structured report the client sees
- Document Editor — a rich page-canvas editor for the final procès-verbal, gated behind a lock-and-dispatch workflow
- Prompt Library — every AI prompt is editable data, not a hardcoded string, and edits take effect on the next generation call
- AI Lab — side-by-side model comparison across providers on the same transcript
Platform
- Real multi-provider AI routing: Gemini, DeepSeek, Kimi, and Groq, with automatic transcript condensation for long recordings
- Real authentication (scrypt password hashing, httpOnly session cookies) — no mock login screen
- Real Deepgram speech-to-text with diarization, with a graceful fixture fallback if no audio was uploaded
- Server-rendered PDF export via
@react-pdf/renderer, streamed as a genuineapplication/pdfdownload - Full dark/light theming and a from-scratch design system — no default shadcn/Tailwind boilerplate look
The core idea — one generation call, three consistent surfaces:
┌─────────────────────────┐
transcript ────────► │ /api/jobs/[id]/report │
(real Deepgram │ tier-aware LLM call │
or fixture) │ → StructuredReport │
└────────────┬────────────┘
│ zod-validated JSON
│ (attendees, agenda, votes,
│ speaker stats, compliance
│ findings, score, narrative)
┌─────────────┼─────────────┐
▼ ▼ ▼
Client Preview Report Analyzer PDF Export
(/preview) (admin dashboard) (react-pdf,
server-rendered)
One StructuredReport (src/lib/report.ts, zod-validated) is produced once per job and consumed identically by all three surfaces — change the data once, every view stays in sync.
Two deliberately separate visual languages:
- App chrome (everything except the report itself) — straw-yellow
#EFD395on a near-black canvas, Sora display type, defined insrc/app/globals.css. - Report output (the client e-book, the Document Editor canvas, the exported PDF) — blue
#2F69FF+ navy#101936+ gold#F6BF2F, print-grade legal-document styling, defined insrc/components/pdf/ReportDocument.tsx.
These never mix — a report always looks like an official document regardless of which theme the app chrome is in.
| Layer | Choice |
|---|---|
| Framework | Next.js 16 (App Router, Turbopack) |
| Language | TypeScript, React 19 |
| Styling | Tailwind CSS v4, shadcn/ui (@base-ui/react primitives) |
| State | Zustand (client cache, synced from the server) |
| Motion | Framer Motion (src/components/motion/ shared primitives) |
| Validation | Zod (structured report schema) |
| AI | @google/genai (Gemini) + openai SDK repointed at DeepSeek/Kimi/Groq |
| Speech-to-text | Deepgram (real prerecorded transcription API) |
@react-pdf/renderer |
|
| Auth | Node crypto.scrypt, httpOnly session cookies |
| Persistence | File-backed JSON store (src/lib/server/db.ts) — swappable seam, see Deployment |
| Testing | Vitest + React Testing Library, Playwright |
| Charts | Recharts |
npm install
cp .env.example .env.local # fill in whichever keys you have — see below
npm run devOpen http://localhost:3000. The client journey starts at /; the admin console is at /admin.
| Variable | Required? | Used for |
|---|---|---|
GEMINI_API_KEY |
Recommended (default model) | Report / speaker-analysis generation |
DEEPSEEK_API_KEY |
Optional | Alternate generation model |
KIMI_API_KEY |
Optional | Alternate generation model |
GROQ_API_KEY |
Optional | Alternate generation model |
DEEPGRAM_API_KEY |
Optional | Real audio/video transcription; falls back to a bundled fixture transcript without it |
At least one LLM key is required for generation to work anywhere in the app (Gemini is the default). Auth needs no external keys.
src/
├── app/
│ ├── (client)/ # metadata → upload → preview → dashboard
│ ├── (admin)/admin/ # queue, folder detail, editor, settings, prompts
│ ├── api/
│ │ ├── auth/ # signup, login, logout, me
│ │ ├── jobs/[id]/ # upload, transcribe, report, speaker-analysis, pdf
│ │ └── prompts/ # prompt library CRUD
│ ├── layout.tsx # font system, theme provider, toast
│ └── globals.css # design tokens (app chrome, dark/light)
├── components/
│ ├── ui/ # shadcn primitives (button, dialog, card, …)
│ ├── motion/ # FadeUp, HoverLift, StaggerGroup, MagneticButton
│ ├── report-analyzer/ # the admin compliance dashboard
│ ├── pdf/ # ReportDocument (react-pdf) — the report visual language
│ └── auth/, client/ # AuthShell, ChatWidget, QuoteDrawer, …
└── lib/
├── server/ # db.ts (persistence), auth.ts, ai.ts, deepgram.ts
├── report.ts # StructuredReport schema + zod validator
├── job.ts, jobsStore.ts # job model + client-side sync cache
└── prompts/registry.ts # default prompt templates, as data
All routes are real and curl-verified end-to-end.
| Route | Method | Description |
|---|---|---|
/api/auth/signup |
POST |
Create an account (scrypt-hashed password) |
/api/auth/login |
POST |
Authenticate, issue a session cookie |
/api/auth/logout |
POST |
Invalidate the current session |
/api/auth/me |
GET |
Current authenticated user |
/api/jobs |
GET, POST |
List / create jobs |
/api/jobs/[id] |
GET, PATCH, DELETE |
Read, update, or remove a job |
/api/jobs/[id]/upload |
POST |
Multipart file upload for a job |
/api/jobs/[id]/transcribe |
POST |
Real Deepgram transcription (with fixture fallback) |
/api/jobs/[id]/report |
POST |
Generate the structured compliance report |
/api/jobs/[id]/speaker-analysis |
POST |
Generate speaker breakdown for a job |
/api/jobs/[id]/pdf |
GET |
Server-rendered PDF download |
/api/prompts |
GET |
List editable prompt templates |
/api/prompts/[id] |
PATCH, DELETE |
Edit or reset a prompt to its default |
/api/generate |
POST |
Direct generation call (used by the public demo preview, no job required) |
npm test # Vitest unit/component tests
npm run test:e2e # Playwright E2E tests
npm run lint # ESLintE2E tests mock /api/generate for speed and determinism; the real LLM path is covered by unit tests on the structured-report schema/validator plus manual end-to-end verification against live providers.
Real, end-to-end:
- Multi-provider AI generation (Gemini / DeepSeek / Kimi / Groq) producing a validated
StructuredReport - Deepgram audio/video transcription with diarization
- Authentication — real password hashing, real sessions
- The full job pipeline — creation, upload, status transitions, persisted server-side
- PDF export — genuinely rendered server-side, not a client blob
- Prompt library — edits are persisted and take effect on the next generation call
Explicit non-goals (by design): payments, per-user ownership scoping on jobs, real-time collaborative editing in the Document Editor.
Deploys cleanly to Vercel with zero extra config (verified locally via vercel build and vercel dev) — the backend auto-detects the Vercel runtime and falls back to /tmp for storage so nothing crashes, though for durable multi-user persistence a real hosted database or a host with a persistent disk (Docker, Render, Railway, Fly.io — all included) is recommended.
docker compose up --build # or import the repo directly on Vercel / Render / Railway / Fly.io