One workspace for a cross-functional product squad. Daily standups, user research, the backlog, and the weekly update live in the same place instead of scattered across Slack, Notion, and Jira — with AI handling the synthesis nobody has time for. Built around the four people on every squad: PM, software engineer, interaction designer, AI engineer.
Every squad I talked to had the same Friday ritual: a PM scrolling back through a week of Slack and Notion to hand-write a status update. The information already existed — standups recorded the work, research held the "why", the backlog held the "what next" — it was just siloed, so it never added up to anything you could read at a glance.
The worst of it was prioritization: stories got ranked by whoever argued loudest, with the research evidence sitting one tab away, unlinked. TeamOS exists to put all of that on one surface — research linked to the stories it justifies, dependencies tracked until resolved, and the weekly synthesis done for you.
A single Bun-workspace monorepo plus a Go workspace, running on the Cloudflare edge over a serverless Postgres core.
web/ next.js 16, react 19, tailwind v4 — the workspace ui
workers/api/ api worker — auth, data, all workspace routes
workers/realtime/ durable object (WorkspaceFeed) + sse fan-out
workers/workflows/ weekly digest, monday 08:00 utc cron
packages/ shared contracts, drizzle/neon db, gemini wrapper, digest builder
services/scoring/ go opportunity-scoring service
A write — submitting a standup or re-ranking the backlog — fans out across the edge in real time:
sequenceDiagram
autonumber
actor User as Squad Member (Browser)
participant Front as Next.js Client
participant API as Cloudflare API Worker
participant Go as Go Scoring Service
participant Neon as Neon Postgres
participant RT as Durable Object (WorkspaceFeed)
participant Peers as Other Squad Members
User->>Front: 1. Submit standup / create story
Front->>API: 2. POST with better-auth JWT
API->>API: 3. Verify JWT via JWKS, check workspace membership
API->>Neon: 4. Persist via Drizzle repository
API->>Go: 5. (backlog) Request opportunity scores
Go-->>API: 6. Return evidence + recency ranking
API->>RT: 7. Broadcast event (shared-secret authed)
RT-->>Peers: 8. Stream update over SSE
API-->>Front: 9. Return result
The weekly digest runs separately: a Cloudflare Workflow fires every Monday at 08:00 UTC, pulls the week from Neon, asks Gemini for a summary, and emails it via MailChannels.
TeamOS uses Google Gemini (gemini-flash-latest) with structured output for three jobs:
- Research synthesis — interview notes condensed into the recurring themes and pain points across every entry.
- Story generation — a rough idea turned into a structured user story, with related research there to link as evidence.
- Weekly digest — a week of standups, blockers, signals, and needs rolled into a five-section summary with a suggested focus.
Opportunity scoring is deliberately not an LLM job — it's a small deterministic Go service that ranks backlog items on capped research evidence plus recency, so prioritization stays explainable.
- Edge-first reads — live updates fan out from a Durable Object over SSE, so an active session doesn't keep polling Postgres.
- Smart placement — the API and workflow workers run near the Neon origin.
- Tested scoring — the Go engine has table-driven tests for the boundary cases: zero evidence, stale research, tie-breaking by ID.
- Runs without Postgres — no
DATABASE_URLmeans an in-memory store, so the app runs with no database.
Realtime at the edge. One Durable Object per workspace holds the live connections; the API worker broadcasts to it and it fans out over SSE. Pushing the live layer to the edge keeps Postgres out of the hot path during a session.
One repository, two backends. Every route depends on a single Repository interface — Drizzle/Neon in production, in-memory locally. Coding to the interface instead of the database meant the whole app worked identically offline.
Auth fails closed. The worker verifies better-auth JWTs against the remote JWKS and rejects when it can't; a dev mock user only appears behind an explicit bypass flag. Every route then re-checks workspace membership — verifying the token isn't enough, so each route confirms the caller actually belongs there.
bun install
cp .env.example .env
bun run dev # web app — http://localhost:3000
cd services/scoring && go run ./cmd/server # scoring serviceWith no DATABASE_URL the app uses an in-memory store; AI features need a GEMINI_API_KEY.
Other scripts: bun run build, bun run typecheck, bun run lint, bun run test.
Proprietary — all rights reserved. See LICENSE. For access or commercial use, contact parth.sankhla98@gmail.com.