Template
Mallowset
The branding page of a payments platform where a merchant uploads a logo and sets a brand colour that is applied to hosted checkout pages and invoice PDFs. A live preview under the controls shows exactly what customers will see, switchable between checkout and invoice.
Brand settings with logo, colour and live checkout preview · App screen: appearance · Small tools and apps · full-stack app (auth + DB)
A mock-up of the screen, drawn from its layout, palette and typefaces. A build follows the full prompt below.
Start from this screenRead the build prompt
Typefaces
The catalog's own faces. A screen composed into a template is drawn in that template's typefaces.
- InterHeadings: Inter 600, 22px for panel title; 16px 600 for tile titles
- InterBody: Inter 400, 16px/1.5; nav 15px 500; captions 14px muted
Patterns
- persistent left sidebar with promo card
- back-link settings header
- two-tile brand asset row (upload tile + colour tile)
- hex input with live swatch
- save button enabled only when dirty
- segmented preview switch
- embedded miniature product preview in browser frame
States it is designed for
- no logo yet (upload tile)
- uploading with progress
- logo too large or wrong type
- invalid hex (inline error, preview unchanged)
- low-contrast brand colour (warning with suggested accessible shade)
- dirty (save enabled)
- saving
- saved toast
- save failed with retry
- read-only for non-admins
Who it is for
- small-business merchants
- finance and ops admins
- developers configuring hosted payments
Layout
- Top bar: wordmark with beta pill left, Support link and avatar right
- Sidebar (200px): icon + label nav (Home, Payments, Payment links, Billing, Invoices, Customers, Products, Developer, Settings active), promo card near bottom with dismiss, accent text link at very bottom
- Main: back link 'Settings', panel on pale blue tint: title, description, right-aligned Save button
- Asset row: Logo tile (dashed drop area with Upload link, caption) and Brand colour tile (large swatch showing hex, pencil button, caption)
- Preview section: label left, segmented Checkout | Invoice PDF centred, browser-frame mock below with split checkout layout
- Below 900px sidebar to drawer; tiles stack; preview scales to width
Palette
Clean, trustworthy, a little playful. A pale blue working surface frames the merchant's own colour as the hero.
- canvas
#f5f9fc - surface
#ffffff - text
#111827 - muted
#5b6474 - border
#d7dde6 - brand
#4a5fe0 - on-brand
#ffffff - brand-disabled
#c3ccf0 - teal-accent
#0d7480 - promo-link
#b04a06 - focus
#3346c9 - tile-border
#8691a2
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text on panel tint | 16.76:1 | 4.5:1 |
| Aa | muted caption on tile | 5.97:1 | 4.5:1 |
| Aa | save button label on brand | 5.24:1 | 4.5:1 |
| Aa | upload link text on tile | 7.34:1 | 4.5:1 |
| Aa | promo accent text on card | 5.49:1 | 4.5:1 |
| Aa | bottom promo link on canvas | 5.18:1 | 4.5:1 |
| focus ring on tile | 7.34:1 | 3:1 | |
| tile border on canvas | 3.01: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
- Inter 600, 22px for panel title; 16px 600 for tile titles
- Body
- Inter 400, 16px/1.5; nav 15px 500; captions 14px muted
Similar to the observed neo-grotesk. Hex values shown in a monospace (JetBrains Mono 500, 20px) on the swatch.
Spacing and imagery
Comfortable; 8px base; panel padding 20px; tiles 260px x 120px visual area; radius 10px tiles and panel, 8px buttons, segmented control 8px; shadow only on the preview frame (0 10px 30px rgba(17,24,39,.08)).
No photography; the preview is a live miniature of the real checkout component. Small coin icons in the promo card.
Components
- sidebar nav
- promo card
- back link
- save button (disabled until dirty)
- logo upload tile with drag-and-drop
- colour tile with hex input and picker
- segmented preview switch
- browser frame preview
- contrast warning chip
Interactions
- Drag a file onto the logo tile to upload; tile shows progress then the logo
- Pencil opens a popover with colour picker and hex input; typing a valid hex updates the preview immediately
- Save enables when anything changes; Cmd/Ctrl+S saves
- Segmented switch cross-fades between checkout and invoice previews
- Leaving with unsaved changes asks for confirmation
- Promo card dismiss slides it out and is remembered
Data
Merchant{id, name}Branding{merchant_id, logo_path, brand_hex, updated_by, updated_at}AuditEvent{id, merchant_id, actor_id, action, before jsonb, after jsonb, at}
Guardrails
Experience
- Show the effect of every change live in the preview
- Warn when the chosen colour would make button text unreadable and offer a fixed shade
- Keep Save disabled until something changed, and say 'Saved' after
- Accept hex with or without #, 3 or 6 digits
- Explain what the logo is used for and recommended size
- Keep the preview representative but clearly labelled as a preview
Accessibility
- Upload tile is a button that also accepts drops, with instructions in text
- Colour tile announces the current hex value
- Contrast warning uses icon plus text
- Segmented control uses tabs semantics controlling the preview panel
- Preview mock is aria-hidden except for a text summary
- Visible focus ring on all controls including the pencil button
Security
- RLS: branding rows readable by merchant members, writable only by admin role
- Logo upload: PNG/SVG/JPEG whitelist, 1 MB cap, SVG sanitised server-side, stored under merchant-scoped path
- Validate hex with a strict regex server-side
- Write an audit event for every branding change
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 an entry'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 entries) - 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. ### SaaS screen baseline - Design every screen for its full set of states: first-run empty, loading skeleton, partial data, error with retry, permission-denied, and success feedback. Each entry lists the states its screen needs. - Keep destructive actions (delete, revoke, downgrade, remove member) behind a confirmation that names the object, and prefer undo over a second dialog where the action is reversible. - Enforce authorisation on the server for every action a screen exposes. Hiding a button is not access control; check the role again in the API or RLS policy. - Never show secrets (API keys, tokens) in full after creation. Show them once, then mask them, and offer rotate and revoke. - Keep the app shell (navigation, workspace switcher, account menu) consistent across screens, and preserve filters, sort and scroll position when the user navigates back.
### Goal
Build **Mallowset**, the Branding settings page of a payments platform. A merchant uploads a logo and sets a brand colour; both are applied to hosted checkout pages and invoice PDFs. A live preview directly under the controls shows the result before saving.
### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Button, Popover, Tabs, AlertDialog, Toast), lucide-react, react-hook-form + zod, TanStack Query. Supabase Auth, Postgres and Storage. A colour picker built on Radix Popover with a hue/saturation area.
### Pages & layout
1. **Shell**: top bar (wordmark + Beta pill, Support, avatar); sidebar nav with Settings active; promo card ('Bill in one currency, settle in another' with 'Join the waitlist' button) and an accent link at the bottom.
2. **/settings/branding** (this screen): back link; tinted panel with title 'Branding', description 'Choose how your business looks on pages your customers see.', Save changes button; tiles for Logo and Brand colour (swatch showing e.g. #4A5FE0 in large mono text); Preview label, segmented Checkout | Invoice PDF, and a browser-frame preview: left column with merchant name, order summary and amount; right column with contact fields and payment method options using the brand colour.
3. Responsive: drawer sidebar below 900px; tiles stack; preview scales with `transform` inside a fixed aspect ratio box.
### Design system
- Colors: `--canvas: #f5f9fc`, `--surface: #ffffff`, `--text: #111827`, `--muted: #5b6474`, `--border: #d7dde6`, `--brand: #4a5fe0`, `--on-brand: #ffffff`, `--brand-disabled: #c3ccf0`, `--teal-accent: #0d7480`, `--promo-link: #b04a06`, `--focus: #3346c9`, `--tile-border: #8691a2`.
- Fonts: Inter (similar to observed) for UI; JetBrains Mono 500 for hex values. Title 22px/600; body 16px/1.5; captions 14px.
- Spacing: 8px base; panel padding 20px; 16px tile gap.
- Radius: tiles and panel 10px; buttons 8px.
- Shadows: preview frame only.
- Motion: 150ms swatch colour transition; 200ms preview cross-fade; reduced motion respected.
- Merchant colour is a runtime CSS variable `--merchant` applied only inside the preview and the real checkout.
### Components & interactions
`SettingsHeader` (back link, title, description, SaveButton), `LogoUploadTile` (drop zone, progress, replace/remove), `BrandColorTile` (swatch, hex text chosen for contrast automatically, pencil Popover with picker and hex Input, ContrastWarning with 'Use suggested shade'), `PreviewSwitch`, `BrowserFrame`, `CheckoutPreview`, `InvoicePreview`, `PromoCard`. Dirty-state guard via AlertDialog on navigation.
### Data & state
`branding(merchant_id pk, logo_path, brand_hex char(7), updated_by, updated_at)` and `audit_events`. Form state in react-hook-form with the saved row as defaults; the preview reads the live form values. Mock merchant 'Kestrel Coffee Roasters', amount 10.00 in a generic currency.
### Accessibility
On-swatch hex text colour is computed (white or near-black) for 4.5:1. Contrast warning appears when white on the brand colour is below 4.5:1 and offers the nearest passing shade. Preview has a text summary for screen readers. Tabs semantics on the switch.
Verified contrast: body text on panel tint: #111827 on #f5f9fc = 16.76:1; muted caption on tile: #5b6474 on #ffffff = 5.97:1; save button label on brand: #ffffff on #4a5fe0 = 5.24:1; upload link text on tile: #3346c9 on #ffffff = 7.34:1; promo accent text on card: #0d7480 on #ffffff = 5.49:1; bottom promo link on canvas: #b04a06 on #f5f9fc = 5.18:1; focus ring on tile: #3346c9 on #ffffff = 7.34:1; tile border on canvas: #8691a2 on #f5f9fc = 3.01:1.
### Security
RLS on `branding`: select for merchant members; insert/update only when the member's role is admin. Storage policy restricts writes to `logos/{merchant_id}/*` for admins; MIME whitelist, 1 MB limit, SVGs sanitised in an Edge Function (strip scripts and external references). Hex validated with `^#[0-9a-fA-F]{6}$` constraint. Every change writes an `audit_events` row via trigger.
### Performance & SEO
Preview renders the real checkout component in a lightweight preview mode (no network). Debounce hex updates by 100ms. Lazy-load the colour picker. Noindex.
### Guardrails
- Invented merchant names and amounts
- Never apply unsaved branding to live pages
- Do not allow unreadable button text without a warning
- Typed code, visible errors
- Acceptance criteria: (1) logo upload validates type and size; (2) hex edits update the preview instantly; (3) Save is disabled until dirty and confirms success; (4) non-admins see read-only controls and RLS blocks writes; (5) works at 390px.