# Output Structure

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.ts
```

## Key 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 jobs
```

### File Storage (R2)

When `fileStorage` is configured:

```
src/
└── routes/
    └── storage.ts              # File upload/download endpoints
quickback/drizzle/
└── files/                      # File metadata migrations
    ├── meta/
    └── 0000_*.sql
```

### Webhooks

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_*.sql
```

### Security 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.ts
```

Cloudflare output also includes an `AUDIT_DB` D1 binding in `wrangler.toml` and migration scripts:

- `db:migrate:audit:local`
- `db: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 report
```

The 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 endpoint
```

The 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 endpoints
```

## Database 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`, `accounts`
- `organizations`, `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 artifacts
- `quickback/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.sql
```

## CMS 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.css
```

On 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.pdf
```

After 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 from `src/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 and prebuilt SPA bundles 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. Bind a directory to a hostname via [`config.apps`](/compiler/config/domains#app-domains) — the compiler emits the matching Worker middleware automatically.

```
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.tsx
```

After 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 from `src/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.tsx` while `cms: true`) fails the compile with a clear error.
- Migrating from hand-edited `src/apps/<name>/`: move the entire folder under `quickback/apps/<name>/` once, then trust the compile cycle. The hermetic `src/` 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):

```toml
[assets]
binding = "ASSETS"
directory = "src/apps"
not_found_handling = "none"
run_worker_first = true
```

See [Multi-Domain Architecture](/compiler/config/domains) for details on hostname routing.

## See Also

- [Providers](/compiler/config/providers) — Configure runtime, database, and auth providers
- [Environment variables](/compiler/config/variables) — Required variables by runtime
- [Multi-Domain Architecture](/compiler/config/domains) — Custom domains and hostname routing
