The dev SPA-fallback plugin used `!req.url.includes('.')` to skip asset
requests, which also matched JWT-shaped `?token=hdr.body.sig` query
strings — so `localhost:5185/?token=...` fell through to the hub
`index.html` instead of `market.html`, breaking the hub→standalone
auth-relay link. Strip the query before the extension check.
Applied to all 7 standalone vite configs.
VitePWA-disabled was supposed to fix stale dev artefacts but each
of the 8 vite servers was still sharing one node_modules/.vite/deps
directory. Concurrent dep optimization runs (any of: server
restart, config edit, new import) raced for that single cache,
producing intermittent 504 "Outdated Optimize Dep" responses for
hashes the requesting tab still held — followed by Vue Router
"Failed to fetch dynamically imported module" cascades when the
victim was a route component (e.g., MarketPage.vue).
Each app now has its own cache dir:
hub node_modules/.vite-hub
castle node_modules/.vite-castle
activities node_modules/.vite-activities
wallet node_modules/.vite-wallet
chat node_modules/.vite-chat
forum node_modules/.vite-forum
market node_modules/.vite-market
tasks node_modules/.vite-tasks
Set via vite's `cacheDir` option in each config. No more racing.
.gitignore already covers node_modules so the new dirs are ignored
automatically.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@rollup/plugin-alias (which Vite uses) iterates alias entries in
definition order and uses the first match. Listing the broad '@' →
./src alias before the specific '@/app.config' → per-app override
means '@/app.config' is matched by '@' first and resolves to
./src/app.config — i.e. the hub config, not the standalone's.
For market this surfaced as:
TypeError: Cannot read properties of undefined (reading 'config')
at new NostrmarketAPI (nostrmarketAPI.ts:170:45)
(nostrmarketAPI reads appConfig.modules.market.config; the hub
config has only base.) The same bug affected castle (ExpensesAPI
reads modules.expenses.config) and wallet (WalletWebSocketService
reads modules.wallet.config.websocket) — both would crash on first
use even though their dev servers started fine. Castle and wallet
silently haven't been exercised yet in this session, so the bug
only surfaced from market.
Fix: put '@/app.config' first in the alias object in all 6
standalone vite configs (castle, market, wallet, chat, forum,
tasks). Comment added at each call site explaining the constraint.
The hub's vite.config.ts doesn't need the override — its
'@/app.config' resolves to ./src/app.config naturally, which IS
the hub config.
Activities (sortir) doesn't need the override either — its app.ts
imports from './app.config' (relative), and no module file under
src/modules/activities reads from '@/app.config'.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Was: every standalone (and the hub) registered a service worker
during \`npm run dev\` via VitePWA's devOptions.enabled = true.
Problem: the dev SW caches index.html and the JS bundle on first
load and survives across vite restarts. Any code change that
required a server restart (e.g. fixing a vite.config.ts merge
conflict) resulted in browsers continuing to serve the cached
pre-restart bundle until the user manually unregistered the SW.
This caused the hub at localhost:5173 to redirect to /market on
refresh — the cached bundle was from the broken-config period
which still had the old monolithic main app's market route.
PWA features (offline, install prompts, manifest) are still tested
by running:
npm run preview # for the hub
npm run preview:<name> # for any standalone
against a real production build, which is the more accurate
environment for PWA verification anyway.
Recovery for anyone with a stale SW lingering in their browser
(needed once after pulling, then never again):
1. DevTools → Application → Service Workers → Unregister
2. DevTools → Application → Storage → Clear site data
3. Hard reload (Ctrl-Shift-R)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fixed-port assignments for each standalone vite dev server, with
strictPort to fail loud if a port is taken (no silent +1 increment
that would break the hub's hardcoded VITE_HUB_<NAME>_URL targets):
hub 5173 (npm run dev)
castle 5180
sortir 5181 (activities)
wallet 5182
chat 5183
forum 5184
market 5185
tasks 5186
`npm run dev:all` boots the hub and all 7 standalones concurrently
via the existing concurrently devDep. The hub's chakra tiles point
at these ports via VITE_HUB_<NAME>_URL in .env.local for end-to-end
local testing of the cross-subdomain auth relay.
Pure dev infrastructure — no production behaviour change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a standalone Nostr marketplace PWA at market.${domain}, built
from the existing src/modules/market plugin. Same standalone pattern
as wallet/chat/castle/activities:
- market.html entry, vite.market.config.ts (outDir: dist-market,
manifest id: market-app, theme: red #dc2626 — Muladhara chakra)
- src/market-app/{main.ts, app.ts, app.config.ts, App.vue} bootstraps
base + market only, with acceptTokenFromUrl for shared auth from hub
- npm run dev:market / build:market / preview:market
- main app SW denylist extended with /market/, /cart/, /checkout/
Closes#18.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>