# The Product record (/docs/components/product-record)

> Spec: written ahead of the package. Not in the published packages: agentPrompt, og, email

> One bounded record of a product feeds its landing, emails, share image, directory entry and agent prompt, so it says one thing everywhere.

> A Product is what a Customer gets from a Startup, with a promise the Customer can rely on.
>
> startupbuilder.dev, [Product](https://startupbuilder.dev/business/nouns/product)

> An Offer is a Product, under a Brand, at a price, on terms, made by a Startup.
>
> startupbuilder.dev, [Offer](https://startupbuilder.dev/business/nouns/offer)

The Product record is one bounded record of a product: its name, Theme, addresses, plans and first calls. Every rendering of the product reads it, so the landing, the emails and the agent prompt never disagree. It projects startupbuilder.dev's Product, its Offers and their Prices, and defines no second Product.

## What mdxui renders

Today each Page record carries the product's facts itself. Harbor's plans below are written into `pages/harbor/pricing.json` by hand, and its home page repeats the name and the first call.

The rendered page: https://next.mdxui.dev/sites/harbor/pricing; its record: https://next.mdxui.dev/pages/harbor/pricing.json

## How it maps

  - **the landing** (alpha): The name, the Theme, the plans and the first call, written into each record by hand
  - **the directory entry** (alpha): The category, the tags, the summary and the date it listed, written by hand
  - **the agent prompt** (spec): The quickstart calls in agent order: the CLI, the MCP server, the SDKs, then `curl`
  - **the share image** (spec): The name, the summary and the Theme; see [Share image](https://next.mdxui.dev/docs/components/renderings/share-image)
  - **the emails** (spec): The name, the Theme and the dashboard address; see [Email](https://next.mdxui.dev/docs/components/renderings/email)

## Status

The record and every rendering that reads it are Spec. The landing and the directory entry render today from Page records that repeat the same facts. A price changed in one record and not another is a disagreement no parse catches.

## Intended Noun

```yaml title="intended Noun: Product record (mdxui.dev namespace)"
noun: Product record
projects: startupbuilder.dev Product, its Offers and Prices; defines nothing new
fields:
  name: { type: string, bound: open, required: true }
  theme: { type: Theme, required: true }
  mark: { type: icon name, required: false }
  apiBase: { type: URL, required: true }
  docsUrl: { type: URL, required: true }
  dashboardUrl: { type: URL, required: false }
  contactUrl: { type: URL, required: false }
  statusUrl: { type: URL, required: false }
  keyPrefix: { type: string, bound: open, required: false }
  quickstart: { type: list of call, count: open, required: true, order: [cli, mcp, sdk, curl] }
  plans: { type: list of Offer, count: open, required: true, each: [price or contact, limit, retention, seats, feature lines, action] }
  questions: { type: list of onboarding question, count: open }
  directory: { category: string, tags: list of string, summary: string, since: date }
```

Every bound is open until the record ships. Each string gets one, measured from real products, as every Section type's strings have.

## Related

  - [Renderings](https://next.mdxui.dev/docs/components/renderings): Every output format of one record.
  - [pricing](https://next.mdxui.dev/docs/sections/pricing): Plans as OfferTiles.
  - [Harbor tides](https://next.mdxui.dev/docs/showcase/harbor): The product these facts describe.

