Everything your next product stands on
Five things you don't have to build
Modules plug in. The kernel provides.
A module is one directory holding a domain's tables, contracts, endpoints, screens, jobs, and events. It registers into a handful of typed registries and imports nothing but the kernel.
A verb grid, not boilerplate
Create, update, archive, delete, live lists — every endpoint shape derives its schemas, method, errors, and OpenAPI metadata from your resource schema.
One declaration, three surfaces
The same procedure serves the typed client, the public REST API, and the AI assistant — permission check, transaction, audit, and events included.
No module imports another
Domains cooperate through the typed event bus, the kernel, or the app shell. The rule has no exceptions, and the linter enforces it.
export const projectCreateOneProcedure = defineCreateOneProcedure({
base: organizationPermissionProcedure("project.manage"),
resource: { type: "project", event: "project.created", schema: ProjectSchema },
openapi: { path: "/projects", summary: "Create a project" },
tool: { description: "Create a project in one of the user's…" },
values: ProjectValuesSchema,
handler: async ({ deps, context, input }) => projectCreateOne(deps, {
organizationId: context.organization.id,
values: input.values,
}),
});A real endpoint from the reference project module — permission gate, REST path, and assistant tool in one declaration.
Identity & tenancy
The B2B basics, with the edge cases handled.
Passwordless sign-in
Email one-time codes on Better Auth, stored hashed, with the vendor's raw endpoints closed in favor of audited procedures.
Organizations & invitations
URL-scoped tenancy, hashed invitation tokens, member caps, and ownership transfer with a last-owner guard.
Roles where nothing is free
A member holds exactly the union of their roles. Modules declare permissions; organizations compose them into roles in a built-in screen.
Sessions you can see
A device list with per-session revoke and sign-out-everywhere-else — every revocation on the record.
API keys
Hashed machine credentials with expiry, rate limits, and quotas. The secret is shown exactly once.
A platform admin tier
A deployment-level admin area with a global audit view and a push console — invisible to regular users.
API & data
Typed end to end — from the database row to the React component to public REST.
One typed API
oRPC and valibot carry types from Postgres to useQuery. During SSR the server calls itself in-process — no HTTP hop.
OpenAPI when you want it
A procedure joins the documented REST surface by declaring a path — with generated reference docs and try-it authentication.
Lists that scale
Keyset cursor pagination with typed, injection-safe filters — identical across every module.
The mutation protocol
Transaction, audit rows, and domain events are one protocol inside the mutation engine — they cannot drift apart.
Postgres conventions
Time-sortable UUIDv7 keys, archive-versus-delete semantics, race-safe unique indexes, and checked-in migrations.
Fail-fast configuration
Each module declares its environment as a schema; boot validates every slice and reports everything missing at once.
Realtime & background work
Live screens and durable jobs with no extra infrastructure.
Live queries
Declare a procedure as live and the screen updates over SSE on every relevant change. No websocket server, no polling.
Streams that survive the tab
Long-running work publishes chunks with a replayable head — close the tab mid-answer and reattach later.
Jobs in your own Postgres
pg-boss queues with retries, backoff, cron, and per-tenant fairness — enqueued inside the same transaction as your rows.
A second process, wired safely
The worker asserts at boot that every declared job has a handler, and shuts down in a fixed, graceful order.
Wake plus reconcile
Events wake jobs for latency; cron sweeps re-derive the outcome, so a missed event delays work instead of losing it.
Tabs that let go
Backgrounded tabs release their live connections after a grace period — realtime that scales past a demo.
Platform services
The features every product needs eventually, already wired.
Files & uploads
Direct-to-storage uploads with server-side verification, WebP thumbnails, tenant-prefixed keys, and a reaper for orphans.
The notification inbox
Everything a person is told lands as a row here; email and push are mirrors the row's own type asks for. A per-type matrix switches the mirrors, never the record.
Transactional email
react-email templates with a themed component kit, localized copy, and a local preview server.
Web push
VAPID notifications with device management, dead-subscription pruning, and an admin broadcast console.
A forensic audit trail
Actor, request, IP, session — and whether a human or the assistant made the change — recorded inside the mutation's transaction.
Search modules extend
Each module registers its searchable resources into one command palette — reusing its own endpoints, so its own permissions answer every query.
Audit entries modules author
A module declares how each of its events reads in the log, keyed to its own event types — an unknown key is a compile error.
Compiled i18n
Paraglide compiles messages for server and client alike — English and Croatian ship with full parity.
An installable PWA
Manifest, icons, a push-capable service worker, and a new-version toast tied to the deployed commit.
The AI assistant
Not a chatbot bolted on — a surface your modules teach.
Built like production
Turns run as background jobs with resumable streams — answers keep arriving after the tab closes.
Your endpoints are its tools
One tool block on a procedure exposes it to the model through the full middleware chain — same permissions, same audit trail.
Answers as UI
Modules bind tool output to prepared views, so the assistant renders tables and cards instead of prose.
Gated by construction
A tool without a permission rung cannot exist, admin surfaces refuse tools outright, and assistant-made changes are labeled in the audit trail.
Built for AI-agent development
The second product: a development harness agents cannot drift in.
The import graph is law
Layering, module isolation, and vendor SDK fences are lint rules — every restriction with a message explaining why.
Tests for what lint can't see
Structure tests catch stray files, missing barrels, and unregistered modules; the env test catches unvalidated configuration.
Hermetic E2E & visual regression
One command builds the production images, boots the full stack in Docker, and pixel-diffs the screens.
Parallel agent stacks
Every git worktree gets its own origin, database, cache, and object store — agents never share cookies or data.
Local HTTPS with h2
A one-command mkcert proxy gives every instance a port-free https origin and removes the SSE connection cap.
A checked-in agent contract
CLAUDE.md carries the non-negotiables, the settled decisions, and the exact checks CI runs.
On the roadmap
Tracked in the open and shipped in phases — the next layers of the platform.
- Billing & usage limits
- Feature flags
- Schedulers
- PDF & Excel exports
- Usage analytics
- WebSocket transport
Build your first module today
Sign in, open the reference modules, and ship a vertical slice with tenancy, audit, realtime, and an assistant already underneath it.
Get started