%%{init: {"theme":"forest","securityLevel":"loose","flowchart":{"curve":"linear","useMaxWidth":true,"nodeSpacing":35,"rankSpacing":45},"themeCSS":".edgePath path { stroke-opacity:.6 } .cluster rect { rx:8; ry:8 }" }}%% flowchart TB classDef group fill:#eef7ff,stroke:#2b6cb0,color:#0b3a60; classDef sec fill:#fef9c3,stroke:#ca8a04,color:#7c2d12; classDef admin fill:#ecfdf5,stroke:#16a34a,color:#064e3b; classDef pub fill:#f1f5f9,stroke:#334155,color:#0f172a; classDef root fill:#f3e8ff,stroke:#6d28d9,color:#3b0764; classDef route fill:#e2e8f0,stroke:#475569,color:#111827; classDef ext fill:#faf5ff,stroke:#a855f7,color:#6b21a8; client((Browser)):::ext api["/api/v1"]:::group rootgrp["Root"]:::group client ==>|HTTP| api client ==>|HTTP| rootgrp subgraph PUBLIC["Public endpoints"] direction LR p_health["GET /health"]:::pub p_csrf["GET /csrf-token"]:::pub p_image_proxy["GET /proxy/image"]:::pub p_seo["GET /seo"]:::pub p_nav["GET /navigation, /social-links"]:::pub p_page_elems["GET /page-elements"]:::pub p_short_public["POST /shortlinks/public"]:::pub p_email["GET /email/open.gif | /email/click | /email/unsubscribe"]:::pub p_setup["GET /setup/status | POST /setup/initialize | POST /setup/validate-smtp"]:::pub p_errors_ingest["POST /errors (rate-limited)"]:::pub p_comments_list["GET /comments (JWT optional)"]:::pub p_eng_rewards["GET /engagement/rewards"]:::pub p_scoreboard_pub["GET /scoreboard | /scoreboard/sponsors | /scoreboard/qr"]:::pub p_settings["GET /settings"]:::pub p_comp_aliases["GET /competition-aliases"]:::pub p_team_logo_over["GET /public/team-logo-overrides"]:::pub p_articles["/articles: featured, list, slug/:slug, :id, read, track-view"]:::pub p_categories["GET /categories"]:::pub p_youtube["GET /youtube/videos"]:::pub p_about["GET /about"]:::pub p_teams["GET /teams, /teams/:id"]:::pub p_players["GET /players, /players/:id"]:::pub p_sponsors["GET /sponsors"]:::pub p_banners["GET /banners"]:::pub p_matches["GET /matches | /matches/history | /standings"]:::pub p_gallery["GET /gallery/albums | /gallery/albums/:id | /gallery/proxy-image"]:::pub p_zonerama["GET /zonerama/album | /zonerama-album | /zonerama/picks"]:::pub p_clothing["GET /clothing"]:::pub p_sweep_pub["GET /sweepstakes/current | /sweepstakes/:id/visual"]:::pub p_polls["GET /polls | /polls/:id | POST /polls/:id/vote | GET /polls/:id/results"]:::pub p_contact["POST /contact"]:::pub p_newsletter_pub["POST /newsletter/subscribe | /newsletter/unsubscribe/:email | /newsletter/setup | /newsletter/preferences"]:::pub p_newsletter_token["POST /newsletter/unsubscribe-token | GET /newsletter/preferences (by token)"]:::pub p_facr["/facr: club/search | club/:type/:id | table"]:::pub end subgraph PROTECTED["Protected (JWTAuth + CSRF for state)"] direction LR prot_sweep["POST /sweepstakes/:id/enter | POST /sweepstakes/:id/played | GET /sweepstakes/my-winnings"]:::route prot_eng["Engagement: GET /leaderboard, /profile, /achievements, /transactions | POST /checkin, /article-read, /redeem | PATCH /profile, /avatar"]:::route prot_comments["Comments: POST /comments | PUT/DELETE /comments/:id | react/unreact | unban-request | report"]:::route prot_editor_preview["/editor: GET/POST /preview/:session_id | apply | delete | validate | GET /variants/:element_name"]:::sec prot_newsletter_me["GET /newsletter/token/me"]:::route prot_user["PUT /me | GET /me"]:::route prot_events["/events (editor): POST, PUT, DELETE"]:::sec prot_shortlinks["/shortlinks (editor): POST, GET"]:::sec prot_articles["/articles (editor): POST, PUT/:id, DELETE/:id, match-link PUT/DELETE"]:::sec prot_admin_groups["/admin/* groups (require admin role)"]:::admin end subgraph ADMIN["Admin groups (JWT + Role: admin)"] direction LR ad_errors["/admin/errors: list, get, external proxies"]:::admin ad_comments["/admin/comments: list, status, bans, unban requests"]:::admin ad_comp_aliases["/admin/competition-aliases: CRUD + reorder"]:::admin ad_settings["/admin/settings: GET/PUT"]:::admin ad_about["/admin/about: GET/PUT/DELETE"]:::admin ad_scoreboard["/admin/scoreboard: GET/PUT + timer + sponsors + QR + presets"]:::admin ad_users["/admin/users: CRUD + send reset + reset by ID"]:::admin ad_matches["/admin/matches: merged list"]:::admin ad_overrides["/admin/*-overrides: GET/PUT/PATCH for match/team logos"]:::admin ad_contacts["/admin/contact-messages: list/get/read/forward/delete"]:::admin ad_newsletter["/admin/newsletter: send/test/preview/status + automation"]:::admin ad_notifications["/admin/notifications: competition, match"]:::admin ad_prefetch["/admin/prefetch: status/trigger"]:::admin ad_cache["/admin/cache: list/file"]:::admin ad_gallery["/admin/gallery: profile, fetch, refresh, delete"]:::admin ad_zonerama["/admin/zonerama: save-album, pick"]:::admin ad_seo["/admin/seo: GET/PUT"]:::admin ad_files["/admin/files: list/unused/duplicates/usage/usages/delete/scan/refresh-tracking"]:::admin ad_navigation["/admin/navigation + /admin/social-links: CRUD + reorder + seed"]:::admin ad_clothing["/admin/clothing: CRUD + reorder"]:::admin ad_polls["/admin/polls: CRUD + stats + votes"]:::admin ad_engagement["/admin/engagement: rewards CRUD, redemptions, leaderboard, transactions, adjust, profile"]:::admin ad_page_elements["/admin/page-elements: CRUD + batch"]:::admin ad_myuibrix["/admin/myuibrix: validate, batch-validate, preview, optimize-layout"]:::admin ad_shortlinks["/admin/shortlinks: create/list + stats"]:::admin ad_sweep["/admin/sweepstakes: CRUD + entries/winners/prizes + finalize"]:::admin end subgraph ROOT["Root endpoints"] direction LR r_robots["GET /robots.txt"]:::root r_sitemap["GET /sitemap.xml"]:::root r_short["GET /s/:code"]:::root r_redirect["GET /r (tracked redirect)"]:::root end api --> PUBLIC api --> PROTECTED api --> ADMIN rootgrp --> ROOT note["Note: This overview groups related endpoints; see routes.go for exact definitions and middlewares."]:::route