diff --git a/.gitignore b/.gitignore index 57b10a5..6d1f429 100644 --- a/.gitignore +++ b/.gitignore @@ -29,7 +29,6 @@ dist.tar.gz # auto-generated build file for PWA dev-dist/sw.js -public/icons/ aio-shadcn-vite.code-workspace dev-dist .specstory/history diff --git a/CLAUDE.md b/CLAUDE.md index 8008bc2..5b890de 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -712,60 +712,8 @@ VITE_ADMIN_PUBKEYS='["pubkey1","pubkey2"]' # Optional: Disable WebSocket if needed VITE_WEBSOCKET_ENABLED=true - -# Brand kit override (defaults to ./branding/default) -BRAND_DIR=branding/cfaun - -# Per-standalone brand override (set by build pipeline, not directly) -BRAND_APP=events ``` -## Brand kit (white-label PWA branding) - -The webapp ships a brand kit architecture so the hub + every standalone -(events, wallet, chat, market, …) can be rebranded per deployment without -forking the codebase. See `branding/README.md` for the deployer contract. - -**Single source of truth:** `branding//` holds `logo.{svg,png}` + -`brand.json`. `vite-branding.ts` reads brand.json and exposes a `@brand` -import alias. `pwa-assets.config.ts` + `@vite-pwa/assets-generator` derive -the full PWA icon set from the single logo source. - -**brand.json schema:** `{ name, shortName?, themeColor?, backgroundColor? }` -— `name` drives the manifest. `themeColor`/`backgroundColor` are optional -chrome overrides; when unset, each standalone's per-app accent applies. - -**In-app logo:** components reference `@brand/logo.png`. Active consumers: -`Login.vue`, `LoginDemo.vue`, `AppSidebar.vue`, `MobileDrawer.vue`. The -Vite alias resolves to the active brand dir at build time. - -**Generated icons:** `public/icons/` is gitignored. `brandAssetsPlugin()` -(registered first in every `vite.*.config.ts`'s plugins[]) runs the -generator once per build/dev start via `buildStart`. Outputs match the -existing filename convention (`icon-192.png`, `icon-maskable-512.png`, -…) so HTML `` hrefs and VitePWA `manifest.icons` reference -`/icons/` consistently across all 9 configs. - -**Per-standalone override:** `branding//icons//logo.{svg,png}` -is checked before the brand's primary logo. The standalone build sets -`BRAND_APP`; deployers just put files in the right place. - -**Switching brands:** -```bash -BRAND_DIR=branding/cfaun pnpm build:events -``` - -**Adding a new in-app logo consumer:** use `` -instead of `@/assets/logo.png`. The latter still works for non-brand -assets (`@/assets/bitcoin.svg`, etc.) — it's only the logo that moved. - -**NixOS deployment:** brand directories will eventually live in -`deploy/server-deploy/hosts//branding/`, with each host's -`services/webapp.nix` calling `inputs.webapp.lib.mkWebapp { brandDir = -./../branding; }`. `flake.nix` exposing `lib.mkWebapp` is a follow-up -to this PR. Until it lands, server-deploy continues to build webapp -through its existing path. See aiolabs/server-deploy#8. - ## Payment Rails Pattern Shared primitives for modules that mix Lightning + fiat (and, future, diff --git a/branding/README.md b/branding/README.md deleted file mode 100644 index 37bb1ce..0000000 --- a/branding/README.md +++ /dev/null @@ -1,110 +0,0 @@ -# Brand kit - -This directory holds the **white-label brand kit** that drives the PWA's icons, manifest name/colors, and in-app `` logo across the hub and every standalone (events, wallet, chat, market, …). - -The committed `default/` is aiolabs's brand and is what unparameterized builds use. Downstream deployers add a sibling directory (e.g. `branding/cfaun/`) and point `BRAND_DIR` at it to ship a fully rebranded build with no fork required. - -## Directory layout - -``` -branding/ - README.md - default/ # aiolabs default, committed - logo.svg # preferred source (sharp at every size) - logo.png # fallback source (≥ 1024×1024 if PNG-only) - brand.json # { name, shortName?, themeColor?, backgroundColor? } - icons/ # optional per-standalone overrides - events/logo.svg - wallet/logo.png - cfaun/ # downstream deployer's brand (gitignored or in deploy repo) - logo.svg - brand.json -``` - -aiolabs's `default/` currently ships PNG-only (1024×1024). Replace with `logo.svg` when a vector source becomes available — produces sharper icons at every size and unlocks `favicon.svg`. - -## Source formats - -**SVG strongly preferred:** - -- Crisp at every output size (192 / 512 maskable / 180 apple / 48 favicon) -- Enables sharp `favicon.svg` for modern browsers -- The in-app `@brand/logo` reference can be tinted via CSS (`currentColor`, filters) - -**PNG accepted with constraints:** - -- **≥ 1024×1024** — smaller sources produce blurry icons on high-DPI Android install screens -- **Square aspect ratio** — PWA icon canvas is square -- **Transparent background** — the generator applies maskable/apple background colors itself -- PNG-source deployments lose the `favicon.svg` benefit and the recolorable in-app logo - -When both `logo.svg` and `logo.png` are present, SVG wins. - -## brand.json schema - -```jsonc -{ - "name": "AIO", // required — drives PWA manifest name - "shortName": "AIO", // optional — PWA home-screen label; defaults to `name` - "themeColor": "#1f2937", // optional — PWA chrome color override (otherwise each standalone keeps its accent) - "backgroundColor": "#fff" // optional — PWA splash background -} -``` - -`themeColor` and `backgroundColor` are *overrides*, not defaults. When unset, each standalone's own accent applies (wallet yellow `#eab308`, chat green `#16a34a`, …) — so the default brand kit preserves the per-app visual identity, and a deployer who wants unified chrome adds the override. - -## Per-standalone overrides - -Place a logo at `branding//icons//logo.{svg,png}` to override the brand's primary logo for a single standalone build. - -Resolution at build time: - -1. `branding//icons//logo.svg` -2. `branding//icons//logo.png` -3. `branding//logo.svg` -4. `branding//logo.png` -5. Build fails with a clear error pointing here. - -`` is set via `BRAND_APP` env var (the standalone build script sets this; deployers don't touch it directly). - -## How to use - -**Building with the default brand:** - -```bash -pnpm build # main shell -pnpm build:events # events standalone -# … one per standalone -``` - -**Building with a deployer's brand:** - -```bash -BRAND_DIR=branding/cfaun pnpm build:events -``` - -`BRAND_DIR` accepts relative paths (resolved from the webapp repo root) or absolute paths (used by the NixOS builder, which mounts the brand directory into the sandbox at a `/nix/store/...-branding` path). - -**Regenerating icons explicitly:** - -The Vite plugin auto-runs the generator on every build/dev start. To run it standalone: - -```bash -pnpm generate-pwa-assets -``` - -Outputs land in `public/icons/` (gitignored). - -## Build pipeline - -1. `BRAND_DIR` is resolved (defaults to `./branding/default`). -2. `vite-branding.ts` reads `brand.json` and exposes `@brand/` alias. -3. `brandAssetsPlugin()` (registered in every `vite.*.config.ts`) runs `scripts/generate-pwa-assets.mjs` once per build via `buildStart`. -4. The script stages the source logo into `public/icons/.brand-source.{svg,png}`, runs `pwa-assets-generator`, then deletes the staged source. -5. Vite copies `public/icons/` into `dist/icons/`. Manifest references `icons/.png`. HTML `` tags reference `/icons/.{ico,png}`. - -## Integration with NixOS deployment - -See [aiolabs/webapp#95](https://git.atitlan.io/aiolabs/webapp/issues/95) for the full architecture. In short: `deploy/server-deploy/hosts//branding/` will hold per-host brands, and each host's `services/webapp.nix` will call `inputs.webapp.lib.mkWebapp { brandDir = ./../branding; }` once `lib.mkWebapp` is exposed from `flake.nix` (separate follow-up issue). - -The architectural payoff: brand and code become independent axes. Logo changes ship via server-deploy commits + redeploys — no webapp release, no `flake.lock` bump. diff --git a/branding/default/brand.json b/branding/default/brand.json deleted file mode 100644 index 2fc12c4..0000000 --- a/branding/default/brand.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "AIO", - "shortName": "AIO" -} diff --git a/branding/default/logo.png b/branding/default/logo.png deleted file mode 100644 index becf3b5..0000000 Binary files a/branding/default/logo.png and /dev/null differ diff --git a/chat.html b/chat.html index 1f0bdfd..fb83dee 100644 --- a/chat.html +++ b/chat.html @@ -6,8 +6,9 @@ - - + + + Chat — Encrypted diff --git a/events.html b/events.html index 801e609..ef24349 100644 --- a/events.html +++ b/events.html @@ -6,8 +6,9 @@ - - + + + %VITE_APP_NAME% diff --git a/forum.html b/forum.html index 8d81ea2..8646936 100644 --- a/forum.html +++ b/forum.html @@ -6,8 +6,9 @@ - - + + + Forum — Discussions diff --git a/index.html b/index.html index 6198b69..76e7922 100644 --- a/index.html +++ b/index.html @@ -7,8 +7,9 @@ - - + + + %VITE_APP_NAME% Hub diff --git a/libra.html b/libra.html index 88a9248..58927c4 100644 --- a/libra.html +++ b/libra.html @@ -6,8 +6,9 @@ - - + + + Libra — Accounting diff --git a/market.html b/market.html index 321435a..3fc32d5 100644 --- a/market.html +++ b/market.html @@ -6,8 +6,9 @@ - - + + + Market — Nostr diff --git a/package.json b/package.json index 439cb84..4fea5ac 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,6 @@ "type": "module", "main": "electron/main.cjs", "scripts": { - "generate-pwa-assets": "node scripts/generate-pwa-assets.mjs", "dev": "vite --host", "build": "vue-tsc -b && vite build", "preview": "vite preview --host", @@ -93,7 +92,6 @@ "@types/node": "^22.18.1", "@types/qrcode": "^1.5.5", "@types/rollup-plugin-visualizer": "^4.2.3", - "@vite-pwa/assets-generator": "^1.0.2", "@vitejs/plugin-vue": "^5.2.1", "@vue/tsconfig": "^0.7.0", "concurrently": "^8.2.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c242e32..d1a8b7c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -150,9 +150,6 @@ importers: '@types/rollup-plugin-visualizer': specifier: ^4.2.3 version: 4.2.4 - '@vite-pwa/assets-generator': - specifier: ^1.0.2 - version: 1.0.2 '@vitejs/plugin-vue': specifier: ^5.2.1 version: 5.2.4(vite@6.4.2(@types/node@22.19.19)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0))(vue@3.5.34(typescript@5.6.3)) @@ -191,7 +188,7 @@ importers: version: 0.8.9(rollup@4.60.4)(vite@6.4.2(@types/node@22.19.19)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0)) vite-plugin-pwa: specifier: ^0.21.1 - version: 0.21.2(@vite-pwa/assets-generator@1.0.2)(vite@6.4.2(@types/node@22.19.19)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0))(workbox-build@7.4.1)(workbox-window@7.4.1) + version: 0.21.2(vite@6.4.2(@types/node@22.19.19)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0))(workbox-build@7.4.1)(workbox-window@7.4.1) vue-tsc: specifier: ^2.2.0 version: 2.2.12(typescript@5.6.3) @@ -714,9 +711,6 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} - '@canvas/image-data@1.1.0': - resolution: {integrity: sha512-QdObRRjRbcXGmM1tmJ+MrHcaz1MftF2+W7YI+MsphnsCrmtyfS0d5qJbk0MeSbUeyM/jCb0hmnkXPsy026L7dA==} - '@electron-forge/cli@7.11.2': resolution: {integrity: sha512-c+C4ndLfHbxwZuCn9G8iT9wD/woLdaVkoSVjAIbj+0nJhi8UmiVsz/+Gxlj4cvhMRTzBMBxudstLU7RocMikfg==} engines: {node: '>= 16.4.0'} @@ -1289,9 +1283,6 @@ packages: '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} - '@quansync/fs@1.0.0': - resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} - '@rollup/plugin-babel@6.1.0': resolution: {integrity: sha512-dFZNuFD2YRcoomP4oYf+DvQNSUA9ih+A3vUqopQx5EdtPGo3WBnQcI/S8pwpz91UsGfL0HsMSOlaMld8HrbubA==} engines: {node: '>=14.0.0'} @@ -1706,11 +1697,6 @@ packages: peerDependencies: zod: ^3.24.0 - '@vite-pwa/assets-generator@1.0.2': - resolution: {integrity: sha512-MCbrb508JZHqe7bUibmZj/lyojdhLRnfkmyXnkrCM2zVrjTgL89U8UEfInpKTvPeTnxsw2hmyZxnhsdNR6yhwg==} - engines: {node: '>=16.14.0'} - hasBin: true - '@vitejs/plugin-vue@5.2.4': resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==} engines: {node: ^18.0.0 || >=20.0.0} @@ -2135,10 +2121,6 @@ packages: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - cacache@16.1.3: resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -2285,10 +2267,6 @@ packages: engines: {node: ^14.13.0 || >=16.0.0} hasBin: true - consola@3.4.2: - resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} - engines: {node: ^14.18.0 || >=16.10.0} - convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -2388,14 +2366,6 @@ packages: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} - decode-bmp@0.2.1: - resolution: {integrity: sha512-NiOaGe+GN0KJqi2STf24hfMkFitDUaIoUU3eKvP/wAbLe8o6FuW5n/x7MHPR0HKvBokp6MQY/j7w8lewEeVCIA==} - engines: {node: '>=8.6.0'} - - decode-ico@0.4.1: - resolution: {integrity: sha512-69NZfbKIzux1vBOd31al3XnMnH+2mqDhEgLdpygErm4d60N+UwA5Sq5WFjmEDQzumgB9fElojGwWG0vybVfFmA==} - engines: {node: '>=8.6'} - decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} @@ -2920,9 +2890,6 @@ packages: humanize-ms@1.2.1: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} - ico-endec@0.1.6: - resolution: {integrity: sha512-ZdLU38ZoED3g1j3iEyzcQj+wAkY2xfWNkymszfJPoxucIUhK7NayQ+/C4Kv0nDFMIsbtbEHldv3V8PU494/ueQ==} - iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -3833,9 +3800,6 @@ packages: engines: {node: '>=10.13.0'} hasBin: true - quansync@1.0.0: - resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==} - queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -4056,9 +4020,6 @@ packages: resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} engines: {node: '>= 0.4'} - sharp-ico@0.1.5: - resolution: {integrity: sha512-a3jODQl82NPp1d5OYb0wY+oFaPk7AvyxipIowCHk7pBsZCWgbe0yAkU2OOXdoH0ENyANhyOQbs9xkAiRHcF02Q==} - sharp@0.33.5: resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -4361,9 +4322,6 @@ packages: resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} engines: {node: '>=14.14'} - to-data-view@1.1.0: - resolution: {integrity: sha512-1eAdufMg6mwgmlojAx3QeMnzB/BTVp7Tbndi3U7ftcT2zCZadjxkkmLmd97zmaxWi+sgGcgWrokmpEoy0Dn0vQ==} - to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -4439,12 +4397,6 @@ packages: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} - unconfig-core@7.5.0: - resolution: {integrity: sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==} - - unconfig@7.5.0: - resolution: {integrity: sha512-oi8Qy2JV4D3UQ0PsopR28CzdQ3S/5A1zwsUwp/rosSbfhJ5z7b90bIyTwi/F7hCLD4SGcZVjDzd4XoUQcEanvA==} - undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} @@ -5504,8 +5456,6 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@canvas/image-data@1.1.0': {} - '@electron-forge/cli@7.11.2(encoding@0.1.13)(lightningcss@1.32.0)': dependencies: '@electron-forge/core': 7.11.2(encoding@0.1.13)(lightningcss@1.32.0) @@ -6284,10 +6234,6 @@ snapshots: '@polka/url@1.0.0-next.29': {} - '@quansync/fs@1.0.0': - dependencies: - quansync: 1.0.0 - '@rollup/plugin-babel@6.1.0(@babel/core@7.29.0)(rollup@4.60.4)': dependencies: '@babel/core': 7.29.0 @@ -6613,15 +6559,6 @@ snapshots: transitivePeerDependencies: - vue - '@vite-pwa/assets-generator@1.0.2': - dependencies: - cac: 6.7.14 - colorette: 2.0.20 - consola: 3.4.2 - sharp: 0.33.5 - sharp-ico: 0.1.5 - unconfig: 7.5.0 - '@vitejs/plugin-vue@5.2.4(vite@6.4.2(@types/node@22.19.19)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0))(vue@3.5.34(typescript@5.6.3))': dependencies: vite: 6.4.2(@types/node@22.19.19)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0) @@ -7093,8 +7030,6 @@ snapshots: dependencies: run-applescript: 7.1.0 - cac@6.7.14: {} - cacache@16.1.3: dependencies: '@npmcli/fs': 2.1.2 @@ -7258,8 +7193,6 @@ snapshots: tree-kill: 1.2.2 yargs: 17.7.2 - consola@3.4.2: {} - convert-source-map@2.0.0: {} copy-anything@4.0.5: @@ -7354,17 +7287,6 @@ snapshots: decamelize@1.2.0: {} - decode-bmp@0.2.1: - dependencies: - '@canvas/image-data': 1.1.0 - to-data-view: 1.1.0 - - decode-ico@0.4.1: - dependencies: - '@canvas/image-data': 1.1.0 - decode-bmp: 0.2.1 - to-data-view: 1.1.0 - decompress-response@6.0.0: dependencies: mimic-response: 3.1.0 @@ -8051,8 +7973,6 @@ snapshots: dependencies: ms: 2.1.3 - ico-endec@0.1.6: {} - iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 @@ -8849,8 +8769,6 @@ snapshots: pngjs: 5.0.0 yargs: 15.4.1 - quansync@1.0.0: {} - queue-microtask@1.2.3: {} quick-lru@5.1.1: {} @@ -9140,12 +9058,6 @@ snapshots: es-errors: 1.3.0 es-object-atoms: 1.1.2 - sharp-ico@0.1.5: - dependencies: - decode-ico: 0.4.1 - ico-endec: 0.1.6 - sharp: 0.33.5 - sharp@0.33.5: dependencies: color: 4.2.3 @@ -9475,8 +9387,6 @@ snapshots: tmp@0.2.5: optional: true - to-data-view@1.1.0: {} - to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -9552,19 +9462,6 @@ snapshots: has-symbols: 1.1.0 which-boxed-primitive: 1.1.1 - unconfig-core@7.5.0: - dependencies: - '@quansync/fs': 1.0.0 - quansync: 1.0.0 - - unconfig@7.5.0: - dependencies: - '@quansync/fs': 1.0.0 - defu: 6.1.7 - jiti: 2.7.0 - quansync: 1.0.0 - unconfig-core: 7.5.0 - undici-types@6.21.0: {} unicode-canonical-property-names-ecmascript@2.0.1: {} @@ -9646,7 +9543,7 @@ snapshots: - rollup - supports-color - vite-plugin-pwa@0.21.2(@vite-pwa/assets-generator@1.0.2)(vite@6.4.2(@types/node@22.19.19)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0))(workbox-build@7.4.1)(workbox-window@7.4.1): + vite-plugin-pwa@0.21.2(vite@6.4.2(@types/node@22.19.19)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0))(workbox-build@7.4.1)(workbox-window@7.4.1): dependencies: debug: 4.4.3 pretty-bytes: 6.1.1 @@ -9654,8 +9551,6 @@ snapshots: vite: 6.4.2(@types/node@22.19.19)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.48.0) workbox-build: 7.4.1 workbox-window: 7.4.1 - optionalDependencies: - '@vite-pwa/assets-generator': 1.0.2 transitivePeerDependencies: - supports-color diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 0000000..1f8c550 Binary files /dev/null and b/public/apple-touch-icon.png differ diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..9fef45b Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/icon-192.png b/public/icon-192.png new file mode 100644 index 0000000..e77168a Binary files /dev/null and b/public/icon-192.png differ diff --git a/public/icon-512.png b/public/icon-512.png new file mode 100644 index 0000000..550b306 Binary files /dev/null and b/public/icon-512.png differ diff --git a/public/icon-maskable-192.png b/public/icon-maskable-192.png new file mode 100644 index 0000000..0f2053d Binary files /dev/null and b/public/icon-maskable-192.png differ diff --git a/public/icon-maskable-512.png b/public/icon-maskable-512.png new file mode 100644 index 0000000..0926f7a Binary files /dev/null and b/public/icon-maskable-512.png differ diff --git a/public/mask-icon.svg b/public/mask-icon.svg new file mode 100644 index 0000000..6bcfe91 --- /dev/null +++ b/public/mask-icon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/pwa-assets.config.ts b/pwa-assets.config.ts deleted file mode 100644 index 93fee71..0000000 --- a/pwa-assets.config.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { defineConfig } from '@vite-pwa/assets-generator/config' -import { copyFileSync, existsSync, mkdirSync } from 'node:fs' -import { join, resolve } from 'node:path' - -const BRAND_DIR = process.env.BRAND_DIR ?? './branding/default' -const BRAND_APP = process.env.BRAND_APP ?? '' - -const candidates: string[] = [] -if (BRAND_APP) { - candidates.push( - join(BRAND_DIR, 'icons', BRAND_APP, 'logo.svg'), - join(BRAND_DIR, 'icons', BRAND_APP, 'logo.png'), - ) -} -candidates.push( - join(BRAND_DIR, 'logo.svg'), - join(BRAND_DIR, 'logo.png'), -) - -const source = candidates.find((p) => existsSync(p)) -if (!source) { - throw new Error( - `No brand logo found. Tried:\n ${candidates.join('\n ')}\n` + - `See branding/README.md for the brand kit contract.`, - ) -} - -// The CLI emits next to the source. Stage into public/icons/ so generated -// PNGs are served at /icons/.png and a single .gitignore line covers -// the whole tree. -const stagingDir = resolve('public/icons') -mkdirSync(stagingDir, { recursive: true }) -const sourceExt = source.toLowerCase().endsWith('.svg') ? '.svg' : '.png' -const stagedSource = join(stagingDir, `.brand-source${sourceExt}`) -copyFileSync(source, stagedSource) - -export default defineConfig({ - headLinkOptions: { preset: '2023' }, - preset: { - transparent: { - sizes: [192, 512], - favicons: [[48, 'favicon.ico']], - }, - maskable: { sizes: [192, 512] }, - apple: { sizes: [180] }, - assetName: (type, size) => { - if (type === 'transparent') return `icon-${size.width}.png` - if (type === 'maskable') return `icon-maskable-${size.width}.png` - if (type === 'apple') return 'apple-touch-icon.png' - throw new Error(`Unknown asset type: ${type}`) - }, - }, - images: [stagedSource], -}) diff --git a/restaurant.html b/restaurant.html index 950aa6d..e910921 100644 --- a/restaurant.html +++ b/restaurant.html @@ -6,8 +6,9 @@ - - + + + Restaurant — Order diff --git a/scripts/generate-pwa-assets.mjs b/scripts/generate-pwa-assets.mjs deleted file mode 100644 index e6cfa01..0000000 --- a/scripts/generate-pwa-assets.mjs +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env node -// Wraps pwa-assets-generator and removes the staged brand source after -// generation. pwa-assets.config.ts copies $BRAND_DIR/logo.{svg,png} -// into public/icons/.brand-source.* because the CLI emits next to the -// source. Without this cleanup the full-resolution source ships in -// dist/icons/ and is publicly served. -import { spawnSync } from 'node:child_process' -import { existsSync, rmSync } from 'node:fs' -import { resolve } from 'node:path' - -const cli = resolve('node_modules/.bin/pwa-assets-generator') -const { status } = spawnSync(cli, process.argv.slice(2), { stdio: 'inherit' }) -if (status !== 0) process.exit(status ?? 1) - -const stagingDir = resolve('public/icons') -for (const ext of ['svg', 'png']) { - const staged = resolve(stagingDir, `.brand-source.${ext}`) - if (existsSync(staged)) rmSync(staged) -} diff --git a/src/components/layout/AppSidebar.vue b/src/components/layout/AppSidebar.vue index b72fe4f..7b5accf 100644 --- a/src/components/layout/AppSidebar.vue +++ b/src/components/layout/AppSidebar.vue @@ -48,7 +48,7 @@ const isActive = (href: string) => {
Logo diff --git a/src/components/layout/MobileDrawer.vue b/src/components/layout/MobileDrawer.vue index 5eeefd3..98b0740 100644 --- a/src/components/layout/MobileDrawer.vue +++ b/src/components/layout/MobileDrawer.vue @@ -77,7 +77,7 @@ const navigateTo = (href: string) => { Logo diff --git a/src/pages/Login.vue b/src/pages/Login.vue index 7f465f4..f0318ac 100644 --- a/src/pages/Login.vue +++ b/src/pages/Login.vue @@ -4,7 +4,7 @@
- Logo + Logo

Virtual Realm

diff --git a/src/pages/LoginDemo.vue b/src/pages/LoginDemo.vue index 4fbb234..13a8dd1 100644 --- a/src/pages/LoginDemo.vue +++ b/src/pages/LoginDemo.vue @@ -5,7 +5,7 @@
- Logo + Logo

Welcome to the Virtual Realm

diff --git a/tasks.html b/tasks.html index 661b57b..6a5b49a 100644 --- a/tasks.html +++ b/tasks.html @@ -6,8 +6,9 @@ - - + + + Tasks — Work Orders diff --git a/vite-branding.ts b/vite-branding.ts deleted file mode 100644 index 4480f15..0000000 --- a/vite-branding.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { spawnSync } from 'node:child_process' -import { readFileSync } from 'node:fs' -import { resolve } from 'node:path' -import type { Plugin } from 'vite' - -/** - * Absolute path to the active brand kit. Deployers point this at their - * own `branding//` directory (see branding/README.md). - * - * Defaults to the committed aiolabs default brand. Used by vite configs - * for the `@brand` import alias and by pwa-assets.config.ts. - */ -export const BRAND_DIR = resolve(process.env.BRAND_DIR ?? './branding/default') - -/** Fields parsed from brand.json. All but `name` are optional. */ -export interface Brand { - /** Brand label — drives PWA manifest name. */ - name: string - /** PWA install/home-screen short label. Defaults to `name`. */ - shortName?: string - /** - * Optional PWA chrome theme color (status bar / title bar when installed). - * When unset, each standalone's vite config keeps its hardcoded accent. - */ - themeColor?: string - /** - * Optional PWA splash background. When unset, each standalone's vite - * config keeps its hardcoded value. - */ - backgroundColor?: string -} - -export const brand: Brand = JSON.parse( - readFileSync(resolve(BRAND_DIR, 'brand.json'), 'utf-8'), -) - -/** - * Spread into a vite config's `resolve.alias` map. Lets components - * import deployer-provided assets via `@brand/` instead of - * hardcoding `@/assets/logo.png`. - */ -export const brandAlias = { - '@brand': BRAND_DIR, -} as const - -/** - * PWA manifest name for a standalone. Combines the brand name with the - * app's own label, or returns the bare brand when no label is given. - * - * Example: `brandManifestName('Wallet')` → "AIO Wallet" / "Cfaun Wallet". - * Example: `brandManifestName()` → "AIO" / "Sortir". - */ -export function brandManifestName(appLabel?: string): string { - return appLabel ? `${brand.name} ${appLabel}` : brand.name -} - -/** - * Vite plugin: regenerate PWA icons under public/icons/ once per build - * / dev-server start, so vite..config.ts's includeAssets + - * manifest.icons always have something to include. Source resolution - * lives in pwa-assets.config.ts. - */ -export function brandAssetsPlugin(): Plugin { - let generated = false - return { - name: 'brand-assets-generator', - buildStart() { - if (generated) return - const { status } = spawnSync( - 'node', - [resolve('scripts/generate-pwa-assets.mjs')], - { stdio: 'inherit' }, - ) - if (status !== 0) { - throw new Error('pwa-assets-generator failed; see output above') - } - generated = true - }, - } -} diff --git a/vite.chat.config.ts b/vite.chat.config.ts index afa3416..c28535f 100644 --- a/vite.chat.config.ts +++ b/vite.chat.config.ts @@ -5,7 +5,6 @@ import { defineConfig, type Plugin } from 'vite' import { VitePWA } from 'vite-plugin-pwa' import { ViteImageOptimizer } from 'vite-plugin-image-optimizer' import { visualizer } from 'rollup-plugin-visualizer' -import { brand, brandAlias, brandAssetsPlugin } from './vite-branding' function chatHtmlPlugin(): Plugin { return { @@ -46,7 +45,6 @@ export default defineConfig(({ mode }) => ({ strictPort: true, }, plugins: [ - brandAssetsPlugin(), chatHtmlPlugin(), vue(), tailwindcss(), @@ -61,19 +59,20 @@ export default defineConfig(({ mode }) => ({ ], }, includeAssets: [ - 'icons/favicon.ico', - 'icons/apple-touch-icon.png', - 'icons/icon-192.png', - 'icons/icon-512.png', - 'icons/icon-maskable-192.png', - 'icons/icon-maskable-512.png', + 'favicon.ico', + 'apple-touch-icon.png', + 'mask-icon.svg', + 'icon-192.png', + 'icon-512.png', + 'icon-maskable-192.png', + 'icon-maskable-512.png', ], manifest: { name: 'Chat — Encrypted', short_name: 'Chat', description: 'End-to-end encrypted Nostr chat', - theme_color: brand.themeColor ?? '#16a34a', - background_color: brand.backgroundColor ?? '#ffffff', + theme_color: '#16a34a', + background_color: '#ffffff', display: 'standalone', orientation: 'portrait-primary', start_url: process.env.VITE_BASE_PATH || '/', @@ -82,10 +81,10 @@ export default defineConfig(({ mode }) => ({ categories: ['social', 'communication'], lang: 'en', icons: [ - { src: 'icons/icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' }, - { src: 'icons/icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' }, - { src: 'icons/icon-maskable-192.png', sizes: '192x192', type: 'image/png', purpose: 'maskable' }, - { src: 'icons/icon-maskable-512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }, + { src: 'icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' }, + { src: 'icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' }, + { src: 'icon-maskable-192.png', sizes: '192x192', type: 'image/png', purpose: 'maskable' }, + { src: 'icon-maskable-512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }, ], }, }), @@ -104,7 +103,6 @@ export default defineConfig(({ mode }) => ({ ], resolve: { alias: { - ...brandAlias, // ORDER MATTERS — @/app.config must precede @ (first-match-wins). '@/app.config': fileURLToPath(new URL('./src/chat-app/app.config.ts', import.meta.url)), '@': fileURLToPath(new URL('./src', import.meta.url)), diff --git a/vite.config.ts b/vite.config.ts index 6363a0b..b3de398 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -5,7 +5,6 @@ import { defineConfig } from 'vite' import Inspect from 'vite-plugin-inspect' import { ViteImageOptimizer } from 'vite-plugin-image-optimizer' import { visualizer } from 'rollup-plugin-visualizer' -import { brand, brandAlias, brandAssetsPlugin } from './vite-branding' // https://vite.dev/config/ // @@ -13,11 +12,6 @@ import { brand, brandAlias, brandAssetsPlugin } from './vite-branding' // the entire origin and blocked Chrome from offering installs for the // path-mounted standalones at /libra/, /market/, etc. The hub is a // launcher page; users install the standalones they actually use. - -// Brand name flows into index.html's `%VITE_APP_NAME% Hub` title via -// Vite's HTML env-var substitution. -process.env.VITE_APP_NAME = brand.name - export default defineConfig(({ mode }) => ({ // Per-app dep cache so concurrent dev servers don't race on .vite/deps cacheDir: 'node_modules/.vite-hub', @@ -26,7 +20,6 @@ export default defineConfig(({ mode }) => ({ strictPort: true, }, plugins: [ - brandAssetsPlugin(), vue(), tailwindcss(), Inspect(), @@ -50,7 +43,6 @@ export default defineConfig(({ mode }) => ({ ], resolve: { alias: { - ...brandAlias, '@': fileURLToPath(new URL('./src', import.meta.url)) } }, diff --git a/vite.events.config.ts b/vite.events.config.ts index 9882456..76c2c31 100644 --- a/vite.events.config.ts +++ b/vite.events.config.ts @@ -5,7 +5,6 @@ import { defineConfig, type Plugin } from 'vite' import { VitePWA } from 'vite-plugin-pwa' import { ViteImageOptimizer } from 'vite-plugin-image-optimizer' import { visualizer } from 'rollup-plugin-visualizer' -import { brand, brandAlias, brandAssetsPlugin, brandManifestName } from './vite-branding' /** * Plugin to rewrite dev server requests to events.html @@ -42,11 +41,12 @@ function eventsHtmlPlugin(): Plugin { * VITE_BASE_PATH=/events/ → app.ariege.io/events/ (shared auth) * (default: /) → bouge.ariege.io (standalone subdomain) * - * Brand name resolves from brand.json under $BRAND_DIR (see - * vite-branding.ts and aiolabs/webapp#95). Surfaced into Vite's HTML - * env-var substitution as VITE_APP_NAME for templated titles. + * Set VITE_APP_NAME to brand the standalone (PWA name, HTML title, console + * logs). cfaun overrides to "Bouge" via NixOS. Defaults to "Events". */ -const APP_NAME = brandManifestName() +const APP_NAME = process.env.VITE_APP_NAME || 'Events' +// Surface the resolved value back into env so Vite's HTML %VITE_APP_NAME% +// substitution picks up the fallback when nothing was explicitly set. process.env.VITE_APP_NAME = APP_NAME export default defineConfig(({ mode }) => ({ @@ -58,7 +58,6 @@ export default defineConfig(({ mode }) => ({ strictPort: true, }, plugins: [ - brandAssetsPlugin(), eventsHtmlPlugin(), vue(), tailwindcss(), @@ -76,19 +75,20 @@ export default defineConfig(({ mode }) => ({ ], }, includeAssets: [ - 'icons/favicon.ico', - 'icons/apple-touch-icon.png', - 'icons/icon-192.png', - 'icons/icon-512.png', - 'icons/icon-maskable-192.png', - 'icons/icon-maskable-512.png', + 'favicon.ico', + 'apple-touch-icon.png', + 'mask-icon.svg', + 'icon-192.png', + 'icon-512.png', + 'icon-maskable-192.png', + 'icon-maskable-512.png', ], manifest: { name: APP_NAME, - short_name: brand.shortName ?? APP_NAME, + short_name: APP_NAME, description: 'Discover events near you', - theme_color: brand.themeColor ?? '#1f2937', - background_color: brand.backgroundColor ?? '#ffffff', + theme_color: '#1f2937', + background_color: '#ffffff', display: 'standalone', orientation: 'portrait-primary', start_url: process.env.VITE_BASE_PATH || '/', @@ -96,10 +96,10 @@ export default defineConfig(({ mode }) => ({ id: 'aiolabs-events', categories: ['social', 'entertainment', 'lifestyle'], icons: [ - { src: 'icons/icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' }, - { src: 'icons/icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' }, - { src: 'icons/icon-maskable-192.png', sizes: '192x192', type: 'image/png', purpose: 'maskable' }, - { src: 'icons/icon-maskable-512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }, + { src: 'icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' }, + { src: 'icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' }, + { src: 'icon-maskable-192.png', sizes: '192x192', type: 'image/png', purpose: 'maskable' }, + { src: 'icon-maskable-512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }, ], }, }), @@ -118,7 +118,6 @@ export default defineConfig(({ mode }) => ({ ], resolve: { alias: { - ...brandAlias, '@': fileURLToPath(new URL('./src', import.meta.url)), }, }, diff --git a/vite.forum.config.ts b/vite.forum.config.ts index 3dcc6e4..0fdebbe 100644 --- a/vite.forum.config.ts +++ b/vite.forum.config.ts @@ -5,7 +5,6 @@ import { defineConfig, type Plugin } from 'vite' import { VitePWA } from 'vite-plugin-pwa' import { ViteImageOptimizer } from 'vite-plugin-image-optimizer' import { visualizer } from 'rollup-plugin-visualizer' -import { brand, brandAlias, brandAssetsPlugin } from './vite-branding' function forumHtmlPlugin(): Plugin { return { @@ -46,7 +45,6 @@ export default defineConfig(({ mode }) => ({ strictPort: true, }, plugins: [ - brandAssetsPlugin(), forumHtmlPlugin(), vue(), tailwindcss(), @@ -61,19 +59,20 @@ export default defineConfig(({ mode }) => ({ ], }, includeAssets: [ - 'icons/favicon.ico', - 'icons/apple-touch-icon.png', - 'icons/icon-192.png', - 'icons/icon-512.png', - 'icons/icon-maskable-192.png', - 'icons/icon-maskable-512.png', + 'favicon.ico', + 'apple-touch-icon.png', + 'mask-icon.svg', + 'icon-192.png', + 'icon-512.png', + 'icon-maskable-192.png', + 'icon-maskable-512.png', ], manifest: { name: 'Forum — Discussions', short_name: 'Forum', description: 'Decentralized link aggregator and discussion forum on Nostr', - theme_color: brand.themeColor ?? '#2563eb', - background_color: brand.backgroundColor ?? '#ffffff', + theme_color: '#2563eb', + background_color: '#ffffff', display: 'standalone', orientation: 'portrait-primary', start_url: process.env.VITE_BASE_PATH || '/', @@ -82,10 +81,10 @@ export default defineConfig(({ mode }) => ({ categories: ['social', 'news'], lang: 'en', icons: [ - { src: 'icons/icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' }, - { src: 'icons/icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' }, - { src: 'icons/icon-maskable-192.png', sizes: '192x192', type: 'image/png', purpose: 'maskable' }, - { src: 'icons/icon-maskable-512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }, + { src: 'icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' }, + { src: 'icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' }, + { src: 'icon-maskable-192.png', sizes: '192x192', type: 'image/png', purpose: 'maskable' }, + { src: 'icon-maskable-512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }, ], }, }), @@ -104,7 +103,6 @@ export default defineConfig(({ mode }) => ({ ], resolve: { alias: { - ...brandAlias, // ORDER MATTERS — @/app.config must precede @ (first-match-wins). '@/app.config': fileURLToPath(new URL('./src/forum-app/app.config.ts', import.meta.url)), '@': fileURLToPath(new URL('./src', import.meta.url)), diff --git a/vite.libra.config.ts b/vite.libra.config.ts index 8fb1ca5..cea9f6e 100644 --- a/vite.libra.config.ts +++ b/vite.libra.config.ts @@ -5,7 +5,6 @@ import { defineConfig, type Plugin } from 'vite' import { VitePWA } from 'vite-plugin-pwa' import { ViteImageOptimizer } from 'vite-plugin-image-optimizer' import { visualizer } from 'rollup-plugin-visualizer' -import { brand, brandAlias, brandAssetsPlugin } from './vite-branding' /** * Plugin to rewrite dev server requests to libra.html @@ -51,7 +50,6 @@ export default defineConfig(({ mode }) => ({ strictPort: true, }, plugins: [ - brandAssetsPlugin(), libraHtmlPlugin(), vue(), tailwindcss(), @@ -68,19 +66,20 @@ export default defineConfig(({ mode }) => ({ ], }, includeAssets: [ - 'icons/favicon.ico', - 'icons/apple-touch-icon.png', - 'icons/icon-192.png', - 'icons/icon-512.png', - 'icons/icon-maskable-192.png', - 'icons/icon-maskable-512.png', + 'favicon.ico', + 'apple-touch-icon.png', + 'mask-icon.svg', + 'icon-192.png', + 'icon-512.png', + 'icon-maskable-192.png', + 'icon-maskable-512.png', ], manifest: { name: 'Libra — Team Accounting', short_name: 'Libra', description: 'Team accounting and expense management', - theme_color: brand.themeColor ?? '#1f2937', - background_color: brand.backgroundColor ?? '#ffffff', + theme_color: '#1f2937', + background_color: '#ffffff', display: 'standalone', orientation: 'portrait-primary', start_url: process.env.VITE_BASE_PATH || '/', @@ -89,10 +88,10 @@ export default defineConfig(({ mode }) => ({ categories: ['finance', 'business', 'productivity'], lang: 'en', icons: [ - { src: 'icons/icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' }, - { src: 'icons/icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' }, - { src: 'icons/icon-maskable-192.png', sizes: '192x192', type: 'image/png', purpose: 'maskable' }, - { src: 'icons/icon-maskable-512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }, + { src: 'icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' }, + { src: 'icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' }, + { src: 'icon-maskable-192.png', sizes: '192x192', type: 'image/png', purpose: 'maskable' }, + { src: 'icon-maskable-512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }, ], }, }), @@ -111,7 +110,6 @@ export default defineConfig(({ mode }) => ({ ], resolve: { alias: { - ...brandAlias, // ORDER MATTERS — @rollup/plugin-alias is first-match-wins. // The more specific @/app.config remap must precede the @ prefix // alias, otherwise '@/app.config' matches '@' first and resolves diff --git a/vite.market.config.ts b/vite.market.config.ts index 01d22b6..bf38430 100644 --- a/vite.market.config.ts +++ b/vite.market.config.ts @@ -5,7 +5,6 @@ import { defineConfig, type Plugin } from 'vite' import { VitePWA } from 'vite-plugin-pwa' import { ViteImageOptimizer } from 'vite-plugin-image-optimizer' import { visualizer } from 'rollup-plugin-visualizer' -import { brand, brandAlias, brandAssetsPlugin } from './vite-branding' function marketHtmlPlugin(): Plugin { return { @@ -46,7 +45,6 @@ export default defineConfig(({ mode }) => ({ strictPort: true, }, plugins: [ - brandAssetsPlugin(), marketHtmlPlugin(), vue(), tailwindcss(), @@ -61,19 +59,20 @@ export default defineConfig(({ mode }) => ({ ], }, includeAssets: [ - 'icons/favicon.ico', - 'icons/apple-touch-icon.png', - 'icons/icon-192.png', - 'icons/icon-512.png', - 'icons/icon-maskable-192.png', - 'icons/icon-maskable-512.png', + 'favicon.ico', + 'apple-touch-icon.png', + 'mask-icon.svg', + 'icon-192.png', + 'icon-512.png', + 'icon-maskable-192.png', + 'icon-maskable-512.png', ], manifest: { name: 'Market — Nostr', short_name: 'Market', description: 'Decentralized marketplace on Nostr with Lightning payments', - theme_color: brand.themeColor ?? '#dc2626', - background_color: brand.backgroundColor ?? '#ffffff', + theme_color: '#dc2626', + background_color: '#ffffff', display: 'standalone', orientation: 'portrait-primary', start_url: process.env.VITE_BASE_PATH || '/', @@ -82,10 +81,10 @@ export default defineConfig(({ mode }) => ({ categories: ['shopping', 'business'], lang: 'en', icons: [ - { src: 'icons/icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' }, - { src: 'icons/icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' }, - { src: 'icons/icon-maskable-192.png', sizes: '192x192', type: 'image/png', purpose: 'maskable' }, - { src: 'icons/icon-maskable-512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }, + { src: 'icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' }, + { src: 'icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' }, + { src: 'icon-maskable-192.png', sizes: '192x192', type: 'image/png', purpose: 'maskable' }, + { src: 'icon-maskable-512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }, ], }, }), @@ -104,7 +103,6 @@ export default defineConfig(({ mode }) => ({ ], resolve: { alias: { - ...brandAlias, // ORDER MATTERS — @/app.config must precede @ (first-match-wins). '@/app.config': fileURLToPath(new URL('./src/market-app/app.config.ts', import.meta.url)), '@': fileURLToPath(new URL('./src', import.meta.url)), diff --git a/vite.restaurant.config.ts b/vite.restaurant.config.ts index 23f27ef..c9c697c 100644 --- a/vite.restaurant.config.ts +++ b/vite.restaurant.config.ts @@ -5,7 +5,6 @@ import { defineConfig, type Plugin } from 'vite' import { VitePWA } from 'vite-plugin-pwa' import { ViteImageOptimizer } from 'vite-plugin-image-optimizer' import { visualizer } from 'rollup-plugin-visualizer' -import { brand, brandAlias, brandAssetsPlugin } from './vite-branding' function restaurantHtmlPlugin(): Plugin { return { @@ -51,7 +50,6 @@ export default defineConfig(({ mode }) => ({ strictPort: true, }, plugins: [ - brandAssetsPlugin(), restaurantHtmlPlugin(), vue(), tailwindcss(), @@ -66,12 +64,13 @@ export default defineConfig(({ mode }) => ({ ], }, includeAssets: [ - 'icons/favicon.ico', - 'icons/apple-touch-icon.png', - 'icons/icon-192.png', - 'icons/icon-512.png', - 'icons/icon-maskable-192.png', - 'icons/icon-maskable-512.png', + 'favicon.ico', + 'apple-touch-icon.png', + 'mask-icon.svg', + 'icon-192.png', + 'icon-512.png', + 'icon-maskable-192.png', + 'icon-maskable-512.png', ], manifest: { name: 'Restaurant — Order', @@ -79,8 +78,8 @@ export default defineConfig(({ mode }) => ({ description: 'Order from your local Nostr-native restaurant with Lightning payments', // Green to differentiate from market red. PDF tile is purple // (see ~/dev/shared/extensions/restaurant/static/image/restaurant.png). - theme_color: brand.themeColor ?? '#16a34a', - background_color: brand.backgroundColor ?? '#ffffff', + theme_color: '#16a34a', + background_color: '#ffffff', display: 'standalone', orientation: 'portrait-primary', start_url: process.env.VITE_BASE_PATH || '/', @@ -89,10 +88,10 @@ export default defineConfig(({ mode }) => ({ categories: ['food', 'shopping'], lang: 'en', icons: [ - { src: 'icons/icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' }, - { src: 'icons/icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' }, - { src: 'icons/icon-maskable-192.png', sizes: '192x192', type: 'image/png', purpose: 'maskable' }, - { src: 'icons/icon-maskable-512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }, + { src: 'icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' }, + { src: 'icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' }, + { src: 'icon-maskable-192.png', sizes: '192x192', type: 'image/png', purpose: 'maskable' }, + { src: 'icon-maskable-512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }, ], }, }), @@ -111,7 +110,6 @@ export default defineConfig(({ mode }) => ({ ], resolve: { alias: { - ...brandAlias, // ORDER MATTERS — @/app.config must precede @ (first-match-wins). '@/app.config': fileURLToPath(new URL('./src/restaurant-app/app.config.ts', import.meta.url)), '@': fileURLToPath(new URL('./src', import.meta.url)), diff --git a/vite.tasks.config.ts b/vite.tasks.config.ts index e903844..1edc3e6 100644 --- a/vite.tasks.config.ts +++ b/vite.tasks.config.ts @@ -5,7 +5,6 @@ import { defineConfig, type Plugin } from 'vite' import { VitePWA } from 'vite-plugin-pwa' import { ViteImageOptimizer } from 'vite-plugin-image-optimizer' import { visualizer } from 'rollup-plugin-visualizer' -import { brand, brandAlias, brandAssetsPlugin } from './vite-branding' function tasksHtmlPlugin(): Plugin { return { @@ -46,7 +45,6 @@ export default defineConfig(({ mode }) => ({ strictPort: true, }, plugins: [ - brandAssetsPlugin(), tasksHtmlPlugin(), vue(), tailwindcss(), @@ -61,19 +59,20 @@ export default defineConfig(({ mode }) => ({ ], }, includeAssets: [ - 'icons/favicon.ico', - 'icons/apple-touch-icon.png', - 'icons/icon-192.png', - 'icons/icon-512.png', - 'icons/icon-maskable-192.png', - 'icons/icon-maskable-512.png', + 'favicon.ico', + 'apple-touch-icon.png', + 'mask-icon.svg', + 'icon-192.png', + 'icon-512.png', + 'icon-maskable-192.png', + 'icon-maskable-512.png', ], manifest: { name: 'Tasks — Work Orders', short_name: 'Tasks', description: 'Decentralized task management on Nostr', - theme_color: brand.themeColor ?? '#4338ca', - background_color: brand.backgroundColor ?? '#ffffff', + theme_color: '#4338ca', + background_color: '#ffffff', display: 'standalone', orientation: 'portrait-primary', start_url: process.env.VITE_BASE_PATH || '/', @@ -82,10 +81,10 @@ export default defineConfig(({ mode }) => ({ categories: ['productivity', 'business'], lang: 'en', icons: [ - { src: 'icons/icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' }, - { src: 'icons/icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' }, - { src: 'icons/icon-maskable-192.png', sizes: '192x192', type: 'image/png', purpose: 'maskable' }, - { src: 'icons/icon-maskable-512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }, + { src: 'icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' }, + { src: 'icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' }, + { src: 'icon-maskable-192.png', sizes: '192x192', type: 'image/png', purpose: 'maskable' }, + { src: 'icon-maskable-512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }, ], }, }), @@ -104,7 +103,6 @@ export default defineConfig(({ mode }) => ({ ], resolve: { alias: { - ...brandAlias, // ORDER MATTERS — @/app.config must precede @ (first-match-wins). '@/app.config': fileURLToPath(new URL('./src/tasks-app/app.config.ts', import.meta.url)), '@': fileURLToPath(new URL('./src', import.meta.url)), diff --git a/vite.wallet.config.ts b/vite.wallet.config.ts index cc9fc9a..f991672 100644 --- a/vite.wallet.config.ts +++ b/vite.wallet.config.ts @@ -5,7 +5,6 @@ import { defineConfig, type Plugin } from 'vite' import { VitePWA } from 'vite-plugin-pwa' import { ViteImageOptimizer } from 'vite-plugin-image-optimizer' import { visualizer } from 'rollup-plugin-visualizer' -import { brand, brandAlias, brandAssetsPlugin } from './vite-branding' /** * Plugin to rewrite dev server requests to wallet.html @@ -50,7 +49,6 @@ export default defineConfig(({ mode }) => ({ strictPort: true, }, plugins: [ - brandAssetsPlugin(), walletHtmlPlugin(), vue(), tailwindcss(), @@ -67,19 +65,20 @@ export default defineConfig(({ mode }) => ({ ], }, includeAssets: [ - 'icons/favicon.ico', - 'icons/apple-touch-icon.png', - 'icons/icon-192.png', - 'icons/icon-512.png', - 'icons/icon-maskable-192.png', - 'icons/icon-maskable-512.png', + 'favicon.ico', + 'apple-touch-icon.png', + 'mask-icon.svg', + 'icon-192.png', + 'icon-512.png', + 'icon-maskable-192.png', + 'icon-maskable-512.png', ], manifest: { name: 'Wallet — Lightning', short_name: 'Wallet', description: 'Lightning Network wallet — send, receive, and manage sats', - theme_color: brand.themeColor ?? '#eab308', - background_color: brand.backgroundColor ?? '#ffffff', + theme_color: '#eab308', + background_color: '#ffffff', display: 'standalone', orientation: 'portrait-primary', start_url: process.env.VITE_BASE_PATH || '/', @@ -88,10 +87,10 @@ export default defineConfig(({ mode }) => ({ categories: ['finance'], lang: 'en', icons: [ - { src: 'icons/icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' }, - { src: 'icons/icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' }, - { src: 'icons/icon-maskable-192.png', sizes: '192x192', type: 'image/png', purpose: 'maskable' }, - { src: 'icons/icon-maskable-512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }, + { src: 'icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' }, + { src: 'icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' }, + { src: 'icon-maskable-192.png', sizes: '192x192', type: 'image/png', purpose: 'maskable' }, + { src: 'icon-maskable-512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' }, ], }, }), @@ -110,7 +109,6 @@ export default defineConfig(({ mode }) => ({ ], resolve: { alias: { - ...brandAlias, // ORDER MATTERS — @/app.config must precede @ (first-match-wins). '@/app.config': fileURLToPath(new URL('./src/wallet-app/app.config.ts', import.meta.url)), '@': fileURLToPath(new URL('./src', import.meta.url)), diff --git a/wallet.html b/wallet.html index b811125..249f51d 100644 --- a/wallet.html +++ b/wallet.html @@ -6,8 +6,9 @@ - - + + + Wallet — Lightning