Creating a Project
Start a new project from the Projects page or during event registration:Project Form Fields
Required Fields
- Name - Project title (used to auto-generate slug)
- Description - What does it do? (supports simple markdown)
Optional Fields
- Starting point - Choose “New project” (from scratch) or “Existing project” (building on something)
- Goal - What you want to accomplish (supports markdown)
- GitHub URL - Link to repository
- Live URL - Deployed project URL
Descriptions and goal text support simple markdown formatting for bold, italic, and links.
Project Slugs
Every project gets a unique slug for its URL:Slug Generation
-
Auto-generated - Derived from project name:
- Lowercase
- Replace non-alphanumeric with hyphens
- Strip leading/trailing hyphens
- Max 60 characters
-
Custom slug - Click “Customize URL” to set manually:
- Lowercase letters, numbers, hyphens only
- Real-time availability check (debounced 400ms)
- Must be unique across all projects
Slug validation
Server action
checkProjectSlugAvailability runs before creation/updateVisual feedback
Green checkmark (available), red X (taken), spinner (checking)
Project Visibility
Projects can be public or event-linked:- Standalone projects - Created via
/projects/new, visible on your profile - Event projects - Linked to hackathons via
eventProjectsjunction table - Filtering - Public queries filter by event and exclude projects owned by banned/hidden profiles
The
getProjectBySlug query includes project members and event links via Drizzle’s relational with syntax.Editing Projects
Project owners can edit any field after creation:Update fields in /projects/{slug}/edit
Shared
ProjectForm component handles both create and edit modesOwnership Checks
All mutation actions verifyproject.profileId === currentUserProfileId:
updateProject- Edit project fieldsdeleteProject- Remove project and cascade cleanup- Team actions - Invite, revoke, remove members
Deleting Projects
Owners can delete projects with confirmation:Linking Projects to Events
Projects can be submitted to events (like hackathons):During Onboarding
- Hackathon registration flow creates project and links it via
eventProjectstable - Junction record stores
eventId,projectId, andsubmittedAttimestamp
Standalone Creation
- Projects created outside events can be linked later if an
eventIdis provided - Query
getHackathonProjectsfilters by event slug and includes team members
Event badge
Project detail pages show event badges for all linked events
Unique constraint
One project can only be linked to each event once (unique on
eventId, projectId)Project Detail Pages
Public project pages at/projects/{slug} display:
- Header - Name, starting point badge, event badges
- Description - Markdown-rendered project description
- Goal - Highlighted goal text (if set)
- Links - GitHub and Live site links
- Team section - Owner, members, and invite UI (owner-only)
- Actions - Edit and Delete buttons (owner-only)
Team Section
See the Teams documentation for details on inviting teammates and managing project members.Server Actions
All project mutations use server actions inapp/(app)/projects/actions.ts:
createProject- Insert project, optionally link to event, fire Discord webhookupdateProject- Update fields with ownership checkdeleteProject- Cascade cleanup in transaction, revalidate pathscheckProjectSlugAvailability- Real-time slug uniqueness check
- Authenticates via Clerk
auth() - Calls
ensureProfile()to get profile ID - Validates inputs
- Performs database operation
- Catches errors and reports to Sentry
- Returns
{ success: boolean, error?: string, data?: T }