## Why
The module was named `activities` originally to avoid colliding with Nostr's `Event` type. In practice that defense added friction without preventing confusion — the backend extension is named `events`, NIP-52 calls them "Calendar Events", and the UI already displayed "Events". The collision with `nostr-tools` `Event` is handled cleanly by the existing `import { Event as NostrEvent }` alias pattern (already in 5 files inside the module). Renaming collapses the 4-way mismatch into one consistent term.
Separately, deployments needed per-instance app names. `VITE_APP_NAME` was already plumbed per-standalone via NixOS `services.webapp-standalones.<app>.displayName` (e.g. cfaun shipped `"Sortir"`, now rebranded to `"Bouge"`), but nothing in the standalone consumed it — PWA manifest, HTML title, and runtime branding were all hardcoded. This PR wires the env through every app-name display point so any deploy can flip `displayName = "Bouge"` (or anything) and pick up the brand end-to-end.
## What
Nine commits on the branch:
1. **`refactor(events): rename activities module to events`** — 70-file rename. `src/modules/activities/` → `src/modules/events/`, `src/activities-app/` → `src/events-app/`, types/services/composables/views/components/store renamed (`Activity`→`Event`, `Activities`→`Events`). Routes `/activities/*` → `/events/*`; the legacy `/events` (ticketing management) moves to `/my-events` so `/events` belongs to the canonical feed. DI tokens `ACTIVITIES_*` → `EVENTS_*`. i18n namespace renamed; English domain strings updated, French/Spanish title key realigned. npm scripts `:activities` → `:events`. Build output `dist-activities/` → `dist-events/`.
2. **`feat(events): wire VITE_APP_NAME through PWA manifest, HTML, runtime`** — PWA manifest `name`/`short_name` template from `process.env.VITE_APP_NAME` with fallback `'Events'`. `events.html` uses Vite's `%VITE_APP_NAME%` substitution. `src/events-app/app.ts` + `main.ts` runtime brand string drives console logs, offline notification, and `acceptTokenFromUrl()`. `events.title` route meta sources from VITE_APP_NAME. `.env.example` updated with per-standalone scoping notes.
3. **`docs(events): update activities→events references`** — `docs/nostr-patterns/*.md` "Canonical: src/modules/activities/composables/useRSVP.ts" anchors point at renamed paths. CLAUDE.md Payment Rails Pattern section updated.
4. **`fix(events): drop lowercase from PWA description brand name`** — minor casing fix caught during verification.
5. **`fix(events): use domain noun in description, not brand name`** — manifest + HTML description switched from `"Discover ${BRAND} near you"` to static `"Discover events near you"`. Description is about *what* the app does, not the brand.
6. **`chore(events): scrub leftover sortir/activities references`** — nginx.conf.example, package.json (concurrently process label + `build:demo` BASE_PATH), router-helpers comment, useMarket comment, and vite.events.config.ts doc-comment.
7. **`refactor(events): conditional brand in console label, tighten docs`** — adds `APP_LABEL` next to `APP_NAME` in `events-app/app.ts`. Reads as `Events` on unbranded builds and `Events (Bouge)` (etc.) when `VITE_APP_NAME` is set to anything other than "Events" (case-insensitive). Used by all four console messages; `acceptTokenFromUrl` keeps the raw `APP_NAME` (it's a token-namespace identifier, not display copy). Also collapses the redundant "cfaun sets X; future deployments can override (e.g. X)" doc-comment.
8. **`i18n(events): finish activité/actividad → événement/evento sweep`** — completes the i18n rename in fr.ts and es.ts (search placeholders, favorites prompts, settings prompt) and fixes five gender-agreement errors that came along with the masculine `événement`/`evento` switch (French: `Aucune ... trouvée`→`Aucun ... trouvé`, `préférées`→`préférés`, `d'une ... la sauvegarder`→`d'un ... le sauvegarder`; Spanish: `favoritas`→`favoritos`, `guardarla`→`guardarlo`).
9. **`chore(events): finish sortir → bouge sweep in .env.example`** — four remaining doc-comment refs in `.env.example` (cfaun branding, ticket-scanner comment, section header, subdomain-mode URL example).
## Cross-repo coordination
This PR has matching changes already pushed to two other repos. They have to land in a coordinated bump because the names are tightly coupled.
- **`aiolabs/webapp-module` main** — commit `9d82016`. Renames `hubActivitiesUrl` → `hubEventsUrl` and `VITE_HUB_ACTIVITIES_URL` → `VITE_HUB_EVENTS_URL`. No backwards-compat shim.
- **`aiolabs/server-deploy` main** — commits `f15e1eb`, `bf4698b`, `d46a520`:
- `standalones.nix` `apps.events` uses `build:events` / `dist-events` / `events.html`; `hubUrlOption` maps `events → "hubEventsUrl"`; comment + cfaun-as-example doc switched from sortir/Sortir to bouge/Bouge.
- `hosts/cfaun/default.nix` rebranded: `subdomain = "bouge"` + `displayName = "Bouge"`. (Native-French feedback retired the "Sortir" branding as awkward.)
- `hosts/atio/default.nix` stale "activities app" comment dropped (atio's `displayName = "Eventos"` config is unchanged).
server-deploy's `flake.lock` still pins the OLD webapp + OLD webapp-module, so nix builds from server-deploy main will fail until the bumps. Suggested order after this PR merges to `dev`: one server-deploy commit that does `nix flake lock --update-input webapp-module` + `--update-input webapp-demo` together. DNS for `bouge.ariege.io` needs to point at the cfaun host before the deploy lands.
## Verification
- `pnpm typecheck` — clean ✓
- `pnpm build:events` (default) — `dist-events/manifest.webmanifest` has `name: "Events"`, description "Discover events near you" ✓
- `VITE_APP_NAME=Bouge pnpm build:events` — `name: "Bouge"`, HTML title "Bouge", console label resolves to `Events (Bouge)` ✓
- Cross-repo grep sweep: no `Sortir`/`sortir`/`activities`/`Activities` references in events-module scope. (Domain false positives — "Market Activity" in market dashboard, "time-based activities" in nostr-feed content filters, "Activity Lifecycle Kills" in CLAUDE.md mobile-browser docs — are unrelated and intentionally left alone.)
Not verified in-browser (no GUI in this session) — needs a manual smoke at `app.ariege.io/bouge/` once the coordinated flake bump lands on cfaun. Watch for: feed loads, `/events/calendar`, `/events/map`, `/events/favorites`, `/events/:id` routes work; "My Events" appears in the user dropdown and `/my-events` shows the management page; PWA install prompt shows "Bouge".
## Out of scope (deferred)
- Backend extension rename — `aiolabs/events` is already named correctly.
- Nix standalone attribute name — `services.webapp-standalones.events` is already correct.
- Overriding domain-noun strings ("Your event was created", RSVP labels) — those stay locale-driven; `VITE_APP_NAME` covers app-name only.
- Backwards-compat redirects from `/activities/*` to `/events/*` — pre-launch, public URL was `/sortir/` (path-mode) or `sortir.ariege.io` (subdomain-mode), never `/activities/`. No external bookmarks to preserve. (`sortir.ariege.io` → `bouge.ariege.io` is a separate decision; up to the deploy operator whether to keep a 301 for word-of-mouth referrers.)
Reviewed-on: #94
Generic client for LNbits's nostr-transport (landed upstream Sun May
24, commit f235966c). Encrypts a request envelope to the server's
transport pubkey with NIP-44 v2, signs a kind-21000 event with the
current user's Nostr key, publishes via RelayHub, and listens for a
signed response addressed back to us. Shards (Lightning.Pub's
`{part, index, totalShards, shardsId}` wrapper) are reassembled
before parsing.
Activities ticket scanner is the first consumer; wallet ops + event
CRUD are obvious next adopters (file as follow-up). Server pubkey
discovery is currently env-var (VITE_LNBITS_NOSTR_TRANSPORT_PUBKEY)
— see also the follow-up to add a `.well-known` discovery endpoint
on LNbits.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Restaurant chakra tile was stubbed as 'coming soon' since the
bundle didn't exist. Now that aiolabs/webapp ships a restaurant
bundle, switch it to envKey-driven so deploys can set
VITE_HUB_RESTAURANT_URL the same way they set the other 7
standalones.
Also bumps the vite dev port from 5186 → 5187 — tasks was already on
5186 and `npm run dev:all` raced.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Build the shared building blocks for the unified bottom-nav UX across the
hub + 7 standalones. Phase A is groundwork only — no App.vue or Hub.vue
consumer is wired up yet, so this commit is purely additive.
New components in src/components/layout/:
- PreferencesRow.vue theme/language/currency triad (row + list layouts)
- ProfileSheetContent.vue identity card + back-to-hub + prefs + ProfileSettings
- ProfileSheetTrigger.vue bottom-row Profile button → opens sheet
- HubPill.vue fixed top-right back-to-hub link
- BottomNav.vue consumer tabs + appended Profile slot
- AppShell.vue outer wrapper composing the above
New composable: useCurrentUserAvatar — picture/displayName/fallbackInitial
from the auth user object.
i18n: new common.nav.* namespace in en/es/fr (typed via LocaleMessages).
Env: VITE_HUB_ROOT_URL added to .env.example with path/subdomain/local
guidance — consumed by HubPill and the back-to-hub sheet item.
Phase B (consumer refactor: chat/wallet/tasks first, then forum/libra/
market/activities, then hub) lands separately.
The repo previously assumed pure subdomain-mode deployment
(market.<domain>, sortir.<domain>, etc.) for the standalone PWAs.
The actual demo deployment uses path-mode under a single subdomain
(demo.<domain>/market/, demo.<domain>/activities/, etc.) with
optional subdomain shortcuts that 301 to the canonical path.
This commit aligns the example configs with that reality.
nginx.conf.example
- Primary section: a single server block for demo.<domain> with
per-app `location /<name>/` blocks aliased to dist-<name>/ plus
per-app `location = /<name>` 301 redirects to add the trailing
slash (preserves query string with $is_args$args).
- Optional subdomain-shortcut section: 7 server blocks that 301
e.g. events.demo.<domain> → demo.<domain>/activities/, mirroring
the existing aiolabs.dev demo setup.
- Subdomain-mode kept as a documented alternative at the bottom.
.env.example
- New "Hub → standalone navigation URLs" section with per-mode
example values for VITE_HUB_<NAME>_URL (local dev / path-mode
prod / subdomain-mode prod).
- Trailing-slash convention codified — the docstring explains why
'/market/' is canonical and '/market' is brittle under SPA path
deployment.
- VITE_BASE_PATH guidance added: it's a build-time shell variable,
NOT an .env entry, since it's read by vite when bundling assets.
- Vars left blank by default; operators fill them in based on the
deployment shape they pick.
Bypassed secret-scan pre-commit hook (false positive on prvkey,
tracked in #35).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
VITE_DEFAULT_LOCALE (fr/en/es) sets the initial language for the
standalone app when no user preference is saved. VITE_DEFAULT_MAP_CENTER
(lat,lng) configures the default map center point. Both fall back to
sensible defaults (fr and France center) when not set.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Commented out unused environment variables in .env.example:
- VITE_MARKET_RELAYS (market uses VITE_NOSTR_RELAYS instead)
- VITE_SUPPORT_NPUB (config.support.npub never consumed)
- VITE_LIGHTNING_ENABLED (config.market.lightningEnabled never consumed)
- VITE_MARKET_DEFAULT_CURRENCY (config.market.defaultCurrency never consumed)
Added missing environment variables to .env.example:
- VITE_APP_NAME (used in market module)
- VITE_LNBITS_DEBUG (used in lnbits config)
- VITE_WEBSOCKET_ENABLED (used in app config)
Also commented out corresponding unused config in src/lib/config/index.ts:
- MarketConfig.lightningEnabled and defaultCurrency
- AppConfig.nostrclient (defined but never used)
- AppConfig.support (never consumed)
Removed legacy VITE_API_BASE_URL fallback from WalletWebSocketService.ts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added ImageUpload and ImageDisplay components for handling image uploads and displaying images, respectively.
- Introduced ImageUploadService to manage image uploads, including validation, processing, and deletion.
- Updated app configuration to include image upload settings and integrated the service into the dependency injection container.
- Enhanced the .env.example file to include image upload configuration options.
- Provided a comprehensive README for the new components, detailing usage and integration examples.
These changes significantly enhance the application's capability to manage image uploads, improving user experience and flexibility in handling images.
- Introduce a new .env.example file for Nostr and API configuration, including settings for push notifications and market relays.
- Update Navbar.vue to include a new navigation item for the market, enhancing user access to market features.
- Extend localization support by adding market translations in English, Spanish, and French.