Architecture
How Cobalt's pieces fit together.
Monorepo layout
apps/
worker/ Cloudflare Worker (Hono), API + site serving
docs/ This documentation site
packages/
database/ Drizzle ORM schema, migrations, DB client
tooling/
typescript/ Shared tsconfig presets
eslint/ Shared ESLint flat configMore apps (dashboard) and packages (auth, ui, seo, analytics, editor, api,
storage, shared, config) land as their respective phases of development begin.
Single-tenant by design
Each Cobalt deployment serves exactly one site. There's no workspace layer, no billing, no subdomain routing between tenants. Want a second site? Deploy Cobalt again. This keeps the schema simple: content tables aren't scoped by a tenant ID anywhere, because there's only ever one tenant per deployment.
Site-wide configuration, name, domain, timezone, lives in a single-row site_settings
table. The database enforces the single row with a check constraint, not application
logic.
Data layer
Postgres via Drizzle ORM, reached from the Worker through
Cloudflare Hyperdrive so requests don't
pay a cold-connection penalty. Locally, the Worker connects directly using a
DATABASE_URL from .dev.vars. In production it reads from the Hyperdrive binding
instead.
Roles
Roles live directly on the users table. No membership table, since there's only one
site to be a member of:
| Role | Publish | Edit others' posts |
|---|---|---|
admin | Yes | Yes |
editor | Yes | Yes |
author | Own posts only | No |
contributor | Drafts only | No |
License
Cobalt is licensed under AGPL-3.0. Modify Cobalt and run it as a network service for others, and you're required to make your modified source available to them too.