// @bun
var l=Object.defineProperty;var d=(a)=>a;function m(a,o){this[a]=d.bind(null,o)}var f=(a,o)=>{for(var r in o)l(a,r,{get:o[r],enumerable:!0,configurable:!0,set:m.bind(o,r)})};var y=(a,o)=>()=>(a&&(o=a(a=0)),o);import h from"@contractspec/lib.ui-link";import{jsx as i,jsxs as u}from"react/jsx-runtime";function n({title:a="Need the operating layer on top of OSS ContractSpec?",body:o="ContractSpec Studio helps teams turn evidence into proposed spec changes, governed delivery loops, and execution-ready task packs while keeping the open contract system as the source of truth.",ctaLabel:r="See what Studio adds",href:p="https://www.contractspec.studio/docs"}){return u("div",{className:"card-subtle space-y-3 p-6",children:[i("h3",{className:"font-semibold text-lg",children:a}),i("p",{className:"text-muted-foreground text-sm",children:o}),i(h,{href:p,className:"btn-primary",children:r})]})}import{CodeBlock as c}from"@contractspec/lib.design-system";import s from"@contractspec/lib.ui-link";import{ChevronRight as g}from"lucide-react";import{jsx as e,jsxs as t}from"react/jsx-runtime";function E(){return t("div",{className:"space-y-8",children:[t("div",{className:"space-y-3",children:[e("h1",{className:"font-bold text-4xl",children:"Next.js: add one endpoint"}),e("p",{className:"text-lg text-muted-foreground",children:"Add ContractSpec to an existing Next.js App Router project by wiring a single operation end-to-end with validation and types."})]}),t("div",{className:"card-subtle space-y-4 p-6",children:[e("h2",{className:"font-bold text-2xl",children:"What you'll build"}),t("ul",{className:"space-y-2 text-muted-foreground text-sm",children:[e("li",{children:"One OperationSpec with SchemaModel validation."}),e("li",{children:"A registry wiring the operation to its handler."}),e("li",{children:"A Next.js route handler that exposes the operation."})]})]}),t("div",{className:"space-y-6",children:[t("div",{className:"space-y-3",children:[e("h2",{className:"font-bold text-2xl",children:"1) Install core packages"}),e(c,{language:"bash",filename:"nextjs-install",code:`bun add -D contractspec
bun add @contractspec/lib.contracts-spec @contractspec/lib.contracts-runtime-server-rest @contractspec/lib.schema`}),t("p",{className:"text-muted-foreground text-sm",children:["Expected output: ",e("code",{children:"added 3 packages"})," and a lockfile update."]})]}),t("div",{className:"space-y-3",children:[e("h2",{className:"font-bold text-2xl",children:"2) Define the operation spec"}),t("p",{className:"text-muted-foreground text-sm",children:["Create ",e("code",{children:"src/contracts/healthcheck.operation.ts"}),":"]}),e(c,{language:"typescript",filename:"src/contracts/healthcheck.operation.ts",code:`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" },
  },
});`})]}),t("div",{className:"space-y-3",children:[e("h2",{className:"font-bold text-2xl",children:"3) Register the operation"}),t("p",{className:"text-muted-foreground text-sm",children:["Create ",e("code",{children:"src/contracts/registry.ts"}),":"]}),e(c,{language:"typescript",filename:"src/contracts/registry.ts",code:`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(),
}));`})]}),t("div",{className:"space-y-3",children:[e("h2",{className:"font-bold text-2xl",children:"4) Add the Next.js handler"}),t("p",{className:"text-muted-foreground text-sm",children:["Create ",e("code",{children:"app/api/ops/[...route]/route.ts"}),":"]}),e(c,{language:"typescript",filename:"app/api/ops/[...route]/route.ts",code:`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 };`}),t("p",{className:"text-muted-foreground text-sm",children:["Expected output: the route responds at",e("code",{children:" /api/ops/healthcheck.get"}),"."]})]}),t("div",{className:"space-y-3",children:[e("h2",{className:"font-bold text-2xl",children:"5) Validate the spec"}),e(c,{language:"bash",filename:"nextjs-validate",code:"contractspec validate src/contracts/healthcheck.operation.ts"}),t("p",{className:"text-muted-foreground text-sm",children:["Expected output: ",e("code",{children:"Validation passed"}),"."]})]}),t("div",{className:"card-subtle space-y-3 p-6",children:[e("h3",{className:"font-semibold text-lg",children:"Example package"}),t("p",{className:"text-muted-foreground text-sm",children:["Use ",e("code",{children:"@contractspec/example.lifecycle-dashboard"})," as a lightweight Next.js snippet reference."]}),e(c,{language:"bash",filename:"nextjs-example",code:`# Inspect the example docs
contractspec examples show lifecycle-dashboard

# Validate all example manifests in this repo
contractspec examples validate --repo-root .`})]}),e(n,{title:"Want real product evidence behind endpoint changes?",body:"Studio correlates meetings, support, analytics, and code signals before compiling endpoint decisions into spec diffs."})]}),t("div",{className:"flex items-center gap-4 pt-4",children:[t(s,{href:"/docs/guides/spec-validation-and-typing",className:"btn-primary",children:["Next: Spec validation + typing ",e(g,{size:16})]}),e(s,{href:"/docs/guides",className:"btn-ghost",children:"Back to guides"})]})]})}export{E as GuideNextjsOneEndpointPage};
