Configuration
Forge keeps configuration in two places: forge.config.ts for build-time
options and .env.local for secrets. Both are fully typed.
forge.config.ts
This file is the single source of truth for how your app is built and deployed:
import { defineConfig } from "@fozmu/forge";
export default defineConfig({
app: {
name: "my-app",
url: "https://my-app.com",
},
database: {
provider: "postgres",
migrations: "./lib/db/migrations",
},
auth: {
providers: ["password", "github"],
sessionTtl: "30d",
},
deploy: {
target: "vercel",
},
});defineConfig gives you autocomplete and type-checking for every field, so
typos fail at build time instead of in production.
Environment variables
Secrets never go in forge.config.ts. Declare them once in lib/env.ts and
Forge validates them on boot:
import { createEnv } from "@fozmu/forge/env";
import { z } from "zod";
export const env = createEnv({
server: {
DATABASE_URL: z.string().url(),
GITHUB_CLIENT_SECRET: z.string().min(1),
},
client: {
NEXT_PUBLIC_APP_URL: z.string().url(),
},
});Now env.DATABASE_URL is typed and guaranteed to exist:
import { env } from "@/lib/env";
const client = connect(env.DATABASE_URL); // string, never undefinedMissing variables fail fast
If a required variable is absent, the app refuses to start and prints exactly
which key is missing. No more silent undefined bugs in production.
Configuration reference
| Key | Type | Default |
|---|---|---|
app.name | string | — |
database.provider | "postgres" | "sqlite" | "mysql" | postgres |
auth.sessionTtl | string (duration) | 7d |
deploy.target | "vercel" | "cloudflare" | "docker" | vercel |