Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions docs/dev/minimal-user-flows/end-to-end-minimal-hackathon.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
{"type":"pages-state","id":1,"at":"before anyone signs in","phase":"—","capabilities":[],"sees":{"anonymous":"the landing page and an empty public hackathon list; a “Log in” button","admin1":"not signed in","user1":"not signed in","user2":"not signed in"}}
{"type":"action","id":2,"actor":"admin1","title":"logs in to the platform","page":"/ → “Log in” → Keycloak sign-in","provides":"username, password","comment":"Signs in through Keycloak; the session is what identifies them and their role on every step below."}

# Hackathon Creation
{"type":"action","id":3,"actor":"admin1","title":"admin creates and publishes the hackathon","page":"/hackathons/create — fill name, dates, visibility, main image","provides":"name, description rich markdown (tables, youtube embeded videos, images), visibility, main image, startsAt, endsAt","comment":"Creates the event and returns the hackathonId every later step targets. Logo is an image url."}
{"type":"action","id":5,"actor":"admin1","title":"admin confirms the event is published","page":"/my/hackathon/{id}/overview","provides":"hackathonId","comment":"Reads the event back to confirm name, description and image URL were stored."}
{"type":"pages-state","id":6,"at":"the event is created and public","phase":"none declared yet","capabilities":["(defaults — nothing scheduled yet)"],"sees":{"anonymous":"the public event page — name, description, logo","admin1":"the full manage hub for the new event (config, timeline, participants, teams, prizes)","user1":"(not registered) the public event page","user2":"(not registered) the public event page"}}

# Hackathon Setup
{"type":"action","id":7,"actor":"admin1","title":"admin builds the custom registration form","page":"/my/hackathon/{id}/forms — Registration form (add questions)","provides":"Affiliation (text, required); Experience level (select, required); Skills (tags); Why do you want to take part? (textarea, required); Dietary requirements (text); T-shirt size (select); I accept the Code of Conduct (consent, required); I consent to event photography (consent)","comment":"The admin composes a CUSTOM registration questionnaire — each question carries a label, a type (short text, single-choice, tags, or long text) and whether it is required. Here: Affiliation (text, required), Experience level (single-choice), Skills (tags), a free-text Motivation (required), Dietary needs, and T-shirt size (single-choice), plus two consent checkboxes (Code of Conduct required, photos optional). Participants answer exactly these on their registration form."}
{"type":"action","id":8,"actor":"admin1","title":"admin builds the custom submission form","page":"/my/hackathon/{id}/forms — Submission form (add questions)","provides":"Repository URL (url, required); Live demo URL (url); One-paragraph summary (textarea, required); Primary category (select, required); Slides (PDF) — upload or link (file-or-url)","comment":"The admin defines the CUSTOM questionnaire teams answer when they turn work in: Repository URL (required), a Live demo URL, a Summary (long text, required), a Primary category (single-choice, required), and Slides (upload or external link). The submission is validated against exactly these questions."}
{"type":"action","id":9,"actor":"admin1","title":"admin sets the voting policy","page":"/my/hackathon/{id}/voting — Rules","provides":"hackathonId, mechanism, oneBallotPer, ownTeamVoting, organizerVoting, tieBreak","comment":"Sets the rules of the vote up front: mechanism, whether own-team votes count, and how ties break."}
{"type":"action","id":11,"actor":"admin1","title":"admin sets the email templates","page":"/my/hackathon/{id}/email","provides":"hackathonId, templates","comment":"The templates the platform sends at each milestone, written once with placeholders."}
{"type":"action","id":12,"actor":"admin1","title":"admin defines the prize table","page":"/my/hackathon/{id}/prizes","provides":"rank, title","comment":"Records the prize table; the admin has the final say on prizes."}
{"type":"action","id":13,"actor":"admin1","title":"admin sets the phases with time windows","page":"/my/hackathon/{id}/??PHASES??","provides":"hackathonId, registrationOpens, registrationCloses, proposalsClose, preferencesClose, submissionsClos","comment":"The clock: when each stage opens and closes. Opened now so registration and proposals can proceed."}
{"type":"action","id":16,"actor":"admin1","title":"admin adds the Ideation phase","page":"/my/hackathon/{id}/timeline → New phase","provides":"hackathonId, name, startsAt, endsAt, description","comment":"Lays the timeline: each phase is a named window participants see. Ideation is first."}
{"type":"action","id":17,"actor":"admin1","title":"admin adds the Hacking phase","page":"/my/hackathon/{id}/timeline → New phase","provides":"hackathonId, name, startsAt, endsAt, description","comment":"The build window."}
{"type":"action","id":18,"actor":"admin1","title":"admin adds the Judging phase","page":"/my/hackathon/{id}/timeline → New phase","provides":"hackathonId, name, startsAt, endsAt, description","comment":"The final window, where voting happens."}
{"type":"action","id":19,"actor":"admin1","title":"admin schedules voting to open in the Judging phase","page":"/my/hackathon/{id}/timeline/{phaseId}/edit — tick “Vote”","provides":"hackathonId, capability, openInPhaseId","comment":"Linking VOTE to the Judging phase means voting opens automatically when that phase becomes current — not before."}
{"type":"action","id":20,"actor":"admin1","title":"admin sets the opening capabilities","page":"/my/hackathon/{id}/manage — capability panel","provides":"hackathonId, capabilities","comment":"Register and propose open now; submit, vote and results stay closed until their phases."}
{"type":"action","id":21,"actor":"admin1","title":"admin declares the Ideation phase current","page":"/my/hackathon/{id}/manage — Now / Next","provides":"hackathonId, phaseId","comment":"Declares which phase is “now” so the hub and participants agree on the current stage."}
{"type":"pages-state","id":22,"at":"setup complete — registration open, Ideation is current","phase":"Ideation","capabilities":["register","propose_projects","set_team_preferences"],"sees":{"anonymous":"the public event page and the two pre-proposed projects","admin1":"everything, plus the Now/Next box showing Ideation","user1":"the public event page with a Join button (registration is open)","user2":"the public event page with a Join button"}}

