Lets a deployer set the in-app color scheme a fresh visitor sees (e.g.
cfaun → darkmatter light) without forking. Two optional brand.json
fields, `theme` (light|dark|system) and `palette` (one of PALETTES),
distinct from `themeColor` which is PWA chrome only.
- vite-branding.ts surfaces them as VITE_BRAND_THEME / VITE_BRAND_PALETTE
at module load, so the default applies app-wide (hub + all standalones)
with no per-config wiring.
- theme-provider reads them as the INITIAL value of theme/palette; a
user's stored choice in localStorage still wins and persists.
- Splits the catppuccin = bare `:root` invariant (now BASE_PALETTE, used
by applyPalette to drop data-theme) from the configurable default.
Without this, a non-catppuccin brand default would strip the
data-theme attribute and silently render catppuccin instead.
Unset → the app's built-ins (dark + catppuccin), unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A brand may ship a wide banner (logo + wordmark in one image) that
replaces the brand-kit logo + app-name pair in a standalone's header.
Events is the first consumer.
Banners are optional and resolve at build time, mirroring the existing
@brand-app-logo chain:
- resolveAppBanner(app?) checks per-standalone override first
(branding/<dep>/icons/<app>/banner.{svg,png}) then the brand's primary
banner (branding/<dep>/banner.{svg,png}); returns null when absent
instead of throwing, so brands without a banner keep logo + name.
- brandAppBannerAliasEntry() always registers the @brand-app-banner
alias (falling back to the logo) so the static import resolves; whether
it renders is gated by the VITE_APP_BANNER build flag.
- EventsPage renders the banner when the flag is set, else logo + name.
Deployers override per-standalone without touching the component. SVG
banners must have their text outlined to paths (browsers lack designer
fonts) — documented in branding/README.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
branding/README's "Integration with NixOS deployment" section now
describes the actual lib.mkWebapp API + the per-host call site, with
a ready-to-paste server-deploy snippet. Also documents the pnpm_10
pin, sharp/autoPatchelfHook handling, and CI=true bypass — anchors
that surface in error logs and benefit from being grep-able.
CLAUDE.md's NixOS deployment paragraph stops calling lib.mkWebapp a
future TODO and points at the API directly.
Adds a `nix build` recipe (default + impure brand override) for local
sanity-checking.
Part of aiolabs/webapp#97.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the seed copy of src/assets/logo.png (8-bit colormap) with
the official AIO logo from ~/Pictures/AIO/aio.png (8-bit/color RGBA,
1024x1024, with alpha — better for maskable icons).
Generator output verified: all 6 icons regenerate cleanly from the
new source.
Part of aiolabs/webapp#95 / #96.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
branding/README.md is the deployer contract:
- Directory layout, source format constraints (SVG > PNG ≥ 1024),
brand.json schema, per-standalone override resolution order
- BRAND_DIR / BRAND_APP usage, generator pipeline walkthrough
- Pointer to issue #95 + the NixOS Phase 2 integration
webapp CLAUDE.md gains a Brand Kit section describing the moving
parts (vite-branding.ts, @brand alias, brandAssetsPlugin,
public/icons/ gitignore, per-app override path) so future sessions
on this repo know the convention without grepping.
Adds BRAND_DIR / BRAND_APP to the Environment Variables example.
Workspace ~/dev/CLAUDE.md note about "brand changes don't need
flake.lock bump" deferred to Phase 2 (server-deploy migration) —
that's when the workflow becomes reality.
Part of aiolabs/webapp#95.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
vite-branding.ts now loads brand.json into a typed `brand` object and
exports a `brandManifestName()` helper. Schema:
{ name (required), shortName?, themeColor?, backgroundColor? }
Default brand.json drops themeColor/backgroundColor — they're optional
overrides; per-app accents (wallet yellow, chat green, …) keep working
via `?? '<existing>'` fallbacks in each standalone's vite config.
events: manifest.name/short_name driven by brand. VITE_APP_NAME env
override stays (Phase 2 server-deploy migration still in flight) and,
when set, overrides both name and short_name to preserve pre-#95
behavior. cfaun's VITE_APP_NAME=Bouge keeps working unchanged.
hub (vite.config.ts): brand.name flows into %VITE_APP_NAME% Hub title.
7 other standalones (wallet, chat, market, forum, tasks, restaurant,
libra): only theme_color/background_color get brand overrides. Their
manifest.name/short_name stay hardcoded so multi-PWA home-screen
labels remain differentiated ("Wallet", "Chat", …) rather than all
collapsing to the brand short_name.
Verified default build: events manifest name=AIO; wallet keeps
"Wallet — Lightning" + #eab308 accent.
Verified VITE_APP_NAME=Sortir override: events name+short_name=Sortir.
Part of aiolabs/webapp#95.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Introduces branding/default/ as the unparameterized aiolabs brand:
- logo.png (1024x1024, seeded from src/assets/logo.png)
- brand.json with name, shortName, themeColor, backgroundColor
First step toward white-label PWA branding (aiolabs/webapp#95). No
consumer wiring yet — that's the next commits. Future deployers
(NixOS hosts in server-deploy, third-party white-labelers) point
BRAND_DIR at their own variant of this layout.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>