Alejandro Gutiérrez 3c0154ae70 feat(broker): port routing + status model from claude-intercom to postgres
Ports the proven claude-intercom broker logic into apps/broker with
SQLite → Drizzle/Postgres translation. Core state engine kept verbatim:
source-priority writes (hook > manual > jsonl), fresh-gating, TTL
sweeper for stuck-working, pending-status race handler, priority
delivery gates (now/next/low), Windows path encoding (5-candidate
fallback incl. Roberto's H:\Claude → H--Claude rule).

New modules:
- broker.ts (492 lines): writeStatus, handleHookSetStatus, sweepers,
  presence lifecycle, message queueing + drainForMember, sourceRank +
  isHookFresh / isSourceFresh logic, findMemberByPubkey (WS auth hook).
- paths.ts (141): cwdToProjectKeyCandidates + findActiveJsonl +
  inferStatusFromJsonl — JSONL fallback inference for peers without
  hooks installed or with stale hook signals.
- types.ts (111): WS protocol envelopes (hello/send/push/ack/error/
  set_status), HookSetStatusRequest/Response, ConnectedPeer view.
- index.ts (323): HTTP on BROKER_PORT+1 for /hook/set-status + /health;
  WebSocket on BROKER_PORT for authenticated peer connections with
  hello/send/set_status handlers; connections registry; heartbeat
  ping/pong every 30s; graceful SIGTERM/SIGINT that marks all active
  presences disconnected.

Mesh scoping: every query/mutation includes meshId. Peer identity is
split between mesh.member (stable) and mesh.presence (ephemeral). WS
hello authenticates by pubkey against mesh.member (signature verify is
stubbed — libsodium wiring lands in client-side package later).

Broker never sees plaintext: nonce + ciphertext are opaque text fields
passed through. Routing happens on targetSpec (pubkey | "#channel" |
"tag:xyz" | "*"), resolved against currently-connected peers.

Dependencies not installed; no tests run. Verified via static review
of imports against @turbostarter/db exports.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 21:32:14 +01:00

TurboStarter Kit

Full-stack monorepo built with Next.js, Expo, Turborepo, and pnpm workspaces.

Prerequisites

Project Structure

apps/
  web/       # Next.js web application (port 3000)
  mobile/    # Expo React Native app
packages/
  ai/        # AI provider integrations
  analytics/ # Analytics providers
  api/       # tRPC API layer
  auth/      # Authentication (BetterAuth)
  billing/   # Payment providers (Stripe, Lemon Squeezy, Polar)
  cms/       # Content management
  db/        # Database (Drizzle ORM + PostgreSQL)
  email/     # Email providers (Resend, Sendgrid, etc.)
  i18n/      # Internationalization
  monitoring/# Monitoring (Sentry, PostHog)
  shared/    # Shared utilities and config
  storage/   # File storage (S3/MinIO)
  ui/        # Shared UI components

Quick Start

1. Install dependencies

pnpm install

2. Configure environment variables

Copy the example env files:

# Root env (database, product name, URL)
cp .env.example .env

# Web app env (auth, billing, email, storage, AI, etc.)
cp apps/web/.env.example apps/web/.env.local

Root .env — minimum required variables:

DATABASE_URL="postgresql://turbostarter:turbostarter@localhost:5440/core"
PRODUCT_NAME="TurboStarter"
URL="http://localhost:3000"
DEFAULT_LOCALE="en"

Note: The database port is 5440 (mapped from Docker), not the default 5432.

apps/web/.env.local — key variables to configure:

Variable Description Required
BETTER_AUTH_SECRET Auth token signing secret Yes
NEXT_PUBLIC_AUTH_PASSWORD Enable password auth (true/false) Yes
NEXT_PUBLIC_URL Public URL of the web app Yes
STRIPE_SECRET_KEY Stripe key (if using Stripe billing) Optional
RESEND_API_KEY Resend key (if using Resend email) Optional
S3_* S3/MinIO storage credentials Optional
OPENAI_API_KEY OpenAI key (if using AI features) Optional

For local MinIO storage, use these S3 settings in apps/web/.env.local:

S3_REGION="us-east-1"
S3_BUCKET="uploads"
S3_ENDPOINT="http://localhost:9000"
S3_ACCESS_KEY_ID="minioadmin"
S3_SECRET_ACCESS_KEY="minioadmin"

See apps/web/.env.example for the full list of available variables.

3. Start infrastructure (Docker Compose)

Start PostgreSQL and MinIO:

docker compose up -d

Wait for services to be healthy:

docker compose up -d --wait

Or use the built-in shortcut:

pnpm services:start

4. Set up the database

Run migrations and seed data:

pnpm services:setup

This runs docker compose up -d --wait, then applies database migrations and seeds initial data.

5. Start development

pnpm dev

The web app will be available at http://localhost:3000.

Docker Commands

Infrastructure Services

Command Description
docker compose up -d Start all services (PostgreSQL + MinIO)
docker compose down Stop all services
docker compose logs -f Follow service logs
docker compose ps Show service status

Or use the pnpm shortcuts:

Command Description
pnpm services:start Start Docker services and wait for healthy
pnpm services:stop Stop Docker services
pnpm services:logs Follow Docker service logs
pnpm services:status Show Docker service status
pnpm services:setup Start services + run DB migrations + seed

Service URLs

Service URL Credentials
Web App http://localhost:3000
PostgreSQL localhost:5440 turbostarter / turbostarter
MinIO API http://localhost:9000 minioadmin / minioadmin
MinIO Console http://localhost:9001 minioadmin / minioadmin

Production Build (Docker)

Build and run the web app as a production Docker image:

docker build -t turbostarter-web .
docker run -p 3000:3000 --env-file apps/web/.env.local turbostarter-web

Development Commands

Command Description
pnpm dev Start all apps in development mode
pnpm build Build all packages and apps
pnpm lint Run ESLint across the monorepo
pnpm format Check formatting with Prettier
pnpm format:fix Fix formatting
pnpm typecheck Run TypeScript type checking
pnpm test Run tests
pnpm auth:seed Seed auth dev accounts

Database Commands

Run from the root (or within packages/db):

Command Description
pnpm --filter @turbostarter/db db:migrate Run database migrations
pnpm --filter @turbostarter/db db:push Push schema changes
pnpm --filter @turbostarter/db db:generate Generate new migration
pnpm --filter @turbostarter/db db:studio Open Drizzle Studio
pnpm --filter @turbostarter/db db:reset Reset database
pnpm --filter @turbostarter/db db:seed Seed database

Dev Login Credentials

After running pnpm services:setup or pnpm auth:seed:

Role Email Password
User me+user@turbostarter.dev Pa$$w0rd
Admin me+admin@turbostarter.dev Pa$$w0rd
Description
ClaudeMesh broker - WebSocket peer broker for Claude Code instances
Readme 40 MiB
Languages
TypeScript 94.7%
JavaScript 2.4%
HTML 1.2%
CSS 1%
Python 0.3%
Other 0.3%