Remplace la documentation PHP par celle de la branche svelte (FR/EN) : architecture statique et bake au build, fonctionnalités portées (Funkwhale inclus), référence de src/lib/config.ts, modÚle CSP par page, PWA, structure du projet, prérequis Node + ImageMagick, mesures Lighthouse, déploiement
40 KiB
đïž ANNU KUTE CED â Hub multimĂ©dia du podcast (SvelteKit)
- đ«đ· Version française
- đ Description
- đł Origine du projet
- đ Sources et instances utilisĂ©es
- ⚠Fonctionnalités
- đ„ VidĂ©os PeerTube
- đș Directs et annonces
- đïž Podcast et musique
- đĄ RĂ©seaux sociaux
- đ Internationalisation
- đš Charte OKI
- đ± PWA et confort dâutilisation
- đ Dons, compte Ă rebours et divers
- đ SEO et donnĂ©es structurĂ©es
- đĄïž SĂ©curitĂ©
- ⥠Performance (mesurée, Lighthouse mobile)
- đ ïž Technologies utilisĂ©es
- đ Structure du projet
- đ PrĂ©requis
- đ Installation et dĂ©veloppement
- âïž Configuration
- đ§ Ordre des sections sur la page dâaccueil
- đĄïž SĂ©curitĂ©
- đ± Progressive Web App (PWA)
- đ DĂ©ploiement
- đšâđ» DĂ©veloppement et contribution
- đ Licence
- đ Contact
- đŹđ§ English version
- đ Description
- đł Project origin
- đ Aggregated sources and instances
- âš Features
- đ„ PeerTube videos
- đș Live streams and announcements
- đïž Podcast and music
- đĄ Social networks
- đ Internationalization
- đš OKI design system
- đ± PWA and user experience
- đ Donations, countdown and more
- đ SEO and structured data
- đĄïž Security
- ⥠Performance (measured, mobile Lighthouse)
- đ ïž Tech stack
- đ Project structure
- đ Requirements
- đ Installation and development
- âïž Configuration
- đ§ Homepage section order
- đĄïž Security
- đ± Progressive Web App (PWA)
- đ Deployment
- đšâđ» Development and contribution
- đ License
- đ Contact
đ Hub multimĂ©dia du podcast ANNU KUTE CED â version SvelteKit statique
đ Multimedia hub for the ANNU KUTE CED podcast â static SvelteKit version
Choisissez votre langue / Choose your language :
đ«đ· Version française · đŹđ§ English version
đ«đ· Version française
đ Description
ANNU KUTE CED est le hub multimĂ©dia du podcast du mĂȘme nom. Il regroupe en un seul lieu :
-
đ„ la chaĂźne PeerTube du podcast (vidĂ©os, shorts, directs) ;
-
đïž son compte Castopod (derniers Ă©pisodes, lecture audio intĂ©grĂ©e) ;
-
đ” une sĂ©lection alĂ©atoire de morceaux Funkwhale (mĂȘme lecteur intĂ©grĂ©) ;
-
đĄ sa timeline Mastodon (actualitĂ©s et annonces).
Cette version est une application SvelteKit 100 % statique (Svelte 5 + TypeScript, adapter-static, prerender intĂ©gral) : toutes les donnĂ©es des instances sont rĂ©cupĂ©rĂ©es au moment du build (« bake ») et le site gĂ©nĂ©rĂ© peut ĂȘtre servi depuis nâimporte quel hĂ©bergement statique â y compris un mutualisĂ© comme o2switch â sans PHP, sans Node, sans base de donnĂ©es. Câest aussi une Progressive Web App installable, avec mode hors ligne, en français et en anglais.
đŻ Mission : offrir un point dâentrĂ©e unique, libre et dĂ©centralisĂ©, pour dĂ©couvrir, Ă©couter et suivre le podcast ANNU KUTE CED sans dĂ©pendre des grandes plateformes propriĂ©taires.
NOTE : La version historique PHP est conservée sur la branche main. Cette documentation décrit la branche svelte.
đł Origine du projet
Cette application est un fork de FEDIVERSE OKI, dĂ©veloppĂ©e par lâORGANISATION KA INTERNATIONALE (OKI), elle-mĂȘme issue du projet kaubuntu.re du mouvement Ka-Ubuntu. La licence dâorigine (GNU AGPL v3) est conservĂ©e et respectĂ©e. La refonte SvelteKit applique la charte OKI (tokens panafricains, thĂšme sombre par dĂ©faut, iconographie SVG krĂ©yĂČl, cadences de motion « gwoka »).
| ĂlĂ©ment | DĂ©tail |
|---|---|
DépÎt upstream |
https://labola.o-k-i.net/ORGANISATION-KA-INTERNATIONALE/FEDIVERSE-OKI |
DépÎt de ce fork |
|
Domaine de production |
|
Gouvernance |
Application maintenue par OKI ; fork porté par le propriétaire du dépÎt cedric (Cédric Famibelle-Pronzola) |
Licence |
GNU Affero General Public License v3 (AGPL-V3) ou ultérieure |
đ Sources et instances utilisĂ©es
Le hub agrĂšge au build les sources du podcast ANNU KUTE CED :
| Service | Instance | Compte / chaĂźne |
|---|---|---|
đ„ PeerTube (vidĂ©os, lives) |
GADE â |
|
đïž Castopod (Ă©pisodes audio) |
KUTE â |
|
đ” Funkwhale (musique) |
MIZIK â |
morceaux alĂ©atoires de lâinstance |
đĄ Mastodon (timeline) |
BOKANTE â |
Toutes ces sources sont modifiables dans src/lib/config.ts (voir Configuration).
⚠Fonctionnalités
đ„ VidĂ©os PeerTube
-
Vidéos récentes, tendances et par catégories (configurables)
-
Shorts : carrousel dédié aux vidéos portrait de moins de 3 minutes (défilement tactile)
-
Page vidéo complÚte : lecteur PeerTube embarqué, description Markdown, badge de licence Creative Commons, commentaires (lecture seule), vidéos suggérées
-
Téléchargement : fichiers directs et playlists HLS, avec résolution et taille
-
Partage : copie de lien, code dâintĂ©gration, e-mail, Facebook, X, WhatsApp, LinkedIn, Telegram
-
Recherche plein texte et par hashtag (préfixe
#) sur un index JSON généré au build
đș Directs et annonces
-
Page Direct (
/direct) : embed du live PeerTube sâil est en cours, avec autoplay -
Annonce du prochain live : date et heure converties automatiquement pour 5 territoires (Maâohi Nui, Martinique/Guadeloupe, Guyane, France, Kanaky), image personnalisable
-
Section hero dâaccueil configurable : live, vidĂ©o unique, playlist ou masquĂ©e
đïž Podcast et musique
-
Castopod : derniers Ă©pisodes via flux RSS, avec lecteur audio intĂ©grĂ© (lecture/pause, avance automatique Ă lâĂ©pisode suivant, Media Session API)
-
Funkwhale : sĂ©lection alĂ©atoire de morceaux de lâinstance, avec le mĂȘme lecteur intĂ©grĂ©
-
Un seul flux à la fois entre les deux lecteurs (bus audio partagé)
đĄ RĂ©seaux sociaux
-
Timeline Mastodon : les 10 derniers posts récupérés au build et rendus en HTML sémantique (plus de bibliothÚque JS embarquée)
đ Internationalisation
-
Interface en français (
/) et en anglais (/en/) : routage par paramĂštre optionnel, bundles JSON,hreflang, attributlangpar route -
KrĂ©yĂČl en signature : page 404 (« Paj la pa la »), page hors-ligne (« Pa gen koneksyon »), verrou maintenance (« An nou tann ! »)
đš Charte OKI
-
ThÚme sombre par défaut (identité de marque), thÚme clair en opt-in persisté en
localStorage, appliqué sans FOUC -
Tokens panafricains (noir/or/vert/rouge), flag-bar de signature, typographies Archivo et Inter self-hébergées en woff2
-
ZĂ©ro emoji en interface : sprite SVG maison (pictos krĂ©yĂČl
ka,lambi,zetwal⊠+ icÎnes UI), zéro Font Awesome, zéro CDN -
Motion « gwoka » : KineticText au scroll (
animation-timeline: view()), barre de progression, reveal syncopĂ© (3+3+2), View Transitions â gate uniqueprefers-reduced-motion
đ± PWA et confort dâutilisation
-
Progressive Web App installable (bouton dâinstallation automatique)
-
Mode hors ligne : shell et pages en cache via Service Worker (Workbox), page
/offlinedédiée -
Indicateur visuel de perte de connexion
-
Interface entiĂšrement responsive (mobile, tablette, desktop)
đ Dons, compte Ă rebours et divers
-
Page de dons : LiberaPay, Ko-fi et Stripe (dons ponctuels et mensuels, montants suggérés)
-
Verrou maintenance : compte Ă rebours multi-fuseaux affichĂ© Ă la place de tout le site quand activĂ© au build, redirection automatique Ă lâĂ©chĂ©ance
-
Bloc « à propos » configurable (titre, deux paragraphes, image légendée)
đ SEO et donnĂ©es structurĂ©es
-
JSON-LD généré automatiquement :
WebSite(avecSearchAction),VideoObject,CollectionPage,BreadcrumbList,Organization -
Balises Open Graph complĂštes et Twitter Cards, canonical,
hreflangfr/en/x-default -
sitemap.xmlgénéré au build (toutes les pages, vidéos comprises) etrobots.txt
đĄïž SĂ©curitĂ©
-
CSP stricte : politique globale en en-tĂȘte (
_headersCloudflare /.htaccessApache) +script-srcdélivré par page en balise<meta>avec les empreintes SHA-256 des scripts inline (aucun'unsafe-inline'pour les scripts) -
ZĂ©ro requĂȘte tierce au chargement hors instances first-party de lâĂ©cosystĂšme (GADE, KUTE, BOKANTE, MIZIK) : ni Google Fonts, ni CDN, ni analytics
-
HTML distant sanitisé au build (posts Mastodon, commentaires) ; descriptions Markdown échappées
-
HSTS,
X-Frame-Options: DENY,X-Content-Type-Options: nosniff,Referrer-Policy,Permissions-Policyrestrictive
⥠Performance (mesurée, Lighthouse mobile)
-
97 / 100 / 100 / 100 (performance, accessibilité, bonnes pratiques, SEO)
-
JS initial â 66 Ko gzip ; poids total de lâaccueil â 900 Ko ; LCP 2,4 s ; TBT 50 ms ; CLS 0
-
Images distantes optimisées au build (WebP via ImageMagick) : vignettes PeerTube, avatars, médias Mastodon, pochettes Castopod
đ ïž Technologies utilisĂ©es
-
⥠SvelteKit 2 + Svelte 5 (runes) + TypeScript strict
-
đŠ
@sveltejs/adapter-static(prerender intégral,trailingSlash: 'always') -
đ±
vite-plugin-pwa(Workbox, generateSW) -
đŒïž ImageMagick (optimisation des images au prebuild)
-
đš CSS vanilla : tokens OKI + styles scopĂ©s â pas de framework CSS
-
đ€
@fontsource/archivo+@fontsource/inter(woff2 copiés dansstatic/fonts/)
đ Structure du projet
âââ docs/
â âââ wireframes/ # Maquettes d'origine (PNG desktop + mobile)
â âââ DEPLOIEMENT-SVELTEKIT.md # Guide build + dĂ©ploiement (o2switch, Cloudflare)
â âââ generate-readme-pdf.sh # Export de la doc : README.html / README.pdf
âââ scripts/
â âââ fetch-podcast-cover.mjs # Prebuild : pochettes Castopod optimisĂ©es (WebP)
â âââ optimize-remote-images.mjs # Prebuild : vignettes/avatars/mĂ©dias optimisĂ©s
â âââ postbuild-csp.mjs # Postbuild : CSP SHA-256 par page (balise meta)
âââ src/
â âââ app.html # %lang%, fonts, theme.js, registerSW.js
â âââ hooks.server.ts # lang fr/en via transformPageChunk
â âââ params/locale.ts # Matcher du paramĂštre [[locale]]
â âââ lib/
â â âââ config.ts # â Toute la configuration d'instance
â â âââ types.ts # Types partagĂ©s (VideoSummary, Episode, PostâŠ)
â â âââ audio-bus.svelte.ts # Un seul flux audio Ă la fois
â â âââ styles/ # oki-tokens.css (charte) + base.css (primitives)
â â âââ i18n/ # fr.json, en.json + helpers (locale, hrefForâŠ)
â â âââ server/ # RĂ©cupĂ©ration des donnĂ©es au build :
â â â âââ http.ts # fetch throttlĂ© (429 â retry), sanitisation
â â â âââ peertube.ts # API GADE (vidĂ©os, shorts, live, commentaires)
â â â âââ castopod.ts # Flux RSS KUTE (Ă©pisodes)
â â â âââ funkwhale.ts # API MIZIK (morceaux alĂ©atoires locaux)
â â â âââ mastodon.ts # API BOKANTE (timeline)
â â â âââ image-map.ts # Mapping images optimisĂ©es (mapImage)
â â â âââ image-map.json # (gĂ©nĂ©rĂ© au prebuild)
â â âââ motion/ # tokens gwoka, action use:reveal
â â âââ components/ # Seo, Nav, Sidebar, Footer, VideoCard,
â â # AudioPlayer, MastodonTimeline, HeroSection,
â â # CountdownLock, OfflineIndicator, motion/âŠ
â âââ routes/
â âââ +layout.ts # prerender = true, trailingSlash
â âââ +error.svelte # 404 krĂ©yĂČl (« Paj la pa la »)
â âââ [[locale=locale]]/ # Toutes les pages, FR (/) et EN (/en/) :
â â âââ +page.svelte # accueil (agrĂ©gateur)
â â âââ video/[uuid]/ # page vidĂ©o (embed, tĂ©lĂ©chargements, partage)
â â âââ categories/[id]/ # page catĂ©gorie
â â âââ recherche/ # recherche (index JSON + filtrage client)
â â âââ direct/ # live + annonce du prochain live
â â âââ dons/ # dons (LiberaPay, Ko-fi, Stripe)
â â âââ mentions-legales/ # mentions lĂ©gales
â â âââ offline/ # page hors-ligne (fallback du SW)
â âââ search-index.json/ # Index de recherche (bake)
â âââ sitemap.xml/ # Sitemap (bake)
âââ static/
â âââ fonts/ # Archivo/Inter woff2 + fonts.css
â âââ images/ # logo, favicons, pochettes, images optimisĂ©es
â âââ icons.svg # Sprite SVG (pictos krĂ©yĂČl + UI)
â âââ theme.js # Anti-FOUC (thĂšme sombre dĂ©faut, clair opt-in)
â âââ registerSW.js # Enregistrement du Service Worker
â âââ manifest.webmanifest # Manifest PWA
â âââ _headers / .htaccess # Headers de sĂ©curitĂ© (Cloudflare / Apache)
â âââ 404.html # 404 statique autonome
â âââ robots.txt / browserconfig.xml
âââ uploads/ # Images d'annonces (non versionnĂ©, hors .gitkeep)
âââ package.json / vite.config.ts # Adapter, PWA, paths.relative: false
âââ README.adoc
đ PrĂ©requis
-
đą Node.js 20+ (recommandĂ© : 22+)
-
đŒïž ImageMagick (
convert) â optimisation des images au prebuild -
đ Pour le dĂ©veloppement : un accĂšs rĂ©seau aux instances (les donnĂ©es sont fetchĂ©es au build)
# Ubuntu / Debian
sudo apt-get install imagemagick
# Fedora / RHEL / CentOS
sudo dnf install ImageMagick
đ Installation et dĂ©veloppement
-
đ„ Clonez le dĂ©pĂŽt et basculez sur la branche :
git clone git@labola.o-k-i.net:cedric/annu-kute-ced.git cd annu-kute-ced git checkout svelte -
đŠ Installez les dĂ©pendances :
npm ci -
đ§ Lancez le serveur de dĂ©veloppement :
npm run dev -
đïž Buildez le site statique :
npm run build # prebuild (images) â prerender (donnĂ©es) â postbuild (CSP) npm run preview # vĂ©rification locale du build
Le dossier build/ contient le site complet, prĂȘt Ă dĂ©poser sur nâimporte quel hĂ©bergement statique.
â
Vérifications qualité : npm run check (svelte-check, 0 erreur / 0 warning exigé).
đ RafraĂźchissement du contenu : les donnĂ©es Ă©tant bakĂ©es au build, un nouveau build est nĂ©cessaire pour afficher les derniĂšres vidĂ©os/Ă©pisodes/posts â voir docs/DEPLOIEMENT-SVELTEKIT.md pour un exemple de cron + rsync.
âïž Configuration
Toute la configuration dâinstance vit dans un seul fichier : src/lib/config.ts (versionnĂ©). Câest lâĂ©quivalent des anciennes constantes PHP â modifiez-le puis rebuildez.
| Export | RĂŽle |
|---|---|
|
Nom, domaine ( |
|
Coordonnées des mentions légales (webmaster, hébergeur o2Switch) |
|
URL de lâinstance, chaĂźne, compte live, durĂ©e max des shorts, volumes par section, tag « indĂ©pendance » |
|
BanniĂšre dâaccueil : |
|
Activation, instance, slug(s) de podcast, nombre dâĂ©pisodes |
|
Activation, instance MIZIK, nombre de morceaux (pool de 50, sélection aléatoire) |
|
Instance, compte, nombre de posts de la timeline |
|
URLs des réseaux sociaux du header/footer (vide = icÎne masquée) |
|
Activation, URLs LiberaPay/Ko-fi, liens Stripe (ponctuels/mensuels), montants, devise |
|
Annonce du prochain live : activation, titre, description, date, image, 5 fuseaux horaires |
|
CatĂ©gories prioritaires (ordre dâaffichage), noms FR/EN, pictos du sprite |
|
Hashtags de la sidebar/footer et de lâaccueil |
|
Bloc « à propos » : activation, titre, deux paragraphes, image + légende (masqué tant que |
|
Verrou maintenance : quand |
NOTE : Les libellés FR/EN vivent dans src/lib/i18n/fr.json et en.json (pas dans config.ts).
đ§ Ordre des sections sur la page dâaccueil
-
Hero â si
hero.typeâ'none'(live, vidĂ©o ou playlist) -
Derniers Ă©pisodes (Castopod) â si activĂ© et Ă©pisodes disponibles
-
Morceaux (Funkwhale) â si activĂ© et morceaux disponibles
-
ActualitĂ©s (timeline Mastodon) â si posts disponibles
-
Shorts â carrousel
-
Vidéos récentes
-
Tendances
-
Une section par catégorie prioritaire (seulement si elle contient des vidéos) + lien « Voir plus »
-
Bloc « à propos » (si activé) + aside hashtags populaires
đĄïž SĂ©curitĂ©
ModĂšle CSP
-
En-tĂȘte global (
static/_headerspour Cloudflare Pages,static/.htaccesspour Apache/o2switch) :style-src,img-src,font-src 'self',connect-src 'self',media-src,frame-src https://gade.o-k-i.net,frame-ancestors 'none',base-uri 'self',form-action 'self',object-src 'none'. Seules origines externes : les instances de lâĂ©cosystĂšme. -
script-srcpar page :scripts/postbuild-csp.mjscalcule les empreintes SHA-256 des scripts inline de chaque page (script de démarrage SvelteKit + JSON-LD) et les injecte dans une balise<meta http-equiv="Content-Security-Policy">complÚte. Aucun'unsafe-inline'pour les scripts. -
Anti-FOUC, redirection de langue et enregistrement du SW en fichiers externes (
theme.js,registerSW.js) : aucun script inline non hashé.
Redirections des anciennes URLs (Apache)
Le .htaccess redirige les URLs historiques PHP : index.php â /, video.php?uuid=X â /video/X/, categories.php?id=N â /categories/N/, recherche.php?q=⊠â /recherche/?q=âŠ, direct.php â /direct/, dons.php â /dons/, mentions-legales.php â /mentions-legales/. Il force aussi HTTPS, sert 404.html et met en cache immutable /_app/ et /fonts/.
đ± Progressive Web App (PWA)
-
đČ Installation native : bouton « Installer » dans le header (Ă©vĂ©nement
beforeinstallprompt) -
đ Mode hors ligne : prĂ©cache du shell (Workbox
generateSW),navigateFallbackvers/offline/ -
đĄ DĂ©tection de connexion : indicateur visuel en cas de perte rĂ©seau
-
đ Mise Ă jour :
autoUpdate+skipWaiting(mise Ă jour silencieuse au prochain chargement) -
Lâenregistrement du SW se fait par le fichier statique
registerSW.js(chemins absolus), jamais par injection du plugin
NOTE : Les flux audio/vidĂ©o des instances ne sont pas interceptĂ©s par le SW (requĂȘtes Range) â seuls le shell et les assets locaux sont prĂ©cachĂ©s.
đ DĂ©ploiement
Voir le guide complet : docs/DEPLOIEMENT-SVELTEKIT.md.
-
o2switch (Apache) : déposer
build/Ă la racine web ; le.htaccessinclus gĂšre HTTPS, headers, redirections des anciennes URLs et 404 -
Cloudflare Pages : build command
npm run build, outputbuild; le_headersinclus applique la sécurité et le cache -
RafraĂźchissement : rebuild planifiĂ© (cron + rsync, ou CI avec webhook aprĂšs publication dâun Ă©pisode)
đšâđ» DĂ©veloppement et contribution
-
đż CrĂ©ez une branche :
git checkout -b ma-fonctionnalite -
đŸ Committez avec des messages atomiques, au format conventionnel :
-
feat: add âŠ,fix: prevent âŠ,docs: update âŠ,refactor: âŠ
-
-
â Avant tout commit :
npm run check(0 erreur / 0 warning) etnpm run buildvert -
đ€ Poussez :
git push origin ma-fonctionnalite -
đ Ouvrez une pull request
Bonnes pratiques du dépÎt :
-
Les remontĂ©es de bugs et propositions sont les bienvenues sur le dĂ©pĂŽt du fork ; les amĂ©liorations gĂ©nĂ©riques peuvent ĂȘtre proposĂ©es en upstream (FEDIVERSE OKI)
-
src/lib/server/image-map.jsonetstatic/images/remote/sont rĂ©gĂ©nĂ©rĂ©s au prebuild : pas dâĂ©dition manuelle -
Conventions Svelte 5 : runes uniquement,
{#each}à clé unique,onclick(jamaison:click), durées lues depuis les tokens CSS
đ Exporter la documentation (HTML / PDF)
docs/generate-readme-pdf.sh # README.html + README.pdf
docs/generate-readme-pdf.sh --html # HTML seulement
docs/generate-readme-pdf.sh --pdf # PDF seulement
PrĂ©requis : asciidoctor, chromium et le paquet fonts-noto-color-emoji. La feuille de style docs/docinfo.html est injectĂ©e automatiquement via le mĂ©canisme docinfo dâAsciidoctor.
đ Licence
Copyright © 2025 Cédric Famibelle-Pronzola & ORGANISATION KA INTERNATIONALE
Ce programme est un logiciel libre : vous pouvez le redistribuer et/ou le modifier selon les termes de la licence publique générale GNU Affero publiée par la Free Software Foundation, soit la version 3 de la licence, soit (à votre choix) toute version ultérieure.
Ce programme est distribuĂ© dans lâespoir quâil sera utile, mais SANS AUCUNE GARANTIE ; sans mĂȘme la garantie implicite de COMMERCIALISATION ou dâADAPTATION Ă UN USAGE PARTICULIER. Voir la licence publique gĂ©nĂ©rale GNU Affero pour plus de dĂ©tails (texte intĂ©gral dans LICENSE).
đŹđ§ English version
đ Description
ANNU KUTE CED is the multimedia hub of the podcast of the same name. It brings together in a single place:
-
đ„ the podcastâs PeerTube channel (videos, shorts, live streams);
-
đïž its Castopod account (latest episodes, built-in audio playback);
-
đ” a random selection of Funkwhale tracks (same built-in player);
-
đĄ its Mastodon timeline (news and announcements).
This version is a 100% static SvelteKit application (Svelte 5 + TypeScript, adapter-static, full prerender): all instance data is fetched at build time ("baked") and the generated site can be served from any static hosting â including shared hosting like o2switch â with no PHP, no Node, no database. It is also an installable Progressive Web App with offline support, in French and English.
đŻ Mission: provide a single, free and decentralized entry point to discover, listen to and follow the ANNU KUTE CED podcast without relying on Big Tech platforms.
|
Note
|
The historical PHP version is kept on the main branch. This documentation covers the svelte branch.
|
đł Project origin
This application is a fork of FEDIVERSE OKI, developed by the ORGANISATION KA INTERNATIONALE (OKI), itself derived from the kaubuntu.re project by the Ka-Ubuntu movement. The original license (GNU AGPL v3) is preserved and respected. The SvelteKit rewrite applies the OKI design system (panafrican tokens, dark theme by default, KrĂ©yĂČl SVG iconography, "gwoka" motion cadences).
| Item | Detail |
|---|---|
Upstream repository |
https://labola.o-k-i.net/ORGANISATION-KA-INTERNATIONALE/FEDIVERSE-OKI |
This forkâs repository |
|
Production domain |
|
Governance |
Application maintained by OKI; fork carried by the repository owner cedric (Cédric Famibelle-Pronzola) |
License |
GNU Affero General Public License v3 (AGPL-V3) or later |
đ Aggregated sources and instances
The hub aggregates the ANNU KUTE CED podcastâs sources at build time:
| Service | Instance | Account / channel |
|---|---|---|
đ„ PeerTube (videos, lives) |
GADE â |
|
đïž Castopod (audio episodes) |
KUTE â |
|
đ” Funkwhale (music) |
MIZIK â |
random tracks from the instance |
đĄ Mastodon (timeline) |
BOKANTE â |
All of these sources can be changed in src/lib/config.ts (see Configuration).
âš Features
đ„ PeerTube videos
-
Recent, trending and per-category videos (configurable)
-
Shorts: dedicated carousel for portrait videos under 3 minutes (touch scrolling)
-
Full video page: embedded PeerTube player, Markdown description, Creative Commons licence badge, comments (read-only), suggested videos
-
Downloads: direct files and HLS playlists, with resolution and size
-
Sharing: copy link, embed code, e-mail, Facebook, X, WhatsApp, LinkedIn, Telegram
-
Full-text search and hashtag search (
#prefix) over a build-generated JSON index
đș Live streams and announcements
-
Live page (
/direct): embeds the PeerTube live stream when one is running, with autoplay -
Next live announcement: date and time automatically converted for 5 territories (Maâohi Nui, Martinique/Guadeloupe, French Guiana, France, Kanaky), custom image
-
Configurable homepage hero section: live, single video, playlist or hidden
đïž Podcast and music
-
Castopod: latest episodes via RSS feed, with a built-in audio player (play/pause, auto-advance to the next episode, Media Session API)
-
Funkwhale: random track selection from the instance, using the same built-in player
-
One stream at a time across both players (shared audio bus)
đĄ Social networks
-
Mastodon timeline: the 10 latest posts fetched at build time and rendered as semantic HTML (no embedded JS library anymore)
đ Internationalization
-
Interface in French (
/) and English (/en/): optional-parameter routing, JSON bundles,hreflang, per-routelangattribute -
KrĂ©yĂČl as a signature: 404 page ("Paj la pa la"), offline page ("Pa gen koneksyon"), maintenance lock ("An nou tann !")
đš OKI design system
-
Dark theme by default (brand identity), light theme as an opt-in persisted in
localStorage, applied without FOUC -
Panafrican tokens (black/gold/green/red), signature flag-bar, self-hosted Archivo and Inter woff2 fonts
-
Zero emoji in the interface: custom SVG sprite (KrĂ©yĂČl pictograms
ka,lambi,zetwal⊠+ UI icons), no Font Awesome, no CDN -
"Gwoka" motion: scroll-driven KineticText (
animation-timeline: view()), progress bar, syncopated reveal (3+3+2), View Transitions â singleprefers-reduced-motiongate
đ± PWA and user experience
-
Installable Progressive Web App (automatic install button)
-
Offline mode: shell and pages cached via Service Worker (Workbox), dedicated
/offlinepage -
Visual indicator when the connection is lost
-
Fully responsive interface (mobile, tablet, desktop)
đ Donations, countdown and more
-
Donation page: LiberaPay, Ko-fi and Stripe (one-time and monthly donations, suggested amounts)
-
Maintenance lock: multi-timezone countdown displayed instead of the whole site when enabled at build time, automatic redirect when it ends
-
Configurable "About" block (title, two paragraphs, captioned image)
đ SEO and structured data
-
Automatically generated JSON-LD:
WebSite(withSearchAction),VideoObject,CollectionPage,BreadcrumbList,Organization -
Full Open Graph and Twitter Cards meta tags, canonical,
hreflangfr/en/x-default -
Build-generated
sitemap.xml(every page, including videos) androbots.txt
đĄïž Security
-
Strict CSP: global policy in headers (
_headersfor Cloudflare /.htaccessfor Apache) + per-pagescript-srcdelivered in a<meta>tag with SHA-256 hashes of inline scripts (no'unsafe-inline'for scripts) -
Zero third-party requests at load time outside the first-party ecosystem instances (GADE, KUTE, BOKANTE, MIZIK): no Google Fonts, no CDN, no analytics
-
Remote HTML sanitized at build time (Mastodon posts, comments); Markdown descriptions escaped
-
HSTS,
X-Frame-Options: DENY,X-Content-Type-Options: nosniff,Referrer-Policy, restrictivePermissions-Policy
⥠Performance (measured, mobile Lighthouse)
-
97 / 100 / 100 / 100 (performance, accessibility, best practices, SEO)
-
Initial JS â 66 KB gzip; homepage total weight â 900 KB; LCP 2.4 s; TBT 50 ms; CLS 0
-
Remote images optimized at build time (WebP via ImageMagick): PeerTube thumbnails, avatars, Mastodon media, Castopod covers
đ ïž Tech stack
-
⥠SvelteKit 2 + Svelte 5 (runes) + strict TypeScript
-
đŠ
@sveltejs/adapter-static(full prerender,trailingSlash: 'always') -
đ±
vite-plugin-pwa(Workbox, generateSW) -
đŒïž ImageMagick (build-time image optimization)
-
đš Vanilla CSS: OKI tokens + scoped styles â no CSS framework
-
đ€
@fontsource/archivo+@fontsource/inter(woff2 copied tostatic/fonts/)
đ Project structure
âââ docs/
â âââ wireframes/ # Original mockups (desktop + mobile PNGs)
â âââ DEPLOIEMENT-SVELTEKIT.md # Build + deployment guide (o2switch, Cloudflare)
â âââ generate-readme-pdf.sh # Docs export: README.html / README.pdf
âââ scripts/
â âââ fetch-podcast-cover.mjs # Prebuild: optimized Castopod covers (WebP)
â âââ optimize-remote-images.mjs # Prebuild: optimized thumbnails/avatars/media
â âââ postbuild-csp.mjs # Postbuild: per-page SHA-256 CSP (meta tag)
âââ src/
â âââ app.html # %lang%, fonts, theme.js, registerSW.js
â âââ hooks.server.ts # fr/en lang via transformPageChunk
â âââ params/locale.ts # [[locale]] param matcher
â âââ lib/
â â âââ config.ts # â All instance configuration
â â âââ types.ts # Shared types (VideoSummary, Episode, PostâŠ)
â â âââ audio-bus.svelte.ts # One audio stream at a time
â â âââ styles/ # oki-tokens.css (brand) + base.css (primitives)
â â âââ i18n/ # fr.json, en.json + helpers (locale, hrefForâŠ)
â â âââ server/ # Build-time data fetching:
â â â âââ http.ts # throttled fetch (429 â retry), sanitizing
â â â âââ peertube.ts # GADE API (videos, shorts, live, comments)
â â â âââ castopod.ts # KUTE RSS feed (episodes)
â â â âââ funkwhale.ts # MIZIK API (random local tracks)
â â â âââ mastodon.ts # BOKANTE API (timeline)
â â â âââ image-map.ts # Optimized images mapping (mapImage)
â â â âââ image-map.json # (generated at prebuild)
â â âââ motion/ # gwoka tokens, use:reveal action
â â âââ components/ # Seo, Nav, Sidebar, Footer, VideoCard,
â â # AudioPlayer, MastodonTimeline, HeroSection,
â â # CountdownLock, OfflineIndicator, motion/âŠ
â âââ routes/
â âââ +layout.ts # prerender = true, trailingSlash
â âââ +error.svelte # KrĂ©yĂČl 404 ("Paj la pa la")
â âââ [[locale=locale]]/ # Every page, FR (/) and EN (/en/):
â â âââ +page.svelte # home (aggregator)
â â âââ video/[uuid]/ # video page (embed, downloads, sharing)
â â âââ categories/[id]/ # category page
â â âââ recherche/ # search (JSON index + client filtering)
â â âââ direct/ # live + next-live announcement
â â âââ dons/ # donations (LiberaPay, Ko-fi, Stripe)
â â âââ mentions-legales/ # legal notice
â â âââ offline/ # offline page (SW fallback)
â âââ search-index.json/ # Search index (baked)
â âââ sitemap.xml/ # Sitemap (baked)
âââ static/
â âââ fonts/ # Archivo/Inter woff2 + fonts.css
â âââ images/ # logo, favicons, covers, optimized images
â âââ icons.svg # SVG sprite (KrĂ©yĂČl pictograms + UI)
â âââ theme.js # Anti-FOUC (dark default, light opt-in)
â âââ registerSW.js # Service Worker registration
â âââ manifest.webmanifest # PWA manifest
â âââ _headers / .htaccess # Security headers (Cloudflare / Apache)
â âââ 404.html # Self-contained static 404
â âââ robots.txt / browserconfig.xml
âââ uploads/ # Announcement images (not versioned, except .gitkeep)
âââ package.json / vite.config.ts # Adapter, PWA, paths.relative: false
âââ README.adoc
đ Requirements
-
đą Node.js 20+ (recommended: 22+)
-
đŒïž ImageMagick (
convert) â build-time image optimization -
đ For development: network access to the instances (data is fetched at build time)
# Ubuntu / Debian
sudo apt-get install imagemagick
# Fedora / RHEL / CentOS
sudo dnf install ImageMagick
đ Installation and development
-
đ„ Clone the repository and switch to the branch:
git clone git@labola.o-k-i.net:cedric/annu-kute-ced.git cd annu-kute-ced git checkout svelte -
đŠ Install dependencies:
npm ci -
đ§ Start the development server:
npm run dev -
đïž Build the static site:
npm run build # prebuild (images) â prerender (data) â postbuild (CSP) npm run preview # local check of the build
The build/ directory holds the complete site, ready to drop on any static hosting.
â
Quality gates: npm run check (svelte-check, 0 errors / 0 warnings required).
đ Content refresh: since data is baked at build time, a new build is required to display the latest videos/episodes/posts â see docs/DEPLOIEMENT-SVELTEKIT.md for a cron + rsync example.
âïž Configuration
All instance configuration lives in a single file: src/lib/config.ts (versioned). It is the equivalent of the old PHP constants â edit it, then rebuild.
| Export | Role |
|---|---|
|
Name, domain ( |
|
Legal notice details (webmaster, o2Switch host) |
|
Instance URL, channel, live account, max shorts duration, per-section volumes, "independence" tag |
|
Homepage banner: |
|
Toggle, instance, podcast slug(s), episode count |
|
Toggle, MIZIK instance, track count (pool of 50, random selection) |
|
Instance, account, timeline post count |
|
Header/footer social network URLs (empty = icon hidden) |
|
Toggle, LiberaPay/Ko-fi URLs, Stripe links (one-time/monthly), amounts, currency |
|
Next live announcement: toggle, title, description, date, image, 5 timezones |
|
Priority categories (display order), FR/EN names, sprite pictograms |
|
Sidebar/footer and homepage hashtags |
|
"About" block: toggle, title, two paragraphs, image + caption (hidden while |
|
Maintenance lock: when |
|
Note
|
Interface texts
FR/EN labels live in src/lib/i18n/fr.json and en.json (not in config.ts).
|
đ§ Homepage section order
-
Hero â if
hero.typeâ'none'(live, video or playlist) -
Latest episodes (Castopod) â if enabled and episodes available
-
Tracks (Funkwhale) â if enabled and tracks available
-
News (Mastodon timeline) â if posts available
-
Shorts â carousel
-
Recent videos
-
Trending
-
One section per priority category (only when it has videos) + "See more" link
-
"About" block (if enabled) + popular hashtags aside
đĄïž Security
CSP model
-
Global header (
static/_headersfor Cloudflare Pages,static/.htaccessfor Apache/o2switch):style-src,img-src,font-src 'self',connect-src 'self',media-src,frame-src https://gade.o-k-i.net,frame-ancestors 'none',base-uri 'self',form-action 'self',object-src 'none'. Only external origins: the ecosystem instances. -
Per-page
script-src:scripts/postbuild-csp.mjscomputes SHA-256 hashes of each pageâs inline scripts (SvelteKit start script + JSON-LD) and injects them into a full<meta http-equiv="Content-Security-Policy">tag. No'unsafe-inline'for scripts. -
Anti-FOUC, language redirect and SW registration as external files (
theme.js,registerSW.js): no unhashed inline script.
Legacy URL redirects (Apache)
The .htaccess redirects historical PHP URLs: index.php â /, video.php?uuid=X â /video/X/, categories.php?id=N â /categories/N/, recherche.php?q=⊠â /recherche/?q=âŠ, direct.php â /direct/, dons.php â /dons/, mentions-legales.php â /mentions-legales/. It also forces HTTPS, serves 404.html and sets immutable caching for /_app/ and /fonts/.
đ± Progressive Web App (PWA)
-
đČ Native installation: "Install" button in the header (
beforeinstallpromptevent) -
đ Offline mode: shell precache (Workbox
generateSW),navigateFallbackto/offline/ -
đĄ Connection detection: visual indicator when the network is lost
-
đ Updates:
autoUpdate+skipWaiting(silent update on next load) -
SW registration is done by the static
registerSW.jsfile (absolute paths), never via plugin injection
|
Note
|
Instance audio/video streams are not intercepted by the SW (Range requests) â only the shell and local assets are precached.
|
đ Deployment
See the full guide: docs/DEPLOIEMENT-SVELTEKIT.md.
-
o2switch (Apache): drop
build/at the web root; the bundled.htaccesshandles HTTPS, headers, legacy URL redirects and 404 -
Cloudflare Pages: build command
npm run build, outputbuild; the bundled_headersapplies security and caching -
Refresh: scheduled rebuild (cron + rsync, or CI with a webhook after an episode is published)
đšâđ» Development and contribution
-
đż Create a branch:
git checkout -b my-feature -
đŸ Commit with atomic messages, conventional format:
-
feat: add âŠ,fix: prevent âŠ,docs: update âŠ,refactor: âŠ
-
-
â Before any commit:
npm run check(0 errors / 0 warnings) and a greennpm run build -
đ€ Push:
git push origin my-feature -
đ Open a pull request
Repository best practices:
-
Bug reports and proposals are welcome on the forkâs repository; generic improvements can be proposed upstream (FEDIVERSE OKI)
-
src/lib/server/image-map.jsonandstatic/images/remote/are regenerated at prebuild: no manual editing -
Svelte 5 conventions: runes only, uniquely keyed
{#each},onclick(neveron:click), durations read from CSS tokens
đ Exporting the documentation (HTML / PDF)
docs/generate-readme-pdf.sh # README.html + README.pdf
docs/generate-readme-pdf.sh --html # HTML only
docs/generate-readme-pdf.sh --pdf # PDF only
Requirements: asciidoctor, chromium and the fonts-noto-color-emoji package. The docs/docinfo.html stylesheet is automatically injected via Asciidoctorâs docinfo mechanism.
đ License
Copyright © 2025 Cédric Famibelle-Pronzola & ORGANISATION KA INTERNATIONALE
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details (full text in LICENSE).