Docs · Why a Product Graph?

Why a Product Graph?

The runtime has to understand your product. Not parse it — understand it.

That means every object has meaning, every relationship has meaning, every workflow has meaning, and every policy has meaning. A pile of source code has none of that: the meaning lives in your head, your docs, and your onboarding calls. A product graph puts it in the artifact itself.

Closure's thesis is that the product exists as governed data. Pages, workflows, skills, and connectors are typed objects on one graph that people and AI evolve together. That's what lets the runtime render the same product as a portal, an assistant, or an agent team — and what lets AI ask questions that are almost impossible against TypeScript:

  • Why does this workflow exist?
  • Which experiences depend on it?
  • Which policies govern it?
  • Can I improve it without breaking a seal?

JSON-LD is the implementation, not the point

Nobody buys JSON-LD. You buy a product graph; JSON-LD is simply how the meaning is represented. Representing it puts hard requirements on the format:

  1. Global identity. Objects reference each other across orgs, packs, and

time. Every object needs an ID that survives export, import, and merge.

  1. Self-describing meaning. An agent (or another company's runtime) must be
   able to look at an object and know what it *is* — not guess from a table
   name or file path.
  1. Typed but open. Schemas must validate payloads without freezing the

world; new object kinds appear weekly.

  1. Plain JSON at rest. Everything downstream — GraphQL, renderers, diffs,

version control, LLM context windows — speaks JSON.

The alternatives, honestly

CandidateWhere it falls short for a product graph
YAMLA syntax, not a data model. No identity, no linking, no types. Fine for config; wrong for a graph of cross-referencing objects.
SQL / PostgresClosure does persist in Postgres. But relational schemas freeze shape at migration time — a graph where AI adds new object kinds weekly can't live behind ALTER TABLE. Tables are the storage, not the model.
Document DB (Mongo etc.)Flexible documents, but no shared semantics: nothing says what a document means, and references are conventions, not contracts.
RDF / OWL full stackSemantically rigorous, practically hostile — triple stores and ontology tooling are a poor fit for product engineering and LLM workflows.
Proprietary formatEvery low-code platform has one. It locks you in and means nothing outside that vendor's runtime.

JSON-LD is the overlap: plain JSON any tool can read, with the three things plain JSON lacks — stable identity (@id), shared vocabulary (@context), and type (schemaRef). It is a W3C standard, so a Closure object is meaningful outside Closure.

What this buys you in practice

  • One store, one API. Every object kind is the same DataObject shape in

GraphQL — no endpoint per feature.

  • AI-native authoring. LLMs read and write JSON natively. Your IDE mutates

the same objects the console edits, via Platform MCP.

  • Portable packs. An Experience Pack is a set of graph objects. Install

copies them into your org; identity and references survive the trip.

  • Governance on the object, not the app. Identity, policy, and audit attach

to typed objects — which is what makes human + AI co-evolution auditable.

The 30-second anatomy

{
  "@context": "https://closureapps.com/schema/context.jsonld",
  "@id": "urn:uuid:7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "schemaRef": "schema:experience",
  "name": "CRM Lite",
  "orgId": "org_acme",
  "data": { "slug": "crm-lite", "homePath": "/" }
}

@id is who it is. schemaRef is what it is. data is the payload the schema validates. That's the whole trick — applied uniformly to everything product-shaped.

Next