This commit is contained in:
Tomas Dvorak
2025-11-21 08:44:44 +01:00
parent c941313fd5
commit f5b6f83974
108 changed files with 8642 additions and 5871 deletions
+40 -40
View File
@@ -1,4 +1,4 @@
%%{init: {"theme":"forest","flowchart":{"curve":"linear"},"themeCSS":"svg { font-family: Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial; } .edgePath path { stroke-dasharray: 6 4; animation: dash 16s linear infinite; } .animated-edge path { stroke-dasharray: 6 4; animation: dash 16s linear infinite; } @keyframes dash { to { stroke-dashoffset: -1000; } } .ext > rect, .ext > polygon, .ext > path { stroke: #7e57c2; } .db > rect, .db > polygon, .db > path { fill: #e3f2fd; stroke: #1e88e5; } .svc > rect, .svc > polygon, .svc > path { fill: #e8f5e9; stroke: #43a047; } .fe > rect, .fe > polygon, .fe > path { fill: #fff8e1; stroke: #f9a825; } .ctrl > rect, .ctrl > polygon, .ctrl > path { fill: #f3e5f5; stroke: #8e24aa; } .mid > rect, .mid > polygon, .mid > path { fill: #e0f2f1; stroke: #00897b; } .model > rect, .model > polygon, .model > path { fill: #ede7f6; stroke: #5e35b1; } .route > rect, .route > polygon, .route > path { fill: #e8eaf6; stroke: #3f51b5; }" }}%%
%%{init: {"theme":"forest","securityLevel":"loose","flowchart":{"curve":"linear","useMaxWidth":true,"nodeSpacing":40,"rankSpacing":50},"themeCSS":"svg { font-family: Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial; } .edgePath path { stroke-opacity:.6 } .ext > rect, .ext > polygon, .ext > path { stroke: #7e57c2; } .db > rect, .db > polygon, .db > path { fill: #e3f2fd; stroke: #1e88e5; } .svc > rect, .svc > polygon, .svc > path { fill: #e8f5e9; stroke: #43a047; } .fe > rect, .fe > polygon, .fe > path { fill: #fff8e1; stroke: #f9a825; } .ctrl > rect, .ctrl > polygon, .ctrl > path { fill: #f3e5f5; stroke: #8e24aa; } .mid > rect, .mid > polygon, .mid > path { fill: #e0f2f1; stroke: #00897b; } .model > rect, .model > polygon, .model > path { fill: #ede7f6; stroke: #5e35b1; } .route > rect, .route > polygon, .route > path { fill: #e8eaf6; stroke: #3f51b5; } .cluster rect { rx:8; ry:8 }" }}%%
flowchart TB
%% ========================= Docker & Runtime =========================
@@ -37,13 +37,13 @@ subgraph DOCKER["Docker Compose (Local Dev/Prod)"]
end
user_browser((User Browser)):::ext
user_browser ==>|HTTP 80| docker_frontend:::animated-edge
user_browser -.->|dev direct (HTTP 8080)| docker_backend
user_browser ==>|HTTP 80| fe_3000
user_browser -.->|dev direct :8080| be_8080
%% ========================= Backend (Go/Gin) =========================
subgraph BACKEND["Backend Service (Golang + Gin) :8080"]
direction TB
cfg[Config (internal/config.Config)\n- APP_ENV/PORT/DEBUG\n- DATABASE_URL (GORM)\n- JWT_SECRET/EXP\n- ALLOWED_ORIGINS (CORS)\n- UPLOAD_DIR/MAX_UPLOAD_SIZE\n- SMTP_* (Email)\n- FRONTEND_BASE_URL\n- PUBLIC_API_BASE_URL\n- ERROR_INGEST_URL/TOKEN\n- FACR_SCRAPER_BASE_URL\n- UMAMI_*\n- CLAMAV_* (optional)]
cfg["Config (internal/config.Config)<br/>- APP_ENV/PORT/DEBUG<br/>- DATABASE_URL (GORM)<br/>- JWT_SECRET/EXP<br/>- ALLOWED_ORIGINS (CORS)<br/>- UPLOAD_DIR/MAX_UPLOAD_SIZE<br/>- SMTP_* (Email)<br/>- FRONTEND_BASE_URL<br/>- PUBLIC_API_BASE_URL<br/>- ERROR_INGEST_URL/TOKEN<br/>- FACR_SCRAPER_BASE_URL<br/>- UMAMI_*<br/>- CLAMAV_* (optional)"]
logger[Logger (pkg/logger)]
db_init[[InitDB() + AutoMigrate()]]:::db
email_svc[EmailService (pkg/email)]:::svc
@@ -77,42 +77,42 @@ subgraph BACKEND["Backend Service (Golang + Gin) :8080"]
subgraph controllers[Controllers]
direction TB
c_auth[AuthController\n/login,/logout,/register,/me\n/password-reset]
c_contact[ContactController\n/contact + newsletter + admin forwarding]
c_auth["AuthController<br/>/login,/logout,/register,/me<br/>/password-reset"]
c_contact["ContactController<br/>/contact + newsletter + admin forwarding"]
c_pass[PasswordController]
c_ai[AIController\n/ai/blog,/ai/about,/ai/css,/ai/instagram]
c_score[ScoreboardController\n/public + admin timer/sponsors/qr]
c_ai["AIController<br/>/ai/blog,/ai/about,/ai/css,/ai/instagram"]
c_score["ScoreboardController<br/>/public + admin timer/sponsors/qr"]
c_about[AboutController]
c_gallery[GalleryController\n/Zonerama profile/albums/picks]
c_files[FilesController\n/list/unused/duplicates/usage\n/scan/refresh-tracking/delete]
c_gallery["GalleryController<br/>/Zonerama profile/albums/picks"]
c_files["FilesController<br/>/list/unused/duplicates/usage<br/>/scan/refresh-tracking/delete"]
c_notify[NotificationsController]
c_email[EmailController\n/open.gif/click/unsubscribe/stats]
c_prefetch[PrefetchController\n/status/trigger]
c_seo[SEOController\n/seo (public) + robots.txt + sitemap]
c_nav[NavigationController\n/navigation + social-links + admin CRUD]
c_poll[PollController\n/public vote/results + admin]
c_sw[SweepstakesController\n/public current/visual + admin CRUD/finalize]
c_cloth[ClothingController\n/public + admin CRUD]
c_pec[PageElementConfigController\n/public + admin CRUD/batch]
c_article[ArticleController\n/create + match-link]
c_base[BaseController\n/health, uploads, categories, teams, players, matches, standings, zonerama, settings, shortlinks(public)]
c_myu[MyUIbrixController\n/validate,/preview,/optimize]
c_editor[EditorPreviewController\n/preview state + variants]
c_short[ShortLinkController\n/public create + admin + redirect /s/:code]
c_comment[CommentController\n/public list + CRUD + reactions\nban/unban/report (admin)]
c_eng[EngagementController\n/rewards/leaderboard/profile/actions]
c_facr[FACRController\n/facr club search/info/table]
c_yt[YouTubeController\n/youtube/videos]
c_umami[UmamiController\n/config + admin initialize/stats]
c_error[ErrorController\n/errors ingest + admin + external]
c_email["EmailController<br/>/open.gif/click/unsubscribe/stats"]
c_prefetch["PrefetchController<br/>/status/trigger"]
c_seo["SEOController<br/>/seo (public) + robots.txt + sitemap"]
c_nav["NavigationController<br/>/navigation + social-links + admin CRUD"]
c_poll["PollController<br/>/public vote/results + admin"]
c_sw["SweepstakesController<br/>/public current/visual + admin CRUD/finalize"]
c_cloth["ClothingController<br/>/public + admin CRUD"]
c_pec["PageElementConfigController<br/>/public + admin CRUD/batch"]
c_article["ArticleController<br/>/create + match-link"]
c_base["BaseController<br/>/health, uploads, categories, teams, players, matches, standings, zonerama, settings, shortlinks(public)"]
c_myu["MyUIbrixController<br/>/validate,/preview,/optimize"]
c_editor["EditorPreviewController<br/>/preview state + variants"]
c_short["ShortLinkController<br/>/public create + admin + redirect /s/:code"]
c_comment["CommentController<br/>/public list + CRUD + reactions<br/>ban/unban/report (admin)"]
c_eng["EngagementController<br/>/rewards/leaderboard/profile/actions"]
c_facr["FACRController<br/>/facr club search/info/table"]
c_yt["YouTubeController<br/>/youtube/videos"]
c_umami["UmamiController<br/>/config + admin initialize/stats"]
c_error["ErrorController<br/>/errors ingest + admin + external"]
end
subgraph services[Services & Jobs]
direction TB
s_errrep[ErrorReporter]
s_prefetch[Prefetcher\nStartPrefetcher(target)]
s_prefetch["Prefetcher<br/>StartPrefetcher(target)"]
s_nlsched[NewsletterScheduler]
s_nlauto[NewsletterAutomation\nweekly, reminders, results]
s_nlauto["NewsletterAutomation<br/>weekly, reminders, results"]
s_sweep[SweepstakesScheduler]
s_umami[UmamiService]
s_facr[FACRService]
@@ -213,8 +213,8 @@ subgraph BACKEND["Backend Service (Golang + Gin) :8080"]
errors_admin["Error Review Admin UI/API: errors.tdvorak.dev"]:::ext
umami_ext["Umami Analytics server"]:::ext
s_facr <---> facr_ext:::animated-edge
s_errrep --> errors_ingest:::animated-edge
s_facr <---> facr_ext
s_errrep --> errors_ingest
c_error <---> errors_admin
s_umami <---> umami_ext
@@ -228,7 +228,7 @@ subgraph BACKEND["Backend Service (Golang + Gin) :8080"]
prometheus --- user_browser
end
user_browser ==>|HTTP /api/v1| api_grp:::animated-edge
user_browser ==>|HTTP /api/v1| api_grp
user_browser ==>|HTTP /robots.txt, /sitemap.xml, /s/:code| root_grp
%% ========================= Frontend (React) =========================
@@ -241,7 +241,7 @@ subgraph FRONTEND[Frontend (React + ChakraUI)]
p_home[HomePage /]
p_blog[BlogPage /blog]
p_newslist[ArticlesListPage]
p_article[ArticleDetailPage /news/:slug | /articles/:id]
p_article["ArticleDetailPage /news/:slug | /articles/:id"]
p_about[AboutPage /o-klubu]
p_club[ClubPage /klub]
p_calendar[CalendarPage /kalendar]
@@ -315,9 +315,9 @@ subgraph FRONTEND[Frontend (React + ChakraUI)]
end
%% FE -> BE API mappings (high level)
fe_router -->|services/api.ts| api_grp:::animated-edge
fe_router -->|services/api.ts| api_grp
p_blog -->|GET /articles| api_grp
p_article -->|GET /articles/slug/:slug, /articles/:id\nPOST /articles/:id/read| api_grp
p_article -->|GET /articles/slug/:slug, /articles/:id<br/>POST /articles/:id/read| api_grp
p_home -->|GET /articles/featured, /matches, /standings, /settings, /navigation| api_grp
p_matches -->|GET /matches,/standings| api_grp
p_match -->|GET /matches/:id| api_grp
@@ -334,7 +334,7 @@ subgraph FRONTEND[Frontend (React + ChakraUI)]
p_short -->|GET /s/:code (root)| root_grp
%% Admin flows
a_articles[ArticlesAdminPage] -->|POST/PUT/DELETE /articles\n/link-match| api_grp
a_articles[ArticlesAdminPage] -->|POST/PUT/DELETE /articles<br/>/link-match| api_grp
a_matches -->|GET /admin/matches| api_grp
a_comments -->|GET/PATCH /admin/comments| api_grp
a_navigation -->|CRUD /admin/navigation| api_grp
@@ -347,7 +347,7 @@ subgraph FRONTEND[Frontend (React + ChakraUI)]
a_analytics -->|/admin/umami| api_grp
%% FE error reporting & analytics
fe_router -->|POST /errors (ErrorReporter)| api_grp:::animated-edge
fe_router -->|POST /errors (ErrorReporter)| api_grp
fe_router -->|GET /umami/config| api_grp
end
@@ -358,7 +358,7 @@ subgraph PORTS[Ports & CORS]
port_be[Backend :8080]
port_fe[Frontend :3000 -> :80]
port_db[Postgres :5432]
cors[CORS AllowedOrigins\n- http://localhost:3000\n- http://localhost:8080\n+ FrontendBaseURL origin\n+ "*" optional in dev]
cors["CORS AllowedOrigins<br/>- http://localhost:3000<br/>- http://localhost:8080<br/>+ FrontendBaseURL origin<br/>+ * optional in dev"]
end
port_be --- docker_backend
port_fe --- docker_frontend