Profiles & cities
profiles
Professional profiles — venues, artists, organizers — under the unified /@<username> handle namespace (v4-style). Dancers keep their own row + handle in `dancers`; the /@handle route resolves either. Reviews attach polymorphically by (type, username).
Columns
| Column | Type | Null | Default | Keys |
|---|---|---|---|---|
| id | uuid | no | gen_random_uuid() | PK |
| username | text | no | — | unique |
| type | text venueartistorganizerpromoter | no | — | |
| name | text | no | — | |
| city | text | yes | — | |
| city_slug | text | yes | — | |
| photo | text | yes | — | |
| bio | text | yes | — | |
| styles | json | yes | [] | |
| languages | json | yes | [] | |
| address | text | yes | — | |
| floor_type | text | yes | — | |
| venue_type | text | yes | — | |
| map_url | text | yes | — | |
| amenities | jsonb | no | [] | |
| capacity | integer | yes | — | |
| opening_hours | jsonb | no | [] | |
| floor_plan | text | yes | — | |
| contact | jsonb | no | {} | |
| lat | double precision | yes | — | |
| lng | double precision | yes | — | |
| guidelines | text | yes | — | |
| booking_model | text freecommercial | no | "commercial" | |
| moderator_name | text | yes | — | |
| moderator_handle | text | yes | — | |
| moderator_since | integer | yes | — | |
| socials | json | yes | [] | |
| photos | jsonb | no | [] | |
| videos | jsonb | no | [] | |
| claimed | boolean | yes | false | |
| status | text visiblehidden | no | "visible" | |
| roles | jsonb | no | [] | |
| created_at | timestamp | yes | now() | |
| source_ref | jsonb | yes | — |
Value lists come from .$type<'a' | 'b'>() in the schema — enforced in TypeScript only, not by the database.
Keys, constraints & indexes
Unique
- (username) profiles_username_unique
Indexes
No secondary indexes.
Foreign keys
None.
Referenced by
- bookable_spaces (profile_id)
- booking_inquiries (profile_id)
- booking_requests (profile_id, organizer_id)
- brand_looks (profile_id)
- events (host_profile_id)
- follows (profile_id)
- gig_applications (profile_id)
- gigs (poster_profile_id)
- giveaway_proposals (profile_id)
- guideline_versions (profile_id)
- handles (profile_id)
- inbound_requests (profile_id)
- mcp_audit (profile_id)
- moderator_elections (profile_id)
- network_links (profile_id, other_profile_id)
- organizer_subscriptions (profile_id)
- profile_access_log (profile_id)
- profile_affiliations (artist_profile_id, organizer_profile_id)
- profile_claims (profile_id)
- profile_contacts (profile_id)
- profile_invites (profile_id)
- profile_members (profile_id)
- profile_sites (profile_id)
- profile_suggestions (profile_id)
- tracked_links (profile_id)
Used by
Code that reads or writes this table, found by static analysis of the tRPC routers and API handlers (including helpers they call).
tRPC procedures
- auth.deleteAccount
- cityVideo.battleMatchup
- cityVideo.cityLeaderboard
- giveaway.propose
- giveaway.proposals
- giveaway.decideProposal
- entity.listVenues
- entity.listArtists
- entity.listCities
- entity.cityDirectory
- entity.listByCity
- entity.movedTo
- entity.getByHandle
- entity.promoterRoster
- booking.upcomingByCity
- booking.getEvent
- booking.request
- election.close
- gigs.applyTo
- gigs.applications
- events.festival
- referral.myLink
- referral.myResults
- referral.eventLinkResults
- referral.promoterDashboard
- referral.promoKit
- follow.myFollows
- business.canManage
- business.myProfiles
- business.search
- business.requestClaim
- business.findExisting
- business.create
- business.get
- business.spaces
- business.saveSpaces
- business.update
- businessEvents.list
- businessEvents.canEdit
- businessEvents.get
- businessEvents.create
- businessEvents.update
- businessEvents.duplicate
- businessEvents.seriesPreview
- businessEvents.createSeries
- businessEvents.series
- businessEvents.publishSeries
- businessEvents.attendees
- businessEvents.restore
- businessEvents.archive
- businessEvents.lineupPhotos
- businessEvents.venueIdeas
- businessEvents.searchProfiles
- businessEvents.addFromInstagram
- businessEvents.inbox
- businessFlyers.caption
- businessFlyers.writeCaption
- businessFlyers.saveCaption
- businessFlyers.state
- businessFlyers.readLook
- businessFlyers.make
- businessFlyers.directions
- businessFlyers.stop
- businessFlyers.again
- businessFlyers.feed
- businessFlyers.fix
- businessFlyers.refresh
- businessFlyers.batch
- businessFlyers.keep
- businessFlyers.copyLooks
- artistInvites.suggest
- artistInvites.pending
- artistInvites.profile
- artistInvites.saveProfile
- artistInvites.link
- artistInvites.notify
- artistInvites.get
- artistInvites.respond
- artistInvites.claim
- venueAsks.ask
- venueAsks.list
- venueAsks.book
- venueAsks.unbook
- inquiries.me
- inquiries.addToEvent
- inquiries.send
- inquiries.forProfile
- inquiries.setStatus
- businessPosts.list
- businessPosts.writeCaption
- businessPosts.saveCaption
- businessPosts.writeCaptions
- businessPosts.propose
- businessPosts.add
- businessPosts.update
- businessPosts.remove
- businessLooks.list
- businessLooks.create
- businessLooks.update
- businessLooks.remove
- businessLooks.read
- businessLooks.generate
- businessSite.get
- businessSite.save
- businessSite.contacts
- businessSite.updateContact
- businessSite.removeContact
- businessTeam.requestAccess
- businessTeam.team
- businessTeam.decideJoin
- businessTeam.setRole
- businessTeam.removeMember
- businessTeam.history
- businessNetwork.list
- businessNetwork.add
- businessNetwork.hide
- businessNetwork.restore
- organizerSubscription.createCheckout
- oauth.authorizeInfo
- oauth.connections
- oauth.auditForProfile
REST & webhooks
- GET /api/cities
- GET /api/cities/:slug
- GET /api/city-options
- POST /api/city-resolve
- GET /api/city-search
- GET /api/contacts/unsubscribe
- ANY /api/profiles/:username/contacts
- GET /api/profiles/:username/events
- GET /api/profiles/:username/site
- ANY /mcp
- ANY /mcp/public
Relations
Rendering diagram…
Diagram source
erDiagram
bookable_spaces {
uuid id PK
uuid profile_id FK
}
booking_inquiries {
uuid id PK
uuid profile_id FK
uuid requester_id FK
}
booking_requests {
uuid id PK
uuid space_id FK
uuid profile_id FK
uuid organizer_id FK
uuid requester_id FK
uuid moderated_by_id FK
}
brand_looks {
uuid id PK
uuid profile_id FK
uuid created_by FK
}
events {
uuid id PK
uuid host_profile_id FK
uuid edited_by FK
}
follows {
uuid id PK
uuid dancer_id FK
uuid profile_id FK
uuid target_dancer_id FK
}
gig_applications {
uuid id PK
uuid gig_id FK
uuid dancer_id FK
uuid profile_id FK
uuid decided_by FK
}
gigs {
uuid id PK
uuid dancer_id FK
uuid poster_profile_id FK
}
giveaway_proposals {
uuid id PK
uuid event_id FK
uuid proposed_by FK
uuid profile_id FK
uuid giveaway_id FK
uuid decided_by FK
}
guideline_versions {
uuid id PK
uuid profile_id FK
uuid election_id FK
uuid moderator_dancer_id FK
}
handles {
text handle PK
uuid dancer_id FK,UK
uuid profile_id FK,UK
}
inbound_requests {
uuid id PK
uuid dancer_id FK
uuid event_id FK
uuid profile_id FK
uuid gig_id FK
}
mcp_audit {
uuid id PK
uuid grant_id FK
uuid dancer_id FK
uuid profile_id FK
text confirm_nonce UK
}
moderator_elections {
uuid id PK
uuid profile_id FK
}
network_links {
uuid id PK
uuid profile_id FK
uuid other_profile_id FK
uuid created_by FK
}
organizer_subscriptions {
uuid id PK
uuid profile_id FK
uuid dancer_id FK
text stripe_subscription_id UK
}
profile_access_log {
uuid id PK
uuid profile_id FK
uuid actor_id FK
uuid subject_id FK
}
profile_affiliations {
uuid id PK
uuid artist_profile_id FK
uuid organizer_profile_id FK
}
profile_claims {
uuid id PK
uuid profile_id FK
uuid dancer_id FK
uuid decided_by FK
}
profile_contacts {
uuid id PK
uuid profile_id FK
uuid dancer_id FK
}
profile_invites {
uuid id PK
uuid profile_id FK
uuid event_id FK
uuid created_by FK
}
profile_members {
uuid id PK
uuid profile_id FK
uuid dancer_id FK
uuid added_by FK
}
profile_sites {
uuid profile_id PK,FK
uuid updated_by FK
}
profile_suggestions {
uuid id PK
uuid profile_id FK
uuid event_id FK
uuid suggested_by FK
}
profiles {
uuid id PK
text username UK
}
tracked_links {
uuid id PK
text code UK
uuid event_id FK
uuid profile_id FK
uuid created_by FK
}
profiles ||--o{ bookable_spaces : "profile_id"
profiles ||--o{ booking_inquiries : "profile_id"
bookable_spaces ||--o{ booking_requests : "space_id"
profiles ||--o{ booking_requests : "profile_id"
profiles |o--o{ booking_requests : "organizer_id"
profiles ||--o{ brand_looks : "profile_id"
profiles |o--o{ events : "host_profile_id"
profiles |o--o{ follows : "profile_id"
gigs ||--o{ gig_applications : "gig_id"
profiles |o--o{ gig_applications : "profile_id"
profiles |o--o{ gigs : "poster_profile_id"
events ||--o{ giveaway_proposals : "event_id"
profiles ||--o{ giveaway_proposals : "profile_id"
profiles ||--o{ guideline_versions : "profile_id"
moderator_elections |o--o{ guideline_versions : "election_id"
profiles |o--o{ handles : "profile_id"
events |o--o{ inbound_requests : "event_id"
profiles |o--o{ inbound_requests : "profile_id"
gigs |o--o{ inbound_requests : "gig_id"
profiles |o--o{ mcp_audit : "profile_id"
profiles ||--o{ moderator_elections : "profile_id"
profiles ||--o{ network_links : "profile_id"
profiles ||--o{ network_links : "other_profile_id"
profiles ||--o{ organizer_subscriptions : "profile_id"
profiles ||--o{ profile_access_log : "profile_id"
profiles ||--o{ profile_affiliations : "artist_profile_id"
profiles ||--o{ profile_affiliations : "organizer_profile_id"
profiles ||--o{ profile_claims : "profile_id"
profiles ||--o{ profile_contacts : "profile_id"
profiles ||--o{ profile_invites : "profile_id"
events |o--o{ profile_invites : "event_id"
profiles ||--o{ profile_members : "profile_id"
profiles ||--o{ profile_sites : "profile_id"
profiles ||--o{ profile_suggestions : "profile_id"
events |o--o{ profile_suggestions : "event_id"
events ||--o{ tracked_links : "event_id"
profiles ||--o{ tracked_links : "profile_id" Defined at server/database/schema.ts:327 as profiles.