Output Structure
Understanding the files and directories generated by the Quickback compiler.
The compiler generates a complete project structure based on your definitions and provider configuration. The output varies depending on your runtime (Cloudflare vs Bun) and enabled features.
Warning: Never edit files in src/ directly. They are overwritten on every compile. Make changes in your quickback/ definitions instead.
Cloudflare Output
src/
├── index.ts # Hono app entry point (Workers export)
├── env.d.ts # Cloudflare bindings TypeScript types
├── db/
│ ├── index.ts # Database connection factory
│ ├── auth-schema.ts # Auth table schemas (dual mode)
│ └── features-schema.ts # Feature table schemas (dual mode)
├── auth/
│ └── index.ts # Better Auth instance & config
├── features/
│ └── {feature}/
│ ├── schema.ts # Drizzle table definition
│ ├── routes.ts # CRUD + action endpoints
│ └── actions.ts # Action handlers (if defined)
├── lib/
│ ├── access.ts # Access control helpers
│ ├── types.ts # Runtime type definitions
│ ├── masks.ts # Field masking utilities
│ ├── services.ts # Service layer
│ ├── audit-wrapper.ts # Auto-inject audit fields
│ └── security-audit.ts # Unsafe cross-tenant audit logger (when needed)
└── middleware/
├── auth.ts # Auth context middleware
├── db.ts # Database instance middleware
└── services.ts # Service injection middleware
quickback/drizzle/
├── auth/ # Auth migrations (dual mode)
│ ├── meta/
│ │ ├── _journal.json
│ │ └── 0000_snapshot.json
│ └── 0000_initial.sql
├── features/ # Feature migrations (dual mode)
│ ├── meta/
│ │ ├── _journal.json
│ │ └── 0000_snapshot.json
│ └── 0000_initial.sql
└── audit/ # Unsafe cross-tenant action audit migrations (when needed)
├── meta/
└── 0000_initial.sql
# Root config files
├── package.json
├── tsconfig.json
├── wrangler.toml # Cloudflare Workers config
├── drizzle.config.ts # Features DB drizzle config
├── drizzle.auth.config.ts # Auth DB drizzle config (dual mode)
└── drizzle.audit.config.ts # Audit DB drizzle config (when unsafe actions exist)Bun Output
src/
├── index.ts # Hono app entry point (Bun server)
├── db/
│ ├── index.ts # SQLite connection (bun:sqlite)
│ └── schema.ts # Combined schema (single DB)
├── auth/
│ └── index.ts # Better Auth instance
├── features/
│ └── {feature}/
│ ├── schema.ts
│ ├── routes.ts
│ └── actions.ts
├── lib/
│ ├── access.ts
│ ├── types.ts
│ ├── masks.ts
│ ├── services.ts
│ └── audit-wrapper.ts
└── middleware/
├── auth.ts
├── db.ts
└── services.ts
quickback/drizzle/ # Single migration directory
├── meta/
│ ├── _journal.json
│ └── 0000_snapshot.json
└── 0000_initial.sql
data/ # SQLite database files
└── app.db
├── package.json
├── tsconfig.json
└── drizzle.config.tsKey Differences by Runtime
| Aspect | Cloudflare | Bun |
|---|---|---|
| Entry point | Workers export default | Bun.serve() with port |
| Database | D1 bindings (dual mode) | SQLite file (single DB) |
| Types | env.d.ts for bindings | No extra types needed |
| Config | wrangler.toml | .env file |
| Migrations | quickback/drizzle/auth/ + quickback/drizzle/features/ | quickback/drizzle/ |
| Drizzle configs | 2 configs (auth + features) | 1 config |
Optional Output Files
These files are generated only when the corresponding features are configured:
Embeddings
When any feature has embeddings configured:
src/
├── lib/
│ └── embeddings.ts # Embedding helpers
├── routes/
│ └── embeddings.ts # POST /api/v1/embeddings endpoint
└── queue-consumer.ts # Queue handler for async embedding jobsFile Storage (R2)
When fileStorage is configured:
src/
└── routes/
└── storage.ts # File upload/download endpoints
quickback/drizzle/
└── files/ # File metadata migrations
├── meta/
└── 0000_*.sqlWebhooks
When webhooks are enabled:
src/
└── lib/
└── webhooks/
├── index.ts # Webhook module entry
├── sign.ts # Webhook payload signing
├── handlers.ts # Handler registry
├── emit.ts # Queue emission helpers
├── routes.ts # Inbound/outbound endpoints
└── providers/
├── index.ts
└── stripe.ts # Stripe webhook handler
quickback/drizzle/
└── webhooks/ # Webhook schema migrations
├── meta/
└── 0000_*.sqlSecurity Audit Database (Unsafe Actions)
When any action enables unsafe cross-tenant mode (unsafe.crossTenant: true):
src/
├── db/
│ └── audit-schema.ts # audit_events table
└── lib/
└── security-audit.ts # mandatory audit writer
quickback/drizzle/
└── audit/
├── meta/
└── 0000_*.sql
# Root
└── drizzle.audit.config.tsCloudflare output also includes an AUDIT_DB D1 binding in wrangler.toml and migration scripts:
db:migrate:audit:localdb:migrate:audit:remote
Security Contract Report and Signature
Generated on every compile (unless disabled via compiler.securityContracts.report.enabled: false):
reports/
├── security-contracts.report.json # Contract evaluation summary + violations
└── security-contracts.report.sig.json # Signature / digest envelope for the reportThe signature file uses HMAC-SHA256 when a signing key is configured, otherwise it falls back to SHA-256 digest mode.
Set compiler.securityContracts.report.signature.required: true to fail compilation when a signing key is missing.
Realtime
When any feature has realtime configured:
src/
├── lib/
│ ├── realtime.ts # Broadcast helpers
│ ├── Broadcaster.ts # Durable Object class (inline in main worker)
│ └── ws-ticket.ts # WebSocket ticket auth utility
└── routes/
└── ws-ticket.ts # POST /realtime/v1/ws-ticket endpointThe Broadcaster DO class is exported from your main worker entry point and runs inline — no separate cloudflare-workers/broadcast/ deployment needed.
Device Authorization
When the deviceAuthorization plugin is enabled:
src/
└── routes/
└── cli-auth.ts # Device auth flow endpointsDatabase Schemas
Dual Database Mode (Cloudflare Default)
The compiler separates schemas into two files:
src/db/auth-schema.ts — Re-exports Better Auth table schemas:
users,sessions,accountsorganizations,members,invitations(if organizations enabled)- Plugin-specific tables (
apiKeys, etc.)
src/db/features-schema.ts — Re-exports your feature schemas:
- All tables defined with
defineTable() - Audit field columns added automatically
Single Database Mode (Bun Default)
src/db/schema.ts — Combined re-export of all schemas (auth + features).
Generated Routes
For each feature, the compiler generates a routes file at src/features/{name}/routes.ts containing:
| Route | Generated When |
|---|---|
GET / | crud.list configured |
GET /:id | crud.get configured |
POST / | crud.create configured |
PATCH /:id | crud.update configured |
DELETE /:id | crud.delete configured |
PUT /:id | crud.put configured |
POST /batch | crud.create exists (auto-enabled) |
PATCH /batch | crud.update exists (auto-enabled) |
DELETE /batch | crud.delete exists (auto-enabled) |
PUT /batch | crud.put exists (auto-enabled) |
GET /views/{name} | views configured |
POST /:id/{action} | Record-based actions defined |
POST /{action} | Standalone actions defined |
All routes are mounted under /api/v1/{feature} in the main app.
Migrations
The compiler runs drizzle-kit generate during compilation to produce SQL migration files. On subsequent compiles, it uses existingFiles (your current migration state) to generate only incremental changes.
The CLI loads migration meta JSON from one location only — <project>/quickback/drizzle/:
quickback/drizzle/auth/meta/quickback/drizzle/features/meta/quickback/drizzle/files/meta/quickback/drizzle/webhooks/meta/quickback/drizzle/audit/meta/quickback/drizzle/meta/(single-database mode)
Quickback owns this state — nothing under a project-root drizzle/ folder is ever read or written.
Migration and report artifacts are written to the quickback/ state directory:
quickback/drizzle/...for Drizzle migration SQL/meta artifactsquickback/reports/...for security contract report artifacts
For non-interactive environments (cloud compile, CI), table/column renames must be declared with compiler.migrations.renames in quickback.config.ts. This avoids interactive rename prompts during migration generation.
Migration files follow the Drizzle Kit naming convention:
0000_initial.sql
0001_add_status_column.sql
0002_create_orders_table.sqlCMS and Account UI Assets
When cms and/or account are enabled, the compiler builds the SPAs from source at compile time and includes the assets in the output.
Each SPA is placed in its own subdirectory under src/apps/:
src/apps/ # Root assets directory
├── cms/ # CMS SPA (served at /cms/ on unified domain)
│ ├── index.html
│ └── assets/
│ ├── app.abc123.js # Content-hashed filenames from Vite
│ └── app.xyz456.css
└── account/ # Account SPA (served at /account/ on unified domain)
├── index.html
└── assets/
├── app.def789.js
└── app.ghi012.cssOn custom domains, each SPA is served at root (/) via hostname-based routing. On the unified domain, CMS is at /cms/ and Account is at /account/.
Static Assets (quickback/public/)
Anything you drop under quickback/public/ is copied verbatim into src/apps/ on every compile. The compiler does not parse, template, or otherwise touch these files — they are bytes that ride past it into the Cloudflare ASSETS binding.
quickback/public/ # Source — checked into your repo
├── favicon.ico
├── robots.txt
├── og/
│ └── og-image.png
└── pdfs/
└── whitepaper.pdfAfter compile:
src/apps/ # Destination — written by the CLI
├── favicon.ico # Served at https://your-domain/favicon.ico
├── robots.txt # Served at /robots.txt
├── og/og-image.png # Served at /og/og-image.png
├── pdfs/whitepaper.pdf
├── cms/ # Compiler-emitted SPA (don't shadow)
└── account/ # Compiler-emitted SPA (don't shadow)Notes:
- The folder is optional. If it doesn't exist, this step is a no-op.
- Files removed from
quickback/public/disappear fromsrc/apps/on the next compile —src/is wiped and rewritten each run. - Hidden entries (
.DS_Store,.git/, dotfiles) are skipped. - A file in
quickback/public/that would overwrite a compiler-emitted path (e.g.quickback/public/cms/index.html) fails the compile with a clear error rather than silently shadowing the SPA shell. - Binaries (images, fonts, PDFs) are copied byte-for-byte — there is no string round-trip.
Source Apps (quickback/apps/)
For hand-authored TypeScript apps that live alongside the compiler-emitted SPA shells, drop them under quickback/apps/<name>/. The CLI copies the tree into src/apps/<name>/ on every compile, byte-for-byte, after the compiler has finished writing.
quickback/apps/ # Source — checked into your repo
├── m/ # A hand-authored mobile companion app
│ ├── index.tsx
│ ├── components/Button.tsx
│ └── lib/utils.ts
└── admin/ # A hand-authored admin tool
└── index.tsxAfter compile:
src/apps/
├── m/index.tsx # Hand-authored — preserved across compiles
├── m/components/Button.tsx
├── m/lib/utils.ts
├── admin/index.tsx
├── cms/ # Compiler-emitted SPA (don't shadow)
└── account/ # Compiler-emitted SPA (don't shadow)When to choose apps/ vs public/:
quickback/public/ | quickback/apps/ | |
|---|---|---|
| Use for | Static binaries (logos, fonts, OG images, PDFs, robots.txt) | Hand-authored TS/TSX/JS app source |
| Skips | Hidden entries only (.DS_Store, .git/) | Hidden entries + node_modules/, dist/, build/, .next/, .turbo/, .cache/ |
| Folder layout | Files at any depth — flat or nested | Apps under named subfolders (m/, admin/, …) |
Notes:
- The folder is optional. If it doesn't exist, this step is a no-op.
- Files removed from
quickback/apps/<name>/disappear fromsrc/apps/<name>/on the next compile —src/is wiped and rewritten each run. - A file in
quickback/apps/that would overwrite a compiler-emitted path (e.g.quickback/apps/cms/index.tsxwhilecms: true) fails the compile with a clear error. - Migrating from hand-edited
src/apps/<name>/: move the entire folder underquickback/apps/<name>/once, then trust the compile cycle. The hermeticsrc/contract holds again.
Generated Wrangler Assets Config
The compiler always generates run_worker_first = true when SPAs are enabled — the Worker handles all SPA routing (per hostname and per path prefix):
[assets]
binding = "ASSETS"
directory = "src/apps"
not_found_handling = "none"
run_worker_first = trueSee Multi-Domain Architecture for details on hostname routing.
See Also
- Providers — Configure runtime, database, and auth providers
- Environment variables — Required variables by runtime
- Multi-Domain Architecture — Custom domains and hostname routing