A full-stack SaaS, built in public. This is a brief technical overview for engineers who want to understand what's actually running under the hood.
40+ API routes8 integrations3 AI model tiers3 Sentry runtimes20+ tracked events2 rate limit layers7 webhook event typesRLS on every tableMCP server on npm
Architecture
Auth & identity
GitHub OAuth via Supabase Auth
Cookie-based sessions with middleware guard
Server-side session check on every dashboard route
PostHog identity on sign-in / reset on sign-out
AI generation
OpenRouter for multi-model routing (GPT-4o, Claude, Mistral)
Streaming SSE from API route to client
Diff-aware prompt — only changed files sent
Per-user generation limits enforced server-side
Sliding-window in-memory rate limiter
GitHub API rate-limit detection & graceful fallback
Database
Supabase PostgreSQL with Row Level Security on every table
Supabase Realtime for live changelog updates
4 migrations tracking schema evolution
Composite indexes on hot query paths
Billing
LemonSqueezy subscriptions + one-time payments
Signed webhook verification (HMAC-SHA256)
Idempotent upserts on subscription & invoice events
Portal URL fetched fresh on each request
Sentry capture on every billing error path
Teams & RBAC
Zustand store for team state across dashboard
Role-based access (owner / member)
Invite flow with token expiry
Integrations
Discord — webhook delivery with per-channel config
Slack — incoming webhook with rich block kit payload
Linear — GraphQL: comment on issue + resolve state
Jira — REST: post comment on ticket
Twitter/X — post thread from changelog
RSS feed — auto-generated on each publish
REST API — signed token, versioned endpoint
MCP server — generate changelogs from Cursor & Claude Desktop
MCP server
Published as shiplog-mcp on npm — zero install via npx
Stdio transport via @modelcontextprotocol/sdk
list_changelogs tool — queries /api/v1/changelogs with pagination
generate_changelog tool — full pipeline: GitHub → AI → save → return URL
API key auth (sl_live_) — bypasses RLS via createAdminClient()
Supports changelog and announcement generation types
Works with Cursor, Claude Desktop, and any MCP-compatible client
Observability
Sentry across client, server, and Edge runtimes
global-error.tsx for root boundary capture
withSentryConfig auto-instrumentation on all routes