Manage Boards, BoardTeams, and Leads inside the Face-app

The admin panel is hosted inside the face-app at face.zooly.ai/admin (no separate deployment). It is Cognito-gated and reuses the same zooly-auth SSO + requireAdmin middleware that powers merch-admin.

Access control

packages/team-leaderboard/client/src/app/admin/admin-auth.tsxAdminAuthGate:

  • Calls GET /api/merch/admin/me.
  • On 401, redirects to VITE_AUTH_URL for login (with a return-to).
  • If the signed-in user's role ≠ admin, shows an Access denied screen.

SPA deep-linking for /admin/* is handled by apps/face-app/vercel.json.

Layout & transport

  • packages/team-leaderboard/client/src/app/admin/admin-layout.tsx — header + nav + outlet wrapper.
  • packages/team-leaderboard/client/src/lib/admin-api.tsadminApi() fetch transport (credentials + base URL).
  • Routes registered under /admin in packages/team-leaderboard/client/src/app/routes.tsx.

Pages

PageFileWhat it does
Boards listadmin/boards-page.tsxList boards + "create board" modal
Board editoradmin/board-detail-page.tsxEdit board chrome (title, subtitle, hero images, background color, sponsor) + a table of its teams
Team editoradmin/team-detail-page.tsxEdit a team (name, colors, flag image, face-paint images, search terms, seed count) + the linked store
Leadsadmin/leads-page.tsxPaginated lead submissions with a kind filter + search

Reusable form fields

Inline-styled components in packages/team-leaderboard/client/src/app/admin/components/ (shared styles in field-styles.ts):

  • Image uploadDropzone.tsx (drag-and-drop via react-dropzone), ImageDropField.tsx (single), MultiImageField.tsx (multi grid). Uploads reuse the shared merch presigned-URL flow (POST /api/merch/upload/presigned-url) via packages/team-leaderboard/client/src/lib/upload.ts (uploadImageToS3()).
  • ColorColorField.tsx (native swatch + hex input), MultiColorField.tsx (ordered list with add/remove).
  • Store pickerStorePickerField.tsx: a dialog to select the linked store (campaign) by name/slug, showing the store name and an "Edit store" link to merch-admin (${APP_URL}/admin/merch/campaigns/:id/builder — merch-admin is served by the same backend). Replaces pasting a raw campaign ID.

These are wired into both editors — board-detail-page.tsx (background color, sponsor logo, hero images) and team-detail-page.tsx (main color, colors, flag image, face-paint images, store picker).

Backing endpoints

See API Reference → Admin API for the full list of apps/zooly-app/app/api/merch/admin/* routes.