Skip to content
brought to you byVoidZero
Private Beta:Void is currently in Private Beta. We do not recommend using it for mission-critical production workloads yet. Please back up your data regularly.

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
  • src/Shared app code
  • public/Static assets (served as-is)
  • .void/Auto-generated (gitignored)
  • vite.config.tsVite config with voidPlugin()
  • void.jsonVoid project config (optional)
  • .envEnvironment variables
  • 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 :id route parameter
  • Catch-all: [...slug] matches the remaining path
  • Route groups: (admin)/ organizes files without affecting URL paths
  • Files starting with _ are ignored

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.ts files export loader for GET data and action for 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 exports a defineMiddleware() handler. Use middleware to set shared context (auth, logging, rate limiting) available to all routes.

db/

Drizzle schema and SQL migration files for the D1 database.

  • 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 types
  • db/schema/: optional. Split tables into separate files and re-export them from db/schema.ts
  • db/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 that run on a cron schedule.

ts
// crons/heartbeat.ts
import { defineScheduled } from 'void';

export const cron = '*/5 * * * *';

export default defineScheduled(async (controller, env) => {
  // runs every 5 minutes
});

queues/

Async queue consumers for background job processing.

ts
// queues/email.ts
import { defineQueue } from 'void';

export default defineQueue(async (batch, env) => {
  for (const msg of batch.messages) {
    // process message
  }
});

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/

Auto-generated directory (gitignored). Contains:

Generate or refresh it with void prepare, or let vite dev / vite build populate it during normal app workflows.

  • .void/
    • db.d.tsDrizzle DB instance types
    • routes.d.tsTyped fetch client types
    • queues.d.tsQueue consumer types
    • tsconfig.jsonTypeScript config fragment
    • v3/Local dev state (D1, KV, R2)

Config Files

FilePurpose
vite.config.tsVite configuration. Must include voidPlugin().
void.jsonOptional Void config for routing, inference, and worker settings
tsconfig.jsonTypeScript config. Extend .void/tsconfig.json for auto-generated types; run void init --tsconfig when an existing config already uses extends.
.envPublic environment variables (committed)
.env.localSecret variables for local dev (gitignored)
.env.productionPublic production variables (committed)
.env.production.localProduction secrets for local testing (gitignored)

See Environment Variables for the full env file loading order.