Template
Creditline
A single-page, editorial-style attribution dashboard that shows how one quarter's revenue is credited to seven marketing channels under first-touch, linear and last-touch models. It exists to explain attribution trade-offs to stakeholders: the total never changes, only the split, and every panel animates to make that visible.
Marketing attribution explainer dashboard · App · Small tools and apps · front-end app (local state)
A mock-up of the homepage, drawn from this design’s layout, palette and typefaces. A build follows the full prompt below.
Start from this templateRead the build prompt
Typefaces
A geometric-leaning display grotesk, a humanist body and a narrow tabular mono give the explanatory, data-journalism feel.
- EpilogueHeadings: headline ~30px 700, panel titles 600 18px
- CommissionerBody: body 14-16px
- InconsolataFigures and code: numbers, axis ticks, uppercase eyebrows
Who it is for
- Growth and marketing leads presenting to execs
- RevOps analysts prototyping reporting
- Agencies reviewing channel mix with clients
- Founders sanity-checking channel credit
Layout
- Header: small uppercase 'CHANNEL CREDIT · Q2' eyebrow, bold question headline, one-line explainer left; floating segmented model toggle (First touch / Linear / Last touch) with theme icon and 'Model guide' button right, plus model blurb
- Full-width revenue rail card: one fixed-length rounded bar split into colour-coded channel segments with % labels and $0 / $2.30M ends
- Two-column row: Spend-versus-revenue bubble chart with saturation curves and ROAS target line; credit waterfall building to the quarter total
- KPI tiles (attributed revenue, blended ROAS, top channel, avg touchpoints)
- Conversion path chips
- Channel detail sortable table with spend, attributed revenue, ROAS, conversions, CPA and 12-week sparkline + delta
- Footnote footer explaining the models and demo data
Palette
Editorial, analytical, calm, precise, explanatory. Reads like an interactive data story rather than a BI tool.
- background (warm grey)
#f6f6f3 - card
#ffffff - text
#101828 - primary blue (toggle)
#1447e6 - channel green (organic)
#1e7f46 - channel red (paid social)
#d52f3e - channel amber (display)
#a46011
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text on background | 16.39:1 | 4.5:1 |
| Aa | muted text on background | 5.51:1 | 4.5:1 |
| Aa | white text on primary toggle | 6.83:1 | 4.5:1 |
| Aa | white label on organic segment | 5.02:1 | 4.5:1 |
| Aa | white label on paid social segment | 4.88:1 | 4.5:1 |
| Aa | white label on paid search segment | 5.49:1 | 4.5:1 |
| Aa | white label on display segment | 4.93:1 | 4.5:1 |
| Aa | white label on referral segment | 5.87:1 | 4.5:1 |
| Aa | white label on email segment | 4.98:1 | 4.5:1 |
| Aa | white label on direct segment | 4.76:1 | 4.5:1 |
| Aa | dark mode body text on card | 13.98:1 | 4.5:1 |
| Aa | dark mode muted text on card | 7.19:1 | 4.5:1 |
| input border on card | 3.02:1 | 3:1 |
As vibld’s tokens
The palette on the fifteen colour tokens vibld styles a project with, each text colour on the fill it is read on. Marked tokens are solved from the palette, because no swatch held that role at 4.5:1.
- background
- card
- muted
- primary
- secondary
- accent
- destructive *
Type scale
- Display
- Epilogue 700, ~30px headline, -0.76px tracking; panel titles Epilogue 600 18px
- Body
- Commissioner 400 14-16px; Inconsolata for numbers, axis ticks and uppercase eyebrows
Geometric headings, humanist body, and tabular mono figures give an editorial data-journalism feel. Accessibility: body copy 16px or larger at 1.5+ line height with a ~70ch max measure; no text below 12px; weights under 400 only at 32px+; uppercase reserved for short labels with 0.05em+ tracking.
Spacing and imagery
Full-width ~1216px canvas, stacked large rounded cards (12-16px radius) with thin borders and faint shadows, 24px gaps, generous padding inside chart panels.
No photos; everything is custom charts -- segmented bar, bubble scatter with curves, waterfall, path chips, sparklines -- with a consistent seven-colour channel palette.
Components
- Segmented model toggle
- Theme toggle
- Model guide popover
- Revenue rail (segmented bar)
- KPI tiles with 'changes with model' chip
- Bubble chart with saturation curves and target line
- Waterfall chart with running total
- Conversion path chips
- Sortable channel table
- Inline sparklines with % delta
- Insight lines in plain language
- Footnote/method note
Interactions
- Model switch triggers staggered animation across panels (~1s)
- Rail segments reorder and slide
- Hover tooltips comparing a channel across all three models
- Sortable table columns; rows reorder on model change
- Dark mode toggle
- Reduced-motion fallback with instant updates
- Unpaid channels show dashes instead of ratios
Data
Channel{id, name, color, paid:boolean, spend, weekly_revenue[12]}Journey{id, touchpoints: channel_id[], conversions, days_to_close, revenue}AttributionResult{model: first|linear|last, channel_id, revenue, conversions, roas, cpa} (derived)Quarter{label, total_revenue, total_conversions}
Build prompt
The baseline every prompt in the catalog assumes, then this design’s own ten sections, from goal to guardrails.
The baseline
### How to use these prompts Paste a template's build prompt into your coding agent as the first message. Each prompt names its own stack, tokens and acceptance criteria; the rules below apply to all of them and can be prepended once per project. ### Engineering baseline - TypeScript strict mode, no `any`, small typed components, feature folders, and one source of truth for design tokens (CSS variables consumed by Tailwind). - Validate every input with a shared zod schema on the client and again on the server or edge function. Never trust client-side checks alone. - Show loading, empty and error states for every async view. Surface errors in plain language with a retry, and log details to the console in development only. - Keep secrets out of the bundle. Only publishable keys (for example a Supabase anon key) belong in client code; service-role keys, API keys and webhooks live in server or edge-function environment variables. ### Data and auth baseline (full-stack templates) - Enable Row Level Security on every table before inserting data. Default-deny, then add owner-scoped policies (`auth.uid() = user_id`) and explicit role checks for admin views. - Store roles in a separate table checked by a security-definer function, never in a user-editable profile field. - Upload files to private storage buckets with size and MIME limits, and serve them through signed URLs. - Rate-limit public endpoints (forms, auth, AI calls) and add a honeypot field or captcha to anonymous forms. - Take payments through a hosted checkout and verify webhooks by signature. Never handle raw card data. ### Accessibility and UX baseline - Target WCAG 2.2 AA: 4.5:1 contrast for normal text and 3:1 for large text, input borders, focus rings and meaningful icons or chart lines. Every palette in this catalog lists its verified pairs; re-check with a contrast tool after any colour change. - Keep body text at 16px or larger with 1.5 line height, nothing below 12px, no light weights under 24px, and uppercase only for short labels. - Give every interactive element a visible focus ring, full keyboard support, semantic landmarks, labelled form fields, and alt text on meaningful images. - Respect `prefers-reduced-motion` for every animation. Give drag-and-drop and carousels keyboard and button alternatives. - Build mobile-first and test at 375px, 768px and 1280px. ### Content guardrails - Use original copy, fictional sample data and placeholder or licensed imagery. Do not reuse another product's name, logo, screenshots or marketing text. - Label demo testimonials and metrics as samples. Collect the minimum personal data the feature needs.
### Goal Build **Creditline**, a one-page interactive attribution explainer for marketing leaders, analysts and agencies. It takes a quarter of fictional B2B journeys across seven channels and shows how revenue credit shifts between first-touch, linear and last-touch models. The central idea to communicate: totals stay fixed; only the split changes. ### Stack React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Radix) for the toggle group, tooltip, popover and table primitives, lucide-react. Use visx or D3 scales with hand-built SVG for the rail, bubble chart, waterfall and sparklines (Recharts is acceptable for the waterfall if simpler), Framer Motion for layout animations and staggered transitions. No backend; data lives in a typed module. ### Pages & layout A single route: 1. **Header**: mono uppercase eyebrow with the quarter, question-style headline, one-sentence explainer. Top-right: floating segmented control (First / Linear / Last), theme button, "Guide" popover, and a one-line description of the active model. 2. **Revenue rail**: fixed-width rounded bar divided into channel segments with name and share; end labels $0 and total; caption noting the bar never changes length. 3. **KPI tiles**: attributed revenue, blended ROAS, top channel, average touchpoints; flag which figure depends on the model. 4. **Two-up panels**: spend vs return (bubble size = budget, modelled diminishing-return curves solid to current spend, dashed beyond, horizontal ROAS target) and a waterfall building to the total. 5. **Journeys**: top multi-touch paths as arrowed chip sequences with conversion counts and days to close. 6. **Channel detail table**: spend, attributed revenue, ROAS, conversions, CPA, 12-week sparkline, delta. 7. **Method footnote**. ### Design system Light default with dark mode. Tokens: `--background: #f6f6f3`, `--card: #ffffff`, `--foreground: #101828`, `--muted: #f1f1ee`, `--border: #e5e7eb`, `--primary: #1447e6`. Channel colours stay pinned: organic `#1e7f46`, paid social `#d52f3e`, paid search `#3461d6`, display `#a46011`, referral `#8e44ad`, email `#0c7d78`, direct `#64748b`. Fonts: Epilogue 600/700 headings, Commissioner body, Inconsolata for numbers with `font-variant-numeric: tabular-nums`. Scale 12/14/16/18/30. Radius 16px cards, 12px controls. Motion: 600ms ease-in-out segment slides, 60ms stagger between panels, all within ~1s. Add `--muted-foreground: #5b6474` and `--input-border: #8c95a6`. Dark mode: `--background: #0e1320`, `--card: #161c2b`, `--foreground: #e6e9ef`, `--muted-foreground: #a1a9b8`, `--primary: #6b8cff`; channel colours stay the same with white segment labels. ### Components & interactions Segmented toggle with keyboard arrows. Rail segments animate width and order with `layout`. Chart tooltips list the channel's value under all three models. Table headers sort ascending/descending with an arrow; rows animate reorder. Unpaid channels show "–" for ROAS/CPA. Empty/error states are unlikely but render a friendly message if data fails validation. ### Data & state Channel(id, name, color, paid, spend, weekly[12]), Journey(touchpoints[], conversions, revenue, days). Compute attribution with pure functions per model and memoise; assert in tests that totals are identical across models. Model, theme and sort live in URL params so views are shareable. Seed seven channels and ~40 journeys for a fictional SaaS company. ### Accessibility Every chart has an accessible name and a visually hidden data table; tooltips are reachable via focus. Colour is never the only channel cue: include labels and dot + name in legends. Channel colours were darkened so white segment labels reach 4.5:1 on every channel. Under `prefers-reduced-motion`, swap animations for instant updates. Toggle group uses `role="radiogroup"`. Type: body 16px+, line height 1.5+, max ~70ch, nothing under 12px. Verified contrast: body text #101828 on #f6f6f3 = 16.39:1; muted text #5b6474 on #f6f6f3 = 5.51:1; white text #ffffff on #1447e6 = 6.83:1; white label #ffffff on #1e7f46 = 5.02:1. ### Security Static app: no secrets, no user input beyond controls. Validate the data module with zod at load. If you later add file upload for custom data, parse client-side with size limits and never render raw HTML. External links use `rel="noopener noreferrer"`. ### Performance & SEO Keep the JavaScript payload small (tree-shake D3 modules). Memoise heavy calculations; animate transforms not layout where possible. Add title, description and OG image for sharing; semantic `h1`/`h2` per panel. Target Lighthouse 95+. ### Guardrails - Fictional company and numbers only; label the data as demo. - No vendor logos or platform trademarks as channel icons. - Typed components, no `any`, visible errors. - Done when: switching models animates every panel within about a second; totals match across models; table sorts and reorders; dark mode works; keyboard and screen-reader users can read every figure.