Getting Started
Get started with Quickback in minutes. Learn how to define database tables with security configuration and compile them into a production-ready API.
Get started with Quickback in minutes. This guide shows you how to define a complete table with security configuration.
Install the CLI
npm install -g @kardoe/quickbackCreate a Project
quickback create cloudflare my-app
cd my-appThis scaffolds a complete project with:
quickback.config.ts— Project configurationquickback/features/— Your table definitions- Example feature with full security configuration
Available templates:
cloudflare— Cloudflare Workers + D1 + Better Auth (free)bun— Bun + SQLite + Better Auth (free)turso— Turso/LibSQL + Better Auth (pro)
File Structure
Each table gets its own file with schema and config together using defineTable:
quickback/
├── quickback.config.ts
└── features/
└── jobs/
├── jobs.ts # Table + security config
├── applications.ts # Related table + config
├── actions.ts # Custom actions (optional)
└── handlers/ # Action handlers (optional)
└── close-job.tsComplete Example
Here's a complete jobs table with all security layers:
// quickback/features/jobs/jobs.ts
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';
import { defineTable } from '@quickback/compiler';
export const jobs = sqliteTable('jobs', {
id: text('id').primaryKey(),
title: text('title').notNull(),
department: text('department').notNull(),
status: text('status').notNull().default('draft'), // draft, open, closed
salaryMin: integer('salary_min'),
salaryMax: integer('salary_max'),
// Ownership - required for firewall data isolation
organizationId: text('organization_id').notNull(),
});
export default defineTable(jobs, {
// 1. FIREWALL - Data isolation
firewall: { organization: {} },
// 2. GUARDS - Field modification rules
guards: {
createable: ["title", "department", "status", "salaryMin", "salaryMax"],
updatable: ["title", "department", "status"],
},
// 3. CRUD - Role-based access control
crud: {
list: { access: { roles: ["owner", "hiring-manager", "recruiter", "interviewer"] }, pageSize: 25 },
get: { access: { roles: ["owner", "hiring-manager", "recruiter", "interviewer"] } },
create: { access: { roles: ["owner", "hiring-manager"] } },
update: { access: { roles: ["owner", "hiring-manager"] } },
delete: { access: { roles: ["owner", "hiring-manager"] }, mode: "soft" },
},
});
export type Job = typeof jobs.$inferSelect;What Each Layer Does
- Firewall: Automatically adds
WHERE organizationId = ?to every query. Users in Org A can never see Org B's data. - Guards: Controls which fields can be modified —
createablefor POST,updatablefor PATCH,protectedfor action-only fields. - CRUD Access: Role-based access control for each operation. All roles can read, only hiring managers can write.
Compile and Run
# Log in (first time only)
quickback login
# Compile your definitions
quickback compile
# Run locally
npm run devGenerated Endpoints
Quickback generates these endpoints from the example above:
| Method | Endpoint | Description |
|---|---|---|
GET | /api/v1/jobs | List jobs (all roles) |
GET | /api/v1/jobs/:id | Get single job |
POST | /api/v1/jobs | Create job (hiring managers only) |
PATCH | /api/v1/jobs/:id | Update job (hiring managers only) |
DELETE | /api/v1/jobs/:id | Soft delete job (hiring managers only) |
Test Your API
After quickback compile and npm run dev, your API is running locally. Open a second terminal and try these requests:
# 1. Create a user account
curl -X POST http://localhost:8787/api/auth/sign-up/email \
-H "Content-Type: application/json" \
-d '{"email": "admin@example.com", "password": "securepassword123", "name": "Admin"}'
# 2. Sign in and get a session token
curl -X POST http://localhost:8787/api/auth/sign-in/email \
-H "Content-Type: application/json" \
-d '{"email": "admin@example.com", "password": "securepassword123"}'
# → Response includes a session token in Set-Cookie header
# 3. Create a record (use the session cookie from step 2)
curl -X POST http://localhost:8787/api/v1/jobs \
-H "Content-Type: application/json" \
-H "Cookie: better-auth.session_token=<token>" \
-d '{"title": "Senior Engineer", "department": "Engineering", "status": "open"}'
# 4. List records
curl http://localhost:8787/api/v1/jobs \
-H "Cookie: better-auth.session_token=<token>"The port depends on your template: 8787 for Cloudflare (wrangler), 3000 for Bun. Check your terminal output for the exact URL.
Next Steps
- Template Walkthroughs — Detailed setup guides
- Full Example — Complete resource walkthrough
- Database Schema — Column types, relations, audit fields
- Firewall — Data isolation patterns
- Access — Role & condition-based control
- Guards — Field modification rules
- Masking — Field redaction for sensitive data
- Actions — Custom business logic endpoints
See Also
- Quickback Stack — The runtime environment where your compiled API runs (D1, KV, R2, auth)
- Account UI — Pre-built authentication and account management UI
- Using the API — CRUD endpoints, filtering, and batch operations