Files
vtuber-awards/docs/ARCHITECTURE.md
T
AzuTear 6b3b0360e7
CI - Build & Verify / Build, Typecheck & Hygiene (push) Successful in 1m1s
CI - Build & Verify / Deploy to award.noveria.net (push) Successful in 1m30s
Add winner archive, host image upload and live demo data
Deliver the demo-ready feature set and seed data so the live site can be
presented end to end:

- Winner archive: ArchivedWinner domain, admin CRUD endpoints/view/manager
  and public archive surface, backed by AddArchivedWinners migration.
- Host presentation: host image upload and artist name on SiteSettings with
  public image endpoint and supporting migrations.
- Clip submissions: idempotent table-ensure migration plus current-season
  demo clips for review workflows.
- Demo seed data: sponsors, share links and 2025 archived winners, with a
  guarded RemoveDemoSeasons cleanup; all seeds guard against real data.
- EnsureRuntimeSchemaParity migration to align runtime schema defensively.
- Admin/home UI refinements; remove unused team role permissions modal and
  dead share-quick-links code.

All seed and schema migrations are idempotent (IF NOT EXISTS / ON CONFLICT)
and skip when real season data is present.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 21:47:52 +02:00

7.3 KiB

Architecture

This document describes the structure, boundaries, flows, and technical rules of the VTuber Star Awards system. For project facts, see PROJECT.md. For coding standards, see CONVENTIONS.md. For recorded trade-offs, see DECISIONS.md.

High-Level Overview

VTuber Star Awards is a production monorepo with a Vue/Vite frontend, an ASP.NET Core 8 minimal API backend, and a PostgreSQL database managed by EF Core migrations.

flowchart LR
    Public["Public users"]
    Team["Team/admin users"]
    Frontend["Vue/Vite frontend"]
    Api["ASP.NET Core API"]
    Domain["Domain models and services"]
    Database["PostgreSQL"]
    Twitch["Twitch OAuth"]
    CI["Gitea Actions"]

    Public --> Frontend
    Team --> Frontend
    Frontend --> Api
    Api --> Domain
    Domain --> Database
    Api --> Twitch
    CI --> Api
    CI --> Frontend
    CI --> Database

The frontend is the user interface. The backend is the source of truth for season state, content, team permissions, moderation, workflow rules, and public overview data.

Architecture Style

Field Value
Style Layered modular monolith
Runtime shape One frontend app, one backend API, one PostgreSQL database
Primary reason Keep deployment simple while preserving clearer internal feature boundaries.
Main trade-off Boundaries depend on code organization and review discipline rather than service isolation.

Repository Structure

VTubeAwards/
  frontend/
    src/
      views/
      components/
      stores/
      lib/
      types/
  Backend/
    Common/
    Configuration/
    Contracts/
    Data/
    Domain/
    Endpoints/
    Extensions/
    Migrations/
    Repositories/
    Security/
    Services/
  docs/
  .gitea/workflows/
Folder Responsibility
frontend/src/views Route-level Vue views.
frontend/src/components Reusable public/admin UI components and composables.
frontend/src/lib API clients, HTTP helpers, formatting, and shared frontend utilities.
frontend/src/types TypeScript contract and payload types.
Backend/Endpoints Minimal API endpoint groups and endpoint-specific mapping helpers.
Backend/Contracts Request and response DTOs.
Backend/Domain Persistent domain entities and core business concepts.
Backend/Data EF Core DbContext, seed/bootstrap code, and design-time setup.
Backend/Repositories Domain-specific persistence boundaries.
Backend/Services Use-case, audit, session, risk, and workflow services.
Backend/Security Session filters, role/permission catalog, and security middleware.
docs Durable project, architecture, workflow, and decision documentation.

Backend Flow

sequenceDiagram
    participant Client as Frontend or API client
    participant Endpoint as Minimal API endpoint
    participant Filter as Admin/session filter
    participant Service as Service or repository
    participant Db as EF Core/PostgreSQL

    Client->>Endpoint: HTTP request
    Endpoint->>Filter: Auth and permission checks when required
    Endpoint->>Service: Validate intent and execute use case
    Service->>Db: Query or persist through DbContext/repository
    Db-->>Service: Domain data
    Service-->>Endpoint: Contract DTO
    Endpoint-->>Client: JSON response or problem result

Endpoint files should stay focused on transport concerns, authorization, mapping, and orchestration. Domain rules and cross-endpoint behavior belong in services, repositories, or domain-specific helpers.

Frontend Flow

flowchart TD
    Route["Vue route/view"]
    Components["Focused components"]
    Composables["Composables and stores"]
    ApiClient["frontend/src/lib/api"]
    Backend["Backend API"]

    Route --> Components
    Components --> Composables
    Composables --> ApiClient
    ApiClient --> Backend

Public pages should render backend/admin truth. Admin pages should favor clear workspace structure, permission-aware controls, explicit loading/error states, and smaller Vue files split by feature.

Data Ownership

Data Owner Notes
Seasons, categories, candidates, winners, archived winners Backend Public and admin views read from canonical backend state; historical archive winners are managed separately from current season winner publication.
Nominations and clip submissions Backend Public writes are validated and reviewed through admin workflows.
Site settings, landing content, footer links, showacts, sponsors Backend Content hub/admin settings own public presentation data.
Team members, roles, permissions, sessions Backend UI may hide controls, but API authorization is authoritative.
Risk flags and audit entries Backend Used for admin review, diagnostics, and accountability.
Frontend interaction state Frontend Local state is allowed only for view state and unsaved form state.

Persistence Boundary

The backend uses EF Core with PostgreSQL. Domain-specific repositories exist for session, risk flag, and audit behavior. Direct AwardsDbContext use is still acceptable inside endpoint groups or services when the operation is simple and local to one feature, but repeated or cross-feature persistence behavior should move behind a repository or focused service.

Production migrations are applied by the Gitea deploy workflow. Development can auto-apply migrations during API startup.

Authentication And Authorization

  • Team/admin authentication is session-based.
  • Twitch OAuth is handled through backend auth endpoints.
  • Admin endpoints use session/permission checks at the trusted backend boundary.
  • The frontend should reflect permissions to improve UX, but never be the only authorization layer.
  • creator is not a normal assignable role in team management.

Security Posture

Area Policy
CORS Non-development environments require explicit configured frontend origins.
Public writes Rate-limited and validated server-side.
Secrets Environment variables only; no checked-in production credentials.
Demo data Controlled by seed/demo environment flags. Production defaults must remain safe.
Headers Security headers are applied by backend middleware.
Audit Admin-relevant changes should emit useful audit records where supported.

Deployment Flow

flowchart LR
    Push["Push to main or manual dispatch"]
    Verify["Build, typecheck, hygiene"]
    Sync["Sync code to production host"]
    Backup["Predeploy PostgreSQL backup"]
    Migrate["Apply EF Core migrations"]
    Restart["Recreate api and web services"]
    Smoke["Health, database, and asset checks"]

    Push --> Verify
    Verify --> Sync
    Sync --> Backup
    Backup --> Migrate
    Migrate --> Restart
    Restart --> Smoke

The production deploy path is encoded in .gitea/workflows/ci.yaml.

Known Constraints

  • There is no dedicated checked-in test project yet.
  • Build/type checks and targeted manual verification are currently required for most changes.
  • Production database migration rollback must be considered before risky schema changes; the pipeline writes backups but does not make destructive migrations automatically safe.
  • Large admin and public Vue surfaces should continue to be split as they grow.