Wellness Hub v8: flow
Entry: prototypes/wellness-hub/v8/index.html (built single-file React app, vanilla output, no build step to run it).
Demo sign-in: seeker@123.com (Seeker) or practitioner@123.com (Practitioner), then the demo code 314159 (pre-filled).
Any other email works too; an email containing the word "practitioner" signs in as a Practitioner.
Routing strategy
- Hash routes. The server has no catch-all, so every view is
index.html#/.... The hash never reaches the server. - The URL is the source of truth. The app route is parsed from
location.hashon first load and on everypopstate/hashchange; clicking a link pushes the hash and re-renders from it. Nothing depends on an earlier screen having set in-memory state. - History. New view, tab, wizard step, detail view or modal = push. Filters, sort, search text = replace (search text is debounced 250 ms). Redirects (signed-out deep link to sign-in, invalid tab to default, already-signed-in visit to sign-in) = replace. Closing a modal or going "Back" in a wizard when the last history entry opened it = history Back, so Forward replays it.
- Real links. Navigation controls render as
<a href="#/...">(right-click copy link, open in new tab, middle click all work). Plain clicks navigate in place; modified clicks use the browser. - Per navigation:
document.titlenames the view; focus moves to the view's<h1>(or<main id="main">); scroll resets to top on a new view and is restored on Back/Forward (position stored inhistory.state); the active nav item hasaria-current="page". - Session. Demo session lives in
sessionStoragekeyvibe.v8.session(never in the URL); a profile created in the practitioner setup flow is kept invibe.v8.profile. Sign out clears both. - Protected / role views. Hub URLs need a session. Signed out: replace with
#/sign-in?next=<requested path>; after sign-in the app returns tonext(by replace). Signed in with the other role: a "This page is for X accounts" view with links to your own hub or Sign out.#/practitioners/meis the signed-in practitioner's own profile. - Not found: unknown routes show a "Page not found" view (title,
<h1>, links home). Unknown tab names fall back to a safe default. - Disclaimer gate. The first time the Discover, modality, practitioner, event or Let's AI views are opened, a one-time "Let's AI is wellness guidance, not treatment" dialog must be acknowledged (stored in
localStoragekeyvibe.disclaimer.v1). It is a consent gate, not a route; it does not close on Esc.
Route table
URL path (after #) |
Screen | State read from the URL | Exit links |
|---|---|---|---|
/ |
Home (hero, Let's AI band, modalities, practitioners, events, practitioner invitation band) | none | all nav, cards, footer |
/ai |
Let's AI chat (logged out) | ask = opening question (optional) |
nav, footer |
/search/modalities /search/practitioners /search/events |
Discover tabs | q; practitioners: location, delivery; events: type, event-location, event-delivery |
cards, tabs |
/modalities/<slug> |
Modality detail (e.g. breathwork) |
tab = overview (default), expect, history; show = practitioners (default) or events; location, delivery, type, event-location, event-delivery |
back to search, practitioner and event cards |
/practitioners/<slug> |
Practitioner profile (e.g. maya-soluz) |
details = credentials (default) or education; panel = events (default) or book; about=1 bio dialog; contact=1 contact face |
search, event, modality links |
/practitioners/me |
Your own profile (Practitioner only) | section = vibes (default) or invitations; invite=1 invite dialog; create-event=1 |
setup (Edit profile) |
/events/<id> |
Event detail (e.g. fullmoon-cacao) |
tab = overview (default), location, attendees, conversations, posts (the last four only after RSVP; otherwise overview); guests = going (default), interested, notgoing |
host, modality, search |
/legal/privacy /legal/terms |
Legal text | none | home |
/sign-in |
Email then code | next = path to return to; step=code |
home |
/join/seeker |
Seeker account wizard, 7 steps | intent = why you are joining (text); step = account, verify, photo, intro, areas, connect, review (a cold load restarts at account because the earlier answers live only in memory) |
sign-in, home |
/join/practitioner/invite |
Request a practitioner invitation (form) | none | home |
/join/practitioner/setup |
Practitioner profile wizard, 3 steps, then welcome dialog | step = about, services, review (restarts at about on a cold load); welcome=1 while the welcome dialog is open |
new profile /practitioners/<username> |
/seeker/<section> and /practitioner/<section> |
Hub (same screens for both roles) | sections: today, ai, feed, journal, practitioners, events, communities, conversations, wallet |
event, practitioner, search |
/<role>/communities/<id> |
Community detail (e.g. c1) |
tab = feed (default), conversation, events, members, about |
communities |
/<role>/conversations/<id> and /<role>/conversations/new |
Thread / new conversation picker | none | conversations |
/<role>/wallet |
Wallet | filter = all (default), benefit, personal |
search |
/<role>/events |
Your events | create-event=1 create-event dialog |
event detail |
| (anything else) | Page not found | none | home, search |
A route for the wrong role (for example #/practitioner/today while signed in as a Seeker) renders the "different account type" view, keeping the URL.
Prose flow
Signed out, people land on Home, search Modalities, Practitioners and Events, open a detail view, and ask Let's AI. RSVP, Follow or Sign in sends them to the Seeker sign-up wizard or to sign-in. After signing in as a Seeker they land on #/seeker/today (or the next route): declare today's vibration, read the feed, journal, message practitioners, join communities and manage a wallet. A Practitioner signs in with the other demo account and sees the same hub, plus "View My Profile" (#/practitioners/me) with Invitations and Create an Event. People invited to the network request an invitation or run the practitioner setup wizard, which ends on their new public profile.
Ready-to-paste deep links
Append to /prototypes/wellness-hub/v8/. Seeker and Practitioner links need a session first (sign in once in that tab); signed out they redirect to sign-in and return.
- Public:
#/,#/search/practitioners?q=reiki,#/search/events?type=Ceremony,#/modalities/breathwork?tab=expect,#/practitioners/maya-soluz?about=1,#/events/fullmoon-cacao,#/ai?ask=Help%20me%20sleep%20better,#/legal/privacy - Sign-up:
#/join/seeker,#/join/practitioner/invite,#/join/practitioner/setup - Seeker:
#/seeker/today,#/seeker/feed,#/seeker/journal,#/seeker/communities/c1?tab=members,#/seeker/conversations/new,#/seeker/wallet?filter=benefit,#/sign-in?next=%2Fseeker%2Fwallet - Practitioner:
#/practitioner/today,#/practitioner/events?create-event=1,#/practitioners/me?section=invitations,#/sign-in?next=%2Fpractitioner%2Ftoday - Errors:
#/nope(not found),#/seeker/todaywhile signed in as Practitioner (wrong role)
Faked versus real
| Thing | Status |
|---|---|
| People, practitioners, modalities, events, communities, conversations, wallet, benefit amounts, attendee lists | Fake sample data (inside the MOCK DATA BOUNDARY markers in the bundle) |
| Sign-in, verification code, account creation, practitioner invitations, RSVP, follow, message send, journal, vibration log, create-event | Fake: in memory only, reset on reload (the session survives reload in sessionStorage) |
| Let's AI chat | Tries a real api.anthropic.com request from the browser; without credentials it fails and the prototype shows its canned supportive reply. History is kept in localStorage (vibe.ai.history.v1). Wellness guidance only, never diagnosis |
| Photos | Unsplash photo ids over brand gradients; the gradient shows if the image is unavailable |
| Routing, history, deep links, focus, titles, session | Real (this version) |
Standards patch (how the compliance layer is organised)
Inside index.html: an STANDARDS PATCH router and app shell in the bundle (before the App component), a <style id="standards-patch"> block (tokens, focus, touch targets, reflow, dark mode, reduced motion) and a <script id="standards-patch-dom"> block (names, labels, states, heading levels, dialogs). See CHANGELOG.md.