Skip to content

aPassie/teamos

Repository files navigation

TeamOS

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.


🔍 Problem Discovery & Origin Story

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.


🛠️ Architecture & Edge Orchestration

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
Loading

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.


🧠 The AI Pipeline

TeamOS uses Google Gemini (gemini-flash-latest) with structured output for three jobs:

  1. Research synthesis — interview notes condensed into the recurring themes and pain points across every entry.
  2. Story generation — a rough idea turned into a structured user story, with related research there to link as evidence.
  3. 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.


⚡ Performance & Engineering Notes

  • 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_URL means an in-memory store, so the app runs with no database.

📂 Core Architectural Learnings

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.


🚀 Run

Needs Bun and Go.

bun install
cp .env.example .env

bun run dev                                  # web app — http://localhost:3000
cd services/scoring && go run ./cmd/server   # scoring service

With 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.


📄 License

Proprietary — all rights reserved. See LICENSE. For access or commercial use, contact parth.sankhla98@gmail.com.

About

One workspace for product squads - daily standups, user research, an evidence-linked backlog and an AI-written weekly digest.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Contributors