# Projects addition by admin
{"type":"action","id":23,"actor":"admin1","title":"admin proposes Project1 (preconfigured)","page":"/my/hackathon/{id}/projects/proposals/propose","provides":"hackathonId, trackId, title, description","comment":"The admin pre-proposes Project1 so the event ships with projects ready — participants prefer and join these rather than proposing their own."}
{"type":"action","id":24,"actor":"admin1","title":"admin approves Project1","page":"/my/hackathon/{id}/projects/proposals → Approve","provides":"projectId","comment":"Approves Project1, making it a real project a team can be built around."}
{"type":"action","id":25,"actor":"admin1","title":"admin proposes Project2 (preconfigured)","page":"/my/hackathon/{id}/projects/proposals/propose","provides":"hackathonId, trackId, title, description","comment":"The admin pre-proposes Project2, so there are two projects to spread the two users across."}
{"type":"action","id":26,"actor":"admin1","title":"admin approves Project2","page":"/my/hackathon/{id}/projects/proposals → Approve","provides":"projectId","comment":"Approves Project2."}

# 1st User registration
{"type":"action","id":27,"actor":"user1","title":"logs in to the platform","page":"/ → “Log in” → Keycloak sign-in","provides":"username, password","comment":"Signs in through Keycloak; the session is what identifies them and their role on every step below."}
{"type":"pages-state","id":28,"at":"user1 signs in — a platform account now exists","who":"user1","page":"/manage/users","shows":"a new row in the platform-wide user list (admin only)"}
{"type":"action","id":29,"actor":"user1","title":"user1 registers","page":"/dashboard → Join","provides":"hackathonId","comment":"user1 registers; waitlisted until the organiser approves."}
{"type":"pages-state","id":30,"at":"user1 joins the hackathon","who":"user1","page":"/my/hackathon/{id}/participants","shows":"a new row badged “Waitlisted” in Manage participants (the registration list)"}
{"type":"action","id":31,"actor":"admin1","title":"admin approves user1","page":"/my/hackathon/{id}/participants → Approve","provides":"hackathonId, userId","comment":"The organiser confirms user1 — approval turns a registrant into a full participant."}
{"type":"pages-state","id":32,"at":"admin approves user1","who":"user1","page":"/my/hackathon/{id}/participants","shows":"user1's row flips from “Waitlisted” to “Confirmed”"}
{"type":"action","id":33,"actor":"user1","title":"user1 configures their profile (name, skills, avatar image URL)","page":"/account — edit profile","provides":"displayName, affiliation, skills, avatarUrl","comment":"user1 fills their platform profile. The avatar is set from an image URL hosted by an EXTERNAL provider — a link, not an upload; the platform stores only the URL."}
{"type":"action","id":34,"actor":"user1","title":"user1 submits the registration form (participation)","page":"/register/{id} — the registration form","provides":"hackathonId, responses, consents","comment":"user1 answers the admin's custom registration questions (affiliation, experience, skills, motivation, diet, T-shirt) and ticks the required consent; the answers are stored against their participation."}

