Skip to content
Generated from docs/architecture/stories.json

User stories

Every user story mapped to the tables, procedures and routes that implement it — checked against the code on every build.

Summary

180 stories · mapped 2026-10-12

Sources (8)
  • linear:WeDance (208 issues -> 151 stories; RAZ-59 merged into RAZ-23 and RAZ-205 into RAZ-110 (same story text); 53 bugs/chores/QA/follow-ups folded into notes or skipped; 2 Canceled skipped)
  • linear:no project (4 WeDance-app issues used as stories: RAZ-241, RAZ-251, RAZ-253, RAZ-272; other user-reports referenced in notes; template/other-repo issues ignored)
  • docs/issues (216 files; all 132 P/G promise files map 1:1 to Linear issues, RAZ-/WED- files are Linear archives — 0 new stories)
  • map:wedance-org 01_Domains/Festival_Experience/Product/meetup-planner/backlog.md + story-map.md (36 stories -> 24 entries; 12 merged into Linear entries or sibling map entries)
  • map:wedance-org 01_Domains/Festival_Experience/Product/festival-schedule/user-journey.md (1 entry; radar, check-in, rating, stats, loyalty merged into meetup entries)
  • map:wedance-org 01_Domains/Festival_Experience/Operations/Stories/*.yml (10 files; all merged into meetup-planner entries)
  • e2e/features/*.feature (3 files; merged into map:meetup-2.1-sign-up, RAZ-241, RAZ-136)
  • code: app/pages, server/trpc/routers (26 routers, 141 procedures), server/api, server/database/schema.ts (37 tables) at worktree HEAD

Stories

180 shown
RAZ-25builtC1beginner

Salsa Quick Pick

As a beginner, I want a quick pick for Salsa described in plain words, so that I can tell at a glance whether it suits me.

Procedures
—
Tables
—
Routes
/find-your-dance/cities/cities/[city]

Evidence: app/pages/find-your-dance.vue:138; app/pages/cities/[city]/index.vue:229

Linear state: Done. Quick pick links to /cities?style=Salsa; the city page preselects the style filter. City content comes from /api/cities/[slug] + events, not a style-specific catalogue.

RAZ-26builtC1beginner

Bachata Quick Pick

As a beginner, I want a quick pick for Bachata described in plain words, so that I can tell at a glance whether it suits me.

Procedures
—
Tables
—
Routes
/find-your-dance/cities

Evidence: app/pages/find-your-dance.vue:139

Linear state: In Review. Same mechanism as RAZ-25.

RAZ-27builtC1beginner

Kizomba Quick Pick

As a beginner, I want a quick pick for Kizomba described in plain words, so that I can tell at a glance whether it suits me.

Procedures
—
Tables
—
Routes
/find-your-dance/cities

Evidence: app/pages/find-your-dance.vue:140

Linear state: In Review. Same mechanism as RAZ-25.

RAZ-28builtC1beginner

Free Taster Class

As a beginner, I want to just try a free taster class, so that I can experience a dance in person before committing to a style.

Routes
/find-your-dance/cities/cities/[city]

Evidence: app/pages/find-your-dance.vue:288; app/pages/cities/[city]/index.vue:362

Linear state: Done. "Taster" is derived client-side (shared/utils/taster isTasterCandidate/isFreePrice) from synced events; there is no taster flag in the data model.

RAZ-30builtC1beginner

Free Tasters

As a Seeker, I want to try free taster classes and choose a dance by how it feels, so that I can pick a style I love instead of guessing from a name.

Procedures
—
Tables
—
Routes
//find-your-dance

Evidence: app/pages/index.vue:36

Linear state: Done. Home journey stage 1 links to /find-your-dance (quiz is live, no longer "coming soon").

RAZ-44builtC1beginner

Where To Start

As a beginner, I want reassurance and a starting point when I don't know which dance is for me, so that I feel welcome instead of overwhelmed.

Procedures
—
Tables
—
Routes
/find-your-dance

Evidence: app/pages/find-your-dance.vue:151

Linear state: Done.

RAZ-46builtC1beginner

Dance-Match Quiz

As a beginner, I want a short quiz that matches me to a dance by how it feels, so that I can pick a style without knowing any dance terms.

Procedures
—
Tables
—
Routes
/find-your-dance

Evidence: app/pages/find-your-dance.vue:160

Linear state: Done. Linear label status:not-built is stale: a client-side feeling-based quiz with a result + "find classes" link exists. No quiz answers are stored.

RAZ-50builtC2dancer

Floor Movers

As a dancer, I want to discover the artists who move the floor, so that I can find teachers, DJs, and performers I want to follow.

Routes
/artists/@[handle]

Evidence: app/pages/artists/index.vue:36

Linear state: Done.

RAZ-55builtC2dancer

Follow Artists

As a dancer, I want to follow teachers, DJs, and performers, so that I can keep track of them across festivals and cities.

Routes
/artists/@[handle]

Evidence: app/pages/@[handle].vue:78; server/database/schema.ts:705

Linear state: Done. Follow targets profiles(type=artist). "Track across festivals" relies on events.byProfile matching the artist name/handle in events.artists; festival lineups (app/data mock teachers) are not linked to profiles.

RAZ-58builtC2dancer

Artist Search

As a dancer, I want to search artists by name or style, so that I can quickly find the ones I'm looking for.

Tables
profiles
Routes
/artists

Evidence: app/pages/artists/index.vue:49

Linear state: Done.

RAZ-64builtC2dancer

Artists by City

As a dancer, I want to filter the artists directory by my city, so that I can find teachers and performers who are actually near me.

Tables
profiles
Routes
/artists

Evidence: app/pages/artists/index.vue:67

Linear state: Done. City filter compares free-text profiles.city strings, not cities.id.

RAZ-66builtC2student

Find Your Teacher

As a Student, I want to browse real teacher profiles showing their styles, languages and schools, so that I can choose a teacher who fits how I want to learn.

Tables
profiles
Routes
//artists/@[handle]

Evidence: app/pages/index.vue:45

Linear state: Done. profiles has styles + languages; there is no "school" field, so the "schools" part of the promise has no data behind it. A second artist model exists in app/data/artists.ts (used by /artists/[id] and festival lineups).

RAZ-303missingC2organiser

Artist profiles: one consistent layout, artist type, filterable properties

As an organiser or dancer, I want artist profiles to share one layout and say what kind of artist they are (dancer, DJ, …) with filterable properties, so that I can understand at a glance why to choose this artist and find artists by type.

Tables
profiles
Routes
/@[handle]/artists

Evidence: server/database/schema.ts:307

Linear state: Triage. Journey inferred (no cuj label). profiles.type only distinguishes venue/artist/organizer; there is no artist sub-type or service column. /artists/[id] (static app/data/artists.ts) and /@[handle] (DB profiles) are two different artist page implementations.

RAZ-45builtC3dancer

City Community

As a dancer, I want to find the venues, artists, and organizers in my city, so that I can connect with my local Cuban dance community.

Tables
profiles
Routes
/cities/cities/[city]/cities/[city]/venues/cities/[city]/organisers/cities/[city]/artists

Evidence: server/api/cities.get.ts:23; app/pages/cities/[city]/venues.vue:7

Linear state: Done. Directory data comes from Nitro routes server/api/cities.get.ts and server/api/cities/[slug].get.ts (not tRPC).

RAZ-47builtC3dancer

Real Numbers

As a dancer, I want to see how many people are in each city's community, so that I can gauge how active a scene is.

Procedures
—
Tables
profiles
Routes
/cities

Evidence: server/api/cities.get.ts:34

Linear state: Done. "Community size" = count of venue+artist+organizer profiles per citySlug, not people/dancers.

RAZ-139builtC3dancer

Every City

As a dancer, I want to browse dance scenes across every city, so that I can explore communities wherever I am.

Procedures
—
Tables
profiles
Routes
/cities/cities/[city]

Evidence: app/pages/cities/index.vue:92

Linear state: Done.

RAZ-162builtC3dancer

One Events Feed

As a regular, I want one city events feed that merges booked venue events with the weekly socials, so that I see everything happening without duplicate sections.

Routes
/cities/[city]/events/[id]

Evidence: app/pages/cities/[city]/index.vue:83; app/pages/cities/[city]/index.vue:84

Linear state: Done. Follow-ups RAZ-223 (beyond-this-week bookings) and RAZ-224 (link to venue) are Done. The feed merges two event sources at read time: booking_requests ("a booking IS a scheduled event") and events (v3-synced).

RAZ-168builtC3dancer

City this-week relevance filter + directory tabs

As a regular, I want a city's venues/organisers/artists to surface who's active this week first, so the city page reflects the living local floor instead of a static roster.

Procedures
—
Routes
/cities/[city]

Evidence: app/pages/cities/[city]/index.vue:542

Linear state: Done.

RAZ-169builtC3dancer

SEO city directory pages (venues / organisers / artists)

As a dancer searching Google, I want dedicated, SEO-friendly directory pages for a city's venues/organisers/artists, so the local scene is discoverable and indexable outside the app shell.

Procedures
—
Tables
profiles
Routes
/cities/[city]/venues/cities/[city]/organisers/cities/[city]/artists

Evidence: server/api/cities/[slug].get.ts:30; app/pages/cities/[city]/artists.vue:7

Linear state: Done.

RAZ-251builtC3dancer

Real upcoming events mirrored from wedance.vip

As a dancer, I want the city pages to show the real upcoming events already listed on wedance.vip, so that the calendar is not empty.

Tables
events
Routes
/cities/[city]/events/[id]

Evidence: scripts/sync-v3-events.ts:1; server/database/schema.ts:624

Linear state: Done. No Linear project (PR tracking issue, chore that reveals a capability); journey inferred. Daily sync; events rows carry source=wedance-v3.

RAZ-253builtC3dancer

Venue/organiser/artist profiles synced from wedance.vip

As a dancer, I want the venues, organisers and artists behind synced events to have profiles linked from those events, so that I can explore who runs the scene.

Routes
/@[handle]/cities/[city]/venues

Evidence: server/utils/v3ProfileSync.ts:1

Linear state: Done. No Linear project (PR tracking issue); journey inferred. Events link to profiles by username text (events.venue_username/organizer_username), not FK. Follow-up RAZ-254 Done.

RAZ-23builtC4traveler

Ticketing referral discounts

As a traveling dancer viewing a friend's year, I want to buy a festival ticket through their link, so that we both get a discount.

Routes
/my-year/festivals/[slug] ✕

Evidence: app/components/SharedYearPlan.vue:216; server/trpc/routers/festivalSignup.ts:281; server/api/stripe/webhook.lib.ts:5

Linear state: Todo. Merged with RAZ-59 (Done, same story text, promise P319). Follow-ups RAZ-266 (webhook completes referral) and RAZ-267 (referrer credit) Done. Journey taken from RAZ-59 labels. Discount % per festival is hardcoded in server/utils/ticket-prices.ts. referral.myReferrals exists but no UI calls it. Drift: Linear Todo while code is built.

RAZ-29builtC4dancer

Auto-Fill Plan

As a dancer, I want to tell WeDance what I'm into and have my plan filled for me, so that I start with the right festivals, classes and socials instead of a blank page.

Routes
/onboarding/my-plan

Evidence: app/pages/my-plan.vue:276; app/pages/my-plan.vue:1727

Linear state: Done. Follow-up RAZ-231 Done. Festival auto-fill picks from the hardcoded my-plan catalogue by matching a style name inside the festival name (not festivals.styles); courses/socials prefer DB events with a mock fallback.

RAZ-32builtC4traveler

Festivals Mapped

As a Traveler, I want every festival mapped with the people who are going shown, so that I can plan trips around events where I'll know or meet other dancers.

Procedures
—
Routes
//festivals

Evidence: app/pages/index.vue:61; server/api/festivals.get.ts:12

Linear state: Done. "Mapped" = listed with city/country; there is no map view.

RAZ-48partialC4dancer

Be Their Partner

As a dancer viewing a friend's year, I want to offer to be their partner at a festival, so that we can attend together.

Procedures
plan.sharedPlan
Routes
/my-year

Evidence: app/components/SharedYearPlan.vue:228

Linear state: Backlog. Button exists but only emits open-festival; no partner offer is stored or delivered to the friend. No partner-request table.

RAZ-51builtC4dancer

Plan Your Year

As a dancer viewing someone else's year, I want to start planning my own, so that I can browse festivals, pick workshops, find partners, and share with friends.

Procedures
—
Tables
—
Routes
/my-year

Evidence: app/components/SharedYearPlan.vue:240

Linear state: Done.

RAZ-52builtC4traveler

Festival Overlap

As a traveling dancer viewing a friend's year, I want to see which festivals we both plan to attend, so that I know where we'll cross paths.

Routes
/my-year

Evidence: app/components/SharedYearPlan.vue:42

Linear state: In Review.

RAZ-56builtC4traveler

Next Festival

As a Traveler, I want a clear button in the hero that takes me to festivals, so that I can start discovering events to attend right away.

Procedures
—
Tables
—
Routes
//festivals

Evidence: app/pages/index.vue:171

Linear state: Done.

RAZ-62builtC4traveler

Who's Going

As a Traveler, I want to know I can see who is attending a festival before I buy, so that I feel confident I won't show up somewhere alone.

Procedures
plan.goingList
Routes
//festivals/festivals/[slug] ✕

Evidence: app/pages/index.vue:176

Linear state: Done. Linear label status:not-built is stale; attendee lists exist (GoingSection).

RAZ-67partialC4traveler

Plan Together

As a traveler, I want to coordinate the trip with other attendees, so that I can arrange dinners, share rides, and line up a first-night partner before I arrive.

Routes
/festivals/[slug] ✕

Evidence: app/pages/festivals/[slug].vue:587; app/pages/festivals/[slug].vue:518

Linear state: Backlog. Rides, dinners and waves are DB-backed; "first-night partner" has no dedicated flow (waves = mutual interest only). Extra activities are a hardcoded ref in the page. Linear Backlog but mostly built (reverse drift).

RAZ-70builtC4dancer

One Place

As a dancer, I want every festival I picked gathered in one place with a clear next action, so that I know what to do this week without hunting through pages.

Procedures
plan.myPlan
Routes
/my-plan

Evidence: app/pages/my-plan.vue:1764

Linear state: Done.

RAZ-75builtC4dancer

One Dashboard

As a dancer, I want my picks, partners and tickets on one dashboard, so that I can follow one next step at a time instead of juggling everything.

Procedures
—
Tables
—
Routes
/my-plan

Evidence: app/pages/my-plan.vue:1769

Linear state: Done. Signed-out preview copy. "My partners" content is driven by localStorage progress (partnerFound), not DB.

RAZ-80builtC4dancer

Do These First

As a dancer, I want the three most important things across my plan surfaced for this week, so that I always know what to do first.

Routes
/my-plan

Evidence: app/pages/my-plan.vue:1844

Linear state: Done. Priorities computed client-side from plan + localStorage track toggles.

RAZ-82partialC4traveler

Arrive With Friends

As a traveler, I want to already know a few people before I arrive at a festival, so that I can walk straight onto the floor instead of standing alone against the wall.

Routes
/festivals/[slug] ✕

Evidence: server/database/schema.ts:716; app/pages/festivals/[slug].vue:1185

Linear state: Backlog. Waves (mutual = festival friends) let you connect with opted-in attendees; no meet-up planning. Linear Backlog while partially built (reverse drift). MySpace still receives mockFriends/mockPartnerMatches from the page.

RAZ-88builtC4traveler

This Year's Festivals

As a traveler, I want to see the festivals I'm going to this year on My Plan, so that I have a clear picture of where I'm headed.

Procedures
plan.myPlan
Routes
/my-plan

Evidence: app/pages/my-plan.vue:2001

Linear state: Done.

RAZ-91builtC4dancer

Your Compass

As a dancer, I want to set dance goals on My Plan, so that I have a compass for where I'm headed.

Routes
/my-plan

Evidence: app/pages/my-plan.vue:1872; app/composables/useGoals.ts:16

Linear state: In Review. Goals are stored as plan_items rows with item_type='goal' (a goal is not a plannable item; overloaded table). RAZ-265/235/255 user reports on goals are Done.

RAZ-94builtC4traveler

Year At A Glance

As a traveler, I want a year-at-a-glance strip of chips on My Plan, so that I can jump straight to any part of my year.

Procedures
plan.myPlan
Routes
/my-plan

Evidence: app/pages/my-plan.vue:2053

Linear state: Done.

RAZ-97partialC4dancer

Pick Workshops

As a dancer, I want to pick workshops from a festival's schedule, so that I can plan which classes I'll attend.

Routes
/festivals/[slug] ✕/my-plan

Evidence: app/pages/festivals/[slug].vue:288; app/pages/my-plan.vue:466

Linear state: Done. Two stores for the same picks: the festival page writes plan_items(item_type=workshop), My Plan's workshop picker reads/writes localStorage. Workshops, teachers and ticket tiers exist only for the hardcoded festivals in app/data/mock-*.ts (plus server/utils/ticket-prices.ts); there is no workshops or tickets table, so DB-only festivals get no schedule. Follow-up RAZ-283 Done.

RAZ-99builtC4traveler

Ticket On Page

As a traveler, I want each festival track in my plan to point me to where I buy the ticket, so that I can complete my booking on the festival page.

Routes
/my-plan/festivals/[slug] ✕

Evidence: app/pages/my-plan.vue:693

Linear state: Done. Ticket status syncs from festivalSignup.myTickets; other track toggles stay in localStorage.

RAZ-102partialC4dancer

Find a Partner

As a dancer, I want to find a dance partner for a festival, so that I don't have to go alone and have someone to dance with.

Routes
/my-plan/festivals/[slug] ✕

Evidence: app/pages/my-plan.vue:749

Linear state: Backlog. "Find one" links to the festival #discover deck (shows name, role, styles). No "looking for a partner" flag per festival; "partner found" is a localStorage toggle.

RAZ-104builtC4traveler

Book Vacation

As a traveling dancer, I want to add a festival's dates to my calendar, so that I can book time off work and protect the trip.

Procedures
—
Tables
—
Routes
/my-plan

Evidence: app/pages/my-plan.vue:632

Linear state: Done. Google Calendar template URL only; no .ics export for other calendar apps.

RAZ-108builtC4dancer

Where You Show Up

As a dancer, I want to see the courses I attend this month, so that I know where I regularly show up to practice.

Routes
/my-plan

Evidence: app/pages/my-plan.vue:2450

Linear state: Done. Courses are plan_items(item_type='event', metadata.type='class'); course fields are copied into metadata at enrol time. RAZ-294 (past classes shown) Done.

RAZ-116builtC4traveler

Find A Ride

As a traveling dancer, I want to find a ride to a festival I'm going to, so that I can get there cheaply and meet other dancers on the way.

Routes
/my-plan/festivals/[slug] ✕

Evidence: app/pages/my-plan.vue:717; server/database/schema.ts:650

Linear state: Done. Covers map stories 3.1 (post a ride) and 3.2 (browse rides). No seat request/accept flow: one row per dancer per festival, offering|looking. RAZ-191 (ride without login) Done.

RAZ-121partialC4traveler

Share A Room

As a traveling dancer, I want to share a room with another dancer at a festival, so that I can save on accommodation and travel with company.

Routes
/my-plan/festivals/[slug] ✕

Evidence: server/database/schema.ts:663; app/pages/festivals/[slug].vue:602

Linear state: Done. A roommate "lookup" is only (festival, dancer): no dates, budget or preferences, so listings cannot show "what they are looking for" (AC3) and map stories 4.1/4.2 (room listing with preferences, request to join) are not covered. Hotel fallback exists. Follow-ups RAZ-295/296 in Triage.

RAZ-123builtC4dancer

Styles Breakdown

As a dancer, I want to see a breakdown of the dance styles in my year, so that I can understand where I spend my dancing time.

Procedures
plan.myPlan
Routes
/my-year

Evidence: app/pages/my-year.vue:217

Linear state: Done.

RAZ-125builtC4dancer

Plan the Year

As a dancer, I want to pick my next festival and plan my year, so that I know which events I'm heading to.

Routes
/festivals/my-year

Evidence: app/pages/festivals/index.vue:67

Linear state: Done.

RAZ-127builtC4traveler

Widen Your Year

As a traveling dancer, I want to discover new people and places, so that my year can grow beyond what I already know and pull me somewhere new.

Routes
/my-plan

Evidence: app/pages/my-plan.vue:1389; server/trpc/routers/plan.ts:470

Linear state: Done. Needs dancer city + styles; RAZ-284 (empty deck) Done.

RAZ-128partialC4dancer

Match Rate

As a dancer, I want to see my partner match rate, so that I know how often I found a partner for the festivals I planned.

Procedures
—
Tables
—
Routes
/my-year

Evidence: app/pages/my-year.vue:16

Linear state: Done. Match rate = festivals with a manual "partner found" toggle / planned festivals. State kept in browser localStorage, not the DB. Not linked to waves or any partner data.

RAZ-131builtC4dancer

Festival Search

As a dancer, I want to search festivals by city, style, or festival name, so that I can quickly find the ones that fit me.

Procedures
—
Tables
festivals
Routes
/festivals

Evidence: app/pages/festivals/index.vue:129

Linear state: Done. Client-side text filter over /api/festivals rows (name, city, styles).

RAZ-133builtC4traveler

My 2026 Year

As a traveling dancer, I want a page that shows my 2026 dance year, so that I can see everything I have planned in one place.

Routes
/my-year

Evidence: app/pages/my-year.vue:279

Linear state: Done.

RAZ-134builtC4dancer

Track Your Year

As a dancer who isn't signed in, I want to understand what My Year offers, so that I can decide to sign up and start tracking my dance year.

Procedures
—
Tables
—
Routes
/my-year

Evidence: app/components/YearPlan.vue:94

Linear state: Done.

RAZ-136builtC4dancer

Tap Going

As a dancer, I want to mark a festival as Going, so that it is added to my year plan.

Routes
/festivals/festivals/[slug] ✕

Evidence: app/composables/useYearPlan.ts:31; e2e/features/auth-going-gate.feature:2

Linear state: Done. Also covered by e2e/features/auth-going-gate.feature. RAZ-230/RAZ-252/RAZ-256 (going without sign-in, not persisting, hardcoded count) Done.

RAZ-140builtC4traveler

Year Snapshot

As a traveling dancer, I want a headline summary of my year, so that I can see how many festivals, workshops, and countries I have planned at a glance.

Procedures
plan.myPlan
Routes
/my-year

Evidence: app/pages/my-year.vue:209

Linear state: Done. Workshop count comes from plan_items(item_type=workshop) grouped by festival (server/trpc/routers/plan.ts).

RAZ-144builtC4traveler

Early Bird Alert

As a traveling dancer, I want to see when a festival's early-bird ticket is about to expire, so that I can buy before the price goes up.

Procedures
plan.myPlan
Routes
/my-year

Evidence: app/components/YearPlan.vue:119; server/database/schema.ts:70

Linear state: In Review. Early-bird deadline/offer are columns on festivals; ticket tiers themselves are not in the DB.

RAZ-147builtC4traveler

Year In Numbers

As a traveling dancer, I want a "My Year in Numbers" summary, so that I can look back on how much dancing I packed into the year.

Procedures
plan.myPlan
Routes
/my-year

Evidence: app/components/YearPlan.vue:345

Linear state: Done.

RAZ-154builtC4traveler

Year, Saved

As a traveling dancer, I want my year plan saved on the server and my upcoming festivals shown on my profile with real friends going, so that my plan survives devices and others can see where I am headed.

Routes
/my-year/u/[username]

Evidence: app/composables/useYearPlan.ts:7; app/pages/u/[username].vue:26

Linear state: In Review. Implemented as generic plan_items(item_type=festival) instead of the dancer_festivals table the issue proposed. RAZ-300/RAZ-299 (my-year sync/stale stats, In Review) indicate client-cache issues.

RAZ-287partialC4dancer

🐞 I want the 'pay due' sign to be a clickable button that redirects me t…

As a dancer enrolled in a course, I want the "Pay due" sign to be a button that takes me to pay for that course, so that I can settle what I owe.

Procedures
—
Routes
/my-plan/events/[id]

Evidence: app/pages/my-plan.vue:2550

Linear state: Done. Journey inferred (courses live in My Plan, C4). "Pay due" links to /events/[id]; there is no course payment flow or payment record.

Activity cards with participant counts

As a festival dancer, I want to see activity cards with participant counts and availability, so that I can tell at a glance what is happening and how popular it is.

Routes
/festivals/[slug] ✕

Evidence: app/components/ActivitiesTab.vue:3; app/pages/festivals/[slug].vue:569

Source: meetup-planner backlog 1.2 + Operations/Stories/1.2-activity-cards.yml. Dinner/ride/room counts are real; "extra activities" cards are a hardcoded array in the page.

"Your festival plan is ready" message

As a festival dancer, I want to receive a "Your festival plan is ready" message summarising my matches, so that I can see everything in one place and get excited.

Procedures
—
Tables
—
Routes
—

Evidence: server/utils/email.ts:88

Only magic-link, password-reset and ticket-confirmation emails exist in server/utils/email.ts.

Check in to an activity / workshop

As a festival dancer, I want to check in to an activity or workshop to confirm I am attending, so that my group and the organiser know I am there.

Procedures
—
Tables
—
Routes
—

Also festival-schedule user-journey step 5 ("Check-in to workshops"). No check-in field or procedure found.

map:meetup-1.9-live-feedmissingC4traveler

Live feed / live radar at the festival

As a festival dancer, I want a live feed of what is happening now (and an opt-in radar of where friends are), so that I can join spontaneous plans during breaks.

Procedures
—
Tables
—
Routes
—

Merged with festival-schedule user-journey "Live radar" (user-journey.md:49). Closest code is city-level "Tonight · hangouts" (RAZ-118), which is not festival-scoped.

Free-spot counter

As a festival dancer, I want to see how many free spots are left, so that I feel urgency to claim mine before they are gone.

Routes
/festivals/[slug] ✕

Evidence: app/pages/festivals/[slug].vue:629; server/database/schema.ts:60

Source: backlog 2.2 + Operations/Stories/2.2-free-spot-counter.yml. A free "join" writes festival_signups, a different table from "Going" (plan_items).

€1 social unlock via Stripe

As a festival dancer, I want to pay €1 via Stripe when the free spots are full, so that I can still join the social activities.

Routes
/festivals/[slug] ✕

Evidence: app/pages/festivals/[slug].vue:680; server/trpc/routers/festivalSignup.ts:117

Source: backlog 2.3 + Operations/Stories/2.3-stripe-payment-link.yml. festivals.stripePaymentLink column also exists for the older payment-link approach.

Ride group chat link

As a festival dancer, I want a WhatsApp/Telegram group link with my ride group after matching, so that I can coordinate pickup.

Procedures
—
Tables
—
Routes
—

Evidence: server/database/schema.ts:650

festival_ride_shares has no group/chat link; only dinner groups have chatLink. Same gap for rooms (backlog 4.3).

Automatic carpool matching

As a festival dancer, I want to be matched to a carpool automatically by origin city and dates, so that I get a ride within hours.

Procedures
—
Tables
—
Routes
—

Ride shares are listed, not matched.

Sign up for a group dinner

As a festival dancer, I want to sign up for a group dinner on a specific evening, so that I can meet new people instead of eating alone.

Routes
/festivals/[slug] ✕

Evidence: app/composables/useDinners.ts:44; server/trpc/routers/dinner.ts:95

Source: backlog 5.1 + Operations/Stories/5.1-dinner-sign-up.yml. No Linear issue tracks the dinner feature.

Assign dinner groups of 4–6

As a festival dancer, I want to be assigned to a dinner group of 4–6 people, so that I have a concrete dinner plan without organising it myself.

Procedures
+4 admin
Routes
/admin/festivals/[slug]

Evidence: server/trpc/routers/admin.ts:26

Source: backlog 5.2 (+5.5 auto-assign) and Operations/Stories/5.2. Grouping is computed by (admin procedure) but triggered by an admin; no diversity logic was verified.

Restaurant reveal on the day

As a festival dancer, I want to receive the restaurant name and address on the day of the dinner, so that I show up at the right place with the surprise intact.

Procedures
dinner.list+1 admin
Tables
dinners
Routes
/admin/festivals/[slug]/festivals/[slug] ✕

Evidence: server/trpc/routers/admin.ts:124; app/components/ActivitiesTab.vue:274

Source: backlog 5.4 + Operations/Stories/5.4-restaurant-reveal.yml.

Book a taxi dancer

As a festival dancer, I want to book a taxi dancer for specific time slots and styles, so that I am guaranteed good dances even if I know nobody.

Procedures
—
Tables
—
Routes
—

Join community-proposed activities

As a festival dancer, I want to browse and join community-proposed activities (beach social, city tour, after-party), so that I can fill gaps between workshops.

Procedures
—
Tables
—
Routes
/festivals/[slug] ✕

Evidence: app/pages/festivals/[slug].vue:569; app/pages/festivals/[slug].vue:576

UI only: four hardcoded activities in a page-local ref; joining is not persisted. No activities table.

Propose a festival activity

As a festival regular, I want to propose a new activity with description, time and max participants, so that I can organise something without WhatsApp chaos.

Procedures
—
Tables
—
Routes
—

Also covers backlog 9.2 (create and manage activities) and 9.3 (activity dashboard).

Rate the festival afterwards

As a festival dancer, I want to rate my experience and leave feedback after the festival, so that I help improve future events.

Tables
reviews
Routes
/festivals/[slug] ✕/@[handle]

Evidence: app/pages/festivals/[slug].vue:1909

Reviews are polymorphic (target_type, target_slug) with no FK. Rating per workshop/teacher (festival-schedule journey step 5) is not supported; teachers in lineups are mock data, not profiles.

Post-festival recap and stats

As a festival dancer, I want a recap of my festival (workshops attended, rides shared, dinners, partners met), so that I can relive it and share it.

Procedures
—
Tables
—
Routes
—

Merged with festival-schedule journey step 6 "festival stats" (user-journey.md:58).

Invite to festivals where people I met are going

As a festival dancer, I want to be invited to upcoming festivals where dancers I met are already signed up, so that I can plan the next one with my crew.

Procedures
—
Tables
—
Routes
—

plan.suggestions recommends festivals but not based on people met (waves).

Persistent crew groups across festivals

As a festival dancer, I want to keep a persistent group with people I connected with across festivals, so that friendships outlast a single event.

Procedures
—
Tables
—
Routes
—

Evidence: server/database/schema.ts:721

Waves are scoped per festival_slug; there is no cross-festival friend/crew entity.

Share local tips with festival visitors

As a festival regular, I want to share local tips (restaurants, transport, hidden gems) visible to all attendees, so that I help visitors without answering the same DM ten times.

Routes
/cities/[city]

Evidence: app/pages/cities/[city]/index.vue:935

Ask-locals exists per city, not per festival, and recommendations are limited to organisers/venues (written as reviews).

Ambassador status / loyalty

As a festival regular, I want to earn ambassador status (and loyalty points toward free passes), so that I feel valued for organising and returning.

Procedures
—
Tables
—
Routes
—

Merged with festival-schedule journey "Loyalty points" (user-journey.md:61).

Compare workshop plans with friends

As a festival dancer, I want to see which workshops my friends attend and compare schedules side by side, so that we can plan the festival together.

Procedures
plan.list
Routes
/festivals/[slug] ✕

Evidence: app/composables/useSharePlan.ts:50; app/pages/festivals/[slug].vue:1092

A shared plan is encoded into the URL (useSharePlan) and rendered read-only; friends' DB plans are not compared. MySpace receives mockFriends.

RAZ-40builtC5member

Roles & Services

As a member of the dance community, I want to see both open roles at events and services artists offer, so that I can either find work or find the right person for my event.

Procedures
gigs.list
Tables
gigs
Routes
/gigs

Evidence: app/pages/gigs/index.vue:45

Linear state: Done.

RAZ-41builtC5member

Apply Or Contact

As a member of the dance community, I want to apply to or contact the poster of a gig, so that I can take the next step on a listing that fits me.

Procedures
gigs.list
Tables
gigs
Routes
/gigs

Evidence: app/pages/gigs/index.vue:174

Linear state: Done. Apply/Contact opens a mailto: to gigs.contactEmail; nothing is stored, so "confirmation sent" is client-side only. Follow-ups RAZ-232/RAZ-260 Done.

RAZ-42builtC5organiser

Post a Gig

As an organizer, I want to post a gig from the Gigs page, so that artists can find and apply to my open role.

Tables
gigs
Routes
/gigs

Evidence: app/pages/gigs/index.vue:128

Linear state: Done. gigs.close and gigs.getById exist but have no UI caller, so a poster cannot close their gig.

RAZ-43builtC5organiser

Help Wanted

As an organizer, I want to post an open role marked "Wanted", so that artists know I am looking to hire for my event.

Tables
gigs
Routes
/gigs

Evidence: server/database/schema.ts:520

Linear state: Done. "Wanted" = kind role.

RAZ-145builtC5artist

Get Booked

As an artist, I want a place where getting booked and booking others both happen, so that I can grow my dance work from one board.

Tables
gigs
Routes
/gigs

Evidence: app/pages/gigs/index.vue:273

Linear state: Done. Gig poster identity is free text (posterName/posterType) plus optional dancerId; not linked to profiles.

RAZ-148builtC5artist

Offer a Service

As an artist, I want to post a service marked "Offering", so that organizers know what I do and can hire me.

Tables
gigs
Routes
/gigs

Evidence: app/pages/gigs/index.vue:273

Linear state: Done. "Offering" = kind offer.

RAZ-161builtC5artist

Artist's Events

As an artist, I want the events I perform at to appear on my /@handle profile, so that dancers can see where to find me.

Routes
/@[handle]

Evidence: app/pages/@[handle].vue:47

Linear state: In Review. Matching is by handle in events.artists with a name fallback (string matching, no FK).

RAZ-57builtC6client

Any Occasion

As a client, I want to see that the service fits my type of occasion, so that I feel confident it works for my wedding, birthday, corporate, or private event.

Tables
—
Routes
/for-events

Evidence: app/pages/for-events.vue:25

Linear state: Done. Event inquiries are not stored in the DB: feedback.inquiry files a Linear issue (see RAZ-276 for an example inquiry).

RAZ-63builtC6client

Pick a Venue

As a client, I want the team to arrange a venue for my event, so that I do not have to find and book a space myself.

Tables
—
Routes
/for-events/venues

Evidence: app/pages/for-events.vue:15

Linear state: Done. Venue service links to /venues. Event inquiries are not stored in the DB: feedback.inquiry files a Linear issue (see RAZ-276 for an example inquiry).

RAZ-68builtC6client

Mojito Bar

As a client, I want catering arranged for my event, so that guests have food and drinks that match the vibe.

Tables
—
Routes
/for-events

Evidence: app/pages/for-events.vue:16

Linear state: Done. Event inquiries are not stored in the DB: feedback.inquiry files a Linear issue (see RAZ-276 for an example inquiry).

RAZ-73builtC6client

Bilingual MC

As a client, I want a host to run my event, so that the energy stays up and guests are guided through the night in their language.

Tables
—
Routes
/for-events

Evidence: app/pages/for-events.vue:17

Linear state: Done. Event inquiries are not stored in the DB: feedback.inquiry files a Linear issue (see RAZ-276 for an example inquiry).

RAZ-78builtC6client

Your BPM

As a client, I want a DJ who plays the styles my guests dance to, so that the music fits the crowd all night.

Tables
—
Routes
/for-events

Evidence: app/pages/for-events.vue:18

Linear state: Done. Event inquiries are not stored in the DB: feedback.inquiry files a Linear issue (see RAZ-276 for an example inquiry).

RAZ-81builtC6client

Show Dancers

As a client, I want professional dancers at my event, so that guests enjoy a showcase or I have choreography for my first dance.

Tables
—
Routes
/for-events

Evidence: app/pages/for-events.vue:19

Linear state: Done. Event inquiries are not stored in the DB: feedback.inquiry files a Linear issue (see RAZ-276 for an example inquiry).

RAZ-90builtC6client

Highlight Reel

As a client, I want photo and video coverage of my event, so that I get a highlight reel I can share afterwards.

Tables
—
Routes
/for-events

Evidence: app/pages/for-events.vue:20

Linear state: Done. Event inquiries are not stored in the DB: feedback.inquiry files a Linear issue (see RAZ-276 for an example inquiry).

RAZ-96builtC6client

Run the Door

As a client, I want the team to handle ticketing and the door, so that paid entry, guest lists, and check-in run smoothly without my staff.

Tables
—
Routes
/for-events

Evidence: app/pages/for-events.vue:21

Linear state: Done. Promise is a done-for-you service; no door/guest-list/check-in tooling exists in code. Event inquiries are not stored in the DB: feedback.inquiry files a Linear issue (see RAZ-276 for an example inquiry).

RAZ-101builtC6client

End-to-End Night

As a client, I want to book the whole night end to end, so that the team handles everything and I simply enjoy my event.

Tables
—
Routes
/for-events

Evidence: app/pages/for-events.vue:22

Linear state: Done. Event inquiries are not stored in the DB: feedback.inquiry files a Linear issue (see RAZ-276 for an example inquiry).

RAZ-107builtC6client

Plan, No Forms

As a client, I want to describe my event in one message and get a plan back, so that I can forward a ready proposal to my partner or CFO without filling out long forms.

Tables
—
Routes
/for-events

Evidence: server/trpc/routers/feedback.ts:119

Linear state: Done. One free-text message; the "plan back" is a human reply off-platform. Event inquiries are not stored in the DB: feedback.inquiry files a Linear issue (see RAZ-276 for an example inquiry).

RAZ-111builtC6client

Same-Day Reply

As a client, I want to know how fast the team replies, so that I can expect a same-day response after I send my event request.

Procedures
—
Tables
—
Routes
/for-events

Evidence: app/pages/for-events.vue:244

Linear state: Done.

RAZ-114builtC6client

Tell Us More

As a client, I want a clear button to start describing my event, so that I can send my request to the team.

Tables
—
Routes
/for-events

Evidence: app/pages/for-events.vue:257

Linear state: Done. Event inquiries are not stored in the DB: feedback.inquiry files a Linear issue (see RAZ-276 for an example inquiry).

RAZ-129partialC6client

Book a Space

As someone planning a dance event, I want to book a space, so that I have a place to host it.

Routes
/venues/@[handle]

Evidence: app/pages/venues.vue:37; app/pages/@[handle].vue:159

Linear state: Done. Booking requests are stored (booking_requests, status pending) but commercial venues are never notified and have no UI or procedure to accept/decline; profiles have no owner, so no one can manage a venue. Only free/OpenAir spaces get decisions via election.moderateBooking.

RAZ-135partialC6client

Request a Date

As someone planning a dance event, I want to pick a dance-ready venue and request a date directly, so that I can secure a suitable space quickly.

Routes
/venues/@[handle]

Evidence: app/pages/@[handle].vue:152

Linear state: Done. Confirmation shown to the requester, but nothing is sent to the venue. Booking requests are stored (booking_requests, status pending) but commercial venues are never notified and have no UI or procedure to accept/decline; profiles have no owner, so no one can manage a venue. Only free/OpenAir spaces get decisions via election.moderateBooking.

RAZ-138builtC6client

Host, Don't Dance

As a client hosting an event, I want a team that produces the dance night for me, so that I can host my guests instead of running the floor myself.

Tables
—
Routes
/for-events

Evidence: app/pages/for-events.vue:108

Linear state: Done.

RAZ-142partialC6client

Social, Class, Private

As someone planning a dance event, I want to book a space for my social, class, or private event, so that I can find a venue that fits my event type.

Procedures
booking.request
Routes
/venues/@[handle]

Evidence: server/database/schema.ts:372

Linear state: Done. Booking requests are stored (booking_requests, status pending) but commercial venues are never notified and have no UI or procedure to accept/decline; profiles have no owner, so no one can manage a venue. Only free/OpenAir spaces get decisions via election.moderateBooking.

RAZ-143builtC6client

Whole Floor

As a client, I want one team to handle every part of the night, so that a single dance or a five-hour party comes together without me piecing it out to many vendors.

Tables
—
Routes
/for-events

Evidence: app/pages/for-events.vue:108

Linear state: Done.

RAZ-158partialC6organiser

Booking Engine

As an organiser, I want to find a venue's bookable spaces, see availability and request a date, so that I can secure space for my event without going off-platform.

Routes
/@[handle]/events/[id]

Evidence: server/database/schema.ts:343; server/trpc/routers/booking.ts:278

Linear state: Done. booking.setAvailability has no UI caller. Booking requests are stored (booking_requests, status pending) but commercial venues are never notified and have no UI or procedure to accept/decline; profiles have no owner, so no one can manage a venue. Only free/OpenAir spaces get decisions via election.moderateBooking. Follow-up RAZ-257 Done. Drift: Linear Done, code partial.

RAZ-159partialC6organiser

Pinakothek Showcase

As a Munich organiser, I want to browse the Pinakothek der Moderne Open Air areas and request a date, so that I can use a flagship free space for social dancing.

Routes
/@[handle]/for-events

Evidence: scripts/seed-pinakothek.ts:1; app/pages/for-events.vue:137

Linear state: Backlog. Seed script exists; RAZ-301 (Triage) says the production seed has not been run, so the profile may not exist in prod.

RAZ-302missingC6organiser

Venue browse: event-relevant filter attributes + filter flow

As an event organiser looking for a wedding, birthday or party space, I want to filter venues by event-relevant attributes (dance floor, mirrors, Wi-Fi, capacity), so that I can find a fitting space among thousands.

Routes
/venues

Evidence: server/trpc/routers/entity.ts:14

Linear state: Triage. Journey inferred. profiles has floorType/venueType only; bookable_spaces has capacity/floorType. No amenities model and no filters on /venues.

RAZ-33partialC7organiser

Ticket Your Festival

As an Organizer, I want to ticket my festival through the platform and get promotion plus real attendee faces on my event page, so that I can sell tickets and build trust in one place.

Procedures
—
Tables
—
Routes
//organizers/create ✕

Evidence: app/pages/index.vue:446

Linear state: Done. Card and CTA exist. An organiser cannot set up ticketing themselves: ticket tiers/prices live in server/utils/ticket-prices.ts and need a code change.

RAZ-34builtC7organiser

Real Faces

As an organizer, I want my festival page to show the real dancers who are going, so that potential attendees see a genuine community and feel confident buying a ticket.

Routes
/organizers ✕/festivals/[slug] ✕

Evidence: app/pages/festivals/[slug].vue:1186

Linear state: Done.

RAZ-35builtC7organiser

Already Planning

As an organizer, I want tools to reach dancers who are already planning their trips, so that I can connect with attendees and promote my event where they are looking.

Procedures
—
Tables
—
Routes
/organizers ✕

Evidence: app/pages/organizers/index.vue:42

Linear state: In Review.

RAZ-36partialC7organiser

Workshop Planner

As an organizer, I want my festival to include a workshop planner for dancers, so that attendees can build a personal schedule and I can see which sessions draw the most interest.

Routes
/organizers ✕/festivals/[slug] ✕

Evidence: app/pages/festivals/[slug].vue:27; app/components/ScheduleTab.vue:48

Linear state: Done. Workshops, teachers and ticket tiers exist only for the hardcoded festivals in app/data/mock-*.ts (plus server/utils/ticket-prices.ts); there is no workshops or tickets table, so DB-only festivals get no schedule. Organisers cannot see interest per session (see RAZ-74).

RAZ-37builtC7organiser

Share as Invite

As an organizer, I want dancers to share their festival plans, so that each share becomes a personal invitation that brings their friends to my event.

Procedures
—
Tables
—
Routes
/organizers ✕/festivals/[slug] ✕

Evidence: app/components/SharePlanModal.vue:43; app/pages/festivals/[slug].vue:1092

Linear state: Done. Shared plan is encoded in the URL, not stored.

RAZ-38builtC7organiser

Year Planning

As an organizer, I want my festival to appear when dancers plan their year, so that I reach people early while they are choosing which festivals to attend.

Routes
/organizers ✕/my-year/festivals

Evidence: app/pages/my-year.vue:81

Linear state: In Review.

RAZ-39partialC7organiser

Plan CTAs

As an event organizer, I want a clear next step on each pricing plan, so that I can move forward with the plan that fits me.

Procedures
—
Tables
—
Routes
/organizers ✕/organizers/create ✕

Evidence: app/pages/organizers/index.vue:100; app/pages/organizers/index.vue:126

Linear state: Done. Starter and Pro both lead to the /organizers/create wizard with a plan param; no trial exists. Network is a mailto.

RAZ-54partialC7organiser

Interactive Schedule

As an organizer, I want dancers to browse my schedule interactively, so that they can find the workshops that fit them and commit to attending.

Procedures
plan.add
Routes
/organizers ✕/festivals/[slug] ✕

Evidence: app/components/ScheduleTab.vue:50

Linear state: Done. Style/level filters and add-to-plan work. Workshops, teachers and ticket tiers exist only for the hardcoded festivals in app/data/mock-*.ts (plus server/utils/ticket-prices.ts); there is no workshops or tickets table, so DB-only festivals get no schedule.

RAZ-61partialC7organiser

Partner Matching

As an organizer, I want leads and follows to find each other before my festival, so that solo dancers arrive with a connection and are more likely to attend.

Routes
/festivals/[slug] ✕

Evidence: server/trpc/routers/wave.ts:182

Linear state: Backlog. dancers.role (lead/follow) is shown in the discover deck but there is no lead↔follow matching or filter. Covers map story 6.3 (auto partner matching). Linear Backlog, partially built.

RAZ-65builtC7organiser

Swipe to Match

As an organizer, I want my attendees to discover partners by swiping, so that finding people to dance with feels easy and playful and draws more dancers to the event.

Routes
/festivals/[slug] ✕

Evidence: app/components/DiscoverDancers.vue:48

Linear state: Done. Covers map stories 6.1 (browse dancers) and 6.2 (send a dance request). festival_waves keys festivals by slug text, unlike other festival tables (festival_id FK).

RAZ-69partialC7organiser

Smart Ticket Picks

As an organizer, I want dancers to be shown the best-value ticket as they plan, so that they buy the right pass with less hesitation and fewer support questions.

Procedures
—
Tables
—
Routes
/organizers ✕/festivals/[slug] ✕

Evidence: app/pages/festivals/[slug].vue:953

Linear state: Done. Recommendation is client-side over the hardcoded ticket list. Workshops, teachers and ticket tiers exist only for the hardcoded festivals in app/data/mock-*.ts (plus server/utils/ticket-prices.ts); there is no workshops or tickets table, so DB-only festivals get no schedule.

RAZ-74missingC7organiser

Workshop Demand

As an organizer, I want to see which workshops are trending before I finalize my schedule, so that I can shape the program around real demand.

Routes
/organizers ✕/organizers/insights

Evidence: server/trpc/routers/festivalInsights.ts:42

Linear state: Backlog. Data exists (plan_items item_type=workshop) but no insights procedure aggregates workshop demand.

RAZ-76builtC7organiser

Take the Stage

As an Organizer, I want the final journey stage to invite me to teach, DJ, host events or open a venue, so that I see the site supports me when I move from dancing to running the scene.

Procedures
—
Tables
—
Routes
//organizers ✕

Evidence: app/pages/index.vue:69

Linear state: In Review.

RAZ-79builtC7organiser

Style & Level Mix

As an organizer, I want to understand the style and level mix of my attendees, so that I can plan a program that fits the dancers actually coming.

Routes
/organizers/insights

Evidence: app/pages/organizers/insights.vue:53

Linear state: Done. Attendees for insights = festival_signups, while "Going" everywhere else = plan_items. Festival ownership is inferred from an onboarded festival_submissions row with the same slug (no owner column). Linear label status:not-built stale.

RAZ-85missingC7organiser

Audience Geography

As an organizer, I want to know where my dancers are travelling from, so that I can focus promotion and plan logistics like travel and accommodation.

Procedures
—
Tables
—
Routes
/organizers ✕

Evidence: app/pages/organizers/index.vue:62

Linear state: Backlog. Only promised in copy. dancers.city is free text, so aggregation would need city canonicalisation (cities table).

RAZ-87builtC7organiser

Host the Night

As an Organizer, I want the home page to recognise that some visitors host events rather than attend them, so that I know the site can help me run my night too.

Procedures
—
Tables
—
Routes
/

Evidence: app/pages/index.vue:431

Linear state: Done.

RAZ-89partialC7organiser

Post-Festival Signal

As an organizer, I want honest feedback after my festival, so that I can learn what worked and improve the next edition.

Tables
reviews
Routes
/organizers ✕/festivals/[slug] ✕

Evidence: app/pages/organizers/index.vue:63

Linear state: Backlog. Festival reviews are collected on the festival page but not shown in organiser insights; mutual endorsements do not exist.

RAZ-93builtC7organiser

Whole Night Supplied

As a Client, I want to see that the team can supply a whole night for a private event, so that I can hire one provider for my wedding, birthday or corporate party instead of piecing it together.

Procedures
—
Tables
—
Routes
//for-events

Evidence: app/pages/index.vue:418

Linear state: Done.

RAZ-95partialC7organiser

Starter Free

As an event organizer, I want to list my event for free on the Starter plan, so that dancers can find me without paying anything to get started.

Routes
/organizers ✕/organizers/create ✕

Evidence: server/database/schema.ts:411; app/pages/organizers/create.vue:380

Linear state: Done. The wizard stores a JSON draft for team review; the listing does not appear in directories until the team creates a festivals row by hand.

RAZ-98builtC7client

Book Us

As a Client, I want a button to book the team for my event, so that I can start a booking request without hunting for contact details.

Procedures
—
Tables
—
Routes
//for-events

Evidence: app/pages/index.vue:431

Linear state: Done.

RAZ-100missingC7organiser

Pro Toolkit

As an event organizer, I want to upgrade to the Pro plan for a single event, so that I get the full set of tools to engage dancers around that event.

Procedures
—
Tables
—
Routes
/organizers ✕/organizers/create ✕

Evidence: app/pages/organizers/index.vue:87

Linear state: Done. Pricing card only; no billing, subscription or plan entitlement in the data model. Drift: Linear Done.

RAZ-103builtC7organiser

Ticket With Us

As an Organizer, I want a button to start ticketing my festival with the platform, so that I can begin listing my event without searching for how.

Procedures
—
Tables
—
Routes
//organizers/create ✕

Evidence: app/pages/index.vue:449

Linear state: Done.

RAZ-106missingC7organiser

Network Plan

As an event organizer running several events, I want an annual Network plan, so that I can cover all my events under one yearly price instead of paying per event.

Procedures
—
Tables
—
Routes
/organizers ✕

Evidence: app/pages/organizers/index.vue:108

Linear state: In Review. Pricing card + mailto only; no plan entity.

RAZ-109builtC7organiser

Where Dancers Are

As an organizer, I want to see how WeDance ticketing puts my festival in front of active dancers, so that I understand why I should list here instead of a generic ticketing site.

Procedures
—
Tables
—
Routes
/organizers ✕

Evidence: app/pages/organizers/index.vue:36

Linear state: Done.

RAZ-112partialC7organiser

List in Minutes

As an event organizer, I want to list my festival quickly, so that I can start filling my dance floor without a long setup.

Routes
/organizers ✕/organizers/create ✕

Evidence: app/pages/organizers/create.vue:380

Linear state: Done. AC4 (appears in directory after submit) not met: drafts await manual onboarding.

RAZ-117builtC7organiser

Free to List

As an event organizer, I want listing and browsing to be free, so that I can join without upfront cost.

Routes
/organizers ✕/organizers/create ✕

Evidence: app/pages/organizers/index.vue:70

Linear state: Done.

RAZ-119builtC7organiser

List Your Festival

As an organizer, I want a clear button to start listing my festival, so that I can begin publishing my event without hunting for where to start.

Procedures
—
Tables
—
Routes
/organizers ✕/organizers/create ✕

Evidence: app/pages/organizers/index.vue:170

Linear state: Done.

RAZ-122builtC7organiser

Ticketing On Us

As a festival organizer, I want to list my festival for free with ticketing covered, so that I can promote and sell without upfront cost.

Routes
/festivals/organizers/create ✕

Evidence: app/pages/festivals/index.vue:195

Linear state: Done. CTA built; listing itself is review-gated (see RAZ-95). Follow-ups RAZ-236/237 Done.

RAZ-124partialC7organiser

Partner Matching

As an organizer, I want my festival to offer partner matching, so that dancers can find someone to attend and dance with, which makes solo dancers more likely to buy a ticket.

Routes
/organizers ✕/festivals/[slug] ✕

Evidence: app/pages/organizers/index.vue:51

Linear state: Backlog. Same capability as RAZ-61.

RAZ-126partialC7organiser

List Your Social

As an organizer of a class or weekly social, I want to list my event for free, so that local dancers can find me.

Routes
/cities/organizers/create ✕

Evidence: app/pages/cities/index.vue:217

Linear state: Done. CTA leads to the festival wizard; there is no flow to list a weekly class or social. events rows come only from the v3 sync, and booking_requests only via venue booking.

RAZ-130builtC7organiser

One-Tap Checkout

As an organizer, I want dancers to buy tickets in a single quick step, so that fewer people abandon the purchase and more plans turn into paid tickets.

Routes
/organizers ✕/festivals/[slug] ✕

Evidence: app/pages/festivals/[slug].vue:893; server/utils/ticket-prices.ts:32

Linear state: Done. Stripe in test mode. Prices resolved server-side from a hardcoded registry (RAZ-228). RAZ-229 Done.

RAZ-137builtC7organiser

Listing to Insights

As an organizer, I want a simple overview of how WeDance works, so that I can quickly understand the path from listing my event to getting attendance insights.

Procedures
—
Tables
—
Routes
/organizers ✕

Evidence: app/pages/organizers/index.vue:129

Linear state: Done.

RAZ-141partialC7organiser

List Your Event

As an organizer, I want to add my festival, schedule, teachers, and venue quickly, so that I can publish my event without a long setup process.

Routes
/organizers ✕/organizers/create ✕

Evidence: server/database/schema.ts:422

Linear state: Done. Schedule and teachers are captured inside the JSON payload only; nothing turns them into workshops/teachers.

RAZ-146builtC7organiser

Dancers Plan

As an organizer, I want dancers to find my event and engage with it before buying, so that interest builds into commitment and ticket sales.

Procedures
—
Tables
—
Routes
/organizers ✕

Evidence: app/pages/organizers/index.vue:131

Linear state: Done.

RAZ-149partialC7organiser

Plans Drive Tickets

As an organizer, I want dancers to be guided from their plan to the right ticket, so that more of the plans they build turn into purchases.

Procedures
—
Tables
—
Routes
/organizers ✕/festivals/[slug] ✕

Evidence: app/pages/organizers/index.vue:136

Linear state: Done. Same capability as RAZ-69.

RAZ-150partialC7organiser

You Get Insights

As an organizer, I want real data about demand, audience, and post-event feedback, so that I can plan future editions with evidence instead of guesswork.

Routes
/organizers/insights

Evidence: app/pages/organizers/insights.vue:37

Linear state: Backlog. Only style & level mix is delivered; demand, geography and post-event signal missing (RAZ-74, RAZ-85, RAZ-89).

RAZ-160builtC7organiser

Booking Terms

As an organiser, I want booking terms that I accept with each request and explainer pages for venues and organisers, so that everyone knows WeDance acts as a connector.

Procedures
booking.request
Routes
/booking-terms/for-venues/@[handle]

Evidence: server/database/schema.ts:384; app/pages/booking-terms.vue:1

Linear state: Done. Linear label status:not-built stale.

RAZ-170builtC7admin

Admin CMS — community groups / giveaways / videos / festivals

As an operator, I want an admin section to manage community groups, giveaways, videos and festivals, so that I can curate content without direct DB edits.

Procedures
+7 admin
Routes
/admin/admin/community-groups/admin/giveaways/admin/videos/admin/festivals

Evidence: app/layouts/admin.vue:1

Linear state: Backlog. Admin festivals page lists festivals and dinners; it cannot create/edit festivals or onboard festival_submissions. Linear Backlog while built (reverse drift).

Embed an activity widget on the festival website

As a festival organiser, I want to embed a WeDance activity widget on my festival website, so that I can offer social activities without building anything.

Procedures
—
Tables
—
Routes
—
RAZ-31builtC8dancer

Every Face Real

As a Dancer, I want the home page to promise that the dances, teachers, cities and people shown are real, so that I trust what I find here more than fake or padded listings elsewhere.

Procedures
—
Tables
—
Routes
/

Evidence: app/pages/index.vue:166

Linear state: Done.

RAZ-49builtC8visitor

Welcome In

As a visitor, I want the home page to greet me and instantly signal this is a place for dancers, so that I feel I've arrived somewhere made for me.

Procedures
—
Tables
—
Routes
/

Evidence: app/pages/index.vue:150

Linear state: Done. RAZ-189 (Datenschutz wording) Done.

RAZ-53builtC8dancer

First Night, Best Year

As a Dancer, I want the home page to promise it supports me from my very first class through my most active year, so that I trust it will grow with me instead of only serving beginners or only pros.

Procedures
—
Tables
—
Routes
/

Evidence: app/pages/index.vue:154

Linear state: Done.

RAZ-60builtC8dancer

First Move To Stage

As a Dancer, I want the journey section to show the path from my first move to performing or hosting my own night, so that I can see where the site can take me over time.

Procedures
—
Tables
—
Routes
/

Evidence: app/pages/index.vue:208

Linear state: Done.

RAZ-72builtC8dancer

Any Dance, Any Step

As a Dancer, I want the journey subhead to reassure me the site fits any dance style and any experience level, so that I don't worry my style or stage isn't covered.

Procedures
—
Tables
—
Routes
/

Evidence: app/pages/index.vue:213

Linear state: Done.

RAZ-83partialC8dancer

No Fake Friends

As a Dancer, I want each ticket sold to appear as a real person on the event page, so that the attendee list I see is genuine and not padded with fake accounts.

Routes
//festivals/[slug] ✕

Evidence: app/pages/index.vue:334; server/database/schema.ts:84

Linear state: Todo. Faces on most event pages come from "Going" clicks (plan_items.shareGoing), not ticket purchases. The ticket-holder roster (festival_signups.verified_ticket_holder + roster_visibility, AttendeeRoster) is used only on /festivals/charanga-habanera-munich-2026, fed by the TicketTailor webhook (server/api/webhooks/tickettailor.post.ts) and the /charanga/claim flow that links ticket rows to dancers.

RAZ-86builtC8dancer

Per-Event Attendees

As a Dancer, I want each event to show a "Who's coming" list of real attendees, so that I can check the crowd before I decide to go.

Routes
//events/[id]

Evidence: app/pages/events/[id].vue:209

Linear state: Done. Linear label status:not-built stale.

RAZ-92builtC8dancer

Five Steps

As a Dancer, I want the home page to explain how it works in five clear steps, so that I know what to expect before I sign up.

Procedures
—
Tables
—
Routes
/

Evidence: app/pages/index.vue:462

Linear state: Done.

RAZ-105builtC8dancer

Europe-Wide Map

As a dancer, I want to browse dance festivals from across Europe in one place, so that I can pick the next event I want to attend without hunting across many sites.

Procedures
—
Routes
/festivals/festivals/[slug] ✕

Evidence: server/api/festivals.get.ts:36; app/pages/festivals/[slug].vue:39

Linear state: Done. Covers map stories 1.1 (festival hero), 1.5 (festival listing) and 1.6 (shareable URLs). Detail page prefers hardcoded app/data mocks and falls back to /api/festivals/[slug]. Festivals also exist as events rows (is_festival). Follow-ups RAZ-233/234 Done; RAZ-175 (past festivals as upcoming) Done, RAZ-285 (removed past festival comes back) Backlog.

RAZ-110builtC8dancer

One-Tap Ticket

As a dancer, I want to buy a festival ticket quickly and securely, so that I get an instant confirmation and know my spot is locked in.

Routes
//festivals/[slug] ✕/my-plan

Evidence: app/pages/festivals/[slug].vue:893; server/api/stripe/webhook.post.ts:5

Linear state: Done. Merged with RAZ-205 (Done, same story, promise P210). Follow-ups RAZ-238/245/250 Done. Stripe test mode. Ticket tiers hardcoded (no tickets table). Linear label status:not-built stale.

RAZ-115builtC8dancer

Opt-In Attendees

As a dancer, I want to see who else is going to a festival when they choose to share, so that I know familiar faces will be there before I commit.

Routes
//festivals/[slug] ✕

Evidence: server/database/schema.ts:571

Linear state: In Review. Covers map story 1.3 (social proof). A second, independent opt-in exists for ticket holders (festival_signups.roster_visibility via festivalSignup.setMyVisibility/getMyVisibility).

RAZ-120builtC8dancer

Closer Than You Think

As a dancer, I want an easy prompt to start finding my next event, so that I can move from the homepage into browsing festivals right away.

Procedures
—
Tables
—
Routes
/

Evidence: app/pages/index.vue:514

Linear state: Done.

RAZ-152builtC8member

Pinakothek Moderator Election (epic)

As a community using a free/OpenAir space, we want to elect a moderator whose guidelines become the rules for free bookings, so that the community, not a platform admin, stewards the space.

Routes
/elections/[handle]/@[handle]

Evidence: app/pages/elections/[handle].vue:103

Linear state: Backlog. Epic (G800) over RAZ-163..166. Linear Backlog / status:not-built, but the full flow is implemented (reverse drift). election.guidelineHistory has no UI caller; profiles still keeps flat moderatorName/Handle/Since next to the election tables.

RAZ-153builtC8member

Bring v4 Users

As an existing WeDance v4 user, I want my account (email and password) migrated into WeDance 2026, so that I can log in with my existing password.

Procedures
—
Tables
dancers
Routes
—

Evidence: scripts/migrate/02-users.mjs:1

Linear state: Backlog. Migration script, not a runtime capability. Linear Backlog with status:built label.

RAZ-157builtC8member

Locals Recommend

As a newcomer to a city, I want to ask locals who is good here and get recommendations, so that I find trusted organisers and venues.

Routes
/cities/[city]

Evidence: app/components/AskLocalsSection.vue:54

Linear state: Backlog. A recommendation becomes a 5-star review (source=recommendation) on a slug-addressed target, auto-stubbed if unknown; it does not create a profiles row. Linear Backlog while built (reverse drift).

RAZ-163builtC8member

Elect the Steward

As a community using a free/OpenAir commons (e.g. the Pinakothek Open Air space), we want to elect a moderator each year, so that the community — not a platform admin — chooses who stewards the space.

Routes
/elections/[handle]

Evidence: server/trpc/routers/election.ts:176

Linear state: Backlog. Reverse drift: Backlog in Linear, implemented in code.

RAZ-164builtC8member

Run on Rules

As a moderator candidate, I want to propose the guidelines the space would run by, so that the community elects me on the basis of the rules I stand for.

Routes
/elections/[handle]

Evidence: server/database/schema.ts:462

Linear state: Backlog. Reverse drift: Backlog in Linear, implemented in code.

RAZ-165builtC8member

The Floor Votes

As a community member, I want to vote for the candidate whose guidelines I support, so that the winning proposal becomes the space's active rules — and I want the ballot to be openly verifiable, so the community trusts the result.

Routes
/elections/[handle]

Evidence: server/trpc/routers/election.ts:254

Linear state: Backlog. Reverse drift: Backlog in Linear, implemented in code.

RAZ-166builtC8member

Steward the Queue

As the elected moderator, I want to approve or decline free-booking requests against the active guidelines, so that confirmed slots follow the community's rules; and I want each term's guidelines versioned, so that history is preserved across elections.

Routes
/elections/[handle]

Evidence: server/trpc/routers/election.ts:385

Linear state: Backlog. Approve/decline built; past-term guideline view (election.guidelineHistory) has no UI caller. Reverse drift: Backlog in Linear.

RAZ-241builtC8dancer

🐞 Forgot password doesn't reset the password As a user who forgot my pa…

As a user who forgot my password, I want to set a new password from an emailed link, so that I can get back into my account.

Routes
/auth/verify

Evidence: server/trpc/routers/auth.ts:161; e2e/features/auth-password-reset.feature:2

Linear state: Done. No Linear project (user-report); journey inferred. Covered by e2e/features/auth-password-reset.feature. Follow-up RAZ-242 Done.

RAZ-246builtC8dancer

Show success confirmation after ticket purchase

As a dancer who just paid for a ticket, I want a clear success confirmation with festival, ticket and amount, so that I know my payment went through.

Procedures
—
Tables
—
Routes
/festivals/[slug] ✕

Evidence: app/pages/festivals/[slug].vue:474

Linear state: Done. Confirmation data is read back from sessionStorage set before the Stripe redirect, not from the server.

RAZ-247builtC8dancer

Send purchase confirmation email after ticket checkout

As a dancer who bought a ticket, I want a confirmation email with the festival, date, ticket and amount, so that I have a receipt.

Procedures
—
Routes
—

Evidence: server/utils/email.ts:88

Linear state: Done.

RAZ-248builtC8dancer

Show 'already purchased' state on festival page after buying a ticket

As a dancer who already has a ticket, I want the festival page to show "You have a ticket" instead of "Get this pass", so that I do not buy twice.

Routes
/festivals/[slug] ✕

Evidence: app/pages/festivals/[slug].vue:883

Linear state: Done.

RAZ-249builtC8dancer

Nudge profile completion after ticket purchase

As a dancer who just bought a ticket with an incomplete profile, I want to be prompted to add my styles, role and city, so that matching, rides and socials work for me.

Procedures
profile.update
Tables
dancers
Routes
/festivals/[slug] ✕

Evidence: app/pages/festivals/[slug].vue:479

Linear state: Done.

RAZ-272builtC8member

🐞 Report a problem Report a problem popup: No screenshot captured? It s…

As any visitor, I want to report a problem with a screenshot from any page, so that the team can fix what I ran into.

Procedures
—
Tables
dancers
Routes
—

Evidence: app/components/ReportProblem.vue:1; app/lib/sentry-feedback.ts:1; app/lib/screen-capture.ts:1

Linear state: In Review. No Linear project; journey inferred. Since 2026-10 reports go to Sentry User Feedback (tag feedback_type=bug|idea) with the Session Replay linked and an optional getDisplayMedia screenshot attached — not Linear issues, not DB rows. The bug reports in this inventory came through the earlier Linear pipeline.

RAZ-275partialC8dancer

🐞 Photo URL This is not user friendly. See in v4 we already have a good…

As a dancer, I want to upload a profile photo instead of pasting a photo URL, so that setting my picture is easy.

Procedures
profile.update
Tables
dancers
Routes
/settings

Evidence: server/api/media/image.post.ts:1; app/pages/settings.vue:224

Linear state: In Review. Journey inferred. Upload to Cloudinary via /api/media/image; RAZ-288 (Triage) reports the endpoint accepts unauthenticated uploads, RAZ-289 UX hardening open.

Sign up / sign in / sign out

As a dancer, I want to sign up with name, email, dance styles, role and city in under a minute, sign out with confirmation and sign back in, so that I can start planning immediately and keep my account.

Routes
/onboarding/auth/verify

Evidence: server/trpc/routers/auth.ts:248; e2e/features/auth-signup-signin.feature:2; app/components/SiteHeader.vue:80

Merges meetup-planner 2.1 (+ Operations/Stories/2.1-sign-up-form.yml), e2e/features/auth-signup-signin.feature, and bug reports RAZ-239 (sign-out confirm, Done), RAZ-240 (redirect after sign-out, Done), RAZ-273 (session lost on refresh, In Review).

Sign up with Google or Facebook

As a dancer, I want to sign up with Google or Facebook, so that I can join in one tap without typing.

Procedures
—
Tables
—
Routes
—

Evidence: server/trpc/routers/auth.ts:60

Auth is email+password and magic link only; dancers.neonAuthId column exists but no OAuth flow found.

RAZ-304unknownvisitor

Event page: clear visitor journey + fix attendee section showing live data

As a visitor on a festival or event page, I want a clear next step for going and an attendee section that shows the right content, so that I know what I can do here.

Routes
/festivals/[slug] ✕/events/[id]

Evidence: app/pages/events/[id].vue:209

Linear state: Triage. Triage. The issue does not name which section shows live data instead of placeholder content, so status cannot be determined from code.

Cross-check against the code

Referenced but not in the code

Procedures named by a story that the router does not have — a typo, a rename, or a story marked further along than the code.

None.

58 stories name a procedure, table or route that does not exist (marked ✕ above).

Unmapped procedures (155)

Public and signed-in procedures no story references — dead code, or a story missing from the map.