Blueprints

Case study · Documentation engineering

Building docs.recurly.com

How I designed, built, and automated the documentation experience for Recurly’s five product hubs on ReadMe: the landing pages, a component design system for guides, a JavaScript behavior layer, and an AI-assisted authoring pipeline.

Author
Christian Arango
Role
Documentation Engineer & Technical Writer
Live site
docs.recurly.com
Captured
Public site, October 13, 2026
The docs.recurly.com landing page: hero with search, an “Explore our documentation” header, and a featured card for the Recover launch.(open full-size image)
docs.recurly.com, the global documentation hub, as published.

At a glance

One system, five product hubs.

Recurly runs separate documentation hubs for Subscriptions, Commerce, Engage, RevRec, and Recover, all on ReadMe. I owned the layer that makes them feel like one product: what readers see, how pages behave, and how new content gets written and shipped.

  1. HTML/CSS

    Landing pages

    The global hub and each product’s home: hero, product cards, quick navigation, cross-product discovery. Responsive down to 375px, reduced-motion aware.

  2. CSS

    Guide design system

    A tokenized component library (overview, plan pill, TOC pills, benefits, steps, callouts, tables, card grids, carousels) layered on top of ReadMe’s own UI.

  3. JavaScript

    Behavior layer

    SPA-safe scripts for navigation, deep-link copying, carousels, and search, written to survive ReadMe’s client-side routing and redeploys.

  4. Claude skill

    Draft → publish-ready MDX

    An authoring skill that turns raw drafts into pasteable MDX using the component library, the house voice, and guardrails learned from the renderer.

  5. Claude + ReadMe connector

    Automated rollout

    Claude connected to ReadMe to restructure existing pages in batches, so a whole hub could move onto the new system at once.

  6. Products

    Engage and Recover

    Engage is the hub I improved most: nearly every page rebuilt. Recover was the last launch I worked on, built on the system from day one.

57
rp-* component classes in the guide design system
586
CSS rule blocks, including 43 ReadMe UI hooks restyled
141/146
Recurly Engage guide pages built on the system
20/21
Recurly Recover guide pages built on the system

Landing pages

A front door for every hub.

The global hub routes readers to each product’s documentation from a single HTML block with its own scoped stylesheet. Each product home is built from the same vocabulary, tuned to how that product’s readers navigate.

  • Featured launch card

    Full-width spotlight for the newest product: content column, logo panel, and a “New” badge whose pulse turns off under prefers-reduced-motion.

  • 2×2 product grid

    Uniform cards with a visual strip, label, title, description, and CTA row. Hover lifts the card, tints the border, and nudges the arrow.

  • Responsive by design

    Breakpoints at 768, 480, and 375px. The featured card stacks, the grid collapses to one column, and type scales down step by step.

  • Defensive against the host

    Overflow protection, min-width: 0 on flex children, and explicit resets so ReadMe’s theme can’t leak underlines or widths into the layout.

  • Search that’s actually ReadMe’s

    The hero search bar is a custom element wired to open ReadMe’s native search, so it looks on-brand without reinventing search.

  • One vocabulary per product home

    Each hub home reuses the same eyebrow, title, and description block, with a quick-navigation panel and task-oriented feature cards tuned to that product’s readers.

Guide design system

Components, not one-off pages.

Every guide is plain MDX. Writers drop in rp-* components; the host theme’s custom CSS does the rest. No inline styles, no per-page CSS, so a design change ships to every page at once. Brand tokens live as CSS custom properties shared by the components and 43 restyled ReadMe UI hooks: header, sidebar, table of contents, code tabs, API playground, changelog, and more.

Adoption across Recurly Engage

Guide pages using each component, out of 146

Page headerrp-page
141
Section pillsrp-toc
133
Key benefitsrp-benefits
127
Definitionrp-definition
125
Requirement listsrp-list
104
Numbered stepsrp-steps
94
Calloutsrp-callout
50
Branded tablestable
49
Navigation cardsrp-nav-grid
20
Content cardsrp-card
12

Same system across hubs: 20 of 21 Recover pages and 163 of the 165 Subscriptions pages sampled open with the rp-page header cluster. Counted from the published MDX.

Anatomy of a guide page

  1. Overview rp-overview

    Two to four sentences on what the page covers.

  2. Plan pill rp-plan

    Who can use the feature, with fixed wording per plan so availability reads the same everywhere.

  3. Callout rp-callout

    Four variants (note, tip, important, warning), each with its own icon and color.

  4. Section pills rp-toc

    Numbered jump links to every top-level section, generated from the headings.

  5. Requirements list rp-list

    Under a Prerequisites or Limitations heading.

  6. Definition rp-definition

    Plain-language “what is this and why does it exist,” distinct from the overview.

  7. Key benefits rp-benefits

    Three or five auto-fit; exactly four switch to a 2×2 grid.

Readers get the same rhythm on every page: what it is, who can use it, where to jump, then the details. Writers get a fixed skeleton instead of a blank page.

Behavior layer

JavaScript that survives a single-page app.

ReadMe renders with React and swaps pages client-side, so a script that runs once on load breaks on the next click. Every module is written to re-attach, self-heal, and stay idempotent.

  • Module 1

    Changelog navigation override

    Points each hub’s native Changelog tab at a custom changelog page and keeps the active tab correct on every route: SPA navigation, reloads, back/forward, and the mobile flyout menu.

  • Module 2

    “Link copied” heading pill

    Click any heading to copy its deep link. A pill floats up and fades out (double requestAnimationFrame so the transition always fires). Re-binds after each page swap.

  • Module 3

    Infinite carousel

    Seamless loop using two clones on each side, an active-card state, arrow-key support, resize-aware positioning, and re-init on navigation.

  • Module 4

    Hero search and image zoom

    The landing search bar opens ReadMe’s native search with bounded polling until the target exists. A lightweight zoom follows the cursor on large screenshots.

