Skip to main content
Events are time-bound community gatherings like hackathons where builders come together to ship AI projects. Buildstory’s event system handles registration, team preferences, and project submissions.

Event Structure

Events are stored in the events table with these fields:
  • name - Event title (e.g., “Hackathon 00”)
  • slug - Unique URL identifier (e.g., “hackathon-00”)
  • description - Event details and rules
  • startsAt / endsAt - Event time window
  • registrationOpensAt / registrationClosesAt - Registration period
  • status - Current event phase (see lifecycle below)

Hackathon 00

The inaugural Buildstory event (March 1-8, 2026) — a 7-day AI building sprint

Event-first design

All features are built to serve events but work independently for long-term use

Event Status Lifecycle

Events progress through five distinct phases:
1

draft

Event created but not yet visible to users
2

open

Registration is open, users can sign up and create projects
3

active

Event is live, participants are building and logging updates
4

judging

Building phase complete, submissions under review
5

complete

Winners announced, event archived
The status enum is defined in lib/db/schema.ts as eventStatusEnum and enforced at the database level.

Registration Flow

New users register for events through the guided onboarding flow at /hackathon:

Step 1: Identity

  • Set display name and username (with real-time availability check)
  • Select country and region (ISO 3166 codes with virtualized comboboxes)

Step 2: Experience

  • Choose experience level:
    • Getting started - New to building with AI
    • Built a few things - Shipped a project or two
    • Ships constantly - Building with AI daily

Step 3: Commitment Level

  • Set your availability:
    • All in - Full-time focus
    • Daily - Regular daily sessions
    • Nights & weekends - Part-time around work
    • Not sure - Playing it by ear

Step 4: Team Preference

  • Declare your team status:
    • Solo - Building alone
    • Has team - Team formed, roster locked
    • Has team (open) - Team formed, accepting members
    • Looking for team - Open to invites
The team preference determines whether you appear in team-finding searches and can receive direct invites.

Step 5: Bridge

  • Choose your path forward:
    • Add a project - Create your hackathon project now
    • Skip for now - Register without a project (can add later)
    • Joining a team - Search for an existing project to join

Steps 6-8: Project Creation (Optional)

  • Project basics - Name, description, custom slug
  • Starting point - New project vs. existing project
  • Project goal - What you want to accomplish

Step 9: Celebration

  • Confetti animation, registration complete!

9 steps

Guided multi-step wizard with progress stepper

Dev mode

?dev=true enables step jumping and mock data for testing

State management

Client-side orchestrator in hackathon-onboarding.tsx owns all state

Event Registrations

Registrations are stored in eventRegistrations with a unique constraint on (eventId, profileId):
{
  eventId: uuid,
  profileId: uuid,
  teamPreference: "solo" | "has_team" | "has_team_open" | "looking_for_team",
  commitmentLevel: "all_in" | "daily" | "nights_weekends" | "not_sure" | null,
  registeredAt: timestamp
}

Completing Registration

The completeRegistration server action:
  1. Validates all required fields (username, team preference)
  2. Checks for existing registration (prevents duplicates)
  3. Updates profile with identity/location/experience
  4. Inserts eventRegistrations row
  5. Fires Discord signup webhook
  6. Checks and fires milestone webhooks (10, 25, 50, 100, etc.)
If a username is already taken, the action fails with a unique violation error caught via isUniqueViolation helper (Neon NeonDbError with code === "23505").

Team Preferences

Your team preference affects discoverability:
PreferenceCan receive invites?Shows in search?Use case
SoloNoNoBuilding alone
Has teamNoNoTeam locked
Has team (open)YesYesAccepting members
Looking for teamYesYesOpen to any invite
The allowInvites profile field (privacy setting) overrides team preference — if disabled, you won’t receive any invites regardless of team preference.

Commitment Levels

Commitment level is optional and stored in eventRegistrations:
  • Used for self-pacing and community matching
  • Not enforced or validated during the event
  • Helps set expectations for team formation

Linking Projects to Events

Projects can be associated with events via the eventProjects junction table:
  • During onboarding - createOnboardingProject auto-links to event
  • Standalone creation - createProject accepts optional eventId param
  • Unique constraint - One project per event (prevents duplicate submissions)

Querying Event Projects

const projects = await getHackathonProjects();
// Returns all projects linked to HACKATHON_SLUG
// Filters out projects from banned/hidden profiles
// Includes team members via relational query

Discord Notifications

Event actions trigger fire-and-forget Discord webhooks:
  • Signup - When completeRegistration succeeds
  • Project creation - When createOnboardingProject or createProject with eventId
  • Milestones - At 10, 25, 50, 75, 100, 150, 200, 250, 500, 1000 signups/projects
All Discord calls are wrapped in try-catch and report errors to Sentry without blocking the user flow.

Public Stats

The getPublicStats query returns real-time event metrics:
{
  totalProfiles: number,      // All visible profiles registered
  totalProjects: number,      // All projects linked to hackathon
  totalEventRegistrations: number
}
Used on the landing page and dashboard for live activity counters.

Build docs developers (and LLMs) love