Single Flutter codebase under client/app/ with web enabled (mobile/desktop can be added later; lib/ is platform-agnostic). Talks to the NestJS backend via a thin REST wrapper; API_BASE is a --dart-define (defaults to the local backend). Screens: - Login: Konfi/guest (invite code), local Teamer password login, Teamer invite redemption. Token persisted in shared_preferences, restored on start; GET /auth/me drives a role-aware home. - Workshop-Wahl (guests): loads /wahl/guest/overview, ordered pick of up to 3 workshops, submits to /wahl/:id/teilnehmer. - Dateien: /files/:kcId list. - Chat: channel + message list (read-only; WS send is a follow-up). State: AppState (ChangeNotifier) exposed via an InheritedNotifier (AppScope) — no third-party state package. flutter analyze clean, flutter build web --release passes, one widget smoke test. Also: interim client/web/ HTML placeholder stays as-is (per plan it is superseded by this Flutter web build). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
KC-APP
Multi-tenant event, election and communication platform for Konfi-Castle events (KCs), replacing the WordPress plugin "Workshop-Wahlen". See plan-kcAppMultiTenantPlatform.prompt.md for the full architecture and phased roadmap.
Structure
backend/— NestJS API (Prisma/PostgreSQL, Authentik OIDC as resource server, guest/Konfi local accounts, roles/permissions foundation, file sharing, chat, local/cloud sync). See backend/README.md for setup. Also serves the web client (see below) directly, so it's the single entry point for the web experience.client/web/— minimal dependency-free HTML/CSS/JS placeholder web client (guest join, Wahl submission, file list, chat) exercising the real API, served by the backend at/. Will be replaced by the Flutter web build once Flutter is available.client/(mobile/desktop) — planned Flutter app, not yet scaffolded (Flutter is not installed in this environment).
Status
Phase 0/1 foundation implemented: monorepo skeleton, Prisma data model (Kc, Gemeinde, User, Membership, GuestAccount, Wahl/Workshop/Teilnehmer/Zuteilung, File, Chat), Authentik JWT resource-server strategy, guest invite-code login, Role-based guard scoped per KC.
Phase 2 (Workshop-Wahl engine) implemented: Wahl/Workshop administration,
guest Teilnehmer submission, Force-Zuteilung overrides, and the assignment
algorithm ported from the WP plugin's kc_run_zuteilung (force-assignments →
wish rounds 1-3 → random fill → consolidation of underfilled workshops),
plus CSV export.
Phase 3 (Dateifreigabe) implemented: Leitungsteam-only upload tagged with a
visibility tier (alle / alle außer Konfis / nur LT), list/download for
Authentik or guest callers filtered by their allowed tiers, storage behind a
provider abstraction defaulting to Nextcloud/WebDAV (S3-compatible storage
as an alternative via STORAGE_PROVIDER=s3).
Phase 5 (Kommunikation) implemented: Gemeinde-Gruppenchat, 1:1-DMs, LT- kanalübergreifende Kanäle, Broadcast (read-only für Konfis); channel/history via REST, real-time send/receive via a raw WebSocket gateway authenticated with the same Authentik/guest tokens as the REST API.
Phase 6 (Hybrid Lokal/Cloud-Server & Sync) implemented: an append-only
replication log (SyncLogEntry) captured by every feature service after its
writes; the local (on-site) server periodically pushes/pulls against the
cloud server's /sync/ingest + /sync/export endpoints (shared-secret
authenticated, not user auth). No conflict resolution needed by design - the
local server is the sole source of truth while an event is live.
The backend now also serves the web client directly (static files from
client/web/, API under /api), so the same process is the single entry
point for the web experience.
Backend builds and boots cleanly (npm run build, node dist/main.js) but
requires a real PostgreSQL database, Authentik instance, and Nextcloud/S3
credentials (see backend/.env.example) to run end to end. Remaining: the
Flutter clients (mobile/desktop; web has an interim plain-HTML client).