Template
Sparkhop
The Share & Settings step of an interactive challenge or quiz builder. Creators grab a public link, share it on social networks, or copy an embed snippet that auto-resizes the challenge inside their own site.
Dark quiz-builder share and embed settings · App screen: share · 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, 20px card titles
- InterBody: Inter 400 16px body; 14px labels (500); 13px code in JetBrains Mono at 1.6
Patterns
- dark two-level sidebar (icon rail + setup nav)
- lime accent Publish button top-right
- rounded outlined cards on dark canvas
- public link field with open-in-new icon
- row of equal social icon buttons
- embed code block with full-width copy button
- "soon" badge on nav item
- breadcrumb with grid icon
States it is designed for
- Never published (link and embed disabled, "Publish to get a link" hint)
- Published and up to date
- Unpublished changes (banner + dot)
- Publishing / publish failed
- Copy failed fallback
- Custom domain configured (link shows domain)
Who it is for
- Marketers running lead-gen quizzes
- Community and event organisers
- Educators embedding challenges
Layout
- Icon rail (~40px): logo, lime + create, builder, analytics, settings, feedback
- Setup nav (~180px): "Challenge setup" title; Main page, Challenge blocks, Question sets (soon), Customization, Integrations, Share & Settings (active)
- Top bar: breadcrumb with grid icon and challenge name; lime Publish right
- Content (max ~430-640px centered): Share card (title, Public link label, link field with open icon, six icon buttons); Embed card (title, instruction, code block, lime Copy code button)
- Mobile: nav in drawer; icon buttons wrap 3x2
Palette
energetic, techy, confident, nocturnal. Neon lime on charcoal makes the publish moment feel like a launch.
- content background
#141414 - sidebar background
#1b1b1b - card surface
#1c1c1c - input and icon button fill
#262626 - primary text
#f2f2f2 - labels, instructions
#a3a3a3 - Publish, Copy code, active icon
#d4ff3a - label on lime
#141414 - card and field outline
#6f6f6f - social glyph blue
#6aa9ff
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | text on card | 15.22:1 | 4.5:1 |
| Aa | muted label on card | 6.76:1 | 4.5:1 |
| Aa | muted on field | 6.00:1 | 4.5:1 |
| Aa | label on lime | 15.94:1 | 4.5:1 |
| field border on card | 3.39:1 | 3:1 | |
| lime focus ring on canvas | 15.94:1 | 3:1 | |
| social glyph on field | 6.29:1 | 3:1 | |
| Aa | text on sidebar | 15.39:1 | 4.5: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, 20px card titles
- Body
- Inter 400 16px body; 14px labels (500); 13px code in JetBrains Mono at 1.6
Similar to the observed geometric grotesk; "soon" badge 12px 600.
Spacing and imagery
Roomy: 8px base; card padding 24px, 16px radius; fields 44px, 8px radius; icon buttons 56x40 with 8px radius and 12px gaps; lime buttons 10px radius; no shadows, 1px outlines.
None; generic social glyphs in the icon buttons (use neutral share icons, not brand marks); a faint vertical-line texture on the sidebar.
Components
- Icon rail with lime create button
- Setup nav with soon badge
- Breadcrumb
- Publish button
- Share card
- Public link field with open-in-new
- Social icon button row
- Embed card with code block
- Copy code button
- Unpublished-changes banner
Interactions
- Open icon opens the public link in a new tab
- Clicking the link field selects and copies with toast
- Social buttons open prefilled share windows
- Copy code copies snippet; label becomes "Copied" for 2s
- Publish shows spinner, then "Published" check; if there are unpublished changes a dot shows on Publish
Data
Challenge{id, owner_id, name, status (draft|published), published_at, slug}Block{id, challenge_id, kind (question|info|form), order}ShareConfig{challenge_id, custom_domain?, allow_embed bool, allowed_origins[]}PublishVersion{id, challenge_id, snapshot jsonb, created_at}
Guardrails
Experience
- Disable link and embed until first publish, with a clear reason
- Show when the live version differs from the draft
- Keep the embed snippet short and explain where to paste it
- Give each social button a visible tooltip label
- Keep Publish reachable from every setup step
Accessibility
- Lime is used only as a fill with near-black text (15.9:1), never as text on dark small sizes
- Icon buttons have aria-labels ("Share on a professional network")
- Code block is a labelled, read-only textarea or <pre> with copy button
- "soon" nav item is aria-disabled with explanation
- Visible lime focus ring on dark surfaces
Security
- Embed only loads from your own script domain; snippet uses a versioned, integrity-checked script
- Optional allowed-origins list enforced by frame-ancestors CSP on the challenge page
- Publishing snapshots validated server-side; RLS owner-only on drafts
- Public link uses slug, not internal IDs; rate-limit submissions on the public challenge
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 **Sparkhop**, the "Share & Settings" step of a dark-themed interactive challenge builder. After publishing, creators copy a public link, share it through social icon buttons, or copy an embed snippet that auto-resizes the challenge inside their own website.
### Stack
React + TypeScript + Vite, Tailwind CSS, shadcn/ui (Button, Tooltip, Toast, Badge) on Radix, lucide-react, TanStack Query. Supabase for auth, challenges and publish versions; a small self-hosted embed script handles iframe resizing.
### Pages & layout
1. **Icon rail**: logo; a lime + create button; builder, analytics, settings, feedback icons.
2. **Setup nav**: "Challenge setup"; Main page, Challenge blocks, Question sets ("soon" badge), Customization, Integrations, Share & Settings (active, lighter fill).
3. **Top bar**: grid icon › "Growth marketing quiz"; lime "Publish" button right.
4. **Share card** (outlined, 16px radius): title "Share"; "Public link" label; a field with the URL and an open-in-new icon button; six equal icon buttons for social and messaging networks with neutral glyphs.
5. **Embed card**: title "Embed"; instruction "Paste this snippet where the challenge should appear"; a monospace code block (script tag + iframe + resize call); a full-width lime "Copy code" button.
6. Mobile: the nav moves to a drawer; icon buttons wrap into 3×2.
### Design system
- Colors: `--canvas: #141414` (content background), `--sidebar: #1b1b1b` (sidebar background), `--card: #1c1c1c` (card surface), `--field: #262626` (input and icon button fill), `--fg: #f2f2f2` (primary text), `--muted: #a3a3a3` (labels, instructions), `--accent: #d4ff3a` (Publish, Copy code, active icon), `--on-accent: #141414` (label on lime), `--border: #6f6f6f` (card and field outline), `--social: #6aa9ff` (social glyph blue).
- Fonts: Inter (similar to the observed geometric grotesk): card titles 20px/600, body 16px/1.5, labels 14px/500, code JetBrains Mono 13px/1.6, badge 12px/600.
- Spacing: 8px scale; 24px card padding; 24px between cards; 12px icon gaps.
- Radius: cards 16px; fields and icon buttons 8px; lime buttons 10px.
- Shadows: none; 1px outlines.
- Motion: 150ms hover lift on icon buttons; copy label swap; Publish spinner.
### Components & interactions
IconRail, SetupNav (the "soon" item is aria-disabled with a tooltip), Breadcrumb, PublishButton (idle, publishing, published, has-changes dot), ShareCard, PublicLinkField (click selects and copies; open icon), SocialIconButton (tooltip label, opens a prefilled share URL), EmbedCard, CodeBlock, CopyCodeButton, UnpublishedBanner, Toast.
### Data & state
Tables: `challenges(id, owner_id, name, status, slug, published_at)`, `blocks(id, challenge_id, kind, order)`, `share_configs(challenge_id, custom_domain, allow_embed, allowed_origins)`, `publish_versions(id, challenge_id, snapshot, created_at)`. Generate the snippet from slug and config. Handle states: never published, up to date, unpublished changes, publishing/failed, copy fallback, custom domain.
### Accessibility
Lime is only a fill behind near-black text, or a focus ring; never small lime text on dark. Icon buttons carry aria-labels and tooltips. The code block is labelled and has its own copy button. Disabled nav items explain why. Focus ring: 2px lime with 2px offset.
Verified contrast: text on card: #f2f2f2 on #1c1c1c = 15.22:1; muted label on card: #a3a3a3 on #1c1c1c = 6.76:1; muted on field: #a3a3a3 on #262626 = 6.00:1; label on lime: #141414 on #d4ff3a = 15.94:1; field border on card: #6f6f6f on #1c1c1c = 3.39:1; lime focus ring on canvas: #d4ff3a on #141414 = 15.94:1; social glyph on field: #6aa9ff on #262626 = 6.29:1; text on sidebar: #f2f2f2 on #1b1b1b = 15.39:1.
### Security
The snippet loads a versioned script from your own domain with a subresource-integrity hash. The challenge page sends `frame-ancestors` from `allowed_origins`. RLS: owners read and write drafts, and the public reads only published snapshots through the slug. Rate-limit public submissions and validate them server-side.
### Performance & SEO
Keep the embed script under 3 KB and load it deferred. Public challenge pages are server-rendered with OG tags; the builder is noindex.
### Guardrails
- Neutral social glyphs and an invented logo; no platform names in labels.
- Link and embed stay disabled until the first publish.
- Acceptance criteria: (1) Publish creates a version and enables sharing; (2) copy link and copy code work, with fallback; (3) the unpublished-changes state appears after edits; (4) the embed resizes in a test page; (5) contrast and keyboard checks pass.