Brands¶
The page at /admin/brands manages brand identity rows: name, primary and
secondary hex colors, and an optional logo file.
Data source¶
The admin page is a thin HTML shell. Alpine.js loads brands via
GET /api/brands (optional q search) and saves with multipart
POST /api/brands or PATCH /api/brands/{brand_id}. Deletes use
DELETE /api/brands/{brand_id}.
This is database configuration. Logos are objects in
AWS_S3_DEFAULT_BUCKET at brands/<brand_id>/<filename>. That prefix is
publicly readable (anonymous GetObject); list/get responses include a
stable public logo_url for display.
Fields¶
| Field | Column / storage | Notes |
|---|---|---|
| Name | name |
Unique, whitespace trimmed |
| Primary color | primary_color |
#RRGGBB (stored uppercase) |
| Secondary color | secondary_color |
#RRGGBB (stored uppercase) |
| Logo | logo_filename + S3 object |
png / jpeg / svg / webp, max 2 MiB |
Each field label has a ? help modal.
Workflow¶
- Open Manage → Brands. Brand name labels elsewhere in admin (match
cards, Play/History sponsor pills, Brand Sponsorships, match details)
deep-link here as
/admin/brands?q=<name>and prefill Search. - Use Search to call
GET /api/brands?q=…(debounced). Matches name, hex color, logo filename, or id (case-insensitive). Click Name, Primary, or Secondary column headers to sort the loaded results (click again to reverse). Choose Per page (10 / 25 / 50 / 100; default 25) and use Previous/Next to page through results. - New Brand or Edit opens a modal; set name, colors, and optional logo.
- Save sends one multipart request (metadata + optional file).
- On edit, Remove current logo clears the S3 object and
logo_filename. - Delete removes the row and any logo object.
Code map¶
| Concern | Location |
|---|---|
| REST CRUD | GET/POST/PATCH/DELETE /api/brands, src/api/routes/brands.py |
| Ops + schemas | src/lib/brands/ |
| Model | src/lib/db/models/brand.py |
| Admin HTML shell | src/api/admin/routes/brands.py |
| Template | src/api/admin/templates/brands/index.jinja2 |
| Alpine app | src/api/admin/static/js/brands_app.js |
| CSS | src/api/admin/static/css/brands.css |
| Tests | src/api/tests/admin/test_brands.py, src/api/tests/test_brands_api.py |
Common failures¶
- Duplicate name (409): another brand already uses that name.
- Invalid color (422): must be
#+ six hex digits. - Invalid logo (400): wrong MIME type, empty file, or over 2 MiB.
- S3 not configured (503):
AWS_S3_DEFAULT_BUCKETunset when uploading, clearing, or deleting a logo.