Open source framework

One backend.
Ship everywhere.

Define your schema once. Get REST, typed routes, realtime, typed client SDK, and optional admin UI. Server-first TypeScript. Built on Drizzle, Zod, Better Auth.

TypeScriptServer-firstZero lock-inMIT license
src/questpie/server/collections/posts.ts
collection("posts") .fields(({ f }) => ({ title: f.text(255).required(), content: f.richText().localized(), status: f.select([ { value: "draft", label: "Draft" }, { value: "published", label: "Published" }, ]), author: f.relation("users").required(), cover: f.upload({ to: "assets" }), tags: f.relation("tags").hasMany({ foreignKey: "postId" }), seo: f.object({ title: f.text(), desc: f.text(160), }), })) .access({ read: true, create: ({ session }) => !!session, update: ({ session, doc }) => doc.authorId === session?.user?.id, }) .options({ versioning: true })
01

One schema, everything generated

Define once. Get the rest for free.

generated — REST
GET /api/collections/posts GET /api/collections/posts/:id POST /api/collections/posts PUT /api/collections/posts/:id DEL /api/collections/posts/:id
REST API

/api/collections/posts

Typed routes

typed, namespaced

Realtime via SSE

subscribe to changes

Typed client SDK

auto-generated types

Admin panel

table, form, block editor

Zod validation

from field definitions

Access control

row-level, field-level

Versioning

workflow stages, drafts → published

i18n

two-table strategy, per-field localization

File Storage

auto-managed uploads & assets

02

File system = source of truth

Drop a file. Get a feature. Codegen discovers everything. No manual registration.

src/questpie/server/
├── collections/
│   ├── posts.ts
│   └── users.ts
├── routes/
│   └── admin/stats.ts
├── blocks/
│   └── hero.ts
├── jobs/
│   └── send-newsletter.ts
├── services/
│   └── stripe.ts
├── seeds/
│   └── demo-data.ts
└── auth.ts
Collections
posts.ts
CRUD + API + Admin
users.ts
Auth-connected
Routes
admin/stats.ts
Type-safe route
Blocks
hero.ts
Visual block
Jobs
send-newsletter.ts
Background job
Other
stripe.ts
Singleton service
demo-data.ts
DB seed
auth.ts
Better Auth
codegen → .generated/module.ts
03

Swap anything

Your infrastructure. Your choice. Click any adapter in the config to swap it.

KV / Cache
Queue
Search
Realtime
Storage
Email
Custom
Write your own adapter
questpie.config.ts
runtimeConfig({ kv: { adapter: () }, queue: { adapter: () }, search: (), realtime: { adapter: () }, storage: { driver: ({ bucket: "assets" }) }, email: { adapter: () }, })
Click the highlighted adapters to swap. Under 50 lines to write your own.
04

Optional admin

Ship the admin panel only when you need it. Swappable package. Web, React Native, or build your own.

collections/posts.ts
collection("posts") .admin(({ c }) => ({ label: "Posts", icon: c.icon("ph:article"), })) .list(({ v }) => v.collectionTable({ columns: ["title", "status", "author", "date"], })) .form(({ v, f }) => v.collectionForm({ fields: [f.title, f.content], sidebar: { fields: [f.status, f.author] }, })) .access({ create: ({ session }) => !!session, update: ({ session, doc }) => doc.authorId === session?.user?.id, })
Posts
TitleStatusAuthorDate
Getting Started GuidePUBLISHEDadminMar 15
Adapter ArchitectureDRAFTadminMar 12
05

End-to-end types

Schema to screen. Zero disconnect. Change a field — TypeScript catches it everywhere.

client.ts
const { docs } = await client.collections.posts.find({ where: { status: { eq: "published" } }, orderBy: { createdAt: "desc" }, with: { author: true, tags: true }, locale: "sk", }); // docs[0].title → string // docs[0].author → User // docs[0].tags → Tag[]
06

Composable

Core parts = user code. Modules compose depth-first with deduplication. Every module uses the exact same conventions as user code.

01

questpie-starter

Auth, users, sessions, API keys, assets. Better Auth integration. Default access. i18n messages.

02

questpie-admin

Admin UI. 18 field renderers, 3 view types, sidebar, dashboard widgets. Table, form, block editor.

03

questpie-audit

Change logging via global hooks. Every create, update, delete tracked. Zero config required.

04

Your module

Same file conventions, same patterns. Build your own module. Publish to npm. No special APIs.

07

Developer experience

The details matter. Instant regeneration, typed scaffolding, build-time validation.

WATCH
$ questpie dev
Watching...
server (23 collections)
admin-client (15 blocks)
SCAFFOLD
$ questpie add collection products
Created collections/products.ts
Regenerated types
VALIDATE
✗ Server defines blocks/hero
but no renderer found
→ Create admin/blocks/hero.tsx
REALTIME
client.realtime.subscribe(
{ resource: "posts" },
(event) => updateUI(event)
);|
Q

One backend. Ship everywhere.

$npx create-questpie