diff --git a/DIAGRAM.md b/DIAGRAM.md new file mode 100644 index 0000000..415a0d9 --- /dev/null +++ b/DIAGRAM.md @@ -0,0 +1,189 @@ +```mermaid +graph TB + classDef page fill:#e1f5fe,stroke:#0288d1 + classDef widget fill:#fff3e0,stroke:#ff9800 + classDef api fill:#f3e5f5,stroke:#9c27b0 + classDef sse fill:#e8f5e9,stroke:#4caf50 + classDef db fill:#fce4ec,stroke:#e91e63 + classDef external fill:#f5f5f5,stroke:#9e9e9e,stroke-dasharray:3 + classDef infra fill:#fff8e1,stroke:#ffc107 + classDef backend fill:#e0f7fa,stroke:#00bcd4 + classDef auth fill:#efebe9,stroke:#795548 + classDef payment fill:#fbe9e7,stroke:#ff5722 + + subgraph External["External World"] + direction LR + User(("User")):::external + Streamer(("Streamer (OBS)")):::external + DiscordUser(("Discord User")):::external + end + + subgraph Infra["Infrastructure — Docker Swarm"] + Nginx["Nginx Reverse Proxy
(SSE: buffering off, 200s timeout)"]:::infra + GiteaCI["Gitea Actions CI/CD"]:::infra + Registry["Private Registry
registry.neko-piranha.ts.net"]:::infra + AppService["App Service
2 replicas · 1 CPU / 1 GB"]:::infra + BackendService["Backend Service
1 replica · 1 CPU / 512 MB"]:::infra + end + + subgraph Pages["Frontend Pages (app/(ui)/)"] + direction TB + Home["/ Home"]:::page + Donate["/donate — Donation Form"]:::page + DonateTop["/donate/top — Leaderboard + Podium"]:::page + DonateAdmin["/donate/admin — Donation Admin"]:::page + Artifact["/artifact — Submission Form"]:::page + ArtifactAdmin["/artifact/admin — Review Panel"]:::page + Rubgram["/rubgram — Service Ordering"]:::page + RubgramAdmin["/rubgram/admin — Admin Panel"]:::page + RubgramSlip["/rubgram/admin/slip — Archive Viewer"]:::page + Tierlist["/tl/[type]/[ver] — Tier Rankings"]:::page + Guide["/guide — Build Guides"]:::page + AdminDash["/admin — Dashboard"]:::page + AdminChar["/admin/char — Character Manager"]:::page + AdminCDN["/admin/cdn — File Manager"]:::page + AdminLog["/admin/log — Audit Log"]:::page + AdminSettings["/admin/settings — Config"]:::page + Login["/login — Admin Login"]:::page + end + + subgraph Widgets["OBS Widgets (app/widget/)"] + DonateWidget["/widget/donate
Donation Alert Popup
SFX + TTS + Animation"]:::widget + DonateTopWidget["/widget/donate/top
Top Donor Bar"]:::widget + ArtifactCountWidget["/widget/artifact-count
Queue Counter"]:::widget + RubgramCountWidget["/widget/rubgram-count
Queue Counter"]:::widget + end + + subgraph APIs["API Routes (app/api/)"] + APIAuth["/api/auth/[...all] — better-auth"]:::api + APITTS["/api/tts — Gemini TTS"]:::api + APIDonateHB["/api/donate/hb — Heartbeat"]:::api + APIRubgramCount["/api/rubgram/count"]:::api + APIAmberSync["/api/amber/sync"]:::api + APIAmberChar["/api/amber/char (ISR)"]:::api + APIAmberLog["/api/amber/log (ISR)"]:::api + APICard["/api/card/[sub] — Card Render"]:::api + APISlip["/api/slip/[id] — Slip Image"]:::api + APIDiscord["/api/discord/users"]:::api + APIHealth["/api/health"]:::api + end + + subgraph SSE["Real-Time SSE (app/sse/)"] + SSEArtifact["/sse/artifact"]:::sse + SSERubgram["/sse/rubgram"]:::sse + SSEDonate["/sse/donate"]:::sse + SSEActive["/sse/active"]:::sse + SSELog["/sse/log"]:::sse + SSETierlist["/sse/tl.{name}"]:::sse + end + + subgraph Backend["Backend (Bun Bytecode)"] + direction TB + RubgramExpiry["Expiration Check
(20min timeout)"]:::backend + RubgramArchive["Monthly Archive
Incremental rounds"]:::backend + AmberCron["Amber Sync Cron
(every 14 days)"]:::backend + CardCache["Card Cache GC"]:::backend + DBSeed["DB Seeding
(admin + defaults)"]:::backend + DiscordWebhook["Discord Webhook
Subscriber"]:::backend + end + + subgraph DB["Database"] + direction LR + subgraph PG["PostgreSQL — Drizzle ORM"] + PublicSchema("public
characters · versions · settings · guides
cdn · auditLog · user · session
account · verification"):::db + ArtifactSchema("artifact
submissions · cards · settings"):::db + EndgameSchema("endgame
submissions · sarchive · expired
slips · settings · discord · types"):::db + TierlistSchema("tierlist
types · tiers · columns · badges
versions · states"):::db + DonateSchema("donate
donations"):::db + end + subgraph Redis["Redis"] + RedisPubSub("Pub/Sub — SSE Broadcasting"):::db + RedisCache("Cache — TTS Audio (7d) · Health (15m)
Discord Users · Amber Hash (24h)"):::db + RedisAuth("Auth Tokens (600s TTL)"):::db + end + end + + subgraph ExtAPI["External APIs"] + AmberAPI["Project Amber
gi.yatta.moe"]:::external + EnkaAPI["Enka Network
enka.network"]:::external + AstralAPI["Astral API
Card Rendering"]:::external + SlipOKAPI["SlipOK
PromptPay Verification"]:::external + SastifyAPI["Sastify
TrueMoney Redemption"]:::external + GeminiAPI["Google Gemini TTS
gemini-2.5-flash-preview-tts"]:::external + DiscordAPI["Discord API
OAuth2 · Bot · Webhooks"]:::external + YouTubeAPI["YouTube API
Live Status"]:::external + PostHogAPI["PostHog Cloud
Analytics + Error Tracking"]:::external + end + + subgraph Auth["Authentication"] + BetterAuth["better-auth
Email/Password · Admin Role
Drizzle Adapter"]:::auth + DiscordOAuth["Discord OAuth2
Rubgram Users
Persisted via cookie token"]:::auth + InternalToken["Internal Tokens
Redis-backed · 600s TTL
X-Internal-Auth header"]:::auth + end + + subgraph Payments["Payment Processing"] + SlipOKFlow["PromptPay (SlipOK)
Slip image → verify → dedup by transRef
Used: Rubgram + Donation"]:::payment + TMNFlow["TrueMoney (Sastify)
Voucher link → redeem API
Used: Donation only"]:::payment + end + + User --> Nginx + Streamer --> Nginx + Nginx --> AppService + GiteaCI --> Registry + + GiteaCI --> AppService + GiteaCI --> BackendService + Registry --> AppService + Registry --> BackendService + + Home --- Donate & Artifact & Rubgram & Tierlist & Guide & AdminDash + Donate --- DonateTop & DonateAdmin + Artifact --- ArtifactAdmin + Rubgram --- RubgramAdmin & RubgramSlip + AdminDash --- AdminChar & AdminCDN & AdminLog & AdminSettings & Login + + BetterAuth --- Login & AdminDash & DonateAdmin & ArtifactAdmin & RubgramAdmin + DiscordOAuth --- Rubgram + InternalToken --- BackendService + + AppService --- PG & Redis + BackendService --- PG & Redis + + Donate --- SlipOKFlow & TMNFlow + Rubgram --- SlipOKFlow + SlipOKFlow --- SlipOKAPI + TMNFlow --- SastifyAPI + + RedisPubSub --- SSEArtifact & SSERubgram & SSEDonate & SSEActive & SSELog & SSETierlist + + DonateAdmin --- SSEDonate + ArtifactAdmin --- SSEArtifact + RubgramAdmin --- SSERubgram + AdminDash --- SSELog + + DonateWidget --- SSEDonate + DonateTopWidget --- SSEDonate + ArtifactCountWidget --- SSEArtifact + RubgramCountWidget --- SSERubgram + + DonateWidget --- APITTS & APIDonateHB + DonateTopWidget --- APIDonateHB + + APITTS --- GeminiAPI + APICard --- AstralAPI & EnkaAPI + APIAmberSync & APIAmberChar & APIAmberLog & APIHealth --- AmberAPI + APIHealth --- EnkaAPI + APIDiscord --- DiscordAPI + SSEActive --- YouTubeAPI + AppService --- PostHogAPI + + BackendService --- DiscordAPI & DiscordWebhook + BackendService --- RubgramExpiry & RubgramArchive & CardCache & DBSeed + AmberCron --- APIAmberSync + + APITTS --- RedisCache + APIHealth --- RedisCache + APIDiscord --- RedisCache + + Donate -. "skip-queue
(promoted)" .-> Artifact +``` diff --git a/README.md b/README.md index 0451c78..a286e3f 100755 --- a/README.md +++ b/README.md @@ -77,195 +77,7 @@ Centralized management panel at `/admin` (guarded by better-auth): - **Audit log:** Last 1000 admin actions with user info - **Section shortcuts:** Links to artifact, rubgram, donate, and tierlist admin -```mermaid -graph TB - classDef page fill:#e1f5fe,stroke:#0288d1 - classDef widget fill:#fff3e0,stroke:#ff9800 - classDef api fill:#f3e5f5,stroke:#9c27b0 - classDef sse fill:#e8f5e9,stroke:#4caf50 - classDef db fill:#fce4ec,stroke:#e91e63 - classDef external fill:#f5f5f5,stroke:#9e9e9e,stroke-dasharray:3 - classDef infra fill:#fff8e1,stroke:#ffc107 - classDef backend fill:#e0f7fa,stroke:#00bcd4 - classDef auth fill:#efebe9,stroke:#795548 - classDef payment fill:#fbe9e7,stroke:#ff5722 - - subgraph External["External World"] - direction LR - User(("User")):::external - Streamer(("Streamer (OBS)")):::external - DiscordUser(("Discord User")):::external - end - - subgraph Infra["Infrastructure — Docker Swarm"] - Nginx["Nginx Reverse Proxy
(SSE: buffering off, 200s timeout)"]:::infra - GiteaCI["Gitea Actions CI/CD"]:::infra - Registry["Private Registry
registry.neko-piranha.ts.net"]:::infra - AppService["App Service
2 replicas · 1 CPU / 1 GB"]:::infra - BackendService["Backend Service
1 replica · 1 CPU / 512 MB"]:::infra - end - - subgraph Pages["Frontend Pages (app/(ui)/)"] - direction TB - Home["/ Home"]:::page - Donate["/donate — Donation Form"]:::page - DonateTop["/donate/top — Leaderboard + Podium"]:::page - DonateAdmin["/donate/admin — Donation Admin"]:::page - Artifact["/artifact — Submission Form"]:::page - ArtifactAdmin["/artifact/admin — Review Panel"]:::page - Rubgram["/rubgram — Service Ordering"]:::page - RubgramAdmin["/rubgram/admin — Admin Panel"]:::page - RubgramSlip["/rubgram/admin/slip — Archive Viewer"]:::page - Tierlist["/tl/[type]/[ver] — Tier Rankings"]:::page - Guide["/guide — Build Guides"]:::page - AdminDash["/admin — Dashboard"]:::page - AdminChar["/admin/char — Character Manager"]:::page - AdminCDN["/admin/cdn — File Manager"]:::page - AdminLog["/admin/log — Audit Log"]:::page - AdminSettings["/admin/settings — Config"]:::page - Login["/login — Admin Login"]:::page - end - - subgraph Widgets["OBS Widgets (app/widget/)"] - DonateWidget["/widget/donate
Donation Alert Popup
SFX + TTS + Animation"]:::widget - DonateTopWidget["/widget/donate/top
Top Donor Bar"]:::widget - ArtifactCountWidget["/widget/artifact-count
Queue Counter"]:::widget - RubgramCountWidget["/widget/rubgram-count
Queue Counter"]:::widget - end - - subgraph APIs["API Routes (app/api/)"] - APIAuth["/api/auth/[...all] — better-auth"]:::api - APITTS["/api/tts — Gemini TTS"]:::api - APIDonateHB["/api/donate/hb — Heartbeat"]:::api - APIRubgramCount["/api/rubgram/count"]:::api - APIAmberSync["/api/amber/sync"]:::api - APIAmberChar["/api/amber/char (ISR)"]:::api - APIAmberLog["/api/amber/log (ISR)"]:::api - APICard["/api/card/[sub] — Card Render"]:::api - APISlip["/api/slip/[id] — Slip Image"]:::api - APIDiscord["/api/discord/users"]:::api - APIHealth["/api/health"]:::api - end - - subgraph SSE["Real-Time SSE (app/sse/)"] - SSEArtifact["/sse/artifact"]:::sse - SSERubgram["/sse/rubgram"]:::sse - SSEDonate["/sse/donate"]:::sse - SSEActive["/sse/active"]:::sse - SSELog["/sse/log"]:::sse - SSETierlist["/sse/tl.{name}"]:::sse - end - - subgraph Backend["Backend (Bun Bytecode)"] - direction TB - RubgramExpiry["Expiration Check
(20min timeout)"]:::backend - RubgramArchive["Monthly Archive
Incremental rounds"]:::backend - AmberCron["Amber Sync Cron
(every 14 days)"]:::backend - CardCache["Card Cache GC"]:::backend - DBSeed["DB Seeding
(admin + defaults)"]:::backend - DiscordWebhook["Discord Webhook
Subscriber"]:::backend - end - - subgraph DB["Database"] - direction LR - subgraph PG["PostgreSQL — Drizzle ORM"] - PublicSchema("public
characters · versions · settings · guides
cdn · auditLog · user · session
account · verification"):::db - ArtifactSchema("artifact
submissions · cards · settings"):::db - EndgameSchema("endgame
submissions · sarchive · expired
slips · settings · discord · types"):::db - TierlistSchema("tierlist
types · tiers · columns · badges
versions · states"):::db - DonateSchema("donate
donations"):::db - end - subgraph Redis["Redis"] - RedisPubSub("Pub/Sub — SSE Broadcasting"):::db - RedisCache("Cache — TTS Audio (7d) · Health (15m)
Discord Users · Amber Hash (24h)"):::db - RedisAuth("Auth Tokens (600s TTL)"):::db - end - end - - subgraph ExtAPI["External APIs"] - AmberAPI["Project Amber
gi.yatta.moe"]:::external - EnkaAPI["Enka Network
enka.network"]:::external - AstralAPI["Astral API
Card Rendering"]:::external - SlipOKAPI["SlipOK
PromptPay Verification"]:::external - SastifyAPI["Sastify
TrueMoney Redemption"]:::external - GeminiAPI["Google Gemini TTS
gemini-2.5-flash-preview-tts"]:::external - DiscordAPI["Discord API
OAuth2 · Bot · Webhooks"]:::external - YouTubeAPI["YouTube API
Live Status"]:::external - PostHogAPI["PostHog Cloud
Analytics + Error Tracking"]:::external - end - - subgraph Auth["Authentication"] - BetterAuth["better-auth
Email/Password · Admin Role
Drizzle Adapter"]:::auth - DiscordOAuth["Discord OAuth2
Rubgram Users
Persisted via cookie token"]:::auth - InternalToken["Internal Tokens
Redis-backed · 600s TTL
X-Internal-Auth header"]:::auth - end - - subgraph Payments["Payment Processing"] - SlipOKFlow["PromptPay (SlipOK)
Slip image → verify → dedup by transRef
Used: Rubgram + Donation"]:::payment - TMNFlow["TrueMoney (Sastify)
Voucher link → redeem API
Used: Donation only"]:::payment - end - - User --> Nginx - Streamer --> Nginx - Nginx --> AppService - GiteaCI --> Registry - - GiteaCI --> AppService - GiteaCI --> BackendService - Registry --> AppService - Registry --> BackendService - - Home --- Donate & Artifact & Rubgram & Tierlist & Guide & AdminDash - Donate --- DonateTop & DonateAdmin - Artifact --- ArtifactAdmin - Rubgram --- RubgramAdmin & RubgramSlip - AdminDash --- AdminChar & AdminCDN & AdminLog & AdminSettings & Login - - BetterAuth --- Login & AdminDash & DonateAdmin & ArtifactAdmin & RubgramAdmin - DiscordOAuth --- Rubgram - InternalToken --- BackendService - - AppService --- PG & Redis - BackendService --- PG & Redis - - Donate --- SlipOKFlow & TMNFlow - Rubgram --- SlipOKFlow - SlipOKFlow --- SlipOKAPI - TMNFlow --- SastifyAPI - - RedisPubSub --- SSEArtifact & SSERubgram & SSEDonate & SSEActive & SSELog & SSETierlist - - DonateAdmin --- SSEDonate - ArtifactAdmin --- SSEArtifact - RubgramAdmin --- SSERubgram - AdminDash --- SSELog - - DonateWidget --- SSEDonate - DonateTopWidget --- SSEDonate - ArtifactCountWidget --- SSEArtifact - RubgramCountWidget --- SSERubgram - - DonateWidget --- APITTS & APIDonateHB - DonateTopWidget --- APIDonateHB - - APITTS --- GeminiAPI - APICard --- AstralAPI & EnkaAPI - APIAmberSync & APIAmberChar & APIAmberLog & APIHealth --- AmberAPI - APIHealth --- EnkaAPI - APIDiscord --- DiscordAPI - SSEActive --- YouTubeAPI - AppService --- PostHogAPI - - BackendService --- DiscordAPI & DiscordWebhook - BackendService --- RubgramExpiry & RubgramArchive & CardCache & DBSeed - AmberCron --- APIAmberSync - - APITTS --- RedisCache - APIHealth --- RedisCache - APIDiscord --- RedisCache - - Donate -. "skip-queue
(promoted)" .-> Artifact -``` +## Architecture Diagram has been moved to DIAGRAM.md ## Architecture