Skip to content

Frontend Artist

Artist company profiles expose the same shared organization access contract as Promoters: invitations, Auth catalog-backed module/general permissions, Core business-unit structure (create, rename, archive), and Auth BU assignments. Granting Finance access assigns the user at Submitter level; Finance workflow roles — Submitter/Approver, approval limits, primary approver, Primary Finance Admin — remain Finance-owned.

Parity caveat: the Artists panel is a simpler implementation than the Promoters one. It has no view/edit permission pairing, no bulk select-all controls, no department-head toggle, and it does not filter the permission catalog to an Artists-owned namespace the way Promoters does. Treat Promoters as the reference implementation. See the Company Access Ownership Matrix.

Related documentation: Artist Module Backend · Artist Product Vision · Artist Endpoint Map · Artist Source of Truth Registry · Middle Agent Workspace

Frontend-Kisum-Artists is implemented.

The repo README is stale in places; the accurate current status comes from the repo TODO/changelog plus the live route tree.

This is the artist / agency operational app.

It is the artist-side consumer of Backend-Kisum-Artists and should be read as:

  • agency / management workflow UI
  • not the promoter marketplace UI
  • not a mock or planning-only repo
  • Next.js 16 + React 19 + Tailwind v4

  • shared Kisum SSO cookie model

  • Authorization: Bearer + x-org calling model (artistsFetch uses credentials: 'omit' — JWT is header-only; persona backend does not read cookies)

  • sidebar app shell with company switching

  • notification bell (2026-07-15): top-right header on @main and Middle Agent desks — aggregates inbox/tasks/activity (V1/V2) and, when deployed, GET /api/v1/notifications with read/unread (V3). Sidebar inbox badge and header share ['booking-inbox','summary'].

  • hard no-agency gate

  • Profile/company bootstrap calls Artists /api/users/companies* (Artists BFF proxies shared Promoters profile routes). Promoters package guard does not block artist JWTs on /api/users/*.

  • People messages (/messages, 2026-07-23): same UX as Promoters — search teammates by name/email, conversation titles show name (email), unread on sidebar Messages and header inbox icon; BFF GET/POST /api/v1/messaging/* (+ Centrifugo when NEXT_PUBLIC_CENTRIFUGE_URL is set).

  • /venues — searchable venue directory: name search, country (ISO2) + city filters, list/cards views, pagination. Shows all venues — active, inactive, claimed, and unclaimed/sleeping — each with a status badge (Active / Inactive / Unclaimed).
  • /venues/[id] — venue detail with Overview / Location / Facilities / Commercial tabs. Commercial shows rent + contacts (product decision: agencies see the full profile). The Overview tab opens with a photos gallery (hero + media images, grid + “show all photos” lightbox), mirroring the Promoters venue hero. :id is the Venues UUID (as in /venues/<uuid> links) or numeric venue id.
  • Browse + view only — no marketplace, booking, spaces, or availability (that stays in the Promoters/Venues apps). The Artists app never writes venue master data.
  • Source: read-only via Backend-Kisum-Artists GET /api/v1/venues[/:id], which proxies the canonical Venues admin feed. Service module: src/services/venues/*. Sidebar has a Venues entry.
  • Fixes the previously blank /venues/<id> page (the route did not exist before, so it fell through to the @main null default).
  • /promoters — searchable promoter tenant directory (Kisum promoters only — not the Artists industry directory): name search, country filter, list/cards views, pagination.
  • /promoters/[id] — detail: header (logo, name, country, shows-delivered count, cancelled count — muted/secondary); People (decision maker first, then department heads grouped by department, then everyone else — name, role, department, work email only, never phone); Past shows (paginated table — date, artist, venue, country; filterable by country and artist).
  • First cross-tenant data disclosure on the platform — no consent record exists anywhere in Auth or Core; the substitute is a visible notice in the Promoters app profile page, not a stored consent row.
  • Browse + view only — no marketplace or booking writes on promoter directory rows. People messaging (/messages) uses the shared inbox via Artists BFF → Backend-Kisum-Chat (same Auth user threads as Promoters/Venues).
  • Source: read-only via Backend-Kisum-Artists GET /api/v1/promoters[/:id[/shows]], which proxies Backend-Kisum-Promoters’ aggregated internal feed (Core identity + Auth staff/department-head + Promoters’ own events + Artists/Venues name resolution). Service module: src/services/promoters/*. Sidebar has a Promoters entry (Megaphone icon).
  • Department names are resolved from Core business units (GET /internal/companies/{id}/business-units), not just an opaque BU UUID — BU UUIDs are random per company; systemTemplateKey is the stable cross-company id, never the UUID.
  • Every field is null-guarded: missing logo falls back to initials, absent country/email/department-head are simply omitted, no field absence 500s the page.
  • Settings -> Agency is live
  • bridged mode: current agency summary + link into company detail
  • not-bridged mode: claim sleeping agency, create new agency request, review own requests
  • operational routes stay locked until the app can confirm the active Auth company is bridged to an artists-company
  • artists list + detail + edit
  • companies list + detail
  • people list + detail + edit (country/city + phone dial from countries)
  • people detail tabs: Overview / Roster / Deals / Events (upcoming roster bookings)
  • people Roster tab: Claim artist drawer (POST /api/v1/people/{id}/roster-claims) — artist search, structured territory multi-picker (regions/subregions/countries + exclusions; Worldwide = region 0), person_role_type role; pending claims show territory summary with Edit (PATCH) and Delete (DELETE cancel) until Admin approves
  • people edit form opens inline inside the detail card (not a separate page shell); Title syncs to company affiliation + Promoters staff display on save
  • people affiliations (companies + artist teams on detail)
  • roster surface — /artists (filters + list/cards); legacy /roster redirects here; detail stays /artists/[id]
  • company claims
  • artist representation claims / approve / reject / disputes
  • availability CRUD — artist detail ?tab=availability: one side sheet for create/edit (TerritoryPicker, flexible dates, kind, notes); detail drawer per window (row click or View) with Edit/Delete and org-scoped guest intake link for available windows. Published available windows surface in the promoter marketplace.
  • touring/artists/[id]/tours and /touring roster shortcut: confirmed bookings only (accepted offers). No manual “create tour” form. Flow: agent publishes availability → promoters offer (marketplace/public) → agent confirms → confirmed dates appear in Touring for logistics/routing work. Pending offers and open windows do not appear in Touring.
  • booking itinerary
  • logistics submissions review
  • relationships directory + detail + org-private notes/flags/ratings
  • agency dashboard, activity, tasks
  • booking finance visibility + handoff dialog

Middle Agent Workspace (non-direct agencies)

Section titled “Middle Agent Workspace (non-direct agencies)”

Nav visibility matches Promoters (2026-07-14): the Middle Agent sidebar entry (violet pill directly below the company switcher) appears as soon as the company has the middle_agency addon active (showMiddleAgentNav = hasMiddleAgencyAddon, checked against activeModules and activePackage.addons). Entering the desk additionally requires artist_workspace_profiles.organization_type to be middle_agent or hybrid (canUseMiddleAgentDesk); otherwise the desk layout redirects to /settings/middle-agent-workspace (no addon → redirect to /dashboard with a billing link). There is no Middle Agent link in the profile dropdown — the sidebar pill is the single entry point, same as Promoters.

The desk is a parallel deal desk (not mixed into direct booking-requests):

  • /settings/middle-agent-workspace — workspace profile
  • /middle-agent — dashboard + urgent actions
  • /middle-agent/roster — private workspace artist cards
  • /middle-agent/contacts — source/buyer CRM
  • /middle-agent/offers + /middle-agent/offers/[id] — dual buyer/source panels, chain, commissions, AI panels
  • /middle-agent/calendar — opportunity calendar (disclaimer: not official availability)
  • /middle-agent/inbound-source-offers — source-agent inbox (direct reps)
  • /middle-agent/partners, /middle-agent/commissions, /middle-agent/reports

Hybrid orgs may show both Middle Agent nav and direct Bookings nav. API: direct to Backend-Kisum-Artists /api/v1/middle-agent/* with artist.middle_* permission gates.

Representative live route families include:

  • /
  • /activity
  • /tasks
  • /artists — artist directory (filters, search, pagination; cards by default, ?view=list for table). Legacy /roster redirects here.
  • /artists/[id] — URL segment is the numeric directory id when available (/artists/123, not uuid); legacy uuid/slug links redirect after load. Tabs: Profile (personal info, genres, platforms), Team, Management, Availability (?tab=availability). Legacy ?tab=genres / ?tab=platforms open Profile.
  • /artists/[id]/edit — Admin-parity multi-step artist form (ArtistFormLayout): basic info, platform data, review/submit; saves via Backend-Kisum-Artists (PATCH artist + PUT profile/genres/platform-accounts/provider-refs). Optional NEXT_PUBLIC_ADMIN_API_BASE_URL proxies Spotify search, external platform fetch, AI bio, and file upload from Admin BFF.
  • /promoters — promoter tenant directory (search, country filter, pagination)
  • /promoters/[id] — promoter detail (identity, staff/department heads, past shows)
  • /companies
  • /companies/[id] — the Users / Invitations / Teams panels read company-workspace endpoints (/api/company-users, /api/company-user-invitations, /api/company-teams, /api/companies/active-package) via the Artists BFF catch-all → Promoters BFF. These are promoter company-workspace features with no native artist backing; they fail (“not linked to promoter data yet” / legacy company storage disabled) for artist agency companies with no legacy promoter Mongo mapping. As of 2026-07-14 services/apis/companies/api.ts degrades reads to an empty result (no error overlay) and mutations throw clean errors (honest toasts).
    • Teams panel — decision (2026-07-14): hide for artist agency companies; do not back natively. The Teams tab is role-gated to promoter, and the getCompanyTeams query now only runs when activeRole === 'promoter', so agency companies never call the endpoint (previously the query fired anyway and degraded to empty). The other team picker (ComboboxTeamsCompanies in the user-detail permission editor) is likewise gated behind activeRole === 'promoter', so no agency-side surface fetches teams. Rationale: company teams are being consolidated as Auth-owned shared teams — cross-module, shared across Promoters/Finance (see Permissions and Permissions Catalog); the Promoters company_teams store this endpoint reads is deprecated (“moved to Auth Backend”) (see Promoters API). A native Artists teams store would create a fourth, module-siloed teams source and is explicitly not the direction. Long-term: artist agency companies participate in teams (if at all) only through the Auth-owned shared-teams API — the same path Promoters/Finance use via the “Users & Access” V2 editor — surfaced by a future Users & Access surface in this app; never a native Artists backing and never the deprecated legacy path.
    • The users panel (CompaniesUsers, ported from Promoters) also calls useOnborda(), so the app root provides OnbordaProvider (context only, no tour overlay) to stop a runtime crash.
  • /companies/[id]/contract-templates — create sends metadata + templateFormat: "docx" (v1 DOCX-only); upload the Word file on /contract-templates/[id] via Upload source (drag & drop or browse; JSON base64 to POST …/upload-source; the <<PLACEHOLDER>> manifest is derived on upload and a toast warns when none are found; the dialog links Download the Kisum standard template). The Source file card also offers Delete file (confirmation dialog → DELETE …/source; removes the S3 object, clears the reference and the derived variables). Files land in S3 kisum.io under files/artists/contracts/templates/, served at https://files.kisum.io/<key>.
  • Contract generation: the booking’s Create-contract dialog always offers “Kisum standard template (auto-filled)” (templateId: 'default') plus the agency’s active templates; on create the backend renders the filled DOCX immediately (toast reports remaining manual fields). The contract Versions panel’s Generate document re-renders via POST /contracts/{id}/generate; version rows link the file (signed PDF → rendered DOCX → source) and show the amber complete-before-signature checklist.
  • Fill fields: the contract Versions panel’s “Fill fields” dialog lists every open <<MARKER>> (plus previously saved values); filled values regenerate the document and persist per contract across regenerations (empty clears). This is the manual path until company legal profiles / rider storage land and auto-fill those markers.
  • Mutual terms acceptance (2026-07-17, Phase C): accepting an offer whose offersheet carries mutualTerms opens the blocking MutualTermsDialog — per-term explicit accept (value-bound; disabled Accept until all checked), “Propose different terms” routes to counter; the offer detail shows a read-only “Contract terms” card with accepted/pending badges. Offers predating structured terms record platform defaults. The dialog’s key/value derivation mirrors the backend’s proposedMutualTermKeys — keep them in sync.
  • Contract signers: party-first picker — Agency/Artist side (company users + current user) vs Buyer/Promoter (the booking buyer’s staff via the cross-tenant promoters directory; work email only). Picking a person fills name/email and sets role to the party; manual entry remains for non-Kisum signers and is forced for external buyers.
  • /people
  • /people/[id]
  • /people/[id]/edit
  • /availabilityagency availability calendar (2026-07-14): density-first Month heatmap (per-day available/hold/blocked counts from GET /api/v1/agency/availability/summary), a search + filter bar (artist / kind / territory), a day drill-down panel, an Agenda list, and a Timeline (Gantt, capped at 50 artist lanes with an honest “narrow with filters” note). Day/agenda/timeline read GET /api/v1/agency/availability. Replaces the old roster-shortcut card list. Final-review fixes (2026-07-14, same day): the search bar’s artist filter now actually scopes results (the backend previously parsed but never applied it — a no-op); the Month view shows a muted note when the summary’s capped flag is true (the backend’s internal 20,000-window fetch cap was hit for the visible range, so totals may undercount).
  • /booking-requestsagency booking inbox (2026-07-15): shows inbound booking_requests and incoming exclusive marketplace booking_offers (promoter-submitted, offerChannel=exclusive). Sidebar Inbox badge polls GET /api/v1/booking-inbox/summary (same pattern as Middle Agent /middle-agent/inbox-summary). Exclusive rows link to /booking-offers/{id}.
  • /booking-offers

Booking workflow ids (2026-07-15): /booking-requests/{id}, /booking-offers/{id}, and /bookings/{id} use the numeric database row id in URLs, links, breadcrumbs, tasks, and notifications — not uuid. The Artists API still accepts uuid on path params for legacy bookmarks; detail pages redirect to the numeric route after load.

Official marketplace availability delivers Exclusive offers to both /booking-requests (inbox + nav badge) and /booking-offers (negotiation pipeline). List and detail label them Exclusive / Official agency, show the submitted offersheet summary, and expose agency actions (counter, accept, decline). On create, Artists sends the same SES email notification path as middle-agent enquiries (MA_ENQUIRY_NOTIFY_EMAILS / EMAIL_FROM). Declined/cancelled/expired offers without a linked booking can be deleted from offer detail (DELETE /api/v1/booking-offers/{offerId}). They never appear in /middle-agent/inbox or require the Middle Agent addon. Acceptance produces the normal confirmed booking used by Contracts, Touring, and Logistics.

  • /bookings
  • /bookings/[id]
  • /contracts
  • /contracts/[id]
  • /touring
  • /tour-plans/[id]
  • /logistics
  • /logistics-submissions/[id]
  • /relationships
  • /relationships/[id]
  • /finance-visibility
  • /settings/agency
  • /settings/middle-agent-workspace
  • /middle-agent (+ roster, contacts, offers, calendar, inbound-source-offers, partners, commissions, reports)

The detailed implementation contract lives in Frontend-Kisum-Artists/PERMISSIONS_MATRIX.md. That file describes a target design, not current runtime behavior — its own first lines say so.

Core owns artist-company business units and seeds three by default (Booking & Representation, Touring & Logistics, Finance). The set is not fixed at three: the Artists access panel can create, rename, and archive business units, so a company’s structure will diverge from the seed. Auth owns shared teams, memberships, permission rules, scopes, individual denies, Finance roles, and rollout mode. Agent portfolios are teams; access to an artist or booking still requires an explicit matching assignment.

The model separates Agent, Booker, Tour Manager, Tour Staff, Finance, Artist Self, tenant Super Admin, and Kisum System Admin responsibilities. Bookers may draft and counter only when granted; final accept, decline, and cancel actions remain separate. Touring roles receive logistics-only views with commercial data redacted. Finance uses the shared platform workflow. Artist master-data changes remain proposals until approved by Kisum System Admin, including proposals submitted by tenant Super Admin.

This is a target design only. Current runtime behavior is unchanged until the route-policy manifest, Auth catalog, domain enforcement, SHADOW evaluation, migration preflight, and company-by-company activation are implemented and verified.

Shared ArtistRosterCard (Frontend-Kisum-Artists/src/components/roster/artist-roster-card.tsx) renders artist photos from imageUrl / artistImageUrl with initials fallback (Kisum purple tokens from the platform design system).

SurfaceData source
/artists (cards view)GET /api/v1/artistsimageUrl
People → Roster tabGET /api/v1/people/{id}/rosterartistImageUrl
/availability(2026-07-14) now the agency availability calendar — no longer a roster-card grid. Calendar data: GET /api/v1/agency/availability/summary (Month heatmap) + GET /api/v1/agency/availability (day/agenda/timeline); roster pipeline still feeds the artist filter options. Artist avatars/initials appear only in drill-down/agenda rows.
/artists/[id] headerGET /api/v1/artists/{id}imageUrl; ?tab=availability opens Availability

These items should be marked as not implemented yet, not described as shipped:

  • delete itinerary item endpoint
  • cross-booking logistics inbox endpoint
  • edit/delete relationship notes, flags, ratings
  • finance-handoff audit list
  • create/archive flows for some directory entities
  • reference-data admin surfaces
  • promoter UX stays out of this app
  • private relationship inputs stay org-private
  • Finance remains the upstream source of truth
  • browser never sends internal API keys

Any doc that still describes this repo as a scaffold/chassis-only app is outdated.

Booking screens — Buyer/Show model (2026-07-16)

Section titled “Booking screens — Buyer/Show model (2026-07-16)”

Booking detail is now single-fetch: artist image, fee, venue UUID, buyer and show date/time all arrive on GET /bookings/:id (the old getArtist + getBookingOffer side-queries are gone). The party card is labeled Buyer and deep-links to /promoters/{buyer.id} (the cross-tenant promoters directory, keyed by Core company UUID) — never to the legacy /companies/* CRM detail; external/guest buyers render as plain text. Venue names link to /venues/{venueId}. List and inbox headers say Buyer (the request pipeline keeps its legacy fields internally). Offer detail renders shows (single-day date + separate HH:MM time), and the version history reads “sent by buyer/agency”.