# 2nd User registration
{"type":"pages-state","id":35,"at":"user1 submits the registration form","who":"user1","page":"/my/hackathon/{id}/participants → View","shows":"their custom-form answers (affiliation, experience, motivation …) are now on file under their row"}
{"type":"action","id":36,"actor":"user2","title":"logs in to the platform","page":"/ → “Log in” → Keycloak sign-in","provides":"username, password","comment":"Signs in through Keycloak; the session is what identifies them and their role on every step below."}
{"type":"pages-state","id":37,"at":"user2 signs in — a platform account now exists","who":"user2","page":"/manage/users","shows":"a new row in the platform-wide user list (admin only)"}
{"type":"action","id":38,"actor":"user2","title":"user2 registers","page":"/dashboard → Join","provides":"hackathonId","comment":"user2 registers."}
{"type":"pages-state","id":39,"at":"user2 joins the hackathon","who":"user2","page":"/my/hackathon/{id}/participants","shows":"a second row badged “Waitlisted”"}
{"type":"action","id":40,"actor":"admin1","title":"admin approves user2","page":"/my/hackathon/{id}/participants → Approve","provides":"hackathonId, userId","comment":"The organiser confirms user2."}
{"type":"pages-state","id":41,"at":"admin approves user2","who":"user2","page":"/my/hackathon/{id}/participants","shows":"user2's row flips to “Confirmed”"}
{"type":"action","id":42,"actor":"user2","title":"user2 configures their profile (name, skills, avatar image URL)","page":"/account — edit profile","provides":"displayName, affiliation, skills, avatarUrl","comment":"user2 fills their profile and sets an avatar from an EXTERNAL image URL (a link to a picture hosted elsewhere)."}
{"type":"action","id":43,"actor":"user2","title":"user2 submits the registration form (participation)","page":"/register/{id} — the registration form","provides":"hackathonId, responses, consents","comment":"user2 answers the same custom questions with their own responses and submits their participation."}
{"type":"pages-state","id":44,"at":"both users are registered and confirmed participants","phase":"Ideation","capabilities":["register","propose_projects","set_team_preferences"],"sees":{"anonymous":"the public event page (never the member area)","admin1":"the participants roster with two confirmed people and their registration answers","user1":"the member area — overview, projects, teams, and their own profile; may set preferences","user2":"the member area; may set preferences"}}

# Projects preferences
{"type":"action","id":45,"actor":"user1","title":"user1 prefers Project1","page":"/my/hackathon/{id}/projects — mark a preferred project","provides":"projectId","comment":"user1 marks the project they want to work on; organisers use preferences for team matching."}
{"type":"pages-state","id":46,"at":"user1 sets a project preference","who":"user1","page":"/my/hackathon/{id}/projects — preferences export","shows":"user1's preferred project shows in the organiser's preferences export"}
{"type":"action","id":47,"actor":"user2","title":"user2 prefers Project2","page":"/my/hackathon/{id}/projects — mark a preferred project","provides":"projectId","comment":"user2 marks their preferred project."}

# Team formation
{"type":"action","id":48,"actor":"admin1","title":"admin exports preferences for team matching in csv/json","page":"/my/hackathon/{id}/projects — Export preferences","provides":"hackathonId","comment":"The organiser pulls everyone's preferences to inform how teams are formed."}
{"type":"action","id":49,"actor":"admin1","title":"admin creates Team1 on Project1","page":"/my/hackathon/{id}/teams/manage → New team","provides":"name, projectId","comment":"Team1 is bound to Project1 — a seat the CSV import will fill."}
{"type":"action","id":50,"actor":"admin1","title":"admin creates Team2 on Project2","page":"/my/hackathon/{id}/teams/manage → New team","provides":"name, projectId","comment":"Team2 is bound to Project2."}
{"type":"action","id":51,"actor":"admin1","title":"admin defines team membership from an uploaded CSV","page":"/my/hackathon/{id}/teams/manage → Import → upload CSV → Apply","provides":"upload teams.csv (columns: user_email, project, team)","comment":"The organiser assigns each confirmed participant to a team in bulk: user1 joins Team1, user2 joins Team2. Align the copy strings to the Manage-Teams importer when running for real."}
{"type":"pages-state","id":52,"at":"teams are formed","phase":"Ideation","capabilities":["set_team_preferences"],"sees":{"anonymous":"the public event page","admin1":"the teams board with Team1 and Team2 and their members","user1":"their team (Team1) and its page","user2":"their team (Team2)"}}
{"type":"pages-state","id":53,"at":"teams assigned from the CSV","who":"user1 & user2","page":"/my/hackathon/{id}/teams","shows":"user1 on Team1 and user2 on Team2 in the teams board / people panel"}

