landing.mdlegal-cookies.mdlegal-privacy.mdwelcome-download.mdwelcome.mdonboarding.mdhome.mdtara.mdJourney flow#
Generated from the authored steps below — click a node to jump to that section.
The end-to-end path from an unknown browser hitting the domain through completed onboarding and a first landing on Home. Catches public-surface gating, OpenGraph crawler exposure, sign-up funnel telemetry, the magic-link / email verification round-trip, and the onboarding handoff into the signed-in shell — bugs that look fine in any single per-view file but stack into broken funnels.
Personas#
- Marketing-campaign click-through — primary; lands on
/welcomeor/landingfrom a paid ad - Editorial reader — lands on
/landing, reads the manuscript lede before starting sign-up - Crawler / link-preview bot — verifies OpenGraph and Twitter card metadata resolve before any human visits
- Direct-URL signed-in route attempt — anonymous user pastes
/taraor/library; middleware must redirect with?redirect=preserved
Pre-conditions#
- Browser has never visited
oshun.app; no cookies, no service worker, no IndexedDB - Network is online
- A fresh, deliverable inbox is available for the magic-link / verification email
- BFF and outbound mail (Mailpit in dev) are healthy
PUBLIC_PATHSandPUBLIC_PREFIXESinproxy.tsmatch the deployed build. Note: the implementation lives only inapps/oshun/web/src/proxy.ts— there is nomiddleware.ts. Next 16 picks up the exportedproxyfunction via theconfigmatcher natively.
Steps#
1. Crawler / link-preview pre-flight#
- Issue a
GET /with aUser-Agent: facebookexternalhit/1.1and verify it resolves to public HTML at/or the anonymous/welcomebounce - Issue a
GET /welcomeand inspect<head>for OpenGraph + Twitter card tags pointing at/welcome/opengraph-imageand/welcome/twitter-image - Issue
GET /opengraph-image,GET /twitter-image,GET /welcome/opengraph-image, andGET /welcome/twitter-image; confirm 200 + PNG content-type - Confirm
metadataBaseishttps://oshun.appso canonical URLs in<link rel="canonical">resolve absolute;/welcomeemitshttps://oshun.app/welcome - Confirm JSON-LD
WebApplicationincludes a freeOfferand afeatureListmentioning all six domains (tara, arete, veritas, nyx, nisaba, metis) - Verify:
shell/01-app-shell.mdMetadata and SEO section - Verify:
customer/00-public/welcome.mdOpenGraph route handlers
2. Cold visit — anonymous user lands on /#
- Browser navigates to the root URL
- Middleware sees no session cookie and redirects to
/welcome?redirect=%2F - Cookie consent banner mounts at bottom of viewport until accept/reject
- Service-worker support is present and
/sw.jsresolves with a JavaScript content-type; manifest and install assets are verified by the PWA smoke suite - Theme color is emitted in metadata; root layout defines cream
#f1ebdd(light) and#241c12(dark) - Cormorant Garamond, Inter, and JetBrains Mono are loaded through
next/fontwithdisplay: 'swap' -
<html lang="en" dir="ltr">is emitted by the root layout - Verify:
shell/02-routing-layouts.mdMiddleware → Public path allowlist
3. Anonymous attempt at a gated route preserves the deep link#
Before signing up, the user pastes a deep link to a signed-in route to test gating.
- Browser navigates to a protected route such as
/profile - Middleware redirects to
/welcome?redirect=%2Fprofile -
WelcomePageViewreads theredirectquery via the page server component;WelcomeAuthPanelcarries the redirect throughbuildPublicAuthEntryPath - Domain launch CTAs preserve encoded deep links such as
/domains/nisaba?origin=home -
?expired=1and?reauth=1variants force sign-in mode; the redirect param is sanitized bysanitizeRedirectPath - Verify:
shell/04-auth-session.mdSession expired / Sign-in flow / Sign-in success
4. Editorial / marketing route browse (optional branch)#
- Navigate to
/landingdirectly -
MarketingLandingrenders the OSHUN masthead, product preview strip, three-column manuscript lede, six room inventory, three static launch scenarios, and three-tier membership row - Pricing tier CTAs link to
/welcome?mode=signupwithentry=marketing-landingand exacttier=Solo|Hearth|Institutionalquery params - The Hearth tier CTA records
public_auth_funnel_cta_clickedwithstep=marketing_tier_signup - The text-only marketing footer renders without descendant legal anchors
- A warmed
/landingdocument replays from the real service worker while offline; standalone 390 px launch has no horizontal overflow and keeps conversion targets at least 44 px - Cookie consent banner persists across
/landing→/welcomenavigation - Verify:
customer/00-public/landing.mdPricing tier CTAs
5. Accept (or reject) cookie consent#
- Click "Accept" on the
CookieConsentBanner - The banner persists a versioned localStorage preference with essential, analytics, functional, and marketing all allowed, then dismisses. It does not itself create analytics cookies; downstream code must consult the stored permission before optional processing.
- Reload — banner does not reappear
- Reject branch persists essential-only permission with analytics, functional, and marketing false; the banner dismisses.
-
PwaUpdatePromptis suppressed only while consent is unresolved; accept or reject both resolve consent, so prompts become eligible after either decision - Verify:
shell/04-auth-session.mdCookie consent gate
6. Choose sign-up from /welcome#
- Default mode resolves to
signup(no?mode=query) -
WelcomeAuthPanelshows the Sign up / Sign in / Recover tab list - Switching tabs reflects in URL state; Left/Right arrows navigate the tablist
- Enter name / email / password
- Public CTAs fire
trackPublicAuthFunnelCtaClicked({ entrySource, mode }); form submission and completion firepublic_auth_funnel_submittedandpublic_auth_funnel_completed -
WelcomeAuthPanelcallsuseAuth().signUp, which posts to/api/auth/signup; the Next route forwards to BFF/v1/auth/signup, creates the session cookies, sends the verification email, and routes the signed-in browser to/onboarding - Verify:
customer/00-public/welcome.mdWelcomeAuthPanel mode tabs + submit
7. Email verification round-trip#
- Mailpit receives the verification email with subject
Verify your Oshun email address; the delivered link preserves?next=/tara(or the original redirect) - Click the actual verification link from the delivered email
- BFF marks the account verified; the signup browser already has HttpOnly
oshun-sessionandoshun-accesscookies, and a fresh browser opening the link receives fresh HttpOnlyoshun-sessionandoshun-accesscookies for that device - The verify-email page refreshes
/api/auth/sessionand readsverified: true - User is bounced to
/onboarding?redirect=/tara(not the original?next=surface yet — the shell intercepts unfinished onboarding first) - Verify:
shell/04-auth-session.mdSign-up flow
8. Onboarding wizard — 10 steps#
OnboardingWizard is the only thing /onboarding/page.tsx renders.
- Welcome step — "Begin" CTA primary
- Goals — multi-select goal cards (
OnboardingGoalId) - Domains — six domain tiles (
OshunDomainId) matchgetShellNavigationDomains() - Interests — multi-select interest chips, each with a recommended-domains hint
- Rhythm (Routine) — daypart timing picker (
OnboardingRoutineTimingId) - Guide — assistant persona, teacher tone, content tone preferences
- Alerts (Notifications) —
OnboardingNotificationPreferenceschannels - Access (Accessibility) —
OnboardingAccessibilityNeedstoggles - Memory —
OnboardingMemoryPreferencesscope choices - Ready (Complete) — final "Finish" submit calls
patchProfilePreferences(patch)and writes the localoshunWebPreferencesStore - Back / Continue / Finish keyboard focus order is sane; Back disabled on first step
- Step deep link
?step=memorymounts directly at that step - Verify:
customer/01-onboarding/onboarding.mdstep-by-step interactions
9. Onboarding completion handoff#
- After Finish, the wizard navigates to the sanitised
redirectPathif set (e.g./tarafrom step 3) — otherwise toresolveFirstRunEntryTarget(entrySource) - No
?next=leak in the URL after handoff - Verify:
customer/01-onboarding/onboarding.mdCompletion handoff
10. First landing on signed-in surface#
- If redirect was
/profile,ProfileDashboardrenders after onboarding completion - If redirect was a public domain launch, the requested domain surface
renders; the covered Nisaba branch lands at
/domains/nisaba?origin=home - If redirect was absent or
/,resolveFirstRunEntryTarget(entrySource)chooses the deliberate first-run domain instead of dropping context - If redirect was
/tara, the Tara journey coverage takes over and verifies today's sit, course, and teachers - If Home is the final target,
HomeWorkspacerenders Tara ritual continuation, Arete practice, Nyx perspective, Metis study continuation, Daypart rail, Domain card grid, Quick actions, Activity feed -
OnboardingResumeBanneris hidden (onboarding now complete) - Shell header shows the five primary tabs with
aria-current="page"on the active one - Mobile bottom nav appears on coarse pointer + viewport <= 640 px
- Verify:
customer/02-home-discovery/home.mdReturning user, full data - Verify:
customer/03-tara/tara.mdToday's sit card
11. Telemetry funnel trail#
-
WelcomePageView,PublicAuthFunnelLink,MarketingAuthCta, andWelcomeAuthPanelemit the verified public-auth events: viewed, CTA clicked, submitted, completed, and failed. - The consent decision is durably represented by the versioned
oshun-cookie-consentpreference record. - Emit and verify a dedicated consent analytics event. No
cookie_consent_accepted/cookie_consent_rejectedsymbol exists in the current source. - Wire the exported onboarding step/completion telemetry helpers into
OnboardingWizard; exporting them fromtaraAnalytics.tsis not proof of emission. - Emit a service-worker registration event. The current PWA telemetry covers
sync queued and update applied, not
pwa_sw_registered. - Define and emit the first signed-in landing event. Neither
home_dashboard_loadednortara_hub_viewedexists in the current web source.
Post-conditions#
- User has a valid session cookie scoped to the host
- Onboarding is complete;
oshunWebPreferencesStorereflects the user's choices - The auth proxy admits signed-in routes and preserves safe redirect targets. Entitlement checks remain owned by downstream route/surface gates; the proxy does not validate every product tier globally.
- Cookie consent decision persisted
- Service worker registered with
oshun-static-v<N>precaching the public shell - No leaked
?redirect=or?next=query params in the address bar after handoff
Failure modes to verify#
- Magic-link email never arrives —
/welcomeexposes recover-mode affordances so the user can request access recovery; recovery request and confirm hit the real BFF routes - User clicks verification link on a different device than they signed up from — verification succeeds; new device gets a fresh session; original device can return manually and refresh session state
- Onboarding abandoned mid-wizard — return to
/later; the homeOnboardingResumeBanner"Continue onboarding" CTA links into/onboarding?mode=resumeat the last incomplete step - Crawler hits
/welcomewith noAccept-Encodingfor images —/welcome/opengraph-imageroute handler still responds with a usable static image - Cookie-consent unresolved — analytics CTAs still fire local events but
no remote tracking pixels load;
PwaInstallPromptandPwaUpdatePromptstay suppressed only while consent is undecided (PwaBootstrap.tsx:242gates oncookieConsent !== null). Deciding — accept OR reject — makes the prompts eligible; reject resolves consent rather than suppressing them. - Signed-in user pastes
/welcomeURL — current behavior is intentional public-route rendering: middleware does not bounce signed-in users away from/welcome; the page renders[data-auth-entry-signed-in]with the continuation action.
E2E coverage#
- Backed by
apps/oshun/web/e2e/auth-entry-flows.spec.ts,apps/oshun/web/e2e/welcome-marketing.spec.ts,apps/oshun/web/e2e/pwa-smoke.spec.ts, andapps/oshun/web/e2e/cookie-consent-compliance.spec.ts— together these exercise the redirect-to-welcome gate, sign-up and onboarding completion, OpenGraph/Twitter metadata, install prompt basics, and cookie-consent accept/reject storage. - Backed by
apps/oshun/web/e2e/first-time-visitor-deepening.spec.ts— drives the step-1 crawler-facing JSON-LDfeatureList(asserts it lists all six domains under afacebookexternalhitUA), the steps 3–4 expired-session re-entry (/welcome?redirect=%2Ftara&expired=1opens with the signin tab selected plus the session-expired banner and re-entry guide), the/landingprimary CTA carryingentry=marketing-landingthrough to/welcome, and the failure mode where a signed-in user visiting/welcomestays on/welcomeand sees the continuation panel rather than being redirected. - Backed by
apps/oshun/web/e2e/public-marketing.spec.ts— drives the dedicated/landingbranch: fixture-backed six-room inventory, static letter scenarios, all three tier CTA href contracts, Hearth tier-click telemetry, text-only footer boundary, 390 px standalone no-overflow and 44 px CTA targets, realsw.jswarm-cache offline replay, social metadata/PNG previews, and sitemap exposure. - Backed by
apps/oshun/web/e2e/first-time-deepening-2.spec.ts— drives the?reauth=1sign-in re-entry variant plus reauth-specific banner and asserts the crawler JSON-LD shape is a schema.orgWebApplicationwith a freeOffer. - Backed by
apps/oshun/web/e2e/email-verify-mailpit.spec.ts— drives the real dev-infra email leg for step 7:/welcomesignup creates the browser's HttpOnlyoshun-sessionandoshun-accesscookies, the BFF sends the verification email over SMTP to Mailpit (:1025), the spec polls Mailpit's API (:8025) by the unique recipient address, opens the actual delivered/auth/verify-email?token=...&next=/taralink, confirms the public BFF token through the verify-email page, auto-hands the already signed-in browser back to/onboarding?redirect=/tarawithout clicking Continue, refreshes/api/auth/session, and asserts the account is nowverified: true. It also opens the same delivered Mailpit link in a fresh browser context with no pre-existing auth cookies and proves the verify-email proxy sets fresh HttpOnlyoshun-sessionandoshun-accesscookies for that device before landing in/onboarding?redirect=/tara. The signup handoff to/onboardingis also asserted before the email link is opened. - Backed by
apps/oshun/web/e2e/email-verify-roundtrip.spec.ts— drives the verify-email page-level states and failure modes, including a fresh token success, replayed-token error, no-token missing state, delayed verifying state, already-verified copy, safenext=/taraContinue handoff, unsafe externalnextfallback to/, and a 44x44 px Continue target at a 390 px viewport. - Backed by
apps/oshun/web/e2e/onboarding-lifecycle.spec.ts— drives the abandonment failure mode: real signup against the dev BFF, leaving a draft at Rhythm, HomeOnboardingResumeBannerreturn to/onboarding?mode=resume, and returning sign-in resuming withredirect=/profilepreserved. - Backed by
apps/oshun/web/e2e/public-legal-pages.spec.ts— drives the public legal branch reached from footer/cookie-consent links: anonymous access for/legal/privacy,/legal/terms,/legal/cookies,/legal/accessibility,/legal/ccpa,/legal/dpa,/legal/lilith, and/legal/lilith/privacy; exact section inventories; cross-legal nav; TOC/back-to-top/print shell controls; 390 px no-overflow and 44 px targets; offline-after-load stability; no telemetry hooks; axe; and the Lilith non-clickable footer markers. - Coverage depth: deep — see
coverage.md. - Remaining delegation: shell chrome, full Home dashboard detail, and the Tara daily-sit content are verified in their own shell/home/Tara walkthroughs and specs; this journey verifies the first-time handoff into those surfaces.
Per-view files touched by this journey#
customer/00-public/landing.md— editorial entry / pricing CTAscustomer/00-public/welcome.md— auth-coupled marketing +WelcomeAuthPanelcustomer/00-public/welcome-download.md— install / PWA install branch for users who choose download instead of sign-upcustomer/00-public/legal-privacy.md— policy linked from cookie consent; covered bypublic-legal-pagescustomer/00-public/legal-cookies.md— cookie consent detail; covered bypublic-legal-pagescustomer/01-onboarding/onboarding.md— the 10-step wizardcustomer/02-home-discovery/home.md— first signed-in landingcustomer/03-tara/tara.md— Tara as the most common signup redirect target
Cross-references#
- Feature spec:
V1/features.md - Architecture:
V1/ARCHITECTURE.md - Related journeys:
install-as-pwa.md— the install branch follows once the user is signed infirst-tara-sit.md— the most common next journey
- Shell docs:
- Component sources:
apps/oshun/web/src/proxy.tsapps/oshun/web/src/app/welcome/page.tsxapps/oshun/web/src/components/welcome/WelcomePageView.tsxapps/oshun/web/src/components/welcome/WelcomeAuthPanel.tsxapps/oshun/web/src/components/onboarding/OnboardingWizard.tsxapps/oshun/web/src/lib/onboarding-routing.tsapps/oshun/web/src/profile/preferences-sync.tsapps/oshun/web/src/components/CookieConsentBanner.tsx
Open questions / known gaps#
- Anonymous gate lives in
proxy.ts—proxy.tsholds the full anonymous-gate logic (PUBLIC_PATHS, redirect-to-welcome, expiry, studio boundary) and exportsproxy+ aconfigmatcher, which Next 16 picks up natively (there is nomiddleware.ts). Covered bysrc/__tests__/middleware-public-paths.test.ts. - OpenGraph / Twitter image routes were crashing in
@vercel/ogdue tovar(--l-*)CSS variables insidesocial-preview.tsx. Satori has no CSS context, so it choked withTypeError: Cannot read properties of null (reading '1'). Replaced with literal hex/rgba constants (kept in sync with the cream variant indesign-system/lilith/lilith.css). - WelcomeAuthPanel auth endpoints — the panel calls
useAuth();signUpposts/api/auth/signup-> BFF/v1/auth/signup,signInposts/api/auth/login-> BFF/v1/auth/login,requestRecoveryposts/api/auth/recovery/request-> BFF/v1/auth/recovery/request, andrecoverAccountposts/api/auth/recovery/confirm-> BFF/v1/auth/recovery/confirm. - Signed-in
/welcomebehavior —proxy.tskeeps/welcomepublic; signed-in users stay on/welcomeand see[data-auth-entry-signed-in], covered byfirst-time-visitor-deepening. - Onboarding save semantics — per-step drafts persist to
oshun.onboarding; final submit writes the local preference store and syncs via/v1/preferences, covered byonboarding-lifecycleandonboarding-deepening. - Cookie rejection and PWA prompts — reject resolves consent; update
prompts are suppressed only while consent is unresolved, covered by
pwa-install-update-offline. - Mailpit verification subject/copy — Mailpit specs assert subject
Verify your Oshun email addressfor the unique recipient and extract the delivered/auth/verify-email?token=...link from the message body. - Connect the onboarding and first-landing telemetry declared in the feature contract to their real UI actions, then add browser assertions for the emitted payloads.