Architecture Overview
PolitikTok follows a Dioxus fullstack architecture where a single Rust codebase compiles to both a server binary and a WebAssembly client. The server renders pages on the first request (SSR) and the browser hydrates them into an interactive SPA.
High-Level Architecture
+------------------+
| Browser |
| (WASM + Hydrate)|
+--------+---------+
|
HTTP / WebSocket
|
+--------+---------+
| Axum Server |
| (Dioxus SSR) |
+--------+---------+
|
+---------+-------+-------+---------+
| | | |
+-----+----+ +--+---+ +------+---+ +---+------+
|PostgreSQL | |Qdrant| | Keycloak | | Ollama |
| (5433) | |(6335)| | (8081) | | (11434) |
+----------+ +------+ +----------+ +----------+Request Lifecycle
Initial page load: The browser requests a URL. The Axum server renders the matching Dioxus component tree to HTML and sends it along with the WASM bundle.
Hydration: The browser loads the WASM binary, which attaches event handlers to the server-rendered DOM without re-rendering. The page becomes interactive.
Client-side navigation: Subsequent page transitions happen entirely in WASM via the Dioxus router. No full-page reloads occur.
Server function calls: When a component needs backend data, it calls a
#[server]function. Dioxus serializes the arguments, sends them as a POST request to a generated endpoint, and deserializes the response.Authentication check: The Axum middleware layer verifies the session cookie on every request. Protected routes redirect unauthenticated users to the Keycloak login flow.
Layered Architecture
The codebase is organized into four layers:
Infrastructure Layer (src/infrastructure/)
Handles cross-cutting concerns that all modules depend on:
- Database (
db.rs) -- PostgreSQL connection pool viasqlx, automatic migrations - Authentication (
auth.rs) -- Keycloak OIDC + PKCE flow, session management - LLM Client (
llm.rs) -- OpenAI-compatible API client with retry, streaming support - Embedding Client (
embedding.rs) -- Text embedding and chunking utilities - Vector Store (
vector_store.rs) -- Qdrant client for upsert, search, and delete - Config (
config.rs) -- Environment variable loading for all subsystems - State (
state.rs) -- Arc-wrapped shared state holding database pool and config references - Middleware (
middleware/) -- Axum middleware for auth enforcement and audit logging
Models Layer (src/models/)
Shared data structures used across modules:
User,Volunteer,Task,Assignment-- people and operationsDonor,Voter-- fundraising and outreachDocument,ChatMessage,ChatSession-- knowledge managementSocialPost,Candidate-- intelligence and analysisRole-- role-based access control (Admin, Staff, Volunteer, ReadOnly)
Modules Layer (src/modules/)
The 26 feature modules, each in its own subdirectory. Every module exposes its functionality exclusively through Dioxus server functions annotated with #[server]. Server functions:
- Run only on the server (behind
#[cfg(feature = "server")]) - Are callable from client components as regular async functions
- Automatically serialize/deserialize arguments and return values
- Have access to the Axum
Extensionlayer for database, config, and auth
Pages & Components Layer (src/pages/, src/components/)
UI code built with Dioxus RSX:
- Pages map 1:1 to routes defined in the
Routeenum inapp.rs - Components are reusable UI building blocks:
Sidebar,DataTable,Card,Modal,LoadingSpinner,StreamingText,Chart,Pagination,Badge,Toast,AlertBanner,FormFields,Feedback - Layouts provide nested structure:
AppShell(main authenticated layout with sidebar) andAdminShell(admin sub-navigation)
Server Startup Sequence
The server startup (src/infrastructure/server_start.rs) follows this order:
- Load environment variables from
.env - Initialize config structs and leak them to
'staticlifetime - Connect to PostgreSQL and run migrations
- Build the
ServerStatewith all config references - Configure the session layer (signed cookies, 24-hour expiry)
- Mount OAuth routes (
/auth,/auth/callback,/logout) - Attach Dioxus fullstack serving with SSR
- Layer middleware: session -> auth enforcement -> extensions
- Bind to the address from
dioxus-cli-configand start serving
Data Flow: Server Function Example
A typical module interaction (e.g., listing volunteers):
Browser Component
|
| calls list_volunteers(search, status_filter, skill_filter)
|
v
Dioxus Server Function
|
| extracts ServerState from Axum extensions
| extracts session for auth check
|
v
SQLx Query
|
| executes parameterized SQL against PostgreSQL
|
v
Response serialized back to browserFor LLM-powered features, the flow extends through the LLM client:
Server Function
|
+-- Query PostgreSQL for context data
|
+-- Build system/user prompt
|
+-- Call LlmClient::generate() -> Ollama /chat/completions
|
+-- Log usage to llm_usage_log table
|
+-- Return generated content to browser