Working in ClaudeDesign custom result pages

Design custom result pages

Turn Claude into your result-page designer — HTML written conversationally, validated against your agent's fields, rendered per respondent.

The Page node (dynamic_output_page) is where Productised products shine — a branded, personalised HTML page generated for every respondent. The Claude Connector makes designing and editing that page a conversation.

You don't write CSS by hand. You don't switch tabs. You don't paste between tools. You describe what you want, Claude writes the HTML, the connector validates it against your AI agent's output fields, and you get a live preview URL.


The four page tools


Token system — how pages render per respondent

A page is HTML with {{ tokens }} that get filled per respondent at render time:

TokenResolves toExample
{{ form:fieldName }}An answer your end user gave{{ form:firstName }} → "Sarah"
{{ object:fieldName }}A structured field your AI agent produced{{ object:overall_score }} → 78
{{ chart:overall_score }}A raw passthrough of any agent field — use inside SVG/HTML attributesstroke-dasharray="{{ chart:overall_score }} 100"
{{ chart:dimN_pct }}A computed percentage from dimN_score × 10style="width:{{ chart:dim1_pct }}%"
{{ custom:key }}A workspace variable{{ custom:product_name }}

Why object: and chart: differ: object: runs values through markdown (so **bold** works in text content), which wraps them in <p> tags — fine inside element content, but corrupts HTML attributes. chart: is a raw passthrough — use it wherever you need the raw value in an attribute, computed bar widths, gauge arcs, etc.

Full token reference →


The coverage check — no more silently-blank pages

When you call create_page or update_page, the connector cross-checks every {{ object:* }} token in your HTML against the AI agent's configured output fields. If any token doesn't match, the tool returns:

  • A warning listing the unmatched tokens
  • A ready-to-run suggested_agent_fields array — name + inferred description for each missing field
  • A fix instruction telling Claude to call set_agent_fields

Claude can then call set_agent_fields with the suggestions in the same conversation. No more shipping pages that render literal {{ object:sleepScore }} tokens because the agent doesn't produce that field.

The same coverage check applies to import_design when you pass a product_id.


Two render modes: fragment vs. document

Productised detects which mode to use automatically based on what you save.

Fragment mode (default — all existing pages and templates) HTML is injected via innerHTML into a centred ~720px card on the page. Scripts do not execute — build score visuals as pure CSS/SVG:

  • Bar fills: <i style="width:{{ chart:dim1_pct }}%;background:#3f7d5f"></i>
  • Ring gauge: <circle pathLength="100" stroke-dasharray="{{ chart:overall_score }} 100" />
  • Numbers: plain tokens ({{ object:overall_score }}), not JS counters

Wrap content in <div style="max-width:640px;margin:0 auto">…</div> to self-centre it.

Document mode (Claude Design output, and any <!DOCTYPE html> page) When the HTML you save starts with <!DOCTYPE html> or <html, Productised switches to document mode automatically — the page is served in an iframe. Scripts execute, custom fonts load from <link> tags, and animations run. This is what enables Claude Design pages to render exactly as they look in Claude Design's own preview panel.

Tokens are still resolved server-side before the iframe loads — {{ object:* }}, {{ form:* }}, {{ chart:* }} all work identically. JavaScript on the page can also access personalisation data via window.PRODUCTISED_DATA (same values, as a JSON object).

Preloaded fonts: Inter and Source Serif 4 are preloaded on every render surface. For any other webfont, include a @import or <link> inline in your page's <head>.


Designing in Claude Design

Most people build in a normal Claude chat. Claude Design is the power-user path when you want finer control over the visual design — but it has a gotcha worth knowing. For the full walkthrough see Design in Claude Design.

Never use Claude Design's "Export → Standalone HTML (offline)" button for a Productised page. That file is a self-contained React app (bundled JavaScript), not static HTML — Productised strips scripts on save, so it imports as a blank page. Instead, keep the connector in the same chat and say "use this as my output page" (Claude saves clean HTML for you), or — if you only have the offline file — ask in the design chat for "a single static HTML file, no JavaScript" and bring that.

Attach the Productised connector and give it the product. Claude Design's default instinct is to build a React app (its native artifact format), which Productised cannot use as an output page. With the connector attached and your product in context, it knows the real deliverable instead. Start your message with something like: "Use my Productised connector. Design the output page for product <id> — read the existing pages and tokens first."

The deliverable is one self-contained, zero-JS HTML document with {{ tokens }} — not React. If Claude Design prototypes in components, ask it to "render this down to a single static HTML file with the Productised tokens baked in, no React" before saving.

It must be saved through the connector. A design that lives only as a Claude Design artifact or a spec file does not exist in Productised. The handoff is update_page (or create_page) — that's what puts it on your live page. Full <!DOCTYPE html> output is auto-detected and stored in document mode (scripts and fonts work in the iframe).

Keep multi-page outputs cohesive. If you ask for "two pages," Claude Design may build two different designs. For one product they share a nav bar and must read as one product — same header, accent, cards, and CTA. Tell it to "match the existing page's design" (the connector returns your other pages so it can), and vary only the content, not the visual language.


