TreeMap
A free, open-source disk-space visualizer. Squarified treemap, duplicate hunting, disk-full forecasting, and cleanup that only ever moves files to the Trash.
Stratis listens to your meeting, tracks whether the decision is complete, and writes the record your team never has time to write.
ProductivityTypeScript · PLpgSQLGitHub @LatesandwichOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
Stratis is an AI co-facilitator for team meetings.
It listens during meetings, captures transcript chunks, sends facilitator-only suggestion cards, and generates post-meeting summaries plus change-based PM document updates. The strategy/tree record is the historical retrieval layer.
The frontend has no dev proxy in production — every request goes to API_BASE/WS_BASE resolved in src/lib/api.ts:Read the full README ↗Stratis is an AI co-facilitator for team meetings.
It listens during meetings, captures transcript chunks, sends facilitator-only suggestion cards, and generates post-meeting summaries plus change-based PM document updates. The strategy/tree record is the historical retrieval layer.
Stratis runs as two deployed services:
| Service | Host | Notes |
|---|---|---|
| Frontend (React + Vite) | Vercel | Static build. Talks to the backend via VITE_API_BASE / VITE_WS_BASE set at build time. |
| Backend (Express) + Database | Railway | Node service + managed PostgreSQL. Backend reads DATABASE_URL. |
The frontend has no dev proxy in production — every request goes to API_BASE/WS_BASE resolved in src/lib/api.ts:
export const API_BASE = import.meta.env.VITE_API_BASE ?? "http://localhost:3001";
export const WS_BASE = import.meta.env.VITE_WS_BASE ?? API_BASE.replace(/^http/, "ws");
VITE_API_BASE to the Railway backend URL (e.g. https://stratis-api.up.railway.app). WS_BASE auto-derives https → wss, so a single var usually covers both.localhost:3001 fallbacks and the Vite proxy in vite.config.js apply to local dev only.pg driver (hosted on Railway)mockgroqollamatyphoon (Thai-tuned LLM, for Thai/English meetings)mocktyphoon (Typhoon Whisper turbo via HuggingFace inference)STRATIS-APP/
├── src/ # Frontend React app
│ ├── App.tsx
│ ├── main.tsx
│ ├── index.css
│ ├── vite-env.d.ts
│ │
│ ├── components/
│ │ ├── BlockRenderer.tsx
│ │ ├── MeetingTransition.tsx
│ │ ├── NodeTypes.tsx
│ │ ├── Sidebar.tsx
│ │ ├── states.tsx
│ │ ├── SuggestionCardStack.tsx
│ │ └── ui.tsx
│ │
│ ├── constants/
│ │ ├── index.d.ts
│ │ └── index.js
│ │
│ ├── context/
│ │ └── AuthContext.tsx
│ │
│ ├── hooks/
│ │ ├── useAiBlocks.ts
│ │ ├── useMediaRecorder.ts
│ │ ├── useSessionRecovery.ts
│ │ └── useSuggestionSocket.ts
│ │
│ ├── lib/
│ │ └── api.ts # API_BASE / WS_BASE (env-driven)
│ │
│ ├── mocks/
│ │ └── summaryMock.ts
│ │
│ ├── pages/
│ │ ├── Dashboard.tsx
│ │ ├── DocumentView.tsx
│ │ ├── Landing.tsx
│ │ ├── Login.tsx
│ │ ├── Meeting.tsx
│ │ ├── Projects.tsx
│ │ ├── Register.tsx
│ │ └── SummaryView.tsx
│ │
│ └── tokens/
│ └── colors.ts
│
├── backend/ # Express backend
│ ├── package.json
│ ├── tsconfig.json
│ │
│ └── src/
│ ├── index.ts
│ │
│ ├── auth/
│ │ ├── jwt.ts
│ │ ├── middleware.ts
│ │ └── routes.ts
│ │
│ ├── config/
│ │ └── env.ts
│ │
│ ├── db/
│ │ ├── database.ts # pg Pool, DATABASE_URL
│ │ ├── migrate.ts # applies schema.sql (--reset runs reset.sql first)
│ │ ├── schema.sql # PostgreSQL schema — additive, safe to re-run
│ │ ├── reset.sql # DESTRUCTIVE drops, only under --reset
│ │ └── seed.ts
│ │
│ ├── lib/
│ │ ├── ids.ts
│ │ └── stt.ts
│ │
│ ├── middleware/
│ │ ├── errorHandler.ts
│ │ └── validateAiOutput.ts
│ │
│ ├── realtime/
│ │ ├── autodetect.ts
│ │ ├── hub.ts
│ │ └── suggestions.ts
│ │
│ └── routes/
│ ├── _placeholder.ts
│ ├── ai.ts
│ ├── document.ts
│ ├── index.ts
│ ├── meeting.ts
│ ├── session.ts
│ ├── summary.ts
│ └── transcript.ts
│
├── ai-service/ # AI provider + structured output layer
│ └── src/
│ ├── index.ts
│ ├── schema.ts
│ │
│ └── providers/
│ ├── groq.ts
│ ├── mock.ts
│ ├── ollama.ts
│ ├── typhoon.ts
│ └── types.ts
│
├── shared/ # Shared frontend/backend types + schemas
│ ├── types.ts
│ └── schema/
│ ├── document-patch-output.schema.json
│ └── live-card-output.schema.json
│
├── dist/ # Frontend build output, ignored
│
├── .github/
├── node_modules/
│
├── .env.example
├── .gitignore
├── index.html
├── package.json # Frontend package
├── package-lock.json
├── vite.config.js
├── tsconfig.json
├── tsconfig.node.json
└── README.md
live_card_output) route to the suggestion card stack, not the transcript renderer.Stratis uses four formal AI output gateways:
live_card_output # in-meeting facilitator cards + chunk classification
document_patch_output # post-meeting PM-document section patches
tree_node_output # structure tree nodes
participant_summary_output# participant-facing post-meeting summary
Formal JSON schemas live in:
shared/schema/live-card-output.schema.json
shared/schema/document-patch-output.schema.json
Sprint 1 MVP also uses a simpler block-style AI output (legacy structured path), still used by /api/ai/structure and the summary route:
{
"blocks": [
{
"type": "TextBlock",
"title": "Short label",
"content": "Plain text body",
"metadata": {}
}
]
}
Block types: TextBlock, DecisionNode, SummaryBlock, QuestionSuggestion.
Shared TypeScript contract (single source of truth):
shared/types.ts
AI parser + system prompts:
ai-service/src/schema.ts
ai-service/src/index.ts
npm install
npm run dev
Frontend runs with Vite. Default URL: http://localhost:5173.
In dev, API requests to /api and /ws are proxied to http://localhost:3001 (see vite.config.js). In production, set VITE_API_BASE (and optionally VITE_WS_BASE) at build time — the Vercel build uses these instead of the proxy.
npm run build
npm run preview
The backend connects to PostgreSQL via DATABASE_URL. In production this is the Railway Postgres connection string; for local dev you can point it at a local Postgres instance or a Railway database URL.
cd backend
npm install
npm run db:migrate
npm run db:seed
npm run db:reset
db:reset drops all tables (CASCADE) then re-applies schema.sql and re-seeds.
npm run dev
Backend default URL: http://localhost:3001. WebSocket hub: ws://localhost:3001/ws.
npm run typecheck
From repo root, with a DATABASE_URL pointing at a reachable PostgreSQL database in your .env:
npm install
cd backend
npm install
npm run db:reset
npm run dev
In another terminal (repo root):
npm run dev
Open:
http://localhost:5173
npm run db:seed creates three demo accounts — a facilitator, a participant and
an admin — against whatever database DATABASE_URL points at.
The password is in backend/src/db/seed.ts. It is not repeated here: this
repository is public, the seed has been run against a hosted database before,
and a working password for a live admin account published in a README is a way
in that needs no exploit at all.
Seed against a local database only, and never leave a seeded admin account active on a deployment that real people use.
Create local env from template:
cp .env.example .env
The backend loads:
.env.<NODE_ENV>
.env
Real env values must not be committed. .gitignore ignores real env files (.env, .env.*, **/.env*) but keeps templates (.env.example, **/.env.example).
| Variable | Used by | Description |
|---|---|---|
NODE_ENV | all | development, staging, or production |
PORT | backend | Express port, default 3001 |
CLIENT_ORIGIN | backend | Allowed CORS origin, default http://localhost:5173 |
DATABASE_URL | backend | PostgreSQL connection string (Railway in prod) |
JWT_SECRET | backend | JWT signing secret |
JWT_EXPIRES_IN | backend | JWT lifetime, default 7d |
AI_PROVIDER | ai-service | groq, ollama, typhoon, or mock |
AI_TIMEOUT_MS | ai-service | AI request timeout, default 10000 |
GROQ_API_KEY | ai-service | Groq API key |
GROQ_MODEL | ai-service | Groq model, default llama-3.3-70b-versatile |
OLLAMA_BASE_URL | ai-service | Ollama URL, default http://localhost:11434 |
OLLAMA_MODEL | ai-service | Ollama model, default llama3.1 |
TYPHOON_API_KEY | ai-service | Typhoon (OpenTyphoon) API key |
STT_PROVIDER | backend | typhoon or mock |
STT_TIMEOUT_MS | backend | STT timeout, default 15000 |
HF_TOKEN | backend | HuggingFace token for Typhoon Whisper STT |
VITE_API_BASE | frontend | Backend base URL (build time). Defaults to http://localhost:3001. |
The app can run with no external AI/STT keys:
mock if a provider is selected but its key is missing.mock mode.A PostgreSQL database (DATABASE_URL) is required for the backend to start.
GET /api/health
POST /api/auth/signup
POST /api/auth/login
GET /api/auth/me
GET /api/meeting
GET /api/meeting/upcoming
GET /api/meeting/dashboard
GET /api/meeting/projects
POST /api/meeting/projects
POST /api/meeting
GET /api/meeting/:id
PATCH /api/meeting/:id
DELETE /api/meeting/:id
GET /api/session
GET /api/session/active
GET /api/session/recover
GET /api/session/:id
POST /api/session
POST /api/session/:id/start
POST /api/session/:id/end
GET /api/transcript
GET /api/transcript/session/:sessionId
POST /api/transcript/chunk
POST /api/transcript/audio-chunk
GET /api/ai
GET /api/ai/test
POST /api/ai/structure
POST /api/ai/suggest
POST /api/ai/suggest/scan
POST /api/ai/suggest/answer
GET /api/ai/suggest/:sessionId
GET /api/summary
GET /api/summary/:sessionId
Generates a participant summary from the session's saved transcript via the validated AI call.
POST /api/document/session/:sessionId/generate # propose PM-document patches (transient)
POST /api/document/session/:sessionId/commit # apply approved patches → next version
GET /api/document/:projectId # current PM document + version history
Text chunk flow (live cards):
Meeting.tsx
→ POST /api/transcript/chunk
→ save transcript row
→ auto-detect answered cards
→ liveCardCall() → live_card_output (validated)
→ backend creates suggestion cards (facilitator only)
→ WebSocket pushes to facilitator
→ SuggestionCardStack renders bottom-right cards
Audio flow:
Meeting.tsx
→ useMediaRecorder
→ POST /api/transcript/audio-chunk
→ backend STT (typhoon | mock)
→ transcript saved
→ liveCardCall() → live_card_output
→ suggestion cards updated
Structured-block flow (legacy / manual):
useAiBlocks.send()
→ POST /api/ai/structure
→ ai-service structuredCall()
→ parse + validate JSON
→ frontend renders valid blocks
Post-meeting document flow:
End session
→ DocumentView: POST /api/document/session/:sessionId/generate
→ documentPatchCall() → document_patch_output (validated)
→ facilitator reviews/edits patches
→ POST /api/document/session/:sessionId/commit
→ new document version + notification
URL shape:
ws://localhost:3001/ws?token=<jwt>&sessionId=<sessionId>
(In production: wss://<railway-host>/ws?....)
Server events:
{ type: "connected", sessionId, role }
{ type: "suggestion:new", card }
{ type: "suggestion:answered", sessionId, cardId, source }
Rules:
sessions.facilitator_id).PostgreSQL. Schema lives in:
backend/src/db/schema.sql
Main tables:
organizations
users
meetings
sessions
transcripts
documents
document_versions
nodes
node_relationships
notifications
consent_logs
The runtime database is hosted (Railway Postgres in production); there are no local SQLite files.
src/App.tsx
src/lib/api.ts
src/context/AuthContext.tsx
src/pages/Meeting.tsx
src/pages/DocumentView.tsx
src/pages/SummaryView.tsx
src/hooks/useAiBlocks.ts
src/hooks/useSuggestionSocket.ts
src/hooks/useMediaRecorder.ts
src/hooks/useSessionRecovery.ts
src/components/BlockRenderer.tsx
src/components/SuggestionCardStack.tsx
src/components/states.tsx
backend/src/index.ts
backend/src/routes/index.ts
backend/src/routes/ai.ts
backend/src/routes/session.ts
backend/src/routes/transcript.ts
backend/src/routes/meeting.ts
backend/src/routes/document.ts
backend/src/routes/summary.ts
backend/src/realtime/hub.ts
backend/src/realtime/suggestions.ts
backend/src/realtime/autodetect.ts
backend/src/db/database.ts
backend/src/db/schema.sql
backend/src/config/env.ts
AI output must be validated before the frontend receives it. Validation path:
ai-service/src/schema.ts # parse + schema validation
backend/src/middleware/validateAiOutput.ts
backend/src/routes/ai.ts
backend/src/routes/transcript.ts
backend/src/routes/document.ts
backend/src/routes/summary.ts
Live cards are not transcript content. Correct route:
live_card_output
→ backend realtime suggestion store
→ WebSocket (facilitator only)
→ SuggestionCardStack
Some pages still use mock data and should be wired to live endpoints in later tasks:
src/pages/Projects.tsx
src/mocks/summaryMock.ts
Do not commit:
.env
.env.*
dist/
node_modules/
Safe to commit:
.env.example
shared/schema/*.json
shared/types.ts
source files
README.md
Frontend:
npm run dev
npm run build
npm run preview
Backend:
cd backend
npm run dev
npm run db:migrate
npm run db:seed
npm run db:reset
npm run typecheck
npm run build
VITE_WS_BASE | frontend | Backend WS base (build time). Derived from VITE_API_BASE if unset. |