---
name: quickback
description: Quickback documentation - use when working with Quickback projects, defining resources, schemas, security pillars (Firewall, Access, Guards, Masking), actions, the Stack runtime services, or deployment
allowed-tools: Read, Grep, Glob, Edit, Write
---

# Quickback

Quickback is a **backend compiler**. Define your database schema and security rules in TypeScript; compile them into either a Hono API or PostgreSQL Row Level Security policies. Pair the output with the Quickback Stack for a complete Supabase alternative on Cloudflare.

It's two products:

## 1. Quickback Compiler — the build tool

Define schema + security in TypeScript. Compile to one of two targets:

- **Quickback for Hono API** — Cloudflare D1 or Neon. Full Hono application with CRUD, batch endpoints, OpenAPI, and an MCP server.
- **Quickback for Supabase** — PostgreSQL Row Level Security policies. Keep Supabase Auth, Storage, and Realtime; Quickback adds the security layer.

The same `defineTable()` definitions work for both targets. The compiler runs as a remote service at `compiler.quickback.dev` (override with `QUICKBACK_API_URL`) — the CLI is a thin client that sends config + features and writes the generated files.

## 2. Quickback Stack — the runtime services

Everything you need around the compiled API for a complete Supabase alternative on Cloudflare:

| Service | What it gives you | Implementation |
|---|---|---|
| **Auth** | Email OTP, passkeys, password, Google OAuth, organizations, admin | Better Auth |
| **Storage** | KV (sessions, cache) and R2 (files) | Cloudflare KV + R2 |
| **Realtime** | WebSocket for live updates | Durable Objects |
| **Queues** | Background jobs, webhook delivery | Cloudflare Queues |
| **Vector & AI** | Embeddings, semantic search | Workers AI |
| **Webhooks** | Signed inbound, retried outbound | Hono + Queues |
| **CMS** | Schema-driven admin UI | Embedded SPA |
| **Account UI** | Login, profile, orgs, admin | Embedded SPA |

Everything runs on the user's own Cloudflare account — no Quickback infrastructure between them and their data.

---

## Quickstart

```bash
npm install -g @quickback-dev/cli
quickback create cloudflare my-app
cd my-app
quickback compile
wrangler deploy
```

Three concept files do most of the work:

- `quickback.config.ts` — project config (template, providers, account UI, CMS, etc.)
- `quickback/features/<feature>/<table>.ts` — table schema + security in one file via `feature()` (or `defineTable` for Drizzle interop)
- `quickback/features/<feature>/actions/<name>.ts` — custom endpoints via `defineAction()` (one file per action)

---

## The security model

Every API request passes through four pillars (the "Definitions"):

```
Request → Firewall → Access → Guards → Database → Masking → Response
            │          │        │                     │
            │          │        │                     └── Hide PII fields
            │          │        └── Block field modifications on writes
            │          └── Check roles & record-level conditions
            └── WHERE-clause data isolation (org / owner / team / soft-delete)
```

| Pillar | Purpose |
|---|---|
| **Firewall** | Compiled WHERE clauses — scope reads/writes to the caller's org, owner, or team. |
| **Access** | Role-based + record-level permissions; **deny by default**. |
| **Guards** | Field-write protection: `createable`, `updatable`, `immutable`, `protected` (action-only). |
| **Masking** | PII redaction; auto-applied for sensitive column names. |

Plus **Views** (named projections with their own access) and **Actions** (custom endpoints with declarative access, transitions, unsafe escape hatch).

**Secure by default.** Nothing is reachable until you explicitly open it. A fresh resource definition produces 401/403 for every caller that isn't an admin.

For the full reference, run `quickback docs compiler/definitions` (or any specific pillar: `firewall`, `access`, `guards`, `masking`, `views`, `actions`).

---

## A complete feature

```ts
// quickback/features/todos/todos.ts
import { feature, q } from "@quickback/compiler";

export default feature("todos", {
  columns: {
    id:             q.id(),
    title:          q.text().required(),
    completed:      q.bool().default(false),
    ownerId:        q.scope("owner"),         // → ctx.userId, auto-firewalled, auto-populated
    organizationId: q.scope("organization"),  // → ctx.activeOrgId, same
  },
  // firewall + soft-delete derived from q.scope() above:
  //   [{ field: 'organizationId', equals: 'ctx.activeOrgId' },
  //    { field: 'ownerId',        equals: 'ctx.userId' },
  //    { field: 'deletedAt',      isNull: true }]
  read: { access: { roles: ["member", "admin"] } },
  crud: {
    create: { access: { roles: ["member", "admin"] } },
    update: { access: { roles: ["admin"] } },
    delete: { access: { roles: ["admin"] }, mode: "soft" },
  },
  guards: {
    createable: ["title", "completed"],
    updatable:  ["title", "completed"],
  },
});
```

```ts
// 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, record, whereRecord, auditFields }) {
    await db.update(todos)
      .set({ completed: true, modifiedAt: auditFields!.modifiedAt })
      .where(whereRecord!(todos));
    return { success: true };
  },
});
```

For the schema column types: `quickback docs compiler/definitions/schema`.
For action shapes (record-based vs standalone, transitions, `unsafe:`): `quickback docs compiler/definitions/actions`.
For Drizzle interop (existing `sqliteTable` schemas): `quickback docs compiler/definitions/feature`.

---

## Defaults the compiler applies

Before flagging "missing X", check whether a default already covers it:

