+ );
+}
diff --git a/src/pages/docs/DocsLanguageProvider.tsx b/src/pages/docs/DocsLanguageProvider.tsx
new file mode 100644
index 0000000..e4c5903
--- /dev/null
+++ b/src/pages/docs/DocsLanguageProvider.tsx
@@ -0,0 +1,25 @@
+import { useState } from "react";
+import {
+ DocsLanguageContext,
+ type DocsLanguage,
+} from "@/pages/docs/docsLanguageContext";
+
+interface DocsLanguageProviderProps {
+ children: React.ReactNode;
+}
+
+export function DocsLanguageProvider({
+ children,
+}: DocsLanguageProviderProps): React.JSX.Element {
+ const [language, setLanguage] = useState("en");
+
+ function toggleLanguage(): void {
+ setLanguage((currentLanguage) => (currentLanguage === "en" ? "fr" : "en"));
+ }
+
+ return (
+
+ {children}
+
+ );
+}
diff --git a/src/pages/docs/DocsLayout.tsx b/src/pages/docs/DocsLayout.tsx
new file mode 100644
index 0000000..9c8bce6
--- /dev/null
+++ b/src/pages/docs/DocsLayout.tsx
@@ -0,0 +1,47 @@
+import { Link, Outlet } from "@tanstack/react-router";
+import { Home } from "lucide-react";
+import { DocsLanguageProvider } from "@/pages/docs/DocsLanguageProvider";
+import { docSections } from "@/pages/docs/docsSections";
+
+export function DocsLayout(): React.JSX.Element {
+ return (
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/pages/docs/architecture/page.tsx b/src/pages/docs/architecture/page.tsx
new file mode 100644
index 0000000..89f2cc9
--- /dev/null
+++ b/src/pages/docs/architecture/page.tsx
@@ -0,0 +1,14 @@
+import architecture from "../../../../docs/technical/architecture.md?raw";
+import { DocsDocument } from "@/pages/docs/DocsDocument";
+import { architectureFr } from "@/pages/docs/docsTranslations";
+
+export function DocsArchitecturePage(): React.JSX.Element {
+ return (
+
+ );
+}
diff --git a/src/pages/docs/docsLanguageContext.ts b/src/pages/docs/docsLanguageContext.ts
new file mode 100644
index 0000000..295bb7f
--- /dev/null
+++ b/src/pages/docs/docsLanguageContext.ts
@@ -0,0 +1,11 @@
+import { createContext } from "react";
+
+export type DocsLanguage = "en" | "fr";
+
+export interface DocsLanguageContextValue {
+ language: DocsLanguage;
+ toggleLanguage: () => void;
+}
+
+export const DocsLanguageContext =
+ createContext(null);
diff --git a/src/pages/docs/docsSections.ts b/src/pages/docs/docsSections.ts
new file mode 100644
index 0000000..3bbc201
--- /dev/null
+++ b/src/pages/docs/docsSections.ts
@@ -0,0 +1,33 @@
+export interface DocSection {
+ path: string;
+ title: string;
+ subtitle: string;
+ meta: string;
+}
+
+export const docSections: DocSection[] = [
+ {
+ path: "/docs",
+ title: "README",
+ subtitle: "Project overview",
+ meta: "01",
+ },
+ {
+ path: "/docs/architecture",
+ title: "Architecture actuelle",
+ subtitle: "Runtime structure",
+ meta: "02",
+ },
+ {
+ path: "/docs/target-architecture",
+ title: "Architecture cible",
+ subtitle: "Next direction",
+ meta: "03",
+ },
+ {
+ path: "/docs/features",
+ title: "Fonctionnalites",
+ subtitle: "Implemented scope",
+ meta: "04",
+ },
+];
diff --git a/src/pages/docs/docsTranslations.ts b/src/pages/docs/docsTranslations.ts
new file mode 100644
index 0000000..7f89281
--- /dev/null
+++ b/src/pages/docs/docsTranslations.ts
@@ -0,0 +1,258 @@
+export const readmeFr = `# La-Fabrik
+
+Une expérience web 3D interactive pour La Fabrik Durable, un service low-tech de réparation et de transformation situé à Altera, une ville post-capitaliste reconstruite en 2039. Les joueurs incarnent un technicien fraîchement intégré et vivent une journée de service : réparer un vélo électrique, remettre en état un réseau d'énergie et améliorer le système d'irrigation d'une ferme verticale.
+
+Construit avec React, Three.js et Vite. Fonctionne dans le navigateur, sans installation côté utilisateur.
+
+## Stack technique
+
+### Build et langage
+
+| Package |
+| -------------------------------------------------- |
+| [TypeScript](https://www.typescriptlang.org/docs/) |
+| [React](https://react.dev/learn) |
+| [Vite](https://vite.dev/guide/) |
+| [ESLint](https://eslint.org/docs/latest/) |
+| [Prettier](https://prettier.io/docs/) |
+
+### Moteur 3D
+
+| Package |
+| ----------------------------------------------------------------------------------------- |
+| [Three.js](https://threejs.org/docs/) |
+| [@react-three/fiber](https://docs.pmnd.rs/react-three-fiber/getting-started/introduction) |
+| [@react-three/drei](https://pmndrs.github.io/drei) |
+| [@react-three/rapier](https://rapier.rs/docs/) |
+| [@react-three/postprocessing](https://github.com/pmndrs/postprocessing) |
+| [GSAP](https://gsap.com/docs/v3/Installation/) |
+
+### Performance et effets
+
+| Package |
+| --------------------------------------------------------------------------- |
+| [r3f-perf](https://github.com/utsuboco/r3f-perf) |
+| [AnimationMixer](https://threejs.org/docs/#api/en/animation/AnimationMixer) |
+
+## Structure du projet
+
+\`\`\`
+la-fabrik/
+├── public/
+│ ├── models/
+│ │ ├── map/ # Carte de base, chargée au démarrage
+│ │ ├── workshop/
+│ │ ├── powerGrid/
+│ │ └── farm/
+│ ├── textures/
+│ └── sounds/
+│
+└── src/
+ ├── world/ # Monde 3D persistant
+ │ ├── World.tsx # Composition principale de la scène
+ │ ├── Map.tsx # Carte de base, toujours montée
+ │ ├── Lighting.tsx # Lumières ambiante, directionnelle et ponctuelles
+ │ ├── Environment.tsx # HDRI, brouillard, ciel
+ │ ├── PostFX.tsx # Bloom, SSAO, aberration chromatique
+ │ ├── zones/ # Zones spatiales, LOD par zone
+ │ └── player/ # Contrôleur joueur et caméra
+ │
+ ├── components/
+ │ ├── 3d/ # Éléments 3D réutilisables
+ │ └── ui/ # Overlays HTML hors Canvas
+ │
+ ├── stateManager/ # Logique, état et orchestration
+ ├── hooks/ # Hooks React autour des managers
+ ├── data/ # Configuration statique
+ ├── shaders/ # Shaders GLSL
+ └── utils/ # Utilitaires partagés et debug
+\`\`\`
+
+## Démarrage
+
+\`\`\`bash
+git clone https://github.com/La-Fabrik-Durable/La-Fabrik.git
+cd La-Fabrik
+npm install
+npm run dev
+\`\`\`
+
+- application : \`http://localhost:5173\`
+- mode debug : \`http://localhost:5173?debug\`
+
+## Licence
+
+Voir le fichier [LICENSE](./LICENSE).
+`;
+
+export const architectureFr = `# Architecture actuelle
+
+Ce document décrit le code réellement présent aujourd'hui dans le dépôt.
+
+## Structure runtime
+
+- \`src/App.tsx\` monte le \`Canvas\`, le \`World\` 3D, l'overlay de performance debug et les overlays HTML.
+- \`src/world/World.tsx\` compose la scène active avec :
+ - l'environnement et l'éclairage
+ - les helpers debug et le mode caméra debug
+ - soit la carte principale, soit la scène de test physique debug
+ - le rig joueur quand le mode caméra actif est \`player\`
+- \`src/world/Map.tsx\` charge le modèle principal de la carte et construit l'octree de collision.
+- \`src/world/debug/TestScene.tsx\` fournit une scène orientée debug pour les interactions et la physique.
+- \`src/world/player/PlayerComponent.tsx\` monte la caméra et le contrôleur.
+- \`src/world/player/PlayerController.tsx\` gère le mouvement pointer lock, le saut et les inputs d'interaction.
+
+## Modèle d'interaction
+
+- \`src/stateManager/InteractionManager.ts\` est la source d'état actuelle des interactions.
+- \`src/components/3d/InteractableObject.tsx\` gère la détection de focus par distance et raycasting.
+- \`src/components/3d/TriggerObject.tsx\` implémente les interactions de type trigger.
+- \`src/components/3d/GrabbableObject.tsx\` implémente les interactions saisir / relâcher.
+- \`src/hooks/useInteraction.ts\` expose un snapshot d'interaction à l'UI React.
+- \`src/components/ui/InteractPrompt.tsx\` affiche le prompt \`E\` pour les interactions trigger.
+
+## Audio
+
+- \`src/stateManager/AudioManager.ts\` fournit actuellement une lecture de sons one-shot avec pool.
+- Les interactions trigger peuvent lancer directement un son via \`AudioManager\`.
+
+## Système debug
+
+- Le mode debug est activé avec \`?debug\`.
+- \`src/utils/debug/Debug.ts\` possède l'instance \`lil-gui\` et les contrôles debug.
+- \`src/hooks/debug/useCameraMode.ts\` et \`src/hooks/debug/useSceneMode.ts\` s'abonnent à l'état debug.
+- \`src/utils/debug/DebugPerf.tsx\` monte \`r3f-perf\` en lazy uniquement en mode debug.
+- \`src/utils/debug/scene/DebugHelpers.tsx\` monte les helpers debug.
+- \`src/utils/debug/scene/DebugCameraControls.tsx\` monte la caméra libre debug.
+
+## Limites actuelles
+
+- Le dépôt est encore un prototype, pas le runtime complet du jeu.
+- \`src/world/debug/TestScene.tsx\` fait encore partie de la composition active.
+- Il n'existe pas encore d'orchestrateur gameplay central comme \`GameManager\`.
+- Les systèmes de missions, zones, cinématiques et dialogues ne sont pas implémentés.
+- Le joueur utilise une collision octree et des règles simples, pas une pile physique gameplay complète.
+`;
+
+export const targetArchitectureFr = `# Architecture cible
+
+Ce document décrit l'architecture visée à moyen terme pour le projet.
+
+## Relation avec le code actuel
+
+- \`docs/technical/architecture.md\` reste la source de vérité de ce qui existe maintenant.
+- Ce document est volontairement aspirational.
+- Si ce document contredit l'implémentation actuelle, l'implémentation actuelle gagne.
+
+## Objectifs
+
+- Garder \`App.tsx\` petit et centré sur l'orchestration.
+- Séparer le code de production du monde des chemins runtime uniquement debug.
+- Garder une source de vérité claire par responsabilité.
+- Faire grandir les systèmes gameplay progressivement, sans préconstruire une architecture vide.
+
+## Couches prévues
+
+### Couche App
+
+- \`App.tsx\` monte la scène canvas et les overlays HTML de premier niveau.
+- Il doit rester fin et éviter la logique gameplay.
+
+### Couche World
+
+- \`src/world/\` doit contenir la composition de scène de production et les objets de scène de production.
+- Responsabilités attendues :
+ - composition du monde
+ - carte, environnement, éclairage
+ - contrôleur joueur
+ - ancres d'interaction de production
+ - post-processing de production si nécessaire
+
+### Couche Debug
+
+- Les scènes et outils uniquement debug doivent être isolés du chemin de production.
+- Responsabilités attendues :
+ - \`lil-gui\`
+ - overlay de performance
+ - helpers de scène
+ - caméra libre et contrôles de calibration
+ - scènes temporaires de test utilisées pendant le développement
+
+### Couche UI
+
+- \`src/components/ui/\` doit contenir les overlays HTML visibles par le joueur.
+- Exemples futurs :
+ - crosshair
+ - flow de chargement
+ - HUD de mission
+ - overlays narratifs
+
+### Couche Gameplay
+
+- À mesure que le projet grandit, l'état gameplay peut évoluer vers une couche d'orchestration plus claire.
+- Sujets probables :
+ - missions
+ - zones
+ - cinématiques
+ - dialogues
+ - audio
+ - interactions
+
+## Règles
+
+- Préférer du code direct et fonctionnel plutôt qu'un échafaudage spéculatif.
+- Les types partagés doivent rester proches de leur domaine jusqu'à avoir plusieurs vrais consommateurs.
+- Éviter de créer de nouveaux managers ou services sans besoin runtime actif.
+- Les chemins runtime uniquement debug doivent être clairement marqués et faciles à retirer plus tard.
+`;
+
+export const featuresFr = `# Fonctionnalités implémentées
+
+Ce document liste les fonctionnalités présentes dans le code actuel.
+
+## Scène
+
+- Scène React Three Fiber plein écran
+- Carte principale chargée depuis \`public/models/map/model.gltf\`
+- Scène de test physique debug sélectionnable depuis le panneau debug
+- Éclairage ambiant et directionnel
+- Configuration de l'environnement de fond
+
+## Joueur
+
+- Mode caméra joueur
+- Orientation souris avec pointer lock
+- Déplacement avec \`ZQSD\`
+- Saut
+- Collision basée sur une octree contre la carte chargée
+
+## Interactions
+
+- Détection de focus par distance et raycast
+- Interactions trigger activées avec \`E\`
+- Interactions grab activées avec le bouton principal de la souris
+- Prompt d'interaction affiché pour les interactions trigger
+
+## Audio
+
+- Lecture de sons one-shot pour les interactions trigger
+- Pool simple par son via \`AudioManager\`
+
+## Outils debug
+
+- Le paramètre \`?debug\` active le panneau debug
+- Contrôles \`lil-gui\` pour le mode caméra, le mode scène et les sphères d'interaction
+- Helpers de scène debug
+- Caméra libre debug
+- Overlay \`r3f-perf\`
+
+## Pas encore implémenté
+
+- système de missions
+- système de zones
+- système de cinématiques
+- système de dialogues
+- flow de chargement
+- minimap et HUD de mission
+- séparation complète production / debug pour les scènes gameplay
+`;
diff --git a/src/pages/docs/features/page.tsx b/src/pages/docs/features/page.tsx
new file mode 100644
index 0000000..e1a510f
--- /dev/null
+++ b/src/pages/docs/features/page.tsx
@@ -0,0 +1,14 @@
+import features from "../../../../docs/user/features.md?raw";
+import { DocsDocument } from "@/pages/docs/DocsDocument";
+import { featuresFr } from "@/pages/docs/docsTranslations";
+
+export function DocsFeaturesPage(): React.JSX.Element {
+ return (
+
+ );
+}
diff --git a/src/pages/docs/page.tsx b/src/pages/docs/page.tsx
new file mode 100644
index 0000000..2fce4b6
--- /dev/null
+++ b/src/pages/docs/page.tsx
@@ -0,0 +1,14 @@
+import readme from "../../../README.md?raw";
+import { DocsDocument } from "@/pages/docs/DocsDocument";
+import { readmeFr } from "@/pages/docs/docsTranslations";
+
+export function DocsReadmePage(): React.JSX.Element {
+ return (
+
+ );
+}
diff --git a/src/pages/docs/target-architecture/page.tsx b/src/pages/docs/target-architecture/page.tsx
new file mode 100644
index 0000000..f5b9b8b
--- /dev/null
+++ b/src/pages/docs/target-architecture/page.tsx
@@ -0,0 +1,14 @@
+import targetArchitecture from "../../../../docs/technical/target-architecture.md?raw";
+import { DocsDocument } from "@/pages/docs/DocsDocument";
+import { targetArchitectureFr } from "@/pages/docs/docsTranslations";
+
+export function DocsTargetArchitecturePage(): React.JSX.Element {
+ return (
+
+ );
+}
diff --git a/src/pages/docs/useDocsLanguage.ts b/src/pages/docs/useDocsLanguage.ts
new file mode 100644
index 0000000..d65a481
--- /dev/null
+++ b/src/pages/docs/useDocsLanguage.ts
@@ -0,0 +1,12 @@
+import { useContext } from "react";
+import { DocsLanguageContext } from "@/pages/docs/docsLanguageContext";
+
+export function useDocsLanguage() {
+ const context = useContext(DocsLanguageContext);
+
+ if (!context) {
+ throw new Error("useDocsLanguage must be used inside DocsLanguageProvider");
+ }
+
+ return context;
+}
diff --git a/src/router.tsx b/src/router.tsx
index 2549a14..f507a2f 100644
--- a/src/router.tsx
+++ b/src/router.tsx
@@ -4,8 +4,12 @@ import {
createRoute,
createRouter,
} from "@tanstack/react-router";
-import { DocsPage } from "@/pages/DocsPage";
import { HomePage } from "@/pages/HomePage";
+import { DocsArchitecturePage } from "@/pages/docs/architecture/page";
+import { DocsLayout } from "@/pages/docs/DocsLayout";
+import { DocsFeaturesPage } from "@/pages/docs/features/page";
+import { DocsReadmePage } from "@/pages/docs/page";
+import { DocsTargetArchitecturePage } from "@/pages/docs/target-architecture/page";
const rootRoute = createRootRoute({
component: Outlet,
@@ -20,10 +24,42 @@ const indexRoute = createRoute({
const docsRoute = createRoute({
getParentRoute: () => rootRoute,
path: "/docs",
- component: DocsPage,
+ component: DocsLayout,
});
-const routeTree = rootRoute.addChildren([indexRoute, docsRoute]);
+const docsIndexRoute = createRoute({
+ getParentRoute: () => docsRoute,
+ path: "/",
+ component: DocsReadmePage,
+});
+
+const docsArchitectureRoute = createRoute({
+ getParentRoute: () => docsRoute,
+ path: "/architecture",
+ component: DocsArchitecturePage,
+});
+
+const docsTargetArchitectureRoute = createRoute({
+ getParentRoute: () => docsRoute,
+ path: "/target-architecture",
+ component: DocsTargetArchitecturePage,
+});
+
+const docsFeaturesRoute = createRoute({
+ getParentRoute: () => docsRoute,
+ path: "/features",
+ component: DocsFeaturesPage,
+});
+
+const routeTree = rootRoute.addChildren([
+ indexRoute,
+ docsRoute.addChildren([
+ docsIndexRoute,
+ docsArchitectureRoute,
+ docsTargetArchitectureRoute,
+ docsFeaturesRoute,
+ ]),
+]);
export const router = createRouter({ routeTree });