# Project structure

A tour of the files in a scaffolded DeepSpace app.

A scaffolded app is a Vite + React project with a Cloudflare Worker entry point. This page lists every file the scaffold ships and what each one is for.

## Top-level files

| File | Purpose |
|---|---|
| `worker.ts` | Hono worker and Durable Object class declarations. Edit to add custom routes or DO classes. |
| `wrangler.toml` | Cloudflare config. The `name` field is set by the CLI from the project name and determines the deploy subdomain; changing it after deploy doesn't move the existing worker. Declare custom bindings here. |
| `index.html` | HTML shell. Set `<html data-theme="...">` to pick a theme, update `<title>` and favicon. |
| `vite.config.ts` | Vite + `@cloudflare/vite-plugin` + generouted config. |
| `package.json` | Dependencies. The scaffold ships `deepspace`, `react`, `react-router` + `@generouted/react-router`, `hono`, `yjs`, the Vercel `ai` SDK with `@ai-sdk/anthropic`/`@ai-sdk/openai`, `@radix-ui/*` primitives, `lucide-react`, `framer-motion`, and `zod`. |
| `tsconfig.json` | TypeScript config. Strict mode, ES2022 target, covers `src/` and `worker.ts`. |
| `postcss.config.js` | PostCSS pipeline for Tailwind v4. |
| `.dev.vars` | Local secrets (gitignored). Not in the template - `deepspace dev` writes SDK-managed keys here on first run. Any keys you add by hand are uploaded as `secret_text` bindings on the next `deepspace deploy`. |

## `src/` - application code

### Pages and providers

| File | Purpose |
|---|---|
| `src/main.tsx` | Vite entry. Mounts `<Routes />` from `@generouted/react-router` into `#root`. |
| `src/pages/_app.tsx` | Root layout. Wraps the tree in `ToastProvider → DeepSpaceAuthProvider → AuthBoot → RecordProvider → RecordScope`. Extend, don't replace. |
| `src/pages/index.tsx` | `/` route. Redirects to `/home`. |
| `src/pages/home.tsx` | `/home` route. Public landing page. |
| `src/pages/[...all].tsx` | Catch-all 404. |
| `src/pages/(protected)/_layout.tsx` | Applies `<AuthGate>` to every route inside the `(protected)/` folder. |
| `src/pages/(protected)/*.tsx` | Gated routes. Ships with `settings.tsx`; add files here for new authenticated pages. |
| `src/components/Navigation.tsx` | Top navigation with auth-aware controls. Reads entries from `src/nav.ts`. |
| `src/components/ui/` | Shadcn-style primitives - `Button`, `Dialog`, `Toast`, `Card`, `EmptyState`, and more. |

Routing is file-based via [generouted](https://github.com/oedotme/generouted): every file under `src/pages/` becomes a route. Folder names in parentheses (`(protected)/`) are route groups - they apply layouts without showing up in the URL.

### Data layer

| File | Purpose |
|---|---|
| `src/schemas.ts` | Exports the array of every collection schema in the app. |
| `src/schemas/` | One file per collection (`users-schema.ts`, `admin-schema.ts`, your custom collections). |
| `src/actions/index.ts` | Server actions - privileged worker functions called via `POST /api/actions/:name`. |
| `src/constants.ts` | `APP_NAME`, `SCOPE_ID`, and role re-exports. |

Schemas are imported by `worker.ts` and baked into the bundle at deploy time. There's no runtime schema registry - adding or changing a schema requires a redeploy.

### Theming and navigation

| File | Purpose |
|---|---|
| `src/themes.ts` | Typed catalog of theme presets. |
| `src/themes.css` | Per-theme CSS variable blocks (15 presets ship with the scaffold). |
| `src/styles.css` | Tailwind v4 entrypoint with the slate baseline `@theme` block. |
| `src/nav.ts` | Top-nav entries. Add new pages here to make them appear in `Navigation.tsx`. |

### Feature surfaces

These ship pre-wired in the scaffold with empty defaults. Edit to populate, or delete the file if the feature isn't needed. Use `npx deepspace add <feature>` to install additional surfaces.

| File | Purpose |
|---|---|
| `src/cron.ts` | Scheduled tasks for `AppCronRoom`. See [Scheduled tasks](/guides/scheduled-jobs). |
| `src/jobs.ts` | Background-job handlers for `AppJobRoom`. See [Background jobs](/guides/background-jobs). |
| `src/ai/tools.ts` | System prompt and tool allowlist for `/api/ai/chat`. |
| `src/ai/chat-routes.ts` | Hono handlers for the AI chat endpoints. |
| `src/integrations.ts` | Per-integration billing config (`developer` vs `user`). |
| `src/subscriptions.ts` | Subscription plan manifest for Stripe billing. |
| `src/products.ts` | One-time product manifest. |

## `tests/` - Playwright specs

| File | Purpose |
|---|---|
| `tests/smoke.spec.ts` | App boot, navigation visibility, sign-in button presence, 404 route, console-error check. |
| `tests/api.spec.ts` | `/api/auth/ok` reachability and a WebSocket smoke check. |
| `tests/collab.spec.ts` | Two-user multi-context sign-in via the `users` fixture from `deepspace/testing`. |
| `tests/helpers/` | Console-error capture helper and the Playwright `globalSetup` that warms up the auth worker. |
| `tests/playwright.config.ts` | Playwright config - `baseURL`, `webServer`, `DEEPSPACE_PORT` plumbing. |

Run with `npx deepspace test`. See [Testing](/guides/testing).

## The Durable Object manifest

`worker.ts` exports a `__DO_MANIFEST__` constant listing the DO classes the app uses:

```ts
export const __DO_MANIFEST__ = [
  { binding: 'RECORD_ROOMS', className: 'AppRecordRoom', sqlite: true },
  { binding: 'YJS_ROOMS', className: 'AppYjsRoom', sqlite: true },
  { binding: 'CANVAS_ROOMS', className: 'AppCanvasRoom', sqlite: true },
  { binding: 'PRESENCE_ROOMS', className: 'AppPresenceRoom', sqlite: true },
  { binding: 'CRON_ROOMS', className: 'AppCronRoom', sqlite: true },
  { binding: 'JOB_ROOMS', className: 'AppJobRoom', sqlite: true },
] as const satisfies DOManifest
```

Each entry has a `binding` (the env binding name your Hono routes look up), a `className` (the DO subclass exported from the same file), and `sqlite` (true for SQLite-backed DOs).

This constant exists for TypeScript inference. The `Env` interface picks up the binding names from it automatically:

```ts
interface Env extends DOBindings<typeof __DO_MANIFEST__> {
  // ...your secrets and custom bindings
}
```

The actual deploy-time bindings and migrations are declared in `wrangler.toml` under `[durable_objects]` and `[[migrations]]`; keep the two in sync. Don't remove classes you no longer use without clearing their stored data first - the records persist across deploys.

## Next steps

- [Quickstart](/get-started/quickstart) - build something with these files.
- [Architecture](/concepts/architecture) - how everything fits together.
- [Data model](/concepts/data-model) - collections, records, and the envelope shape.
