refactor(events): rename activities module to events + wire VITE_APP_NAME for per-deployment branding #94
6 changed files with 33 additions and 17 deletions
feat(events): wire VITE_APP_NAME through PWA manifest, HTML, runtime
The standalone events app was hardcoded to "Sortir" branding (PWA name
"Sortir — Activités & Événements", HTML title, console logs, URL token
handler ID). VITE_APP_NAME was already plumbed per-standalone via NixOS
`services.webapp-standalones.<app>.displayName` in server-deploy, but
nothing inside the app consumed it.
Routes the env through every app-name display point:
- PWA manifest `name` / `short_name` (vite.events.config.ts): both pull
from `process.env.VITE_APP_NAME`, defaulting to `'Events'` when
unset. Description, `id`, and `lang` un-frenched to brand-agnostic
defaults. The Vite config also writes the resolved value back to
`process.env` so Vite's built-in HTML `%VITE_APP_NAME%` substitution
picks up the fallback.
- HTML title + apple-mobile-web-app-title + description (events.html):
use `%VITE_APP_NAME%` for build-time substitution. `<html lang>` drops
the hardcoded `fr` (locale is now runtime-driven via i18n).
- Runtime branding (events-app/app.ts, main.ts): a top-level
`APP_NAME = (import.meta.env.VITE_APP_NAME as string) || 'Events'`
feeds the console logs, the offline-ready notification, and the
`acceptTokenFromUrl()` cross-subdomain handler.
- Main events route title (modules/events/index.ts:32): reads
VITE_APP_NAME so document.title / breadcrumbs show the deployment
brand. Sub-route titles (Calendar, Map, Favorites) stay literal —
they're contextual labels, not the app name.
- .env.example now explains the per-standalone scoping and points at
the NixOS knob for production deploys.
Domain-noun strings ("Search events…", RSVP labels, "Your event was
created") stay in i18n and translate per language — VITE_APP_NAME does
not flow into those.
Verification: `pnpm dev:events` → default `Events` brand;
`VITE_APP_NAME=Bouge pnpm dev:events` → PWA manifest, tab title, console
logs all show "Bouge". cfaun's existing `displayName = "Sortir"` keeps
producing a Sortir-branded build via the same path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
commit
a7ffe74337
|
|
@ -1,4 +1,10 @@
|
||||||
# App Configuration
|
# App Configuration
|
||||||
|
# Per-standalone display name — sets browser tab title, PWA install
|
||||||
|
# name/short_name, and the brand string in console logs. Each standalone
|
||||||
|
# (events, wallet, chat, market, …) gets its own VITE_APP_NAME at build
|
||||||
|
# time via NixOS `services.webapp-standalones.<app>.displayName` (see
|
||||||
|
# server-deploy). cfaun ships the events app as "Sortir"; defaults to
|
||||||
|
# "Events" / "Wallet" / etc. when unset.
|
||||||
VITE_APP_NAME=MyApp
|
VITE_APP_NAME=MyApp
|
||||||
|
|
||||||
# Nostr Configuration
|
# Nostr Configuration
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="fr">
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
||||||
|
|
@ -9,9 +9,9 @@
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180">
|
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180">
|
||||||
<link rel="mask-icon" href="/mask-icon.svg" color="#FFFFFF">
|
<link rel="mask-icon" href="/mask-icon.svg" color="#FFFFFF">
|
||||||
<title>Sortir — Events</title>
|
<title>%VITE_APP_NAME%</title>
|
||||||
<meta name="apple-mobile-web-app-title" content="Sortir">
|
<meta name="apple-mobile-web-app-title" content="%VITE_APP_NAME%">
|
||||||
<meta name="description" content="Découvrez les événements près de chez vous">
|
<meta name="description" content="Discover %VITE_APP_NAME% near you">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,16 @@ import { i18n, changeLocale, type AvailableLocale } from '@/i18n'
|
||||||
import { installLenientAuthGuard, markAuthReady, catchAllRoute } from '@/lib/router-helpers'
|
import { installLenientAuthGuard, markAuthReady, catchAllRoute } from '@/lib/router-helpers'
|
||||||
import { acceptTokenFromUrl } from '@/lib/url-token'
|
import { acceptTokenFromUrl } from '@/lib/url-token'
|
||||||
|
|
||||||
|
const APP_NAME = (import.meta.env.VITE_APP_NAME as string) || 'Events'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the standalone events app
|
* Initialize the standalone events app
|
||||||
*/
|
*/
|
||||||
export async function createAppInstance() {
|
export async function createAppInstance() {
|
||||||
console.log('🚀 Starting Sortir — Events App...')
|
console.log(`🚀 Starting ${APP_NAME}...`)
|
||||||
|
|
||||||
// Accept token from URL before anything else (cross-subdomain auth relay)
|
// Accept token from URL before anything else (cross-subdomain auth relay)
|
||||||
acceptTokenFromUrl('Sortir')
|
acceptTokenFromUrl(APP_NAME)
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
|
|
@ -114,7 +116,7 @@ export async function createAppInstance() {
|
||||||
;(window as any).__container = container
|
;(window as any).__container = container
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('✅ Sortir app initialized')
|
console.log(`✅ ${APP_NAME} initialized`)
|
||||||
return { app, router }
|
return { app, router }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,10 +124,10 @@ export async function startApp() {
|
||||||
try {
|
try {
|
||||||
const { app } = await createAppInstance()
|
const { app } = await createAppInstance()
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
console.log('🎉 Sortir app started!')
|
console.log(`🎉 ${APP_NAME} started!`)
|
||||||
eventBus.emit('app:started', {}, 'app')
|
eventBus.emit('app:started', {}, 'app')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('💥 Failed to start Sortir app:', error)
|
console.error(`💥 Failed to start ${APP_NAME}:`, error)
|
||||||
document.getElementById('app')!.innerHTML = `
|
document.getElementById('app')!.innerHTML = `
|
||||||
<div style="padding: 20px; text-align: center; color: red;">
|
<div style="padding: 20px; text-align: center; color: red;">
|
||||||
<h1>Failed to Start</h1>
|
<h1>Failed to Start</h1>
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ registerSW({
|
||||||
}, intervalMS)
|
}, intervalMS)
|
||||||
},
|
},
|
||||||
onOfflineReady() {
|
onOfflineReady() {
|
||||||
console.log('Sortir app ready to work offline')
|
console.log(`${(import.meta.env.VITE_APP_NAME as string) || 'Events'} ready to work offline`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ export const eventsModule = createModulePlugin({
|
||||||
name: 'events',
|
name: 'events',
|
||||||
component: () => import('./views/EventsPage.vue'),
|
component: () => import('./views/EventsPage.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Events',
|
title: (import.meta.env.VITE_APP_NAME as string) || 'Events',
|
||||||
requiresAuth: false,
|
requiresAuth: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -35,12 +35,21 @@ function eventsHtmlPlugin(): Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vite config for the standalone standalone events app.
|
* Vite config for the standalone events app.
|
||||||
*
|
*
|
||||||
* Set VITE_BASE_PATH to deploy under a path prefix:
|
* Set VITE_BASE_PATH to deploy under a path prefix:
|
||||||
* VITE_BASE_PATH=/sortir/ → app.ariege.io/sortir/ (shared auth)
|
* VITE_BASE_PATH=/sortir/ → app.ariege.io/sortir/ (shared auth)
|
||||||
* (default: /) → sortir.ariege.io (standalone subdomain)
|
* (default: /) → sortir.ariege.io (standalone subdomain)
|
||||||
|
*
|
||||||
|
* Set VITE_APP_NAME to brand the standalone (PWA name, HTML title, console
|
||||||
|
* logs). cfaun sets "Sortir" via NixOS; future deployments can override
|
||||||
|
* (e.g. "Bouge"). Defaults to "Events".
|
||||||
*/
|
*/
|
||||||
|
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 }) => ({
|
export default defineConfig(({ mode }) => ({
|
||||||
base: process.env.VITE_BASE_PATH || '/',
|
base: process.env.VITE_BASE_PATH || '/',
|
||||||
// Per-app dep cache so concurrent dev servers don't race on .vite/deps
|
// Per-app dep cache so concurrent dev servers don't race on .vite/deps
|
||||||
|
|
@ -76,18 +85,17 @@ export default defineConfig(({ mode }) => ({
|
||||||
'icon-maskable-512.png',
|
'icon-maskable-512.png',
|
||||||
],
|
],
|
||||||
manifest: {
|
manifest: {
|
||||||
name: 'Sortir — Activités & Événements',
|
name: APP_NAME,
|
||||||
short_name: 'Sortir',
|
short_name: APP_NAME,
|
||||||
description: 'Découvrez les activités et événements près de chez vous',
|
description: `Discover ${APP_NAME.toLowerCase()} near you`,
|
||||||
theme_color: '#1f2937',
|
theme_color: '#1f2937',
|
||||||
background_color: '#ffffff',
|
background_color: '#ffffff',
|
||||||
display: 'standalone',
|
display: 'standalone',
|
||||||
orientation: 'portrait-primary',
|
orientation: 'portrait-primary',
|
||||||
start_url: process.env.VITE_BASE_PATH || '/',
|
start_url: process.env.VITE_BASE_PATH || '/',
|
||||||
scope: process.env.VITE_BASE_PATH || '/',
|
scope: process.env.VITE_BASE_PATH || '/',
|
||||||
id: 'sortir-activities',
|
id: 'aiolabs-events',
|
||||||
categories: ['social', 'entertainment', 'lifestyle'],
|
categories: ['social', 'entertainment', 'lifestyle'],
|
||||||
lang: 'fr',
|
|
||||||
icons: [
|
icons: [
|
||||||
{ src: 'icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' },
|
{ src: 'icon-192.png', sizes: '192x192', type: 'image/png', purpose: 'any' },
|
||||||
{ src: 'icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' },
|
{ src: 'icon-512.png', sizes: '512x512', type: 'image/png', purpose: 'any' },
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue