Skip to main content
vibld

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

  1. Top bar: wordmark with beta pill left, Support link and avatar right
  2. 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
  3. Main: back link 'Settings', panel on pale blue tint: title, description, right-aligned Save button
  4. Asset row: Logo tile (dashed drop area with Upload link, caption) and Brand colour tile (large swatch showing hex, pencil button, caption)
  5. Preview section: label left, segmented Checkout | Invoice PDF centred, browser-frame mock below with split checkout layout
  6. 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

SampleWhereRatioNeeds
Aabody text on panel tint16.76:14.5:1
Aamuted caption on tile5.97:14.5:1
Aasave button label on brand5.24:14.5:1
Aaupload link text on tile7.34:14.5:1
Aapromo accent text on card5.49:14.5:1
Aabottom promo link on canvas5.18:14.5:1
focus ring on tile7.34:13:1
tile border on canvas3.01:13: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.

Open the builderAll templatesThis palette on its own