Commit graph

4 commits

Author SHA1 Message Date
d4d088fb50 feat(branding): per-brand default theme + palette via brand.json
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>
2026-06-15 22:12:13 +02:00
8f2c401e00 feat(branding): optional per-app banner replacing logo + name in header
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>
2026-06-15 22:11:01 +02:00
0ede6f70db docs(nix): document lib.mkWebapp in branding/README + CLAUDE.md
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>
2026-06-10 10:46:17 +02:00
3dfed23b43 docs(branding): brand kit contract + CLAUDE.md section
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>
2026-06-10 00:02:23 +02:00