Template
Pathbloom
The workflow step of a lifecycle-messaging campaign wizard. Marketers drag message and data blocks from a palette onto a vertical journey that starts from a trigger, branches on conditions, waits for time windows and sends emails or in-app messages. Incomplete blocks are flagged so the campaign cannot launch half-configured.
Campaign journey builder with step wizard and block palette · App screen: flowchart · 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, 18px campaign name; 16px panel headings
- InterBody: Inter 400 16px/1.5 panels; 14px node text
Patterns
- dark top bar with trial countdown and upgrade
- icon rail plus section sidebar
- horizontal wizard stepper with checkmarks
- autosave indicator beside primary Next
- left block palette grouped by category with premium badges
- dotted canvas with vertical flow and true/false branches
- left-border colour coding by node type
- inline warning chip on incomplete nodes
- floating canvas toolbar with zoom and sticky notes
States it is designed for
- empty workflow (trigger only, with 'drag a block here' zone)
- incomplete nodes with warning chips
- premium block locked (tooltip + upgrade link)
- autosaving / autosaved / save failed
- validation failed on Next (list of issues, click to focus node)
- test mode vs live mode badges
- trial expired (read-only with upgrade banner)
Who it is for
- lifecycle marketers
- growth teams
- product marketers
Layout
- dark top bar: workspace switcher, test-mode badge, trial days-left text, green Upgrade button, help, notifications, settings, profile
- icon rail (48px) and section sidebar (~200px): Dashboard, Analysis, Campaigns active, Broadcasts, Transactional, Drafts, People, Custom objects, Segments, Activity logs, Data & integrations, Content
- breadcrumb row
- campaign header: editable name with pencil, stepper (Trigger, Settings, Goal & exit, Workflow active, Review), Exit link, disabled 'Autosaved' pill, dark Next
- left palette (~240px): 'Copy from workflow' link; Messages group (email, in-app, push, chat message, SMS); Data group (create/update person, send event, batch update, segment update, query collection with Premium badge, send and receive data); scroll chevron
- canvas: dotted grid, top-right toolbar (tips, image, sticky note, zoom out, 75%, zoom in, search), nodes stacked vertically with connectors and True/False branch pills
- on <1100px the palette becomes a bottom sheet; stepper collapses to 'Step 4 of 5'
Palette
Organised and capable; a calm neutral canvas with colour used strictly to encode node types.
- top bar
#0e2b2b - top bar text
#ffffff - canvas
#f9f9f7 - node / panel surface
#ffffff - primary text
#1e2a28 - secondary text
#56625f - upgrade button
#6fd08c - warning chip fill
#fde68a - warning chip text
#5c4400 - wait/delay border
#c9670f - message border
#6a52e8 - stepper check
#1e7a47
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | top bar text | 15.01:1 | 4.5:1 |
| Aa | body text | 14.82:1 | 4.5:1 |
| Aa | muted text on canvas | 6.02:1 | 4.5:1 |
| Aa | upgrade label | 7.92:1 | 4.5:1 |
| Aa | warning chip text | 7.39:1 | 4.5:1 |
| wait border | 3.87:1 | 3:1 | |
| message border | 5.27:1 | 3:1 | |
| stepper check | 5.34: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, 18px campaign name; 16px panel headings
- Body
- Inter 400 16px/1.5 panels; 14px node text
Group labels 12px uppercase 600, 0.06em tracking with a coloured dot; badges 12px 600.
Spacing and imagery
Dense builder: palette items 36px with 1px border and 6px radius; nodes 280px wide, 6px radius, 3px coloured left border; 32px vertical connector length; branch pills 12px text in 20px pills.
Line icons for every block; a yellow sticky note graphic in the toolbar; no photos.
Components
- TopBar (WorkspaceSwitcher, ModeBadge, TrialCountdown, UpgradeButton)
- IconRail + SectionSidebar
- WizardStepper
- AutosaveIndicator
- BlockPalette with PremiumBadge
- JourneyCanvas
- TriggerNode
- MessageNode
- BranchNode with TruePill/FalsePill
- TimeWindowNode
- DelayNode
- WarningChip
- CanvasToolbar
- StickyNote
Interactions
- drag a block from the palette onto a connector drop zone (dnd-kit); drop zones highlight
- click a node to open its config drawer
- branch node creates two lanes that rejoin
- autosave 1s after changes; indicator shows Saving… / Autosaved
- Next validates the workflow and lists incomplete nodes
- zoom 25–150% with buttons and Cmd/Ctrl + wheel; sticky notes draggable
Data
Campaign{id, workspace_id, name, status (draft|live|paused), wizard_step, trigger jsonb, goal jsonb, exit jsonb}JourneyNode{id, campaign_id, type (email|in_app|push|chat|sms|update_person|event|batch_update|segment_update|query|webhook|branch|time_window|delay), config jsonb, parent_id, branch (true|false|null), position, complete bool}StickyNote{id, campaign_id, text, x, y}Workspace{id, plan, trial_ends_at, mode (test|live)}
Guardrails
Experience
- Encode node type with a left border colour and an icon, and keep that mapping in a legend.
- Flag incomplete nodes inline with a short chip rather than blocking edits.
- Autosave continuously and show it; never ask users to remember to save.
- Keep Next as the single dark primary; Exit is a quiet link.
- Show locked premium blocks with a badge and explanation instead of hiding them.
Accessibility
- Every drag has a keyboard alternative: select a block, then choose 'Insert after…' from a menu.
- Stepper uses an ordered list with aria-current='step' and text status (complete/incomplete).
- Branch lanes are labelled 'If true' / 'If false' in text.
- Warning chips have text; colour is secondary.
- Canvas zoom level is announced and toolbar buttons have labels.
Security
- RLS: campaigns, nodes and notes scoped to workspace members; publishers only can set status to live.
- Validate node configs server-side (addresses, templates, webhook URLs with SSRF protection).
- Test mode must never send to real recipients; enforce server-side.
- Audit status changes and publishes.
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 **Pathbloom**, the Workflow step of a lifecycle-messaging campaign wizard. Users assemble a vertical journey from a trigger through message, data, branch, time-window and delay blocks, see incomplete blocks flagged, and continue to Review once everything validates.
### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Sheet, Tooltip, Badge, Command), lucide-react, dnd-kit for palette-to-canvas drag, TanStack Query, react-hook-form + zod for node config drawers, date-fns for time windows. Supabase Auth and Postgres.
### Pages & layout
1. **App shell**: dark top bar, icon rail, section sidebar.
2. **/campaigns/:id/:step** wizard with steps Trigger, Settings, Goal & exit, **Workflow (this screen)**, Review.
3. Workflow step: palette, canvas, toolbar, config drawer.
4. Responsive: palette as bottom sheet under 1100px; canvas read-only under 700px.
### Design system
- Colors: `--topbar: #0e2b2b` (top bar), `--top-fg: #ffffff` (top bar text), `--canvas: #f9f9f7` (canvas), `--surface: #ffffff` (node / panel surface), `--fg: #1e2a28` (primary text), `--muted: #56625f` (secondary text), `--upgrade: #6fd08c` (upgrade button), `--warn-bg: #fde68a` (warning chip fill), `--warn-fg: #5c4400` (warning chip text), `--wait: #c9670f` (wait/delay border), `--message: #6a52e8` (message border), `--check: #1e7a47` (stepper check).
- Fonts: Inter 600, 18px campaign name; 16px panel headings for headings; Inter 400 16px/1.5 panels; 14px node text for body. Group labels 12px uppercase 600, 0.06em tracking with a coloured dot; badges 12px 600.
- Spacing: Dense builder: palette items 36px with 1px border and 6px radius; nodes 280px wide, 6px radius, 3px coloured left border; 32px vertical connector length; branch pills 12px text in 20px pills.
- Radius: 6px nodes, palette items and buttons; pills for branch labels.
- Shadows: nodes 0 1px 2px; drawer 0 8px 24px.
- Motion: 150ms drop-zone highlight; node insert 150ms fade/scale; none under reduced motion.
- Node-type legend: message = violet border, wait/delay = orange border, branch = teal, data = slate.
### Components & interactions
TopBar, IconRail, SectionSidebar, WizardStepper, AutosaveIndicator, BlockPalette, PremiumBadge, JourneyCanvas, node components per type, BranchPills, WarningChip, CanvasToolbar, StickyNote, NodeConfigDrawer, ValidationPanel.
Interactions: drag a block from the palette onto a connector drop zone (dnd-kit); drop zones highlight; click a node to open its config drawer; branch node creates two lanes that rejoin; autosave 1s after changes; indicator shows Saving… / Autosaved; Next validates the workflow and lists incomplete nodes; zoom 25–150% with buttons and Cmd/Ctrl + wheel; sticky notes draggable.
States to build: empty workflow (trigger only, with 'drag a block here' zone); incomplete nodes with warning chips; premium block locked (tooltip + upgrade link); autosaving / autosaved / save failed; validation failed on Next (list of issues, click to focus node); test mode vs live mode badges; trial expired (read-only with upgrade banner).
### Data & state
Journey is a tree stored as nodes with `parent_id` and `branch`. Completion is computed per node from its zod schema. Autosave debounced 1s with optimistic cache. Seed an 'Onboarding series' campaign with trigger 'signed up', welcome email (incomplete), a 'free account?' branch, a weekday time window, a one-day delay and an upgrade email (incomplete).
Model: `Campaign{id, workspace_id, name, status (draft|live|paused), wizard_step, trigger jsonb, goal jsonb, exit jsonb}`; `JourneyNode{id, campaign_id, type (email|in_app|push|chat|sms|update_person|event|batch_update|segment_update|query|webhook|branch|time_window|delay), config jsonb, parent_id, branch (true|false|null), position, complete bool}`; `StickyNote{id, campaign_id, text, x, y}`; `Workspace{id, plan, trial_ends_at, mode (test|live)}`.
### Accessibility
Every drag has a keyboard alternative: select a block, then choose 'Insert after…' from a menu. Stepper uses an ordered list with aria-current='step' and text status (complete/incomplete). Branch lanes are labelled 'If true' / 'If false' in text. Warning chips have text; colour is secondary. Canvas zoom level is announced and toolbar buttons have labels.
Verified contrast: top bar text: #ffffff on #0e2b2b = 15.01:1; body text: #1e2a28 on #ffffff = 14.82:1; muted text on canvas: #56625f on #f9f9f7 = 6.02:1; upgrade label: #0e2b2b on #6fd08c = 7.92:1; warning chip text: #5c4400 on #fde68a = 7.39:1; wait border: #c9670f on #ffffff = 3.87:1; message border: #6a52e8 on #ffffff = 5.27:1; stepper check: #1e7a47 on #ffffff = 5.34:1.
### Security
RLS: campaigns, nodes and notes scoped to workspace members; publishers only can set status to live. Validate node configs server-side (addresses, templates, webhook URLs with SSRF protection). Test mode must never send to real recipients; enforce server-side. Audit status changes and publishes. RLS per table: `campaigns` select/update for workspace members, status change to live only for role `publisher`; `journey_nodes` and `sticky_notes` follow their campaign; `workspaces` select for members, update by owners.
### Performance & SEO
Virtualise palette groups if long; memoise nodes; lazy-load config drawers per type. App routes noindex.
### Guardrails
- Encode node type with a left border colour and an icon, and keep that mapping in a legend.
- Flag incomplete nodes inline with a short chip rather than blocking edits.
- Autosave continuously and show it; never ask users to remember to save.
- Keep Next as the single dark primary; Exit is a quiet link.
- Show locked premium blocks with a badge and explanation instead of hiding them.
- Write all copy fresh; use invented people, companies and numbers only. No real brands, logos, wordmarks or third-party product names anywhere in the UI or seed data.
- Do not trace or copy any existing product's layout assets, icons or illustrations; draw generic ones.
- Acceptance criteria:
- [ ] Blocks can be added by drag or keyboard menu
- [ ] Branches render two labelled lanes
- [ ] Incomplete nodes show a warning chip and block Next with a list
- [ ] Autosave indicator reflects state
- [ ] Premium blocks are visible but locked with an explanation