Customer Story
Build a customer page at src/pages/use-cases/<slug>.js (route /use-cases/<slug>).
Unified route. Customer stories and use cases now live together under
src/pages/use-cases/. Customer pages still use the CustomerStory module (testimonial,
flow diagram, thanks section) — this skill — while use-case recipes use the UseCaseStory
module (see the use-case-landing skill). The two render side by side on the shared
/use-cases listing: a "Customer stories" grid followed by a "Use cases" grid. The old
/customers and /customers/<slug> URLs 301-redirect to /use-cases via vercel.json.
Read first
src/components/patterns/CustomerStory/index.js — barrel exports.
src/pages/use-cases/luckynote.js — reference page. Mirror its structure.
.cursor/skills/customer-story/references/template.md — template with {{TOKEN}} placeholders.
.cursor/skills/customer-story/references/cta-routing.md — use-case → CTA href mapping.
Shared module
All primitives live in src/components/patterns/CustomerStory/. Import by name. Never re-declare locally.
| Export |
Notes |
ACCENT |
Shared accent object (text: 'link'). Imported, never defined locally. |
CUSTOMERS |
Registry of all customer metadata (slug, name, blurb, icon, quote, author, role, avatar, initials). |
Section, SectionInner, Caption, Figure, FigureImage |
Layout primitives. |
DashedGridOverlay |
Decorative background. |
Eyebrow |
Accent-aware label. Pass accent={ACCENT}. |
Testimonial |
Props: accent, quote, author, role, company, initials, optional avatar, maxWidth. |
MoreCustomers |
Filters out currentSlug. Self-omits when < 2 siblings. |
CtaSection |
CTA panel. Uses colors.link for background tint internally. Props: accent, headlinePrefix, headlineAccent, body, href, label, optional mt. |
WhyCard |
Props: accent, number, kicker, title, body. |
FlowDiagram |
Props: accent, nodes array ({ label, sub, active? }). |
Typography
- Paragraphs:
<Text as='p'> — uses Text defaults (fontSize: [1,1,2,2], lineHeight: 3).
- Section headings:
<Text as='h2'> — same base component.
- No
BodyText, no SubheadBase. Just Text with the appropriate as prop.
Hero structure
The hero shows logo + company name (not a "Customer story" tag):
<Flex css={theme({ alignItems: 'center', gap: 2, pb: [3, 3, 4, 4] })}>
<img src='/images/clients/{{ICON}}' alt='' width='40' height='40'
css={theme({ display: 'block', borderRadius: 2, width: '40px', height: '40px' })}
style={{ objectFit: 'cover' }} decoding='async' />
<Text css={theme({ color: 'black', fontSize: 2, fontWeight: 'bold', lineHeight: 1 })}>
{{CUSTOMER_NAME}}
</Text>
</Flex>
Section order
Hero (logo + name, h1, intro paragraph, ArrowLink CTA)
AboutCustomer (Eyebrow, h2, paragraphs, external link, Testimonial)
HowTheyUseIt (Eyebrow, h2, paragraphs, FlowDiagram or image)
WhyMicrolink (Eyebrow, h2, lead paragraph, 3× WhyCard)
CtaSection (shared)
MoreCustomers (shared)
ThanksSection (logo + acknowledgement)
CUSTOMERS registry
When adding a customer, append to src/components/patterns/CustomerStory/customers.js:
{
slug: '<slug>',
name: '<name>',
blurb: '<~10 words, period>',
icon: '/images/clients/<icon>',
category: '<product> API',
quote: '<short quote for index page>',
author: '<name>',
role: '<role>',
avatar: '/images/clients/<avatar>.jpeg',
initials: '<XX>'
}
The unified /use-cases listing (src/pages/use-cases/index.js) is data-driven over
CUSTOMERS — the rotating hero, the "Trusted by innovative companies" logo bar, and the
"Customer stories" grid all map over it. Appending here is enough; you do not edit
index.js per customer. The cards link to /use-cases/<slug>.
Hard rules
- Never invent customer claims, metrics, or features. If the website doesn't say it, ask.
- Never use
pink/secondary/pinky/pinkest accent — reserved for feature pages.
- External links to customer sites: use
<Text as='a' target='_blank' rel='noopener'>, NOT the repo Link component (which adds noreferrer, killing SEO backlink value).
- Hero CTA label format:
See how to integrate <product>. Must differ from bottom CTA label.
<h1> must include scrollMarginTop: 4.
- Head title format:
<name>: <use case> (no brand suffix — Meta appends — Microlink).
- Head image must be absolute URL:
cdnUrl('banner/screenshot.jpeg').
- Never run prettier. Lint with
npx standard src/pages/use-cases/<slug>.js.
Workflow
Ask one question at a time:
- Customer name — compute slug, verify no collision in
src/pages/use-cases/ (the folder now holds customer stories and use-case recipes).
- Website URL — WebFetch homepage + key pages. Build factual notes.
- How they use Microlink — which products, where in stack. Feeds How/Why sections + CTA routing.
- Testimonial — real quote (author + role + avatar), placeholder, or none.
- Screenshots — primary screenshot, diagram style (flow/image/placeholder), optional hero image.
- Customer logo — SVG for ThanksSection, or text-only fallback.
- CTA routing — infer from use case per
references/cta-routing.md. Propose and confirm.
- Registry — append entry to
customers.js.
- Summary — show all values, wait for explicit confirmation before writing.
Verification
npx standard src/pages/use-cases/<slug>.js — fix until clean.
- Grep for
{{ — no placeholders remaining.
- Verify section order matches canonical list.
- Verify Hero CTA ≠ Bottom CTA label.
- Verify entry added to
customers.js.
Updating existing pages
Read the file, identify what needs changing, run only relevant steps, re-lint.
1---2name: customer-story3description: Scaffold a customer story page under src/pages/use-cases/ from the CustomerStory module.4---56# Customer Story78Build a customer page at `src/pages/use-cases/<slug>.js` (route `/use-cases/<slug>`).910> **Unified route.** Customer stories and use cases now live together under11> `src/pages/use-cases/`. Customer pages still use the **CustomerStory** module (testimonial,12> flow diagram, thanks section) — this skill — while use-case recipes use the **UseCaseStory**13> module (see the `use-case-landing` skill). The two render side by side on the shared14> `/use-cases` listing: a "Customer stories" grid followed by a "Use cases" grid. The old15> `/customers` and `/customers/<slug>` URLs 301-redirect to `/use-cases` via `vercel.json`.1617## Read first18191. `src/components/patterns/CustomerStory/index.js` — barrel exports.202. `src/pages/use-cases/luckynote.js` — reference page. Mirror its structure.213. `.cursor/skills/customer-story/references/template.md` — template with `{{TOKEN}}` placeholders.224. `.cursor/skills/customer-story/references/cta-routing.md` — use-case → CTA href mapping.2324## Shared module2526All primitives live in `src/components/patterns/CustomerStory/`. Import by name. Never re-declare locally.2728| Export | Notes |29|---|---|30| `ACCENT` | Shared accent object (`text: 'link'`). Imported, never defined locally. |31| `CUSTOMERS` | Registry of all customer metadata (slug, name, blurb, icon, quote, author, role, avatar, initials). |32| `Section`, `SectionInner`, `Caption`, `Figure`, `FigureImage` | Layout primitives. |33| `DashedGridOverlay` | Decorative background. |34| `Eyebrow` | Accent-aware label. Pass `accent={ACCENT}`. |35| `Testimonial` | Props: `accent`, `quote`, `author`, `role`, `company`, `initials`, optional `avatar`, `maxWidth`. |36| `MoreCustomers` | Filters out `currentSlug`. Self-omits when < 2 siblings. |37| `CtaSection` | CTA panel. Uses `colors.link` for background tint internally. Props: `accent`, `headlinePrefix`, `headlineAccent`, `body`, `href`, `label`, optional `mt`. |38| `WhyCard` | Props: `accent`, `number`, `kicker`, `title`, `body`. |39| `FlowDiagram` | Props: `accent`, `nodes` array (`{ label, sub, active? }`). |4041## Typography4243- Paragraphs: `<Text as='p'>` — uses `Text` defaults (fontSize: [1,1,2,2], lineHeight: 3).44- Section headings: `<Text as='h2'>` — same base component.45- No `BodyText`, no `SubheadBase`. Just `Text` with the appropriate `as` prop.4647## Hero structure4849The hero shows logo + company name (not a "Customer story" tag):5051```jsx52<Flex css={theme({ alignItems: 'center', gap: 2, pb: [3, 3, 4, 4] })}>53 <img src='/images/clients/{{ICON}}' alt='' width='40' height='40'54 css={theme({ display: 'block', borderRadius: 2, width: '40px', height: '40px' })}55 style={{ objectFit: 'cover' }} decoding='async' />56 <Text css={theme({ color: 'black', fontSize: 2, fontWeight: 'bold', lineHeight: 1 })}>57 {{CUSTOMER_NAME}}58 </Text>59</Flex>60```6162## Section order6364```65Hero (logo + name, h1, intro paragraph, ArrowLink CTA)66AboutCustomer (Eyebrow, h2, paragraphs, external link, Testimonial)67HowTheyUseIt (Eyebrow, h2, paragraphs, FlowDiagram or image)68WhyMicrolink (Eyebrow, h2, lead paragraph, 3× WhyCard)69CtaSection (shared)70MoreCustomers (shared)71ThanksSection (logo + acknowledgement)72```7374## CUSTOMERS registry7576When adding a customer, append to `src/components/patterns/CustomerStory/customers.js`:7778```js79{80 slug: '<slug>',81 name: '<name>',82 blurb: '<~10 words, period>',83 icon: '/images/clients/<icon>',84 category: '<product> API',85 quote: '<short quote for index page>',86 author: '<name>',87 role: '<role>',88 avatar: '/images/clients/<avatar>.jpeg',89 initials: '<XX>'90}91```9293The unified `/use-cases` listing (`src/pages/use-cases/index.js`) is data-driven over94`CUSTOMERS` — the rotating hero, the "Trusted by innovative companies" logo bar, and the95"Customer stories" grid all map over it. Appending here is enough; **you do not edit96`index.js` per customer.** The cards link to `/use-cases/<slug>`.9798## Hard rules99100- Never invent customer claims, metrics, or features. If the website doesn't say it, ask.101- Never use `pink`/`secondary`/`pinky`/`pinkest` accent — reserved for feature pages.102- External links to customer sites: use `<Text as='a' target='_blank' rel='noopener'>`, NOT the repo `Link` component (which adds `noreferrer`, killing SEO backlink value).103- Hero CTA label format: `See how to integrate <product>`. Must differ from bottom CTA label.104- `<h1>` must include `scrollMarginTop: 4`.105- Head title format: `<name>: <use case>` (no brand suffix — `Meta` appends ` — Microlink`).106- Head image must be absolute URL: `cdnUrl('banner/screenshot.jpeg')`.107- Never run prettier. Lint with `npx standard src/pages/use-cases/<slug>.js`.108109## Workflow110111Ask one question at a time:1121131. **Customer name** — compute slug, verify no collision in `src/pages/use-cases/` (the folder now holds customer stories *and* use-case recipes).1142. **Website URL** — WebFetch homepage + key pages. Build factual notes.1153. **How they use Microlink** — which products, where in stack. Feeds How/Why sections + CTA routing.1164. **Testimonial** — real quote (author + role + avatar), placeholder, or none.1175. **Screenshots** — primary screenshot, diagram style (flow/image/placeholder), optional hero image.1186. **Customer logo** — SVG for ThanksSection, or text-only fallback.1197. **CTA routing** — infer from use case per `references/cta-routing.md`. Propose and confirm.1208. **Registry** — append entry to `customers.js`.1219. **Summary** — show all values, wait for explicit confirmation before writing.122123## Verification1241251. `npx standard src/pages/use-cases/<slug>.js` — fix until clean.1262. Grep for `{{` — no placeholders remaining.1273. Verify section order matches canonical list.1284. Verify Hero CTA ≠ Bottom CTA label.1295. Verify entry added to `customers.js`.130131## Updating existing pages132133Read the file, identify what needs changing, run only relevant steps, re-lint.