changelog-nav.jsjs
// Capture phase: runs before ReadMe's
// own React click handlers
window.addEventListener("click", handleClick, true);

// Child-list changes only, so this script's
// own class/href writes can't loop back
state.observer = new MutationObserver(handleRouteCheck);
state.observer.observe(document.body, {
  childList: true, subtree: true,
});

// ReadMe updates URL, article, and active
// classes in separate render passes
[50, 150, 400, 900].forEach((ms) =>
  setTimeout(queueApply, ms));
Excerpt from the published behavior layer.
  • Stable hooks only

    Targets ReadMe’s rm- classes and ARIA labels, never the hashed CSS-module names that change on every deploy.

  • Idempotent by construction

    A global key with destroy() tears down the previous instance if the script loads twice.

  • Respects user intent

    Cmd/Ctrl/Shift-clicks and middle-clicks keep native behavior, with the corrected URL already in place.

AI-assisted authoring

A Claude skill that writes publish-ready MDX.

I encoded the design system, the brand voice, and every renderer quirk I found into a Claude skill. Paste in a raw draft; get back MDX that goes straight into the ReadMe editor.

  1. Step 0

    Detect doc type

    General, Exports, Payment Gateways, Commerce, Engage, or API Guide, each with its own section registry.

  2. Step 1

    One round of questions

    Scans for what would become a TODO (plan tier, missing URLs, empty code) and asks once, in a single batch.

  3. Step 2

    Generate

    Applies voice, grammar, terminology, and component templates. Title, meta description, and MDX.

  4. Output

    Paste and publish

    Pure MDX: markdown headings, rp-* divs, native components, and a TODO list only for what was deferred.

popular-uses.mdmdx
<div class="rp-page">
  <div class="rp-overview">Recurly Engage supports a variety of
    proven engagement patterns ...</div>
  <div class="rp-plan"><i class="fa-solid fa-key" aria-hidden="true"></i>
    Available to all customers on any Recurly Engage subscription plan</div>
  <div class="rp-toc">
    <a class="rp-toc-pill" href="#definition"><span class="rp-toc-num">1</span>Definition</a>
    <a class="rp-toc-pill" href="#key-benefits"><span class="rp-toc-num">2</span>Key benefits</a>
  </div>
</div>

### Prerequisites

<ul class="rp-list">
  <li>You must have <strong>Company</strong>, <strong>App Administrator</strong>,
  or <strong>App Member</strong> permissions in Recurly Engage.</li>
</ul>
Published header cluster from a Recurly Engage page, as ReadMe serves it.

Guardrails learned the hard way

  • No blank lines inside a div

    ReadMe’s MDX parser exits HTML context on a blank line and renders the rest as raw code.

  • {curly} placeholders become ALL_CAPS

    A single {site_id} is evaluated as JSX and blocks the whole page.

  • CodeTabs, not Tabs, for code

    Consecutive fences with no blank line render as one multi-language block.

  • Never invent; never alter code

    Suspect code gets a TODO for developer review instead of a silent fix.

Automation

Claude and the ReadMe connector.

A skill makes one page fast. Rebuilding a whole hub needs a loop. I connected Claude to ReadMe and ran the skill against existing pages, so restructuring became a review job instead of a copy-paste job.

  1. Read

    Pull the live page

    Claude reads the current page content from ReadMe through the connector.

  2. Transform

    Run the skill

    The page is rebuilt on the rp-* system with the house voice and structure.

  3. Write

    Update in ReadMe

    The new MDX goes back to the same page, keeping its slug and place in the sidebar.

  4. Review

    Human check

    I review the rendered page, fix what the renderer disagrees with, and fold lessons back into the skill.

135/146
Engage pages last updated in September–October 2026, the window in which the hub moved onto the design system
ReadMe updatedAt, read from each published page
  • Consistency at scale

    Every page gets the same header cluster, section order, and components, which is hard to hold by hand across hundreds of pages.

  • The skill kept getting better

    Each renderer bug found in review became a rule in the skill, so the next batch didn’t repeat it.

  • Writers stay in control

    Automation proposes; a person approves. Nothing ships without a rendered check.

Products

The hub I improved most, and the last one I launched.

Recurly Engage

Engage documents a product for growth and lifecycle teams: prompts, experiments, segments, SDKs, and dozens of partner integrations. Today 141 of its 146 guide pages follow the same skeleton and component set. Instructional pages read as procedures, with numbered step cards and screenshots at a consistent width; thirty-plus partner pages share one template, so readers know where setup, fields, and troubleshooting live.

Recurly Recover

Recover is Recurly’s standalone retry engine for failed payments. Its hub launched on the finished system (20 of 21 pages use the rp-page structure), with a developer-first landing page and an API guide that leads with the request a developer actually sends.

Outcomes

What changed for readers.

Results from my wider role at Recurly (2023–2026), of which this system was a central part.

45%
reduction in support ticket volume, through an audit of every API endpoint, version, and field against real support feedback, release-triggered automation, and visual-clarity improvements
56→92%
user-reported documentation satisfaction after consolidating three products’ docs into one ReadMe Enterprise hub
2025
Technology Impact Award, presented by Recurly’s CTO