Theguiggs/TourGuideSite

0

stars

306

commits

TypeScript

primary language

Sep 11, 2026

updated

README

TourGuideWeb — Portail Guide, Studio & Administration

Portail web Next.js compagnon de TourGuideApp. Permet aux guides de créer, enregistrer, éditer et soumettre leurs tours audio, et aux administrateurs de modérer le contenu. Embarque un microservice Python local pour TTS, traduction et détection de silence.


1. Prérequis machine

OutilVersionNotes
Node.js≥ 20LTS recommandé
npm≥ 10livré avec Node
Python3.11+Microservice TTS + traduction
pipdernièrelivré avec Python
Git≥ 2.40

Vérification rapide :

node -v          # v20.x+
python --version # 3.11+

2. Installation Next.js

cd c:\Projects\Bmad\TourGuideWeb
npm install

Configuration (.env.local)

Deux modes possibles :

Mode stub (par défaut en dev local) — pas besoin d'AWS :

"NEXT_PUBLIC_USE_STUBS=true" | Out-File -Encoding ascii .env.local

Mode API réelle — copier .env.local.example puis renseigner :

Copy-Item .env.local.example .env.local

Variables principales :

VariableUsage
NEXT_PUBLIC_USE_STUBStrue pour stubs locaux, sinon AppSync réel
NEXT_PUBLIC_AWS_REGIONRégion Amplify
NEXT_PUBLIC_USER_POOL_ID / NEXT_PUBLIC_USER_POOL_CLIENT_IDCognito
NEXT_PUBLIC_APPSYNC_URL / NEXT_PUBLIC_APPSYNC_API_KEYAppSync
NEXT_PUBLIC_S3_BUCKETBucket S3
STRIPE_SECRET_KEY / NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYPaiements
NEXT_PUBLIC_MICROSERVICE_URLURL du microservice Python (par défaut http://localhost:8000)
NEXT_PUBLIC_MICROSERVICE_API_KEYClé API du microservice (tourguide-tts-2026 en local)

3. Lancer le serveur Next.js

npm run dev

Application disponible sur http://localhost:3000.

CommandeUsage
npm run devServeur de développement (hot reload)
npm run buildBuild de production
npm run startDémarrer le build de production
npm run lintESLint
npm run typecheckVérification TypeScript
npm run testTests Jest (~399 tests, 50 suites)
npm run e2eTests Playwright E2E
npm run e2e:uiPlaywright en mode UI
npm run e2e:reportRapport Playwright
npm run seedInitialiser la base de données

4. Routes principales

Public

RouteDescription
/Page d'accueil
/catalogueCatalogue des tours par ville
/catalogue/[city]Tours d'une ville
/catalogue/[city]/[tourSlug]Détail d'un tour
/guides/[guideSlug]Page publique d'un guide

Espace Guide

RouteDescription
/guide/login · /guide/signupAuth guide
/guide/profile · /guide/dashboard · /guide/revenueCompte & revenus
/guide/tours/[tourId]/reviewsAvis d'un tour
/guide/studioListe des sessions studio
/guide/studio/[sessionId]Détail session
/guide/studio/[sessionId]/editÉditeur de texte
/guide/studio/[sessionId]/generalInfos générales
/guide/studio/[sessionId]/itineraryÉditeur d'itinéraire
/guide/studio/[sessionId]/photosGestion photos
/guide/studio/[sessionId]/previewPrévisualisation
/guide/studio/[sessionId]/recordEnregistrement audio
/guide/studio/[sessionId]/scenesGestion des scènes
/guide/studio/[sessionId]/submissionSoumission pour modération

Administration

RouteDescription
/admin/analyticsAnalytics et funnel
/admin/guides · /admin/guides/[guideId]Gestion des guides
/admin/moderation · /admin/moderation/[moderationId] · /admin/moderation/historyFile de modération
/admin/tours · /admin/tours/[tourId]Gestion des tours

5. Microservice Python (TTS + Traduction + Silence)

Le dossier microservice/ contient un serveur FastAPI qui expose :

EndpointRôleImplémentation
GET /healthSonde de santé
POST /v1/tts/generateSynthèse vocale (texte → WAV base64)edge-tts (Microsoft, gratuit, sans GPU)
POST /v1/translate/marianmtTraduction FR ↔ EN/IT/DE/ESMarianMT (Helsinki-NLP, CPU)
POST /v1/silence-detectDétection de silences dans un audio S3pydub

Langues TTS supportées : fr · en · it · de · es · ja · ko · zh · ru. Paires de traduction : fr↔en, fr↔it, fr↔de, fr↔es.

Post-traitement audio

L'endpoint TTS ajoute ~210 ms de silence en tête et ~900 ms en queue de chaque appel. Comme une scène SSML est rendue en plusieurs appels (un par run, un par chunk de 2000 caractères) puis concaténée, chaque raccord portait ~1,1 s de blanc et un <break time="1s"/> durait en réalité ~2,1 s — c'est ce qui donnait le rendu saccadé. services/audio_post.py détoure chaque chunk, réinsère la pause exacte demandée et normalise le niveau de la scène entière.

Réglages (variables d'environnement, valeurs par défaut entre parenthèses) :

VariableRôle
TTS_SENTENCE_GAP_MS (220)pause entre deux phrases d'une même scène
TTS_RUN_GAP_MS (70)pause à une coupure en milieu de phrase (bords d'un <prosody>, virgule)
TTS_TARGET_DBFS (-18)niveau RMS visé pour la scène
TTS_PEAK_CEILING_DBFS (-1)plafond crête — le gain ne peut jamais saturer
TTS_TRIM_DB (-50) · TTS_TRIM_KEEP_MS (25) · TTS_EDGE_FADE_MS (8)détourage et fondus de raccord

Comparer un rendu avant/après (écrit deux WAV et mesure les pauses) :

cd microservice
python tts_ab.py                    # scène d'exemple
python tts_ab.py --sample prosody   # scène avec <prosody> / <emphasis>
python tts_ab.py --text-file ma-scene.txt --voice fr-FR-DeniseNeural

5.1 — Lancement (Windows / PowerShell)

cd c:\Projects\Bmad\TourGuideWeb\microservice
.\start-local.ps1

Le script :

  1. crée un venv .venv/ si absent,
  2. installe torch (CPU) puis fastapi, uvicorn, edge-tts, transformers, pydub, soundfile…,
  3. exporte MICROSERVICE_API_KEY=tourguide-tts-2026,
  4. démarre uvicorn sur http://localhost:8000.

5.2 — Lancement manuel (toute plateforme)

cd microservice
python -m venv .venv
source .venv/bin/activate            # Linux/macOS
# .\.venv\Scripts\Activate.ps1       # Windows

pip install torch --index-url https://download.pytorch.org/whl/cpu
pip install fastapi "uvicorn[standard]" edge-tts soundfile pydub requests transformers sentencepiece

export MICROSERVICE_API_KEY=tourguide-tts-2026
python -m uvicorn local_server:app --host 0.0.0.0 --port 8000

Le fichier requirements.txt cible la version GPU (main.py, Qwen3-TTS). Pour le mode local CPU (local_server.py), utiliser les commandes ci-dessus ou start-local.ps1.

5.3 — Sanity check

# Health
curl http://localhost:8000/health

# TTS (avec clé API)
curl -X POST http://localhost:8000/v1/tts/generate `
  -H "Content-Type: application/json" `
  -H "X-API-Key: tourguide-tts-2026" `
  -d '{"text":"Bonjour Paris","language":"fr"}'

# Traduction
curl -X POST http://localhost:8000/v1/translate/marianmt `
  -H "Content-Type: application/json" `
  -H "X-API-Key: tourguide-tts-2026" `
  -d '{"text":"Bonjour","source_lang":"fr","target_lang":"en"}'

5.4 — Exposition au mobile (TourGuideApp)

Pour que TourGuideApp consomme le microservice depuis un device Android :

# Émulateur Android (alias vers l'hôte)
MICROSERVICE_URL=http://10.0.2.2:8000

# Device physique (LAN)
MICROSERVICE_URL=http://192.168.x.x:8000

# Demo / tunnel public
MICROSERVICE_URL=https://xxx.ngrok-free.app

5.5 — Docker (optionnel, GPU)

cd microservice
docker build -t tourguide-microservice .
docker run -p 8000:8000 -e MICROSERVICE_API_KEY=tourguide-tts-2026 tourguide-microservice

6. Stack technique

CoucheTechnologie
FrameworkNext.js 16.1.6 · App Router
FrontendReact 19 · TypeScript 5 · Tailwind CSS 4
BackendAWS Amplify 6.16 (Cognito + AppSync + S3)
StateZustand 5
CartesLeaflet 1.9 · React-Leaflet 5
PaiementsStripe
TestsJest 30 · Playwright 1.58
MicroserviceFastAPI · edge-tts · MarianMT · pydub
Design System@murmure/design-system (file:./packages/design-system)

7. Arborescence

TourGuideWeb/
├── src/
│   ├── app/              # Pages Next.js (App Router)
│   │   ├── catalogue/    # Catalogue public
│   │   ├── guide/        # Espace guide (profil, dashboard, studio)
│   │   ├── admin/        # Administration
│   │   └── guides/       # Pages publiques des guides
│   ├── components/       # Composants partagés
│   ├── lib/
│   │   ├── api/          # Couche AppSync + microservice-config.ts
│   │   ├── stores/       # 9 stores Zustand
│   │   ├── studio/       # Services studio (recorder, player, prompter, mixer…)
│   │   ├── multilang/    # Traduction batch, i18n, staleness
│   │   ├── amplify/      # Config Amplify + SSR utils
│   │   └── auth/         # Contexte authentification
│   ├── hooks/            # use-auto-save, use-auto-refund
│   ├── config/           # api-mode.ts (stubs vs real)
│   └── types/            # guide, moderation, studio, tour
├── microservice/         # Python (TTS, traduction, silence detection)
│   ├── local_server.py   # Variante CPU (edge-tts + MarianMT)
│   ├── main.py           # Variante GPU (Qwen3-TTS)
│   ├── services/         # tts_service, translation_service, silence_service
│   ├── start-local.ps1   # Lanceur Windows
│   └── Dockerfile        # Image GPU
├── packages/design-system/ # DS local (alias @murmure/design-system)
├── content/tours/        # Packages de tours premium
├── e2e/                  # Tests Playwright
├── scripts/              # Seeds, photos, TTS reference
└── docs/                 # Plans de test, sanity checks

8. PWA & Favicons

Le portail expose un manifest.json PWA et 5 assets favicons (SVG + 3 PNG + apple-touch-icon + ICO legacy). La source de vérité visuelle est le composant <PinNegatif> du package @murmure/design-system (Story 2.4). Ne jamais modifier les binaires public/favicon* à la main — toute modification passe par <PinNegatif> + re-run du pipeline.

Re-export après modification de <PinNegatif>

cd design-system
npm run tg:export-icons -- --variant light --output-dir ../assets/icons
# puis copier vers TourGuideWeb/public/, et :
npx png-to-ico assets/icons/favicon-32.png > TourGuideWeb/public/favicon.ico

Détails complets : docs/favicon-setup.md.

FichierPourquoi
favicon.svgVectoriel — Chrome/Firefox/Safari récents
favicon-32.pngFallback PNG petite taille
favicon.icoLegacy IE / anciens navigateurs
favicon-192.png / favicon-512.pngIcônes PWA Android (manifest)
apple-touch-icon-180.pngiOS "Ajouter à l'écran d'accueil"

Manifest PWA : theme_color: #C1262A (grenadine), background_color: #F4ECDD (paper), display: standalone, start_url: /. Score Lighthouse PWA cible : ≥ 90.


9. Lien avec TourGuideApp

Ce projet est le portail web compagnon de TourGuideApp. Les deux partagent :

  • le backend AWS Amplify (Cognito, AppSync, S3),
  • le design system @murmure/design-system (mais en consommation différente : file:../design-system côté mobile, file:./packages/design-system côté web),
  • le microservice TTS/traduction (hébergé ici, consommé par les deux).

10. Documentation

DocumentChemin
Guide utilisateurUSERGUIDE.md
Plan de test E2E (ISTQB)docs/plan-de-test-e2e-istqb.md
Sanity check guidedocs/guide-sanity-check.md
Tests backend manuelsbmad/test-manuel-backend-persistence.md
Tests E2E Playwrighte2e/README.md
Tours premiumcontent/tours/README.md
Favicons & PWAdocs/favicon-setup.md

10 bis. Exploitation : sécurité et sondes (lot 2, 2026-09-11)

Cibler un backend depuis un script

Tous les scripts de scripts/ prennent leur cible dans scripts/_backend.mjs : --app-id=<apiId AppSync> ou la variable APPSYNC_API_ID. Aucun défaut — un script sans cible refuse de tourner, et les identifiants des piles mortes sont refusés nommément. L'épreuve src/__tests__/dead-backend-ids.test.ts interdit tout identifiant mort dans le dépôt.

$env:APPSYNC_API_ID = (aws appsync list-graphql-apis --query "graphqlApis[0].apiId" --output text)
node scripts/inspect-db.mjs

Clés et variables côté serveur

VariableRôle
ORS_API_KEYconteneur webClé OpenRouteService, servie par le relais /api/routing (guide authentifié, borne par compte). Ne JAMAIS la préfixer NEXT_PUBLIC_.
NEXT_PUBLIC_GOOGLE_MAPS_API_KEYbuild webClé de l'iframe Street View : elle est publique par nature. La restreindre par référent HTTP au domaine du portail dans la console Google Cloud, sinon elle est réutilisable par un tiers.
ALLOWED_AUDIO_HOSTSconteneur microserviceHôte(s) exact(s) du bucket S3 d'où la détection de silence accepte un audio. Sans valeur, aucun téléchargement.
MICROSERVICE_API_KEYles deuxComparée en temps constant. /health reste public, tout le reste l'exige.

Sondes

  • GET /api/health (portail) : exerce la lecture IAM du profil de guide. Un 503 ici signifie que tout le Studio a perdu synthèse et traduction, même si la page d'accueil répond. Branchée sur le healthcheck Docker du service web.
  • GET /health (microservice) : fournisseur de synthèse réel, jobs en vol.

Content-Security-Policy

Elle est construite par requête dans src/proxy.ts (nonce + 'strict-dynamic', hôtes AWS exacts lus dans amplify_outputs.json) et définie une seule fois dans src/lib/security/csp.ts. L'épreuve csp.test.ts compare la politique aux hôtes externes réellement référencés par le code : ajouter un hôte au code sans l'ajouter à la politique fait échouer la suite. Vérification navigateur après un build : node <scratch>/csp-check.mjs http://localhost:3000 charge une douzaine de pages et rapporte toute violation.

11. Dépannage rapide

SymptômeSolution
Next.js dev: EADDRINUSE :3000npx kill-port 3000 puis npm run dev
401 Invalid API key du microserviceVérifier NEXT_PUBLIC_MICROSERVICE_API_KEY côté web et MICROSERVICE_API_KEY côté Python
Microservice : torch import lentPremier appel à /v1/translate charge MarianMT (~30 s, lazy)
MarianMT échoue à téléchargerConfigurer un proxy HF ou pré-télécharger : huggingface-cli download Helsinki-NLP/opus-mt-fr-en
ngrok page interstitielleL'en-tête ngrok-skip-browser-warning: true est déjà ajouté par getMicroserviceHeaders()
Playwright échoue en CInpx playwright install --with-deps

Contributors

Theguiggs

305 commits

codex

1 commits

Theguiggs/TourGuideSite

0

stars

306

commits

TypeScript

primary language

Sep 11, 2026

updated

README

TourGuideWeb — Portail Guide, Studio & Administration

Portail web Next.js compagnon de TourGuideApp. Permet aux guides de créer, enregistrer, éditer et soumettre leurs tours audio, et aux administrateurs de modérer le contenu. Embarque un microservice Python local pour TTS, traduction et détection de silence.


1. Prérequis machine

OutilVersionNotes
Node.js≥ 20LTS recommandé
npm≥ 10livré avec Node
Python3.11+Microservice TTS + traduction
pipdernièrelivré avec Python
Git≥ 2.40

Vérification rapide :

node -v          # v20.x+
python --version # 3.11+

2. Installation Next.js

cd c:\Projects\Bmad\TourGuideWeb
npm install

Configuration (.env.local)

Deux modes possibles :

Mode stub (par défaut en dev local) — pas besoin d'AWS :

"NEXT_PUBLIC_USE_STUBS=true" | Out-File -Encoding ascii .env.local

Mode API réelle — copier .env.local.example puis renseigner :

Copy-Item .env.local.example .env.local

Variables principales :

VariableUsage
NEXT_PUBLIC_USE_STUBStrue pour stubs locaux, sinon AppSync réel
NEXT_PUBLIC_AWS_REGIONRégion Amplify
NEXT_PUBLIC_USER_POOL_ID / NEXT_PUBLIC_USER_POOL_CLIENT_IDCognito
NEXT_PUBLIC_APPSYNC_URL / NEXT_PUBLIC_APPSYNC_API_KEYAppSync
NEXT_PUBLIC_S3_BUCKETBucket S3
STRIPE_SECRET_KEY / NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYPaiements
NEXT_PUBLIC_MICROSERVICE_URLURL du microservice Python (par défaut http://localhost:8000)
NEXT_PUBLIC_MICROSERVICE_API_KEYClé API du microservice (tourguide-tts-2026 en local)

3. Lancer le serveur Next.js

npm run dev

Application disponible sur http://localhost:3000.

CommandeUsage
npm run devServeur de développement (hot reload)
npm run buildBuild de production
npm run startDémarrer le build de production
npm run lintESLint
npm run typecheckVérification TypeScript
npm run testTests Jest (~399 tests, 50 suites)
npm run e2eTests Playwright E2E
npm run e2e:uiPlaywright en mode UI
npm run e2e:reportRapport Playwright
npm run seedInitialiser la base de données

4. Routes principales

Public

RouteDescription
/Page d'accueil
/catalogueCatalogue des tours par ville
/catalogue/[city]Tours d'une ville
/catalogue/[city]/[tourSlug]Détail d'un tour
/guides/[guideSlug]Page publique d'un guide

Espace Guide

RouteDescription
/guide/login · /guide/signupAuth guide
/guide/profile · /guide/dashboard · /guide/revenueCompte & revenus
/guide/tours/[tourId]/reviewsAvis d'un tour
/guide/studioListe des sessions studio
/guide/studio/[sessionId]Détail session
/guide/studio/[sessionId]/editÉditeur de texte
/guide/studio/[sessionId]/generalInfos générales
/guide/studio/[sessionId]/itineraryÉditeur d'itinéraire
/guide/studio/[sessionId]/photosGestion photos
/guide/studio/[sessionId]/previewPrévisualisation
/guide/studio/[sessionId]/recordEnregistrement audio
/guide/studio/[sessionId]/scenesGestion des scènes
/guide/studio/[sessionId]/submissionSoumission pour modération

Administration

RouteDescription
/admin/analyticsAnalytics et funnel
/admin/guides · /admin/guides/[guideId]Gestion des guides
/admin/moderation · /admin/moderation/[moderationId] · /admin/moderation/historyFile de modération
/admin/tours · /admin/tours/[tourId]Gestion des tours

5. Microservice Python (TTS + Traduction + Silence)

Le dossier microservice/ contient un serveur FastAPI qui expose :

EndpointRôleImplémentation
GET /healthSonde de santé
POST /v1/tts/generateSynthèse vocale (texte → WAV base64)edge-tts (Microsoft, gratuit, sans GPU)
POST /v1/translate/marianmtTraduction FR ↔ EN/IT/DE/ESMarianMT (Helsinki-NLP, CPU)
POST /v1/silence-detectDétection de silences dans un audio S3pydub

Langues TTS supportées : fr · en · it · de · es · ja · ko · zh · ru. Paires de traduction : fr↔en, fr↔it, fr↔de, fr↔es.

Post-traitement audio

L'endpoint TTS ajoute ~210 ms de silence en tête et ~900 ms en queue de chaque appel. Comme une scène SSML est rendue en plusieurs appels (un par run, un par chunk de 2000 caractères) puis concaténée, chaque raccord portait ~1,1 s de blanc et un <break time="1s"/> durait en réalité ~2,1 s — c'est ce qui donnait le rendu saccadé. services/audio_post.py détoure chaque chunk, réinsère la pause exacte demandée et normalise le niveau de la scène entière.

Réglages (variables d'environnement, valeurs par défaut entre parenthèses) :

VariableRôle
TTS_SENTENCE_GAP_MS (220)pause entre deux phrases d'une même scène
TTS_RUN_GAP_MS (70)pause à une coupure en milieu de phrase (bords d'un <prosody>, virgule)
TTS_TARGET_DBFS (-18)niveau RMS visé pour la scène
TTS_PEAK_CEILING_DBFS (-1)plafond crête — le gain ne peut jamais saturer
TTS_TRIM_DB (-50) · TTS_TRIM_KEEP_MS (25) · TTS_EDGE_FADE_MS (8)détourage et fondus de raccord

Comparer un rendu avant/après (écrit deux WAV et mesure les pauses) :

cd microservice
python tts_ab.py                    # scène d'exemple
python tts_ab.py --sample prosody   # scène avec <prosody> / <emphasis>
python tts_ab.py --text-file ma-scene.txt --voice fr-FR-DeniseNeural

5.1 — Lancement (Windows / PowerShell)

cd c:\Projects\Bmad\TourGuideWeb\microservice
.\start-local.ps1

Le script :

  1. crée un venv .venv/ si absent,
  2. installe torch (CPU) puis fastapi, uvicorn, edge-tts, transformers, pydub, soundfile…,
  3. exporte MICROSERVICE_API_KEY=tourguide-tts-2026,
  4. démarre uvicorn sur http://localhost:8000.

5.2 — Lancement manuel (toute plateforme)

cd microservice
python -m venv .venv
source .venv/bin/activate            # Linux/macOS
# .\.venv\Scripts\Activate.ps1       # Windows

pip install torch --index-url https://download.pytorch.org/whl/cpu
pip install fastapi "uvicorn[standard]" edge-tts soundfile pydub requests transformers sentencepiece

export MICROSERVICE_API_KEY=tourguide-tts-2026
python -m uvicorn local_server:app --host 0.0.0.0 --port 8000

Le fichier requirements.txt cible la version GPU (main.py, Qwen3-TTS). Pour le mode local CPU (local_server.py), utiliser les commandes ci-dessus ou start-local.ps1.

5.3 — Sanity check

# Health
curl http://localhost:8000/health

# TTS (avec clé API)
curl -X POST http://localhost:8000/v1/tts/generate `
  -H "Content-Type: application/json" `
  -H "X-API-Key: tourguide-tts-2026" `
  -d '{"text":"Bonjour Paris","language":"fr"}'

# Traduction
curl -X POST http://localhost:8000/v1/translate/marianmt `
  -H "Content-Type: application/json" `
  -H "X-API-Key: tourguide-tts-2026" `
  -d '{"text":"Bonjour","source_lang":"fr","target_lang":"en"}'

5.4 — Exposition au mobile (TourGuideApp)

Pour que TourGuideApp consomme le microservice depuis un device Android :

# Émulateur Android (alias vers l'hôte)
MICROSERVICE_URL=http://10.0.2.2:8000

# Device physique (LAN)
MICROSERVICE_URL=http://192.168.x.x:8000

# Demo / tunnel public
MICROSERVICE_URL=https://xxx.ngrok-free.app

5.5 — Docker (optionnel, GPU)

cd microservice
docker build -t tourguide-microservice .
docker run -p 8000:8000 -e MICROSERVICE_API_KEY=tourguide-tts-2026 tourguide-microservice

6. Stack technique

CoucheTechnologie
FrameworkNext.js 16.1.6 · App Router
FrontendReact 19 · TypeScript 5 · Tailwind CSS 4
BackendAWS Amplify 6.16 (Cognito + AppSync + S3)
StateZustand 5
CartesLeaflet 1.9 · React-Leaflet 5
PaiementsStripe
TestsJest 30 · Playwright 1.58
MicroserviceFastAPI · edge-tts · MarianMT · pydub
Design System@murmure/design-system (file:./packages/design-system)

7. Arborescence

TourGuideWeb/
├── src/
│   ├── app/              # Pages Next.js (App Router)
│   │   ├── catalogue/    # Catalogue public
│   │   ├── guide/        # Espace guide (profil, dashboard, studio)
│   │   ├── admin/        # Administration
│   │   └── guides/       # Pages publiques des guides
│   ├── components/       # Composants partagés
│   ├── lib/
│   │   ├── api/          # Couche AppSync + microservice-config.ts
│   │   ├── stores/       # 9 stores Zustand
│   │   ├── studio/       # Services studio (recorder, player, prompter, mixer…)
│   │   ├── multilang/    # Traduction batch, i18n, staleness
│   │   ├── amplify/      # Config Amplify + SSR utils
│   │   └── auth/         # Contexte authentification
│   ├── hooks/            # use-auto-save, use-auto-refund
│   ├── config/           # api-mode.ts (stubs vs real)
│   └── types/            # guide, moderation, studio, tour
├── microservice/         # Python (TTS, traduction, silence detection)
│   ├── local_server.py   # Variante CPU (edge-tts + MarianMT)
│   ├── main.py           # Variante GPU (Qwen3-TTS)
│   ├── services/         # tts_service, translation_service, silence_service
│   ├── start-local.ps1   # Lanceur Windows
│   └── Dockerfile        # Image GPU
├── packages/design-system/ # DS local (alias @murmure/design-system)
├── content/tours/        # Packages de tours premium
├── e2e/                  # Tests Playwright
├── scripts/              # Seeds, photos, TTS reference
└── docs/                 # Plans de test, sanity checks

8. PWA & Favicons

Le portail expose un manifest.json PWA et 5 assets favicons (SVG + 3 PNG + apple-touch-icon + ICO legacy). La source de vérité visuelle est le composant <PinNegatif> du package @murmure/design-system (Story 2.4). Ne jamais modifier les binaires public/favicon* à la main — toute modification passe par <PinNegatif> + re-run du pipeline.

Re-export après modification de <PinNegatif>

cd design-system
npm run tg:export-icons -- --variant light --output-dir ../assets/icons
# puis copier vers TourGuideWeb/public/, et :
npx png-to-ico assets/icons/favicon-32.png > TourGuideWeb/public/favicon.ico

Détails complets : docs/favicon-setup.md.

FichierPourquoi
favicon.svgVectoriel — Chrome/Firefox/Safari récents
favicon-32.pngFallback PNG petite taille
favicon.icoLegacy IE / anciens navigateurs
favicon-192.png / favicon-512.pngIcônes PWA Android (manifest)
apple-touch-icon-180.pngiOS "Ajouter à l'écran d'accueil"

Manifest PWA : theme_color: #C1262A (grenadine), background_color: #F4ECDD (paper), display: standalone, start_url: /. Score Lighthouse PWA cible : ≥ 90.


9. Lien avec TourGuideApp

Ce projet est le portail web compagnon de TourGuideApp. Les deux partagent :

  • le backend AWS Amplify (Cognito, AppSync, S3),
  • le design system @murmure/design-system (mais en consommation différente : file:../design-system côté mobile, file:./packages/design-system côté web),
  • le microservice TTS/traduction (hébergé ici, consommé par les deux).

10. Documentation

DocumentChemin
Guide utilisateurUSERGUIDE.md
Plan de test E2E (ISTQB)docs/plan-de-test-e2e-istqb.md
Sanity check guidedocs/guide-sanity-check.md
Tests backend manuelsbmad/test-manuel-backend-persistence.md
Tests E2E Playwrighte2e/README.md
Tours premiumcontent/tours/README.md
Favicons & PWAdocs/favicon-setup.md

10 bis. Exploitation : sécurité et sondes (lot 2, 2026-09-11)

Cibler un backend depuis un script

Tous les scripts de scripts/ prennent leur cible dans scripts/_backend.mjs : --app-id=<apiId AppSync> ou la variable APPSYNC_API_ID. Aucun défaut — un script sans cible refuse de tourner, et les identifiants des piles mortes sont refusés nommément. L'épreuve src/__tests__/dead-backend-ids.test.ts interdit tout identifiant mort dans le dépôt.

$env:APPSYNC_API_ID = (aws appsync list-graphql-apis --query "graphqlApis[0].apiId" --output text)
node scripts/inspect-db.mjs

Clés et variables côté serveur

VariableRôle
ORS_API_KEYconteneur webClé OpenRouteService, servie par le relais /api/routing (guide authentifié, borne par compte). Ne JAMAIS la préfixer NEXT_PUBLIC_.
NEXT_PUBLIC_GOOGLE_MAPS_API_KEYbuild webClé de l'iframe Street View : elle est publique par nature. La restreindre par référent HTTP au domaine du portail dans la console Google Cloud, sinon elle est réutilisable par un tiers.
ALLOWED_AUDIO_HOSTSconteneur microserviceHôte(s) exact(s) du bucket S3 d'où la détection de silence accepte un audio. Sans valeur, aucun téléchargement.
MICROSERVICE_API_KEYles deuxComparée en temps constant. /health reste public, tout le reste l'exige.

Sondes

  • GET /api/health (portail) : exerce la lecture IAM du profil de guide. Un 503 ici signifie que tout le Studio a perdu synthèse et traduction, même si la page d'accueil répond. Branchée sur le healthcheck Docker du service web.
  • GET /health (microservice) : fournisseur de synthèse réel, jobs en vol.

Content-Security-Policy

Elle est construite par requête dans src/proxy.ts (nonce + 'strict-dynamic', hôtes AWS exacts lus dans amplify_outputs.json) et définie une seule fois dans src/lib/security/csp.ts. L'épreuve csp.test.ts compare la politique aux hôtes externes réellement référencés par le code : ajouter un hôte au code sans l'ajouter à la politique fait échouer la suite. Vérification navigateur après un build : node <scratch>/csp-check.mjs http://localhost:3000 charge une douzaine de pages et rapporte toute violation.

11. Dépannage rapide

SymptômeSolution
Next.js dev: EADDRINUSE :3000npx kill-port 3000 puis npm run dev
401 Invalid API key du microserviceVérifier NEXT_PUBLIC_MICROSERVICE_API_KEY côté web et MICROSERVICE_API_KEY côté Python
Microservice : torch import lentPremier appel à /v1/translate charge MarianMT (~30 s, lazy)
MarianMT échoue à téléchargerConfigurer un proxy HF ou pré-télécharger : huggingface-cli download Helsinki-NLP/opus-mt-fr-en
ngrok page interstitielleL'en-tête ngrok-skip-browser-warning: true est déjà ajouté par getMicroserviceHeaders()
Playwright échoue en CInpx playwright install --with-deps

Contributors

Theguiggs

305 commits

codex

1 commits

Languages

TypeScript

69.5%

JavaScript

21.1%

Python

7.0%