Products and Services as pages
How a Product becomes a landing, a pricing page and a listing, and how a Service becomes an intake form, a sent page and terms, each one a record.
A Product is what a Customer gets from a Startup, with a promise the Customer can rely on.Product startupbuilder.dev
An Offer is a Product, under a Brand, at a price, on terms, made by a Startup.Offer startupbuilder.dev
startupbuilder.dev defines the Product, the Service and their Offers. mdxui draws the pages a customer reads about them. A Business that sells a Product and one that sells a Service need different pages, and each page is one record.
A Product: say it, price it, list it
Vanroster sells crew scheduling as software. Its Product reaches a customer through three pages.
| Page | Template | What it carries | Record |
|---|---|---|---|
| Landing | api-product | The promise, the proof, the features and the plans, in the order a buyer reads | pages/vanroster/home.json |
| Pricing | api-product | Plans as OfferTiles, a plan table and the pricing questions | pages/vanroster/pricing.json |
| Product page | directory-product | One feature as a listing: its head, facts, calls and endpoints | pages/vanroster/product/dispatch.json |
{
"$schema": "https://next.mdxui.dev/schema.json",
"theme": "callboard",
"frame": "none",
"template": "api-product",
"title": "Plans · Vanroster",
"description": "Three Vanroster plans, priced per crew a month. Office users are free on every plan.",
"sections": [
{
"kind": "nav",
"shell": {"inset":"bleed","density":"none","surface":"glass","sticky":true},
"block": {
"type": "nav",
"menu": "push",
"collapse": 880,
"brand": {"href":"/","text":"Vanroster","mark":"radar"},
"links": [
["/product/dispatch","Dispatch"],
["/pricing","Pricing"],
["/changelog","Changelog"],
["/security","Security"]
],
"cta": {"href":"/contact","label":"Book a walkthrough"}
}
},
{
"kind": "section",
"shell": {"inset":"contained","density":"section"},
"block": {
"type": "pricing",
"layout": "cards",
"head": {
"eyebrow": "Plans",
"title": "Priced per crew, never per seat.",
"lede": "A crew is one van and the people in it. Office users sign in free on every plan."
},
"tiers": [
{
"name": "Crew",
"price": "$29",
"note": "a crew a month",
"desc": "One depot and up to 10 crews.",
"features": ["The dispatch board","Skills on every job","Customer arrival texts"],
"cta": "Start a trial",
"href": "/contact"
},
{
"name": "Fleet",
"price": "$24",
"note": "a crew a month",
"desc": "11 to 100 crews across up to 10 depots.",
"features": ["Everything in Crew","Swaps between depots","Overtime flags on the board","The Dispatch API"],
"cta": "Start a trial",
"href": "/contact",
"featured": true
},
{
"name": "Region",
"price": "Quoted",
"note": "from 100 crews",
"desc": "Any number of depots, with single sign-on.",
"features": ["Everything in Fleet","Single sign-on with SAML","Audit log export","A named dispatch contact"],
"cta": "Book a walkthrough",
"href": "/contact"
}
],
"featuredBadge": "For many depots",
"note": "Prices exclude tax. A crew counts in a month once it holds a job."
}
},
{
"kind": "section",
"shell": {"inset":"contained","density":"section"},
"block": {
"type": "plan-table",
"title": "Every plan, line by line",
"columns": ["Crews","Depots","API","Sign-on","Log kept"],
"rows": [
{"name":"Crew","cells":["1 to 10","1","no","no","1 year"]},
{"name":"Fleet","cells":["11 to 100","up to 10","yes","no","3 years"]},
{"name":"Region","cells":["100 or more","any","yes","SAML","7 years"],"note":"Quoted per year"}
],
"foot": "Every plan includes the board, crew phones and customer texts. [Security](/security) lists where data is kept."
}
},
{
"kind": "section",
"shell": {"inset":"contained","density":"section"},
"block": {
"type": "faq",
"head": {
"eyebrow": "Questions",
"title": "Before the trial ends.",
"lede": "Grouped by billing, the trial and your data."
},
"groups": [
{
"title": "Billing",
"items": [
{
"q": "What counts as a crew?",
"a": "One van and the people in it. A crew counts in a month once it holds a job. A crew with no jobs that month costs nothing."
},
{
"q": "Do office users cost extra?",
"a": "No. Dispatchers, managers and owners sign in free on every plan."
}
]
},
{
"title": "The trial",
"items": [
{
"q": "What happens after 14 days?",
"a": "The board stays readable. New jobs stop until a plan is chosen."
},
{
"q": "Can I import from a spreadsheet?",
"a": "Yes. Vanroster reads crews, skills and jobs from one CSV file each."
}
]
},
{
"title": "Your data",
"items": [
{
"q": "Where is the data kept?",
"a": "In the region chosen at sign-up, the EU or the US. The [security page](/security) lists both."
},
{
"q": "Can I take it with me?",
"a": "Yes. Every plan exports crews, jobs and the change log as CSV or JSON at any time."
}
]
}
]
}
},
{
"kind": "footer",
"shell": {"inset":"contained","density":"footer"},
"block": {
"type": "footer",
"layout": "areas",
"brand": {"href":"/","text":"Vanroster","mark":"radar"},
"blurb": "Crew scheduling for field-service teams: heating, electrical, plumbing, cleaning and grounds.",
"columns": [
{
"title": "Product",
"links": [["/product/dispatch","Dispatch"],["/pricing","Pricing"],["/changelog","Changelog"]]
},
{"title":"Company","links":[["/security","Security"],["/contact","Contact"]]},
{
"title": "For agents",
"links": [["/product/dispatch","The Dispatch API"],["/records.zip","Site records (.zip)"]]
}
],
"cta": {"href":"/contact","label":"Book a walkthrough","icon":"arrow-right"},
"note": [
"Vanroster is a worked example on mdxui.dev, not a customer.",
"Rendered by @mdxui/site. Forms here do not send."
]
}
}
]
}
The pricing page's plans are Offers: a name, a price, terms and an action. Each is an OfferTile in pricing, and the same plans line up feature by feature in plan-table.
A Service: take the inquiry, set the terms
Ledgerhouse sells bookkeeping, done by two partners. A Service starts with a conversation, so its pages ask before they sell.
| Page | Template | What it carries | Record |
|---|---|---|---|
| Services | article | What the firm does, as a list of engagements | pages/ledgerhouse/services.json |
| Intake | contact | An eight-field form and the steps that follow it | pages/ledgerhouse/intake.json |
| Sent | article | What happens next, after the form | pages/ledgerhouse/intake/sent.json |
| Terms | article | The engagement terms, as a document | pages/ledgerhouse/terms.json |
{
"$schema": "https://next.mdxui.dev/schema.json",
"theme": "vaultline",
"frame": "none",
"template": "contact",
"title": "Intake · Ledgerhouse",
"description": "Eight questions. A partner replies within two working days with a fixed fee and a start date.",
"sections": [
{
"kind": "nav",
"shell": {"inset":"bleed","density":"none","surface":"glass","sticky":true},
"block": {
"type": "nav",
"menu": "none",
"brand": {"href":"/","text":"Ledgerhouse","mark":"landmark"},
"links": [["/services","Services"],["/pricing","Fees"],["/about","About"]],
"cta": {"href":"/intake","label":"Start intake"}
}
},
{
"kind": "section",
"shell": {"inset":"contained","density":"section"},
"block": {
"type": "cta-form",
"head": {
"eyebrow": "Intake",
"title": "Eight answers, one fixed fee.",
"lede": "A partner reads every intake. The reply names a fee and a start date within two working days."
},
"action": "/intake/sent",
"fields": [
{"name":"name","type":"text","label":"Name"},
{"name":"email","type":"email","label":"Email","placeholder":"you@business.example"},
{"name":"business","type":"text","label":"Business name"},
{
"name": "entity",
"type": "select",
"label": "Entity",
"options": ["Sole owner","Partnership","Corporation","Not sure"]
},
{
"name": "software",
"type": "select",
"label": "Software",
"options": ["A cloud package","A desktop package","Spreadsheets","None yet"]
},
{
"name": "volume",
"type": "select",
"label": "Transactions",
"options": ["Under 150 a month","150 to 400 a month","400 to 1,000 a month","Over 1,000 a month"]
},
{
"name": "behind",
"type": "select",
"label": "Books behind",
"options": ["Up to date","1 to 3 months","4 to 12 months","More than a year"]
},
{
"name": "notes",
"type": "textarea",
"label": "Anything else",
"placeholder": "Payroll, owners, deadlines"
}
],
"submit": "Send intake",
"note": "A partner replies within two working days."
}
},
{
"kind": "section",
"shell": {"inset":"contained","density":"section"},
"block": {
"type": "steps",
"head": {"eyebrow":"After you send","title":"Three steps to a first close."},
"steps": ["A partner reads the answers","A fixed fee and date","The engagement letter, signed"]
}
},
{
"kind": "footer",
"shell": {"inset":"contained","density":"footer"},
"block": {
"type": "footer",
"layout": "columns",
"brand": {"href":"/","text":"Ledgerhouse","mark":"landmark"},
"blurb": "Bookkeeping and tax for small businesses, by two partners and no handoffs.",
"columns": [
{
"title": "The firm",
"links": [
["/services","Services"],
["/services/monthly-close","Monthly close"],
["/pricing","Fees"],
["/about","About"]
]
},
{"title":"Clients","links":[["/intake","Intake"],["/terms","Terms of engagement"]]},
{
"title": "For agents",
"links": [["/records.zip","Site records (.zip)"],["/services/monthly-close","What a close report holds"]]
}
],
"note": [
"Ledgerhouse is a worked example on mdxui.dev, not a customer.",
"Rendered by @mdxui/site. Forms here do not send."
]
}
}
]
}
The intake is a cta-form of up to eight bounded fields. Contact flow and 404 shows where its post goes.
One record per page, one Theme per Business
Every page above is its own record, and every record of one Business names one Theme. A plan changed on the pricing page is changed there only; the Product record is the Spec that gives every page one source for those facts.