Onboarding Flow
1.0.0Supabase auth journey from marketing site to dashboard.
On this page
- Landing → Dashboard Flow (Supabase Auth)
- 1. Applications in Play
- 2. User Journey Overview
- 3. Authentication with Supabase
- Supported Providers
- Environment Requirements
- 4. Onboarding Flow
- Multi-Step Wizard
- 5. Dashboard Experience
- 6. Session Propagation to Generated Apps
- 7. Linking Dashboard Actions to Apps
- 8. Troubleshooting
Landing → Dashboard Flow (Supabase Auth)
This document walks through the user journey from the marketing site to the dashboard, including Supabase authentication, organization onboarding, and how the session propagates to generated apps.
Last reviewed: October 16, 2025
1. Applications in Play
| App | Path | Purpose | Hosting |
|---|---|---|---|
| Landing | apps/landing → https://infiniteapps.ai | Marketing, pricing, CTA to sign up | Vercel |
| Dashboard | apps/dashboard → https://dashboard.infiniteapps.ai | Multi-tenant control plane | Vercel |
| Generated Apps | apps/<slug>-web | Customer-facing experiences on custom domains | Vercel (default) |
The landing page links directly to the dashboard, which handles Supabase authentication and organization management.
2. User Journey Overview
Visitor hits landing page
↓
Clicks “Start Building” (CTA)
↓
Redirected to dashboard.infiniteapps.ai
↓
Supabase auth flow (Google/GitHub/email)
↓
Post-auth redirect → onboarding if no organization
↓
Dashboard home with organization context
3. Authentication with Supabase
Dashboard uses the Supabase helpers in apps/dashboard/src/lib/supabase.
// apps/dashboard/src/app/(auth)/callback/route.ts
import { createServerSupabaseClient } from '@/lib/supabase/server';
export async function GET(request: NextRequest) {
const supabase = createServerSupabaseClient();
const code = request.nextUrl.searchParams.get('code');
if (code) {
await supabase.auth.exchangeCodeForSession(code);
}
return NextResponse.redirect(new URL('/', request.url));
}
Supported Providers
- Google OAuth
- GitHub OAuth
- Email magic link (passwordless)
- Additional providers configurable via Supabase dashboard
Environment Requirements
# apps/dashboard/.env.local
NEXT_PUBLIC_SUPABASE_URL="https://<project>.supabase.co"
NEXT_PUBLIC_SUPABASE_ANON_KEY="public-anon-key"
SUPABASE_SERVICE_ROLE_KEY="service-role-key"
NEXT_PUBLIC_DASHBOARD_URL="https://dashboard.infiniteapps.ai"
4. Onboarding Flow
After authentication, if the user has no organization memberships, they are routed to /onboarding.
// apps/dashboard/src/app/(app)/layout.tsx
const { memberships } = await getOrganizationContext();
if (memberships.length === 0) {
redirect('/onboarding');
}
Multi-Step Wizard
- Step 1 - Organization basics: Name + slug with inline validation and auto-suggested slug; progress autosaves via
POST /api/onboarding/progress. - Step 2 - Starter template: Users pick from curated templates (filters by industry). Selection is written to
organizations.starter_template. - Step 3 - Launch checklist: Users review billing, domain, and telemetry prerequisites. Each checklist item deep-links into the corresponding dashboard tab.
Finishing the wizard triggers /api/onboarding/complete:
await fetch('/api/onboarding/complete', {
method: 'POST',
body: JSON.stringify({ name, slug, templateId }),
});
The handler:
- Inserts/updates the
organizationsrow (idempotent if the autosave already created it). - Creates
organization_memberswith roleOWNER. - Seeds default billing + domain scaffolds.
- Records the onboarding telemetry event (
onboarding_completed). - Redirects to dashboard home (
/).
5. Dashboard Experience
Once inside an organization:
- Overview: Hero tiles surface subscription, domain verification, and recommended next actions; recent app launches and tasks sit below the fold.
- Apps tab: Filter/search catalog by status, tags, and owner; saved views persist per user.
- Billing tab: Manage Stripe subscription and invoices.
- Members tab: Invite teammates, adjust roles.
- Integrations tab: Review connection health, open detail drawers, and rerun verification.
- Analytics tab: Activity, Revenue, and Reliability panels with callouts when data sources are missing.
- Settings tab: Manage Doppler references, secrets, and workspace preferences.
The global navigation bar now supports keyboard shortcuts (/ to focus search, g + [o|a|b|m|i|n] for quick nav). A persistent feedback button writes to feedback_entries with organization context.
All data fetches go through the Supabase-aware data layer (apps/dashboard/src/lib/data).
6. Session Propagation to Generated Apps
Customer apps rely on Supabase Auth as well, but with isolated contexts:
- Generated app uses the same Supabase project (shared) unless configured for dedicated.
app_userstable + prefixed tables capture end-user data.- RLS policies enforce
{app_id}scoping.
During generation, Forge CLI writes:
NEXT_PUBLIC_SUPABASE_URL=<shared-or-dedicated-url>
NEXT_PUBLIC_SUPABASE_ANON_KEY=<app-specific-key>
SUPABASE_SERVICE_ROLE_KEY=<app-specific-service-key>
APP_ID=<uuid from Supabase apps table>
TABLE_PREFIX=<slug_>
Generated apps include middleware to set the current app context before querying Supabase:
export const getAppSupabase = () =>
createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{ global: { headers: { 'x-app-id': process.env.APP_ID! } } }
);
7. Linking Dashboard Actions to Apps
- Creating an app via dashboard inserts into Supabase then enqueues a Forge CLI job (or instructs operator to run it).
- Domain verification status is surfaced to the customer with retry/refresh buttons that call Supabase RPCs.
- Audit logs live in
audit_logstable and capture who did what (organization context).
8. Troubleshooting
| Symptom | Fix |
|---|---|
| Redirect loop after login | Verify NEXT_PUBLIC_DASHBOARD_URL and Supabase redirect URLs. |
| Users stuck on onboarding despite org membership | Check organization_members table; ensure RLS policy includes new roles. |
| Generated app cannot authenticate | Confirm Doppler secrets were synced; anon key/service role must match the intended Supabase project. |
| Domain verification spinner never completes | See docs/MULTI_APP_CONFIGURATION.md for DNS verification steps; ensure CNAME points to apps.infiniteapps.ai. |
Keep this flow document updated whenever auth providers change, onboarding collects new data, or session handling is modified.