Define your backend once. Forge builds the rest.
Forge is a contract-first backend compiler for TypeScript. A .forge file is the canonical source of truth for your domain model, runtime validation, JSON Schema, OpenAPI contracts, Prisma schema, and generated NestJS backend scaffolding.
namespace commerce
enum OrderStatus {
pending
paid
cancelled
}
contract Order {
id: uuid @primary @default(uuid())
customerId: uuid
total: decimal
status: OrderStatus @default(pending)
paid: boolean @default(false)
invariant total > 0
invariant paid == true || status != "cancelled"
}
The design principle is simple:
one contract -> one semantic model -> consistent generated artifacts
Forge 1.0.0 is the first stable release. The core compiler path is in place: semantic imports, invariants, generators, Prisma Migrate integration, client SDK generation, drift detection, watch mode, formatter, Prisma/Nest E2E coverage and CLI diagnostics.
Forge uses Prisma Migrate for database migrations. Forge does not yet generate authentication, authorization policies or production deployment manifests. Generated Nest projects are intentionally compact scaffolds that you can extend.
pnpm install
pnpm build
node packages/cli/dist/index.js init
node packages/cli/dist/index.js compileCompile selected targets:
node packages/cli/dist/index.js compile --target typescript,zod,json-schema,prisma,openapi,nestForge currently generates:
- TypeScript interfaces and enum constants
- Zod schemas, including defaults and invariant refinements with arithmetic and
&&/|| - JSON Schema documents
- Prisma schema with primary keys, unique fields, indexes, defaults, enums and relation fields
- OpenAPI 3.0.3 schemas and CRUD paths
- NestJS modules, controllers, DTOs, services, PrismaService and Zod request validation
- Fetch-based TypeScript client SDK
namespace blog
enum PostStatus {
draft
published
}
contract User {
id: uuid @primary @default(uuid())
email: string @unique @index
posts: Post[]
}
contract Post {
id: uuid @primary
authorId: uuid
author: User @foreign(authorId)
title: string
tags: string[]
status: PostStatus @default(draft)
invariant title != ""
}
Supported primitive types:
string, int, float, decimal, boolean, uuid, datetime, date, bytes, json
Supported modifiers:
@primary, @unique, @index, @default(...), @foreign(...), @readonly, @optional
forge init
forge validate
forge check
forge compile
forge compile --target typescript,zod,prisma,client
forge generate openapi
forge generate nest
forge generate client
forge doctor
forge diff
forge migrate dev --name init
forge migrate deploy
forge format
forge format contracts/**/*.forge
forge dev
forge cleanforge check is intended for CI. It validates syntax, semantics, references, configuration and target compatibility before generation.
forge format formats configured contracts, or only the explicit files/globs passed after the command.
forge migrate first regenerates generated/prisma/schema.prisma, then delegates to Prisma Migrate. Use forge migrate dev --name init locally and forge migrate deploy in deployment environments.
forge dev performs an initial compile, then watches .forge files and forge.config.json for recompilation without exiting on compile errors.
forge.config.json:
{
"contracts": "contracts/**/*.forge",
"output": "generated",
"targets": ["typescript", "zod", "json-schema", "prisma"]
}packages/
language/ Langium grammar, parser boundary, semantic model, diagnostics
compiler/ intermediate representations such as database schema
generators/ TypeScript, Zod, JSON Schema, Prisma, OpenAPI and NestJS generators
cli/ command-line interface
tests/ parser, semantic, generator and CLI tests
examples/ sample Forge contracts
docs/ language, architecture and target documentation
pnpm build
pnpm testThe full test suite compiles the monorepo and runs Node's built-in test runner.
- Architecture
- Language
- Generators
- CLI
- Changelog
- Recipe: Simple CRUD
- Recipe: Multi-File Relations And Invariants
- Recipe: Advanced Types, Defaults And Custom Primary Keys
Forge's goal is not to be a template engine. It is a compiler: source is parsed once, resolved once, represented semantically once, and every artifact is generated from that shared meaning.