DEV Community

Cover image for Before Launching My AI Tool, I Rebuilt the Onboarding 3 Times. Here’s Why
Shola Jegede
Shola Jegede Subscriber

Posted on

Before Launching My AI Tool, I Rebuilt the Onboarding 3 Times. Here’s Why

Onboarding isn’t a nice-to-have.

It’s the first impression. The tutorial. The sales pitch. The trust-building moment. And it’s the one thing that determines whether your users stay... or leave.

Before launching my AI app (learnflow AI) publicly, I rebuilt the onboarding flow three separate times.

Each time, I had to tear down assumptions, rewrite logic, and rethink the entire first-time experience.

Why? Because every version failed to answer a simple question:

"Why should I care about this tool — and how do I win here?"

Here’s the full story with mistakes included.

Attempt #1: Instant Start — But No Guidance

The Idea

Make it feel frictionless. Land on dashboard → see a clear call to action → create an AI tutor → start learning.

The Flow

  • After signing up, users landed on the dashboard
  • Top action was a big “Create Tutor” button
  • No walkthrough, no context, no orientation

The Problem

Users didn’t know what a tutor meant or what it would do.

  • "Create a tutor for what?"
  • "Where do I go next?"
  • "Is this real-time AI or not?"

Diagram: V1 Onboarding Flow

User signs up ↳ Sees pricing table (Kinde hosted) ↳ Chooses Free or Pro ↳ Lands on Dashboard ↳ Sees “Create Tutor” button ↳ No context, no help, no clear goal 
Enter fullscreen mode Exit fullscreen mode

What I Learned

Removing friction doesn’t remove confusion. Fewer steps ≠ better onboarding.

Attempt #2: Prebuilt Tutors and Progress Hints

The Idea

People need momentum. Don’t drop them into a blank screen.

The Flow

  • Dashboard now featured popular public tutors from other users
  • Each tutor had a “Start Session” CTA
  • Above the fold: "Create Your First Tutor" prominently shown
  • Once a session started, users saw their credit count and a soft upgrade CTA

Code: Displaying Public Tutors

<section className="px-4 lg:px-6 space-y-4 mt-10 sm:mt-0"> <h1 className="text-xl sm:text-3xl">Popular Tutors</h1> <section className="home-section"> {companions?.map((companion) => ( <CompanionCard key={companion._id as Id<"companions">} {...companion} color={getSubjectColor(companion.subject)} /> ))} </section> </section> 
Enter fullscreen mode Exit fullscreen mode

UX Wins:

  • Users could explore before committing
  • Visual interest replaced an empty dashboard
  • The call-to-action was goal-oriented, not abstract

Diagram: V2 Onboarding Flow

User signs up ↳ Sees pricing table (Kinde hosted) ↳ Chooses Free or Pro ↳ Lands on Dashboard ↳ Sees public tutors + "Create Tutor" prompt ↳ Starts session or creates own 
Enter fullscreen mode Exit fullscreen mode

What I Learned

Show. Don’t tell. Give users somewhere to go even if they’re not ready to create yet.

Attempt #3: Embedded Guidance and Upgrade Nudges

The Idea

Prompt users to either create a new tutor through a stepper UI form.

The Flow

  • Tutor creation form was redesigned into a guided stepper
  • Each field explained with short text (subject, voice style, duration, etc.)
  • After creation, users land in a session room — not back on dashboard
  • A sticky banner appears after 2 sessions: "You have 8 credits left. Upgrade now →"

Key Goals

UX Goal Strategy
Show value fast Highlight working examples (prebuilt tutors)
Guide action Stepper UI for building a new tutor
Build habit Credits, limits, and upgrade prompts

Convex Logic: Onboarding State

export const setOnboardingStep = mutation({ args: { userId: v.id("users"), step: v.string() }, handler: async (ctx, args) => { await ctx.db.patch(args.userId, { onboardingStep: args.step }); }, }); 
Enter fullscreen mode Exit fullscreen mode

Diagram: Final Flow

Final flow diagram

Outcome: Ready to Launch

With onboarding v3, users finally:

  • Understood what tutors were
  • Saw working examples instantly
  • Were guided into the learning experience
  • Encountered clear, upgrade-aware nudges

Billing: Powered by Kinde

We use Kinde for authentication, and crucially, early plan selection.

What Happens on Signup:

  1. User signs up →
  2. Redirected to Kinde-hosted pricing table
  3. Selects plan (free or pro)
  4. Kinde injects this into their session metadata
const { getUser } = getKindeServerSession(); const user = await getUser(); const plan = user?.user_metadata?.plan || "free"; 
Enter fullscreen mode Exit fullscreen mode

No backend billing setup, no custom checkout — just Kinde’s prebuilt logic + Stripe.

Credits + Feature Locking

Learnflow AI gives 10 free voice sessions (1 per credit).

Convex schema:

users: defineTable({ email: v.string(), plan: v.optional(v.string()), credits: v.optional(v.number()), }) 
Enter fullscreen mode Exit fullscreen mode

On each session, you deduct credits:

const creditCost = user.plan === "pro" ? 0 : 1; if (user.credits < creditCost) { throw new Error("Out of credits. Upgrade to continue."); } await ctx.db.patch(user._id, { credits: user.credits - creditCost, }); 
Enter fullscreen mode Exit fullscreen mode

Readiness to Launch: Final Checklist

First-time experience includes guidance and call-to-action

Public tutors surface value even without engagement

Tutor builder guides user through creation with context

Kinde pricing table ensures early plan selection

Credits and plans synced across Kinde and Convex

Sticky upgrade CTA appears after early usage

Convex tracks onboarding progress, allows segmentation

What I’d Tell Past Me

  1. You can’t onboard users into ambiguity. Make the value visible.
  2. Let people explore before committing. Curiosity converts.
  3. Your database needs onboarding logic. Don’t hardcode onboarding state.
  4. Don’t hide pricing behind clicks. Make plan choice part of the signup journey.
  5. Nudge softly. You don’t need a paywall popup — a subtle reminder works better.

Final Thoughts

Most onboarding advice is about simplifying. But sometimes you don’t need less — you need more structure.

If users don’t get why they’re here, what they can do, or what’s next — they’ll bounce.

Rebuilding onboarding 3 times forced me to design for:

  • Context, not guesswork
  • Guided actions, not open-ended prompts
  • Real upgrade paths, not buried links

In the end, I didn’t just build better onboarding.
I built a product that was ready to meet users where they are.

Top comments (0)