User Onboarding Flow Builder
No-code product tour and onboarding flow builder. AI generates flows from screenshots. Indie-priced under Appcues. Weekend MVP guide + prompts.
Activation is where most SaaS products die quietly. The average SaaS hits 5–10% signup-to-active conversion. Best-in-class products hit 30%+, and the difference is almost entirely onboarding. A great product tour shown at the right moment lifts day-7 retention 15–25 points. The founders who know this also know they cannot justify Appcues at $249/month or Pendo at "call us" pricing. So they do one of three things, all bad. They ship no onboarding at all and hope the product speaks for itself. They hack together a modal with Intro.js that breaks every time the app UI changes. Or they pay an agency $5K to build a single onboarding flow that gets stale by the next product release. None of these loops produce a learning system. None tell the founder which step users drop off at.
Built for Developers, Solo Founders.
Suggested stack: Next.js 14 (admin app), Vanilla JS widget (runtime), Supabase, GPT-4 Vision for flow generation, Cloudflare CDN for widget.js, Stripe Billing + usage events. Weekend scope: about 12 hours.
The Problem
Activation is where most SaaS products die quietly. The average SaaS hits 5–10% signup-to-active conversion. Best-in-class products hit 30%+, and the difference is almost entirely…
The Solution
A multi-tenant no-code builder where the admin paints tooltips, modals, checklists, and hotspots onto a live preview of their app, and the system emits an embeddable JS snippet.…
Market Research
Appcues raised $30M+ Series B (2021) with public ARR estimates in the $20M+ range. Pendo is a $2.6B-valued unicorn. Category validation is decisive.
Competitive Landscape
Appcues / Pendo — Category leaders. Appcues raised $30M+ and powers 1,700+ customers. Pendo is $2.6B unicorn with enterprise focus. Deep features, polished editors, opaque…
Business Model
Free ($0) — 1 flow, 1,000 tour views/mo, “Powered by” badge, 3 AI generations/mo
Recommended Tech Stack
Next.js 14 (admin app) — Admin dashboard: flow library, visual editor (drag-drop steps + element picker from screenshot), analytics. Server Actions for flow CRUD. Vercel hosting.
AI Prompts to Build This
Copy these build prompts into Claude, Cursor, or your AI coding tool. Create a free account to unlock the full research behind them.
1. Admin App + Editor
Create a Next.js 14 App Router admin SaaS for building product tours. Supabase backend, Tailwind, TypeScript. Schema: - tenants(id, slug, owner_user_id, site_url, stripe_customer_id, plan ENUM[free,solo,team], monthly_views_used INT, created_at) - flows(id, tenant_id, name, status ENUM[draft,live,paused], trigger_type ENUM[url_match,event,manual], trigger_config JSONB, segment_rules JSONB) - steps(id, flow_id, position INT, step_type ENUM[tooltip,modal,hotspot,checklist], target_selector TEXT, title, body, buttons JSONB) - tour_events(id, tenant_id, flow_id, step_id, event ENUM[fired,advanced,completed,dismissed], visitor_id, occurred_at) Routes: - /dashboard (flow list, quick stats) - /flows/[id]/edit (visual editor + step list) - /flows/[id]/analytics (funnel: started → step 1 → step 2 → completed) - /install (snippet copy, docs) - /settings (billing, team) Visual editor: - Left panel: ordered step list, drag to reorder, add/remove. - Center panel: iframe of tenant.site_url (fallback: image of screenshot). On hover, show element outline; click to set target_selector via unique CSS path generator. - Right panel: step properties (type, title, body, buttons, transition). Preview mode: simulates the tour running on the site_url preview. Use postMessage from iframe to parent for event tracking.
2. Screenshot-to-Flow (GPT-4 Vision)
Implement screenshot-to-flow AI generation. This is the category differentiator. User flow: 1. On /flows/new, user uploads a screenshot of their app dashboard (drag-drop, PNG/JPG up to 4MB). 2. Upload to Supabase Storage; get signed URL. 3. Call OpenAI Chat Completions with gpt-4o, image_url pointing to the signed URL. System prompt: "You analyze SaaS dashboard screenshots and generate 5-step product tours for new users. For each step, identify a key UI element and write a friendly 1-2 sentence tooltip. Return JSON matching: {steps: [{position: 1-5, target_description: 'CSS selector or human description of the element', element_type: 'button|input|card|menu|chart|other', title: 'short', body: 'longer friendly microcopy', reason_for_step: 'why show this step'}]}. Prioritize the elements that enable the user's first success moment." 4. Use response_format: {type: 'json_schema'}. Validate structure. 5. Render the 5 generated steps in the visual editor. target_description is prefilled as a placeholder; user clicks on the element in the iframe preview to replace with a real selector. 6. Show the reason_for_step as an inline comment on each step (coaching, not committed to the flow). Cost: ~$0.03 per generation. Cap Free tier at 3/month; no cap on Solo/Team. Cache the generation by image hash so re-uploads don't cost twice.3. Embeddable JS Runtime
Build the standalone widget runtime. This is what ships in customer apps. widget.js (vanilla, ~25KB minified, no framework): (function() { const tenantId = document.currentScript.getAttribute('data-tenant'); const visitorId = getOrCreateVisitorId(); // localStorage const apiBase = 'https://api.product.com'; // 1. Fetch live flows for this tenant (cached 60s at CDN) fetch(`${apiBase}/v1/flows?tenant=${tenantId}`).then(r => r.json()).then(({flows}) => { // 2. For each flow, check trigger conditions vs current URL / user segment flows.forEach(flow => evaluateAndRun(flow, visitorId)); }); function evaluateAndRun(flow, visitorId) { // Trigger check: url_match uses minimatch on window.location.pathname if (!matchesTrigger(flow)) return; // Segment check: simple key/value match against window.__product_identify__ or cookie if (!matchesSegment(flow, visitorId)) return; // Mount a Shadow DOM root so our styles don't leak const root = document.createElement('div'); root.attachShadow({mode: 'open'}); document.body.appendChild(root); runTour(flow, root.shadowRoot, visitorId); } function runTour(flow, root, visitorId) { let stepIndex = 0; renderStep(flow.steps[0]); // Send 'fired' event trackEvent('fired', flow.id, flow.steps[0].id, visitorId); function renderStep(step) { const target = document.querySelector(step.target_selector); if (!target) { // Retry with MutationObserver for 5 seconds, then skip return waitForElement(step.target_selector, 5000).then(el => renderStep({...step, _target: el})).catch(() => advance()); } // Position tooltip/modal relative to target; attach Next/Prev/Skip buttons. //... render Shadow DOM content... } } function trackEvent(event, flowId, stepId, visitorId) { navigator.sendBeacon(`${apiBase}/v1/events`, JSON.stringify({tenantId, event, flowId, stepId, visitorId, ts: Date.now()})); } })(); Customer embed: Identify API (optional): Test matrix: React SPA (Next.js dev), Vue SPA (Nuxt), vanilla static site, Shopify/Webflow. Runtime should handle all four without modification.