typebase-io-cli generate-server
Generate server files locally for custom hosting or inspection.
Last updated on
The generate-server command builds your server files locally instead of deploying them. This is useful when you want to:
- Self-host your server on your own infrastructure
- Inspect the generated code to understand what Typebase produces
- Customize the deployment process beyond what
npx typebase-io-cli deployoffers
Quick start
npx typebase-io-cli generate-serverThis generates a complete, runnable server in the typebase/_server/ directory (by default).
It regenerates _generated/ first (the same work codegen does), then type-checks your project against those fresh types, then builds.
Output formats
You can choose between three output formats:
TypeScript (default)
npx typebase-io-cli generate-server --output tsGenerates TypeScript source files. You'll need to compile them yourself before running.
ESM (ECMAScript Modules)
npx typebase-io-cli generate-server --output esmGenerates JavaScript files using import/export syntax. Ready to run with Node.js (with "type": "module") or Deno.
CommonJS
npx typebase-io-cli generate-server --output cjsGenerates JavaScript files using require/module.exports syntax. Ready to run with Node.js without "type": "module".
HTTP adapters
Typebase supports multiple HTTP adapters. The adapter determines how your server handles incoming HTTP requests:
| Adapter | Description | Best for |
|---|---|---|
node | Node.js built-in http.createServer | Self-hosting with Node.js (default) |
bun | Bun's built-in HTTP server | Self-hosting with Bun |
hono | Hono framework | Vercel, general-purpose |
fastify | Fastify framework | High-performance Node.js |
deno | Deno's built-in Deno.serve | Deno Deploy |
cloudflare | Cloudflare Workers fetch handler | Cloudflare Workers |
npx typebase-io-cli generate-server --adapter hononpx typebase-io-cli generate-server --adapter nodenpx typebase-io-cli generate-server --adapter fastifyOptions
| Flag | Description | Default |
|---|---|---|
--output <type> | Output format: ts, esm, or cjs | ts |
--adapter <adapter> | HTTP adapter: node, bun, hono, fastify, deno, cloudflare | node |
--out-dir <path> | Output directory for generated files | _server |
--watch | Rebuild on every change inside your typebase/ directory | false |
--port <number> | Port the generated server listens on | 8080 |
Default configuration
You can set defaults in your typebase.json so you don't have to pass flags every time:
{
"server": {
"output": "esm",
"adapter": "hono",
"outDir": "_server",
"port": 8080
}
}See the Configuration page for all available options.
What gets generated
The generated server directory contains:
_server/
src/
index.ts # Server entry point (with the chosen adapter)
_generated/
server.ts # Action builder and middleware setup
actions/ # Your action files (copied and processed)
db/ # Your schema and relations (if applicable)
auth.ts # Your auth config (if applicable)
env.ts # Validated environment variables (if applicable)
publisher.ts # Publisher runtime config (if applicable)
package.json # Dependencies for the server
tsconfig.json # TypeScript configsrc/publisher.ts is emitted when the project has a publisher.ts; it creates the configured provider with the runtime resources it needs. For the db provider, that is the generated database client.
src/env.ts is emitted whenever your project has an env.ts, a db/schema.ts, or an auth.ts — anything that means the server has variables to validate. dotenv is added to package.json, and dotenv/config imported by index.ts, only when that env module exists and the adapter is not cloudflare, which reads its values from Worker bindings rather than process.env. A server with nothing to read gets neither.
Watch mode
generate-server is a snapshot, so every edit normally means running it again. --watch does that for you:
npx typebase-io-cli generate-server --watchIt builds once, then rebuilds whenever anything inside your typebase/ directory changes. Press x or Ctrl+C to stop.
The first build reports each step. Every rebuild after that is a single Regenerating... line, so a long session stays
readable. Errors are still printed in full.
Changes to _generated/ and to the output directory are ignored. Generation writes to both, so watching them would
make every build trigger the next one.
If you save again while a build is running, that build is cancelled and a new one starts, so the output always reflects your latest sources rather than a half-finished older run. A build is only cancellable up to the point where it starts replacing the output directory; the final copy always runs to completion, so the directory is never left half written.
A failed build, a type error most often, does not stop the watcher. The error is printed and the next change triggers another attempt.
Watch mode rebuilds the files in the output directory. A server you already started from them keeps running the old code until you restart it. See Work locally.
Watch mode is a long-running command. If you drive the CLI from a script or an agent, run it in the background or with a timeout, and stop it with
SIGINT rather than x when the output is piped.
Regeneration
Each run rebuilds the server from scratch and replaces the previous output directory — files whose source was deleted or renamed don't linger. Two exceptions survive regeneration because they belong to you, not the generator: .env and node_modules. Install dependencies and configure your env once; re-runs keep both.
If a generation fails, the previous output is left untouched, so a working server is never destroyed by a failed rebuild.
As a safety measure, the CLI only replaces a directory it recognizes as its own: one that is empty, doesn't exist yet, or contains the generated @typebase-io/server package. Pointing --out-dir (or server.outDir) at any other non-empty directory aborts with an error instead of overwriting it.
Running the generated server
After generating the server, you can run it like any Node.js project:
cd typebase/_server
# Install dependencies
npm install
# Run (if TypeScript output)
npx tsx src/index.ts
# Run (if ESM output)
node src/index.js
# Run (if CJS output)
node src/index.jsThe server starts on port 8080 by default. Override it with --port or the server.port field in typebase.json.