Systeric / Docs
Open App →

Our Stack

Everything lives in one repo, one package manager, one set of conventions. This page is the map: what we use for each layer, and why it’s the right tool for what we’re building.


The pieces#

LayerWhat we useWhy / where
Monorepopnpm workspaces + Turborepoapps/* and packages/* in one repo (pnpm-workspace.yaml); turbo run build | dev | lint | typecheck | test shares a cache across every package
LanguageTypeScriptEvery app and package is "type": "module" TS, checked in CI (typecheck)
Marketing & docs siteAstroapps/landing: the static site you’re reading right now
Product APIHono + tRPC + Drizzle ORM + PostgreSQL + better-authapps/api: Hono is the HTTP layer, tRPC types the API end-to-end, Drizzle is the “dumb persistence” layer over Postgres (see Database Migrations), better-auth owns sessions
Product web appReact + Vite + TanStack Router/Queryapps/web: plus Tiptap and Yjs/Hocuspocus for the collaborative doc editor, shared through packages/editor
Shared packagespackages/domain, shared, editor, ui, pgmqDomain entities and value objects, shared Zod schemas/types, the editor, UI components, and a Postgres-backed queue, reused across the API, web, and Lore apps
ObservabilityOpenTelemetryHTTP, Postgres, and tRPC are auto-instrumented for free at boot (apps/api/src/instrumentation.ts); see Observability for where traces and metrics land and how to add your own
Product analytics & session replayPostHogposthog-js in the web app, posthog-node in the API; replay is masked by default; see Session Replay
TestingVitest everywhere, Playwright for e2eSee Testing & TDD for what to test and what CI runs

Other apps in the monorepo#

Two more apps follow the same patterns above: lore-api (Hono + Drizzle + PostgreSQL + better-auth, a knowledge-base API with its own database) and lore-web (React + Vite + TanStack, its front end). glide-mcp is smaller and different in kind: an MCP server that lets an AI agent drive Glide directly instead of through a browser; see Glide MCP for what it does.


Why this shape#

The API’s job is to keep business logic in the domain, not the database: Postgres stores rows and enforces shape, nothing more (see Database Migrations for the “no defaults in the schema” rule). tRPC means the web app and the API share types end-to-end with no separate schema to keep in sync. OpenTelemetry and PostHog answer two different questions: OpenTelemetry tells you what the system did (which query was slow, where a trace really started); PostHog’s replay tells you what one user did. You reach for observability to debug the backend, and for a replay to understand a confusing flow from the outside.

None of this is fixed for its own sake. If a lighter tool solves the same problem for a new app in the monorepo, that’s a conversation, not a rule, but changing a piece here is a decision to bring to the team, not a solo call.


Related: Observability, Database Migrations, Session Replay, Environment Setup