# Architecture ## Contexte Remplace une série de scripts `.cmd` (`./downloader`, non versionné) par une application web : parcourir une chaîne YouTube, mettre des vidéos/audios en file d'attente, les télécharger en parallèle avec suivi en temps réel, et les livrer au navigateur de l'utilisateur. Pas d'intégration Emby, pas d'authentification (usage LAN). ## Structure du dépôt ``` server/ Backend Fastify (TypeScript, ESM) client/ Frontend TypeScript vanilla (esbuild + sass) .forgejo/workflows/ CI : lint + typecheck + tests + build, puis publication Docker ``` Pas de `docker-compose.yml` pour l'instant (une seule image, pas encore de dépendances externes type base de données). ## Backend (`server/`) - Fastify 5, TypeScript strict, ESM (`"type": "module"`, imports relatifs en `.js`, résolution `NodeNext`). - `src/index.ts` : bootstrap (plugins, écoute, arrêt propre SIGINT/SIGTERM). - `src/config.ts` : configuration runtime depuis l'environnement (`PORT`, `HOST`, `CLIENT_DIST_PATH`). - `src/routes/` : routes Fastify enregistrées comme plugins (`health.ts` pour l'instant). Les futurs domaines métier (découverte de chaîne, file d'attente, téléchargement, notifications temps réel) suivront le même principe de service modulaire autonome, un fichier/dossier par domaine sous `src/`. - Le serveur sert aussi les fichiers statiques de `client/dist` via `@fastify/static`. - Tests : Vitest (`server/test/`), via `app.inject()` (pas de serveur HTTP réel démarré en test). ## Frontend (`client/`) - TypeScript vanilla, pas de framework. Chaque vue = un dossier avec `Vue.ts` / `Vue.html` / `Vue.scss` (gabarit importé comme chaîne brute, style Sass importé et compilé). Voir `src/shell/` pour l'exemple actuel (placeholder). - Build via `build.mjs` (esbuild), pas d'outil de build plus lourd (Vite, webpack) : le script compile `src/app.ts` en bundle ESM, copie `src/index.html`, et compile/regroupe les `.scss` importés en un `app.css` voisin (plugin esbuild maison qui délègue au paquet `sass`). - Pas encore de router : une seule vue (shell) pour l'instant. Un routeur sera introduit avec la première vraie vue (parcours de chaîne). ## Lint Biome.js à la racine (`biome.json`), applique aux deux paquets (`server/src`, `client/src`) - pas d'ESLint/Prettier. `downloader/` (scripts legacy, non versionné) est explicitement exclu. ## Docker / CI-CD - `server/Dockerfile` : image multi-étapes construite avec pour contexte la racine du dépôt (`docker build -f server/Dockerfile .`), car elle a besoin à la fois de `server/` et `client/`. Étapes : build client (esbuild) → build serveur (tsc) → image runtime (Node 22 Alpine + `ffmpeg` + binaire autonome `yt-dlp`, utilisateur non-root `node`). - `yt-dlp` et `ffmpeg` sont installés dans l'image (pas vendorisés dans le dépôt, contrairement aux scripts `.cmd` d'origine qui embarquaient `yt-dlp.exe` et un build ffmpeg complet). - `.forgejo/workflows/publish-docker.yml` : job `test` (lint racine, typecheck/tests/build serveur, typecheck/build client) puis job `publish` (build + push de l'image vers `git.dev.kyuno.fr/kyuno/youtubedownloader`, seulement si `test` passe et hors PR). Tags : `latest` + sha court sur push `main`, `X.Y.Z`/`X.Y`/`latest` sur tag `vX.Y.Z`. Nécessite le secret de dépôt `REGISTRY_TOKEN` (à créer manuellement, voir l'en-tête du workflow - un jeton d'API n'a pas le droit d'écrire dans le registre de paquets). ## Statut Squelette d'infrastructure seulement : serveur qui répond, client placeholder, Docker, CI. Aucune des fonctionnalités métier (découverte de chaîne, file d'attente, téléchargement yt-dlp, notifications temps réel) n'est encore implémentée - elles arriveront par PR successives.