OSS-first docs
These docs teach the open system first: contracts, generated surfaces, runtimes, governance, and incremental adoption. Studio shows up as the operating layer on top, not as the source of truth.
Next.js: add one endpoint
Add ContractSpec to an existing Next.js App Router project by wiring a single operation end-to-end with validation and types.
What you'll build
- One OperationSpec with SchemaModel validation.
- A registry wiring the operation to its handler.
- A Next.js route handler that exposes the operation.
1) Install core packages
bun add -D contractspec
bun add @contractspec/lib.contracts-spec @contractspec/lib.contracts-runtime-server-rest @contractspec/lib.schemaExpected output: added 3 packages and a lockfile update.
2) Define the operation spec
Create src/contracts/healthcheck.operation.ts:
import { defineQuery } from "@contractspec/lib.contracts-spec/operations";
import { SchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
const HealthcheckOutput = new SchemaModel({
name: "HealthcheckOutput",
fields: {
status: { type: ScalarTypeEnum.NonEmptyString(), isOptional: false },
checkedAt: { type: ScalarTypeEnum.DateTime(), isOptional: false },
},
});
export const HealthcheckQuery = defineQuery({
meta: {
key: "healthcheck.get",
version: "1.0.0",
description: "Return service health status",
owners: ["@platform.core"],
tags: ["health", "observability"],
},
io: {
input: null,
output: HealthcheckOutput,
},
policy: {
auth: "public",
},
transport: {
rest: { method: "GET" },
gql: { field: "healthcheck_get" },
mcp: { toolName: "healthcheck_get-v1" },
},
});3) Register the operation
Create src/contracts/registry.ts:
import {
OperationSpecRegistry,
installOp,
} from "@contractspec/lib.contracts-spec/operations";
import { HealthcheckQuery } from "./healthcheck.operation";
export const registry = new OperationSpecRegistry();
installOp(registry, HealthcheckQuery, async () => ({
status: "ok",
checkedAt: new Date().toISOString(),
}));4) Add the Next.js handler
Create app/api/ops/[...route]/route.ts:
import { makeNextAppHandler } from "@contractspec/lib.contracts-runtime-server-rest/rest-next-app";
import { registry } from "@/contracts/registry";
const handler = makeNextAppHandler(registry, async () => ({
actor: "public",
tenantId: "public",
}));
export { handler as GET, handler as POST };Expected output: the route responds at /api/ops/healthcheck.get.
5) Validate the spec
contractspec validate src/contracts/healthcheck.operation.tsExpected output: Validation passed.
Example package
Use @contractspec/example.lifecycle-dashboard as a lightweight Next.js snippet reference.
# Inspect the example docs
contractspec examples show lifecycle-dashboard
# Validate all example manifests in this repo
contractspec examples validate --repo-root .Want real product evidence behind endpoint changes?
Studio correlates meetings, support, analytics, and code signals before compiling endpoint decisions into spec diffs.
See what Studio addsGuides
Follow concrete adoption paths for existing apps, generated docs, CI gating, and typed surfaces.
Import an existing codebase
Stabilize a live codebase incrementally instead of rewriting it from scratch.
Why ContractSpec
Keep educational and comparison content reachable without letting it define the primary OSS learning path.