# Quickback — Backend Compiler with Security Baked In > Canonical documentation: https://docs.quickback.dev > Full doc tree for agents: run `quickback docs` in a project, or browse https://docs.quickback.dev Quickback is a **backend compiler**: define your database schema and security rules in TypeScript, compile them into a production-ready API. Two targets: - **Hono API** on Cloudflare (D1 or Neon) — full app: CRUD + batch endpoints, auth, OpenAPI, MCP server, optional embedded CMS and Account UI. - **Supabase RLS** — PostgreSQL Row Level Security policies; keep Supabase Auth/Storage/Realtime, Quickback adds the security layer. Everything runs in the user's own Cloudflare account. The compiler is a remote service (`compiler.quickback.dev`); the CLI is a thin client. ## Quickstart ```bash npm install -g @quickback-dev/cli quickback create cloudflare my-app cd my-app quickback build # generates src/ + migrations; never touches a database npm run deploy # applies D1 migrations, then wrangler deploy ``` Or start from a prompt in the browser: https://start.quickback.dev ## File Structure ``` quickback/ ├── quickback.config.ts # project config (providers, cms, account, …) ├── features/ │ └── {feature}/ │ ├── {feature}.ts # schema + security in one file (feature()) │ └── actions/{name}.ts # custom endpoints (defineAction), one per file └── drizzle/{db}/ # generated migrations — COMMIT THESE src/ # generated worker — never hand-edit ``` `quickback build` fully regenerates `src/` and appends incremental migrations to `quickback/drizzle/` (diffed from the committed meta). Custom code lives only under `quickback/`. ## Core Concept: feature() ```typescript // quickback/features/todos/todos.ts import { feature, q } from "@quickback/compiler"; export default feature("todos", { columns: { id: q.id(), title: q.text({ maxLength: 200 }).required(), completed: q.bool().default(false), organizationId: q.scope("organization"), // → ctx.activeOrgId, auto-firewalled ownerId: q.scope("owner"), // → ctx.userId, auto-firewalled + stamped ...q.audit(), // createdAt/By, modifiedAt/By (visible, managed) ...q.softDelete(), // deletedAt/By — required for delete mode "soft" }, read: { access: { roles: ["member", "admin"] } }, create: { access: { roles: ["member", "admin"] } }, update: { access: { roles: ["admin"] } }, delete: { access: { roles: ["admin"] }, mode: "soft" }, guards: { createable: ["title", "completed"], updatable: ["title", "completed"], }, }); ``` Custom endpoint: ```typescript // quickback/features/todos/actions/complete.ts import { z } from "zod"; import { defineAction } from "../.quickback/define-action"; import { todos } from "../todos"; export default defineAction({ description: "Mark todo as complete", input: z.object({}), access: { roles: ["member", "admin"], record: { completed: { equals: false } }, }, async execute({ db, whereRecord }) { await db.update(todos).set({ completed: true }).where(whereRecord!(todos)); return { success: true }; }, }); ``` Existing Drizzle schemas (`sqliteTable` / `pgTable`) work via `defineTable(table, config)` — see https://docs.quickback.dev/define/escape-hatches ## Security Model — four pillars, deny by default ``` Request → Firewall → Access → Guards → Database → Masking → Response ``` 1. **Firewall** — compiled WHERE clauses isolating data by organization, owner, or team. Derived automatically from `q.scope()` columns; soft-delete (`deletedAt IS NULL`) is AND-merged in. 2. **Access** — role-based + record-level permissions on every read/write. Nothing is reachable until explicitly allowed. 3. **Guards** — field-write protection: `createable`, `updatable`, `immutable`, `protected` (action-only). 4. **Masking** — PII redaction; sensitive column names (`email`, `phone`, `ssn`, …) are auto-masked unless you override with a `masking:` block. Also: **Views** (named field projections with their own access) and **Actions** (declarative access, state transitions, `unsafe:` escape hatch). ## Key Rules - `organization_id` / `owner_id` columns drive isolation; `user_id` is informational only and warns on feature tables — rename to `owner_id` or declare an explicit firewall. - Tables with neither isolation column must declare `firewall: { exception: true }`. - Audit + soft-delete columns are authored visibly via `...q.audit()` / `...q.softDelete()` spreads — the compiler validates they are declared. - Batch endpoints (`POST/PATCH/DELETE /api/v1/{resource}/batch`, max 100 records) report `meta.transactional` — D1 and Neon-over-HTTP are fail-fast without rollback; websocket/Postgres providers get real transactions. ## Project Config ```typescript // quickback/quickback.config.ts import { defineConfig, defineRuntime, defineDatabase, defineAuth } from "@quickback/compiler"; export default defineConfig({ name: "my-app", template: "hono", features: { organizations: true }, cms: true, // embedded admin data UI at /cms account: true, // login/profile/orgs UI at /account providers: { runtime: defineRuntime("cloudflare", { compatibilityDate: "2025-01-01" }), database: defineDatabase("cloudflare-d1", { generateId: "prefixed" }), auth: defineAuth("better-auth", { emailAndPassword: { enabled: true }, plugins: { organization: true }, }), }, }); ``` The CMS and Account SPAs are embedded in the generated worker; per-project settings reach them at serve time via an injected `window.__QUICKBACK_RUNTIME` config. ## More - Docs: https://docs.quickback.dev — sections: /start, /define, /configure, /api, /platform, /ui/admin (CMS), /ui/account (Account UI), /tooling/cli - In a project: `quickback docs ` prints the same docs locally - Generated projects include AGENTS.md with the security model and decision guide - Start (prompt-to-backend): https://start.quickback.dev