Colour theme is configurable at runtime from two seed colours (brand + accent); neutrals stay fixed for contrast safety. Tailwind v4 var()-based tokens let a :root:root override recolour everything with no rebuild; the 50->950 ramps are derived via a color-mix ladder. Config lives in the DB config table (admin UI: Config > Farbschema, presets + custom pickers + live preview), served on the public /event endpoint with env defaults (THEME_PRESET/PRIMARY/ACCENT), propagated live via event-updated SSE, and cached in localStorage for a no-flash boot. The keepsake export mirrors the same ladder in Rust so offline archives match the event theme. COMMENTS_ENABLED (env, default true) is a boot-time kill-switch: the backend rejects new comments with 403 and the frontend hides the comment button (feed card) and panel/composer (lightbox). Existing comments stay in the DB, hidden, and return when re-enabled. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
45 lines
1.9 KiB
Rust
45 lines
1.9 KiB
Rust
//! Unauthenticated, read-only endpoints safe to expose before a user has joined.
|
|
|
|
use axum::Json;
|
|
use axum::extract::State;
|
|
use serde::Serialize;
|
|
|
|
use crate::services::config;
|
|
use crate::state::AppState;
|
|
|
|
#[derive(Serialize)]
|
|
pub struct PublicEventDto {
|
|
pub name: String,
|
|
pub slug: String,
|
|
/// Whether the comment feature is on (env `COMMENTS_ENABLED`). The frontend hides
|
|
/// the whole comment UI when false; exposed here so even the pre-auth shell knows.
|
|
pub comments_enabled: bool,
|
|
/// Active colour theme. `preset` is an id the frontend maps to a palette (or
|
|
/// "custom"); `primary`/`accent` are the `#rrggbb` seeds the ramps derive from.
|
|
/// Resolved as DB-config override → env default. Public so the theme applies on
|
|
/// the very first (pre-auth) paint without a flash.
|
|
pub theme_preset: String,
|
|
pub theme_primary: String,
|
|
pub theme_accent: String,
|
|
}
|
|
|
|
/// Public event identity + presentation config, used by the pre-auth join/recover
|
|
/// screens (which event am I joining, what does it look like). Only non-user-scoped
|
|
/// fields are exposed, so this is safe without a token. Identity comes straight from
|
|
/// instance config; the theme is resolved from the runtime `config` table (admin UI)
|
|
/// falling back to the env-seeded default.
|
|
pub async fn get_public_event(State(state): State<AppState>) -> Json<PublicEventDto> {
|
|
let cache = &state.config_cache;
|
|
Json(PublicEventDto {
|
|
name: state.config.event_name.clone(),
|
|
slug: state.config.event_slug.clone(),
|
|
comments_enabled: state.config.comments_enabled,
|
|
theme_preset: config::get_str(cache, "theme_preset", &state.config.default_theme_preset)
|
|
.await,
|
|
theme_primary: config::get_str(cache, "theme_primary", &state.config.default_theme_primary)
|
|
.await,
|
|
theme_accent: config::get_str(cache, "theme_accent", &state.config.default_theme_accent)
|
|
.await,
|
|
})
|
|
}
|