Set up a Claude Design system that's Productised-ready

If you build a custom design system inside Claude Design, configure it so its output is Productised-compatible by default — then every page it produces is the right shape, and you never have to correct it mid-conversation. Paste the block below into your Claude Design design-system's guidelines:

PRODUCTISED OUTPUT PAGES — house rules

Deliverable: every result page is ONE self-contained HTML file with ZERO JavaScript.
Never a React/JSX app, never multiple files, never a separate spec doc. If you prototype
in components, render down to a single static HTML file before handing off.

Personalisation: pages fill per respondent via {{ tokens }}, never hard-coded values.
  • {{ object:fieldName }} — AI Agent output (scores, insights, tier labels, prose)
  • {{ form:fieldName }}   — your end user's intake answers (e.g. their name)
  • {{ chart:overall_score }}, {{ chart:dimN_pct }}, {{ chart:dimN_color }} — computed
    visual values; use these INSIDE HTML/SVG attributes (object: tokens corrupt attributes)
  • {{ custom:key }}       — workspace variables (booking links, brand text)
Call get_design_brief(product_id) to read the product's REAL token names. Never invent them —
an unknown token renders blank.

Score visuals are pure CSS/SVG (no JS):
  • bar fill:  <i style="width:{{ chart:dim1_pct }}%;background:{{ chart:dim1_color }}"></i>
  • ring:      <circle pathLength="100" stroke-dasharray="{{ chart:overall_score }} 100" />
  • numbers:   the plain token, e.g. {{ object:overall_score }}

Layout: self-centre at ~640px (max-width:640px;margin:0 auto) — or output a full
<!DOCTYPE html> document if you need fonts/scripts (it renders in an iframe).
Fonts 'Inter' and 'Source Serif 4' are preloaded.

Semantic score colours are SEPARATE from the brand accent: green #3f7d5f (strong),
amber #b5772f (developing), red #c0452f (focus). Use these for scores; use the brand
accent for chrome and the CTA.

Multi-page: all pages of one product share a nav bar. Reuse the same header, accent,
cards, and CTA across them — vary content, never the visual language.

Handoff: SAVE the page into the product with update_page (existing) or create_page (new).
A design that isn't saved through the connector does not exist in Productised.

With that in place, ask Claude Design to "use my Productised connector, call get_design_brief for product <id>, then design and save the output page." It will pull your real tokens and existing pages, design a single-file HTML page that matches, and save it live — no React detour, no manual port.


Porting designs from Lovable, v0, or Cursor

You can bring in HTML from any design tool using import_design. The tool cleans and validates the HTML before saving, detects placeholder text like "Maya" or "[Name]", and suggests the right tokens.

How each tool's output translates:

ToolOutput typeWorks in Productised?How
Claude Design (connector in the chat)Clean HTML saved via the connector✅ YesSay "use this as my output page" — Claude saves it. Details →
Claude Design — "Export → Standalone HTML (offline)" fileReact app bundle❌ No — imports blankDon't use it. Ask for "a single static HTML file, no JavaScript" instead
Cursor / any AI that writes HTMLFull HTML or fragment✅ DirectlyPaste into Claude, import_designupdate_page
LovableReact app (default)⚠️ Ask for plain HTMLPrompt: "Give me a single standalone HTML file with no React, no imports, no build step"
v0React components (default)⚠️ Ask for plain HTMLPrompt: "Output as a plain HTML file using only inline CSS and vanilla JS"
Figma / Webflow / FramerVaries⚠️ Export HTML firstExport as HTML, paste into import_design

For Lovable and v0: these tools default to React output that requires a build environment. Explicitly ask them for a "standalone single-file HTML" and they'll produce something that works. Once you have that HTML, paste it into a Claude conversation and say "import this design to my product" — the connector handles the rest.

Asking Claude to translate for you: If you have a Lovable or v0 design you like but can't get a plain HTML export, paste the design's component code into Claude and say "convert this to a self-contained HTML page using inline CSS and vanilla JS, then import it to my [product name] result page." Claude will translate it and save it in one go.


Typical design conversations

Ask Claude to design from scratch:

"Design a results page for my AI Readiness Scorecard. Score gauge at the top, a strength + critical gap pair, a 6-row dimension breakdown with bars and insights, three priority actions, then a CTA to book a strategy call."

Iterate on what's there:

"Show me the current page. Move the strength/gap row above the score gauge, make the gauge ring orange, and tighten up the dimension breakdown spacing."

Paste in a design from elsewhere:

"I exported this from Figma — import it and tell me what tokens I need to set up." (paste the HTML)

Switch templates:

"Swap to the Radar template — keep the same agent fields if possible."

Result page templates →


Editing pages from the canvas, using Claude

In the Productised app, when you select a Page node in the canvas, the right-side panel shows a "Copy HTML for Claude" button. Click it — the page's HTML + CSS is copied to your clipboard. Paste it into a Claude conversation, ask for changes, and save the new version back via update_page.

That round-trip works either way: design in Claude, save through the connector; or design in the dashboard, copy to Claude, iterate, save back.