Project Structure
Overview
A Void app uses file-based conventions to define routes, pages, middleware, and more. All directories are optional, so you only need the pieces your app actually uses.
- routes/API endpoints (file-based routing)
- pages/Full-stack server-rendered pages
- middleware/Global request middleware
- db/Drizzle schema and SQL migrations
- crons/Scheduled cron jobs
- queues/Async queue consumers
- email/Inbound email handlers
- durable-objects/Durable State modules
- src/Shared app code
- public/Static assets (served as-is)
- .void/Auto-generated (gitignored)
- vite.config.tsVite config with voidPlugin()
- void.config.tsVoid project config (optional)
- .envLocal environment values
- env.tsEnvironment schema
- package.json
- tsconfig.json
routes/
File-based HTTP API endpoints built on Hono. Each file exports named HTTP method handlers.
- routes/
- api/
- hello.ts→ GET|POST /api/hello
- users/
- index.ts→ GET|POST /api/users
- [id].ts→ GET|PUT|DELETE /api/users/:id
- search/
- [...query].ts→ GET /api/search/* (catch-all)
- Named exports:
export const GET = defineHandler(...),export const POST = ... - Dynamic segments:
[id]becomes:idroute parameter - Catch-all:
[...slug]matches the remaining path - Route groups:
(admin)/organizes files without affecting URL paths - Files starting with
_are ignored - Environment suffix:
debug.dev.tsbuilds in development only,metrics.prod.tsin production only
See Server Routing for the full guide.
pages/
Full-stack server-rendered pages with co-located data loading. Available with Vue, React, Svelte, and Solid adapters.
- pages/
- layout.tsxRoot layout (wraps all pages)
- index.tsx→ /
- index.server.tsServer-side loader & action for /
- about.tsx→ /about
- users/
- layout.tsxNested layout for /users/*
- [id].tsx→ /users/:id
- [id].server.tsServer-side loader & action for /users/:id
- blog/
- hello.md→ /blog/hello (Markdown page)
.server.tsfiles exportloaderforGETdata andactionfor mutations, paired with the page component of the same name- Layouts nest automatically and persist across navigations
- Markdown pages are supported with frontmatter
See Pages Routing for the full guide.
middleware/
Global middleware that runs on every request. Numeric prefixes control execution order.
- middleware/
- 01.logger.tsRuns first
- 02.auth.tsRuns second
Each file default-exports a defineMiddleware() handler. Use middleware to set shared context (auth, logging, rate limiting) available to all routes.
db/
Drizzle schemas and SQL migrations for D1, PostgreSQL, or MySQL.
- db/
- schema.tsDrizzle schema (source of truth)
- schema/Optional: split into multiple files
- migrations/
- 20260410161500_*.sql
- 20260410161501_*.sql
db/schema.ts: your Drizzle table definitions and the source of truth for DB typesdb/schema/: optional. Split tables into separate files and re-export them fromdb/schema.tsdb/migrations/: generated SQL migration files, applied in order on deploy
Generate schema with void gen model or write it by hand. Generate migrations with void db generate.
crons/
Scheduled jobs. Each file exports a cron expression and a default defineScheduled() handler.
queues/
Queue consumers. Each file default-exports a defineQueue() handler.
email/
Inbound email handlers. A file's name selects the recipient; _default.ts handles other addresses.
durable-objects/
Durable State modules. Each file default-exports a defineDurableState() definition.
src/
Shared application code such as components, utilities, and types. This directory has no special convention, so organize it however you like.
public/
Static assets served as-is at the root path. Files here are not processed by Vite.
.void/
Generated types and local development state (gitignored). Run void prepare to create the types, or let vite dev and vite build update them.
Config Files
| File | Purpose |
|---|---|
vite.config.ts | Vite configuration. Must include voidPlugin(). |
void.config.ts | Optional Void config for routing, inference, and worker settings |
tsconfig.json | TypeScript config. Extend .void/tsconfig.json for auto-generated types; run void init --tsconfig when an existing config already uses extends. |
.env | Local development values only (gitignored; never deployed) |
env.ts | Checked-in env names, types, defaults, and requiredness |
See Environment Variables for local, production-secret, and client build behavior.