# Hackathon phase
{"type":"action","id":54,"actor":"admin1","title":"admin advances to the Hacking phase","page":"/my/hackathon/{id}/manage — Now / Next → advance","provides":"hackathonId, phaseId","comment":"Moving the marker into Hacking opens the submissions the phase names."}

# Projects submissions
{"type":"pages-state","id":55,"at":"Hacking phase — submissions open","phase":"Hacking","capabilities":["create_project_submissions"],"sees":{"anonymous":"the public event page","admin1":"submissions as they arrive","user1":"a “Turn in work” control for Team1","user2":"a “Turn in work” control for Team2"}}
{"type":"action","id":56,"actor":"user1","title":"user1 turns in Team1's work","page":"/my/hackathon/{id}/submissions","provides":"teamId, projectId, result, form","comment":"user1 submits Team1's work against Project1."}
{"type":"pages-state","id":57,"at":"user1 turns in Team1's work","who":"Team1","page":"/my/hackathon/{id}/submissions","shows":"Team1's submission appears for organisers to review"}
{"type":"action","id":58,"actor":"user2","title":"user2 turns in Team2's work","page":"/my/hackathon/{id}/submissions","provides":"teamId, projectId, result, form","comment":"user2 submits Team2's work."}

# Voting phase
{"type":"action","id":59,"actor":"admin1","title":"admin advances to the Judging phase","page":"/my/hackathon/{id}/manage — Now / Next → advance","provides":"hackathonId, phaseId","comment":"Advancing to Judging opens the VOTE capability, which was linked to this phase in setup."}
{"type":"action","id":60,"actor":"admin1","title":"admin opens voting","page":"/my/hackathon/{id}/voting → Open voting","provides":"hackathonId, votingEnabled","comment":"Voting needs BOTH this master switch and the VOTE capability the Judging phase opened; the organiser flips it here."}
{"type":"pages-state","id":61,"at":"Judging phase — voting open","phase":"Judging","capabilities":["vote"],"sees":{"anonymous":"the public event page","admin1":"the tally as ballots arrive (organisers do not vote)","user1":"a ballot to cast (not for their own team)","user2":"a ballot to cast"}}
{"type":"action","id":62,"actor":"admin1","title":"admin creates a vote category","page":"/my/hackathon/{id}/voting → Add category","provides":"hackathonId, name, description, votingMethod, voterType","comment":"A category is what ballots are cast in; opening voting needs at least one."}
{"type":"action","id":63,"actor":"user1","title":"user1 casts a ballot (for Team2)","page":"/my/hackathon/{id}/voting → cast a ballot","provides":"singleChoice","comment":"user1 votes for the other team's submission — own-team voting is off in this event's policy."}
{"type":"pages-state","id":64,"at":"user1 casts a ballot","who":"user1","page":"/my/hackathon/{id}/voting — tally (organiser-only)","shows":"user1's ballot is counted in the tally; ballots are organiser-only to read"}
{"type":"action","id":65,"actor":"user2","title":"user2 casts a ballot (for Team1)","page":"/my/hackathon/{id}/voting → cast a ballot","provides":"singleChoice","comment":"user2 votes for the other team."}

# Winners assignation
{"type":"action","id":66,"actor":"admin1","title":"admin records the winner","page":"/my/hackathon/{id}/voting → record placement","provides":"categoryId, submissionId, position, title","comment":"The admin places the winner from the tally — results are advisory until the admin records them (the admin has the final voice)."}
{"type":"action","id":67,"actor":"admin1","title":"admin publishes the results","page":"/my/hackathon/{id}/manage — capability panel (View results)","provides":"hackathonId, capabilities","comment":"Turning on VIEW_RESULTS is what publishes the placements to participants."}
{"type":"pages-state","id":68,"at":"results published","phase":"Judging","capabilities":["vote","view_results"],"sees":{"anonymous":"the public event page (and published winners, if surfaced there)","admin1":"the recorded placements","user1":"the published winner on the results page","user2":"the published winner"}}
{"type":"action","id":69,"actor":"user1","title":"user1 views the published results","page":"/my/hackathon/{id}/voting — Results","provides":"categoryId","comment":"user1 sees the published winner. The event is complete."}
{"type":"action","id":70,"actor":"user2","title":"user2 views the published results","page":"/my/hackathon/{id}/voting — Results","provides":"categoryId","comment":"user2 sees the published winner. The event is complete."}
Loading
Loading