- **Soft-delete is the default.** `deletedAt` / `deletedBy` are auto-injected at the SQL layer; firewall auto-AND-merges `deletedAt IS NULL`. Opt out with `crud.delete.mode: 'hard'`.
- **Audit fields auto-injected.** `createdAt`, `createdBy`, `modifiedAt`, `modifiedBy` — never declare them in user code. The audit-wrapper auto-populates `createdBy` / `modifiedBy` from `ctx.userId`.
- **Sensitive columns auto-masked.** `email`, `phone`, `ssn`, `password`, `creditCard`, etc. get `show: { or: 'owner', roles: ['admin'] }` by default; falls back to `roles: ['admin']` only when there's no `ownerId` column. Absence of a `masking:` block does NOT mean plain-text — it means the compiler-default is in effect. Declare `masking:` only to override.
- **Firewall auto-derived** for tables with a single isolation column (e.g., `organizationId` only).
- **Soft-delete cascade** reaches cross-feature children with each child's own firewall AND-merged.
- **Reserved keys in `access.record`.** `and`, `or`, `roles`, `userRole` are rejected inside `record:` at compile time — those go on the parent access node.

---

## The scoped DB — what it does and doesn't do

The action context's `db` is a Drizzle wrapper that:

- **Does** auto-AND the resource's firewall WHERE clause into every `select` / `update` / `delete`.
- **Does** route soft-delete `delete()` calls to a `deletedAt` / `deletedBy` UPDATE.
- **Does NOT** auto-populate insert values. `db.insert(table).values({...})` writes whatever you pass — pass `organizationId` (and any other isolation columns) explicitly. Audit fields ARE auto-populated; tenant-scope columns are not.

For unscoped writes (cross-tenant support, platform admin), use the `unsafe:` object form on the action — it forces an audit reason and gates on platform admin role.

---

## Quickback CLI (commands the user runs)

```bash
quickback compile           # compile project (prompts to log in if not authenticated)
quickback create <template> # new project from template
quickback login             # authenticate via browser device flow
```

The CLI calls `compiler.quickback.dev` by default. Override with `QUICKBACK_API_URL=http://localhost:3000` for self-hosted compilation.

This skill does not have shell access — surface CLI commands to the user as instructions, don't try to run them.

---

## Looking up details

The full documentation is bundled alongside this `SKILL.md` as plain markdown files. To pull reference material on demand:

```
Glob:  docs/**/*.md                    # discover topics
Read:  docs/compiler/definitions/firewall.md
Grep:  "deletedAt" docs/                # search across the whole docs tree
```

The path layout mirrors the public docs site (https://docs.quickback.dev). Open any topic file for the authoritative reference; the skill body above is intentionally just orientation.

**Compiler — definitions** (`docs/compiler/definitions/<topic>.md`)
- `schema` — column types, `q.text/int/bool/uuid/timestamp/json/scope/...`, FKs, indexes
- `feature` — `feature()` shape, `q.scope()`, soft delete, audit fields
- `firewall` — predicates, scope detection, exceptions
- `access` — roles, record predicates, role hierarchy, `PUBLIC`, pseudo-roles
- `guards` — createable / updatable / immutable / protected
- `masking` — types, `show:`, search/filter gating, auto-detection
- `read` — `read.access`, `read.views`, `read.query`, pagination + filtering
- `views` — named projections with column-level access
- `actions` — record-based vs standalone, transitions, `unsafe:`, `whereRecord(table)`
- `validation` — minLength, max, enum, pattern, email
- `concepts` — secure-by-default, defense in depth, request flow

**Compiler — config** (`docs/compiler/config/<topic>.md`)
- `providers` — runtime / database / auth provider selection
- `variables` — env vars, secrets
- `bindings` — extra Cloudflare bindings (queues, R2, etc.)
- `output` — `build.outputDir`, custom dependencies
- `domains` — multi-domain hostname routing (CMS / account / admin)
- `spa` — single-worker SPA mount (your product app at the apex)
- `single-tenant` — disable organizations
- `agents` — robots.txt, llms.txt, MCP, OAuth discovery

**Stack — runtime services** (`docs/stack/<topic>.md`)
- `auth` — Better Auth integration, JWT optimization, plugins, device-auth, security
- `storage/{kv,r2}` — using KV and R2 in actions
- `realtime` — Durable Objects, WebSocket
- `queues` — handlers, retries, dead-letter
- `vector/embeddings` — auto-embedding columns, semantic search
- `webhooks/{inbound,outbound}` — signed inbound, retried outbound
- `cms` — schema-driven admin UI, dashboard, record layouts, table views, schema registry
- `account-ui` — login, profile, orgs, admin, passkeys, API keys, CLI authorize, with Quickback or standalone

**Getting started** (`docs/compiler/getting-started/<topic>.md`)
- `templates` — full template list
- `template-cloudflare` — recommended starting point
- `full-example` — top-to-bottom walkthrough
- `hand-crafted` — building from `template-empty`
- `patterns` — common multi-tenant / hierarchical / public patterns

**Cloud / CLI** (`docs/compiler/cloud-compiler/<topic>.md`)
- `cli` — full CLI reference
- `authentication` — login flow, API keys, sessions
- `endpoints` — POST /compile, GET /templates, GET /health
- `local-compiler` — running the compiler locally in Docker

**Other** — `docs/changelog.md`, `docs/compiler/claude-code-skill.md`

For online navigation: <https://docs.quickback.dev>.
