From 07449de1872b44a72b55552e7ccffddc38f86cf5 Mon Sep 17 00:00:00 2001 From: Yvv Date: Mon, 16 Mar 2026 04:40:48 +0100 Subject: [PATCH] =?UTF-8?q?Pages=20d=C3=A9tail=20num=C3=A9rique=20:=20somm?= =?UTF-8?q?aire=20flottant,=20nav=20ctx,=20shadoks=20geek,=20contenu=20enr?= =?UTF-8?q?ichi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - [slug].vue : sommaire sticky (overflow:clip sur parent), prev/next en haut, 6 shadoks geek (pinguin+USB, web-of-trust, rubber-duck, caféine, debugger loupe, rack serveur) - Nouveaux types de sections : territoire (bouquet sweethomeCloud, 2 modèles éco, tableau matériel dépliable), projet (carte gestation) - cloud-libre.yml : section sweethomeCloud complète avec infra 50 000 hab. (~2€/an/hab) - authentification-wot.yml : trustWallet, correction WoT Duniter (Ed25519+Scrypt, sigQty=5, stepMax=3), DID/VC standards - logiciel-libre.yml : carte projet wishBounty - home.yml + numerique.yml : cloud-libre → sweethomeCloud, description RGPD/local-first - AxisBlock.vue : bulles de présentation inline dans les cards (plus de tooltip absolu) - Analytics : useTracking.ts (Umami), docker-compose.umami.yml, /api/stats fédération - nuxt.config.ts : config Umami runtime Co-Authored-By: Claude Sonnet 4.6 --- CONTRIBUTING.md | 25 +- README.md | 6 + app/app.vue | 12 + app/components/home/AxisBlock.vue | 43 +- app/composables/useTracking.ts | 20 + app/pages/numerique/[slug].vue | 1826 ++++++++++++++++- docker/docker-compose.umami.yml | 52 + nuxt.config.ts | 10 + server/api/stats/index.get.ts | 43 + site/pages/home.yml | 10 +- site/pages/numerique.yml | 4 +- site/pages/numerique/authentification-wot.yml | 208 +- site/pages/numerique/cloud-libre.yml | 342 ++- site/pages/numerique/logiciel-libre.yml | 242 ++- 14 files changed, 2776 insertions(+), 67 deletions(-) create mode 100644 app/composables/useTracking.ts create mode 100644 docker/docker-compose.umami.yml create mode 100644 server/api/stats/index.get.ts diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 82a2fc2..9e81e66 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -50,10 +50,26 @@ Les fichiers YAML sont dans `site/pages/`, organisés en sous-dossiers par secti - Overrides light mode dans `main.css` (`.palette-light .text-white` → couleur adaptive) - Admin : tous les `color: white` dans les composants admin sont remplacés par `hsl(var(--color-text))` sauf les boutons sur fond `hsl(var(--color-primary))` (`AdminSaveButton`, `.login-btn`) +## Navigation contextuelle — pages détail + +`[slug].vue` (numérique, citoyenne) embarque : +- **Prev/next** (`ctx-nav`) en haut de page — liens vers les pages adjacentes dans la section +- **Sommaire flottant** (`.sommaire-sidebar`, `position: sticky`) dans un aside absolu à droite — visible ≥ 1300px, `overflow: clip` sur le parent pour ne pas casser le sticky + +Les ancres sont des `
` avec `scroll-margin-top: 5.5rem` (offset header fixe). + +## Types de sections YAML + +`[slug].vue` supporte : `arguments`, `fiche`, `equivalents`, `llm`, `atelier`, `links`, `insight`, `tiers`, `projet`, `territoire`. + +`type: territoire` : économies alternatives (euro/Ğ1), grille bouquet de services, tableau matériel dépliable (`
`). +`type: projet` : carte gestation avec grille de features. + ## Shadoks Illustrations SVG inline sur chaque page, thématiques par section : -- Numérique : métiers tech/industrie (codeuse, électricien, soudeuse...) +- Numérique index : métiers tech/industrie (codeuse, électricien, soudeuse, cryptographe...) +- Numérique détail : postures geek (pinguin+USB, web-of-trust, rubber duck, caféine, rack serveur, debugger loupe) - Économique : artisanat/agriculture (boulangère, potier, forgeron...) - Citoyenne : navigation/justice/théâtre (capitaine, avocate, comédien...) - Modèle éco : livre/édition (typographe, calligraphe, conteuse...) @@ -61,6 +77,13 @@ Illustrations SVG inline sur chaque page, thématiques par section : Règles : corps compact, longues pattes, grands pieds plats, bec pointu, postures variées. CSS : `position: absolute`, `pointer-events: none`, `opacity 0.18-0.28`, animation float, `display: none` sur mobile. +Parent avec `overflow: clip` (pas `overflow: hidden` qui casserait `position: sticky`). + +## Analytics + +`app/composables/useTracking.ts` — wrapper Umami. Activé si `NUXT_PUBLIC_UMAMI_WEBSITE_ID` est défini. +`server/api/stats/index.get.ts` — endpoint public pour la fédération inter-instances (observatoires territoire). +`docker/docker-compose.umami.yml` — stack Umami + PostgreSQL avec labels Traefik. ## Redirections diff --git a/README.md b/README.md index 6a9df21..ff67320 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,12 @@ pnpm build # Build production Port réservé : **3000** (ne pas changer). +## Analytics + +Umami self-hosted (optionnel). Configurer `NUXT_PUBLIC_UMAMI_WEBSITE_ID` et `NUXT_PUBLIC_UMAMI_URL` dans l'environnement. +Déploiement séparé : `docker/docker-compose.umami.yml` → `stats.librodrome.org`. +Stats publiques exposées via `/api/stats` pour la fédération inter-instances. + ## Déploiement Docker + Traefik, CI via Woodpecker. Domaine : `librodrome.org`. diff --git a/app/app.vue b/app/app.vue index 17b182a..b3eebd6 100644 --- a/app/app.vue +++ b/app/app.vue @@ -17,6 +17,18 @@ const paletteStore = usePaletteStore() onMounted(() => paletteStore.applyToDOM()) +// Umami analytics — inject script only when configured +const runtimeConfig = useRuntimeConfig() +if (runtimeConfig.public.umamiWebsiteId && runtimeConfig.public.umamiUrl) { + useHead({ + script: [{ + src: `${runtimeConfig.public.umamiUrl}/script.js`, + defer: true, + 'data-website-id': runtimeConfig.public.umamiWebsiteId, + }], + }) +} + useHead({ titleTemplate: (title) => { return title ? `${title} — Le Librodrome` : 'Le librodrome' diff --git a/app/components/home/AxisBlock.vue b/app/components/home/AxisBlock.vue index 88f64dd..1ab753c 100644 --- a/app/components/home/AxisBlock.vue +++ b/app/components/home/AxisBlock.vue @@ -37,6 +37,15 @@

{{ item.description }}

+ + +
+
+
+ {{ item.presentation.title }} +
+

{{ item.presentation.text }}

+
@@ -173,7 +182,7 @@ function itemAttrs(item: AxisItem) { border: 1px solid hsl(var(--color-text) / 0.08); background: hsl(var(--color-surface)); transition: border-color 0.2s, box-shadow 0.2s; - overflow: hidden; + /* overflow: visible pour laisser le tooltip sortir du cadre */ } .axis-item:hover { @@ -248,6 +257,8 @@ function itemAttrs(item: AxisItem) { gap: 0; border-top: 1px solid hsl(var(--color-text) / 0.06); background: hsl(var(--color-bg) / 0.4); + border-bottom-left-radius: 0.75rem; + border-bottom-right-radius: 0.75rem; } .axis-actions-row { @@ -309,4 +320,34 @@ function itemAttrs(item: AxisItem) { background: hsl(var(--color-accent) / 0.08); border-color: hsl(var(--color-accent) / 0.2); } + +/* Presentation inline — projet en gestation, affiché dans la card */ +.axis-presentation-inline { + margin-top: 0.75rem; + padding: 0.5rem 0.75rem; + border-radius: 8px; + background: hsl(var(--color-accent) / 0.07); + border: 1px solid hsl(var(--color-accent) / 0.18); +} + +.axis-pi-header { + display: flex; + align-items: center; + gap: 0.3rem; + margin-bottom: 0.2rem; + color: hsl(var(--color-accent)); +} + +.axis-pi-title { + font-size: 0.75rem; + font-weight: 700; + letter-spacing: 0.02em; +} + +.axis-pi-text { + font-size: 0.72rem; + color: hsl(var(--color-text) / 0.55); + line-height: 1.45; + margin: 0; +} diff --git a/app/composables/useTracking.ts b/app/composables/useTracking.ts new file mode 100644 index 0000000..036327c --- /dev/null +++ b/app/composables/useTracking.ts @@ -0,0 +1,20 @@ +/** + * Umami analytics wrapper — safe server-side, no-op when not configured. + * Usage: const { track } = useTracking() + * track('player:open') + * track('axis:navigate', { axis: 'numerique' }) + */ +export function useTracking() { + const runtimeConfig = useRuntimeConfig() + const enabled = !!runtimeConfig.public.umamiWebsiteId + + function track(event: string, data?: Record) { + if (!import.meta.client || !enabled) return + const umami = (window as Record).umami as + | { track: (event: string, data?: unknown) => void } + | undefined + umami?.track(event, data) + } + + return { track, enabled } +} diff --git a/app/pages/numerique/[slug].vue b/app/pages/numerique/[slug].vue index 5ed0708..cb8698a 100644 --- a/app/pages/numerique/[slug].vue +++ b/app/pages/numerique/[slug].vue @@ -1,25 +1,243 @@ @@ -61,11 +614,32 @@ const route = useRoute() const slug = route.params.slug as string -const { data: content } = await usePageContent(`numerique/${slug}`) +const [{ data: content }, { data: homeData }] = await Promise.all([ + usePageContent(`numerique/${slug}`), + usePageContent('home'), +]) const appConfig = useAppConfig() const sejeteral0Url = (appConfig.sejeteral0 as { url: string })?.url ?? '#' +// Sommaire — titres des sections ayant un titre +interface Section { type: string; title?: string } +const sommaire = computed(() => + (content.value?.sections as Section[] ?? []) + .map((s, i) => ({ title: s.title, id: `s${i}` })) + .filter(s => !!s.title), +) + +// Prev / next dans la section numérique +interface AxisItem { label: string; to?: string; icon?: string } +const sectionItems = computed( + () => (homeData.value as Record | null)?.axes?.numerique?.items as AxisItem[] ?? [], +) +const currentPath = `/numerique/${slug}` +const currentIdx = computed(() => sectionItems.value.findIndex(i => i.to === currentPath)) +const prevItem = computed(() => currentIdx.value > 0 ? sectionItems.value[currentIdx.value - 1] : null) +const nextItem = computed(() => currentIdx.value < sectionItems.value.length - 1 ? sectionItems.value[currentIdx.value + 1] : null) + useHead({ title: content.value?.meta?.title ?? slug, }) @@ -121,4 +695,1208 @@ useHead({ border-radius: 0.75rem; background: hsl(var(--color-surface)); } + +/* scroll-margin-top pour compenser le header fixe */ +.section-anchor { + scroll-margin-top: 5.5rem; +} + +/* ── Navigation prev/next (en haut) ── */ +.ctx-nav { + display: grid; + grid-template-columns: 1fr auto 1fr; + gap: 0.5rem; + align-items: center; +} + +.ctx-nav-spacer { min-width: 0; } + +.ctx-nav-btn { + display: flex; + align-items: center; + gap: 0.45rem; + padding: 0.5rem 0.875rem; + border-radius: 20px; + text-decoration: none; + font-size: 0.8rem; + font-weight: 500; + color: hsl(var(--color-text-muted)); + background: hsl(var(--color-surface)); + border: 1px solid hsl(var(--color-text) / 0.08); + transition: all 0.15s; + min-width: 0; +} + +.ctx-nav-btn:hover { + color: hsl(var(--color-primary)); + border-color: hsl(var(--color-primary) / 0.25); + background: hsl(var(--color-primary) / 0.05); +} + +.ctx-nav-prev { justify-content: flex-start; } + +.ctx-nav-next { justify-content: flex-end; } + +.ctx-nav-prev span, +.ctx-nav-next span { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.ctx-nav-index { + justify-content: center; + background: hsl(var(--color-primary) / 0.08); + border-color: hsl(var(--color-primary) / 0.15); + color: hsl(var(--color-primary)); + font-size: 0.75rem; + padding: 0.45rem 0.75rem; + white-space: nowrap; + flex-shrink: 0; +} + +.ctx-nav-index:hover { background: hsl(var(--color-primary) / 0.15); } + +@media (max-width: 480px) { + .ctx-nav { grid-template-columns: auto 1fr auto; } + .ctx-nav-prev span, .ctx-nav-next span { display: none; } + .ctx-nav-prev, .ctx-nav-next { padding: 0.5rem; } +} + +/* ── Zone sections — relative pour ancrer le sidebar ── */ +.sections-area { + position: relative; +} + +/* ── Sidebar sommaire — position absolue, ne décale pas le contenu ── */ +.page-sidebar { + display: none; /* caché par défaut (mobile) */ + position: absolute; + top: 3.5rem; + right: 0; + width: 10.5rem; + height: 100%; +} + +/* Activé uniquement quand il y a assez de place (>= largeur max-w-4xl + sidebar) */ +@media (min-width: 1300px) { + .page-sidebar { + display: block; + } +} + +.sommaire-sidebar { + position: sticky; + top: 5.5rem; + padding: 0.875rem; + border-radius: 14px; + background: hsl(var(--color-surface)); + border: 1px solid hsl(var(--color-text) / 0.07); +} + +.sommaire-sidebar-title { + font-family: var(--font-mono); + font-size: 0.65rem; + font-weight: 700; + letter-spacing: 0.1em; + text-transform: uppercase; + color: hsl(var(--color-text-muted)); + margin: 0 0 0.6rem; +} + +.sommaire-sidebar-list { + list-style: none; + padding: 0; + margin: 0; + display: flex; + flex-direction: column; + gap: 0.1rem; +} + +.sommaire-sidebar-link { + display: flex; + align-items: baseline; + gap: 0.45rem; + padding: 0.28rem 0.4rem; + border-radius: 8px; + text-decoration: none; + font-size: 0.75rem; + color: hsl(var(--color-text-muted)); + line-height: 1.4; + transition: color 0.12s, background 0.12s; +} + +.sommaire-sidebar-link:hover { + color: hsl(var(--color-primary)); + background: hsl(var(--color-primary) / 0.06); +} + +.sommaire-n { + display: inline-flex; + align-items: center; + justify-content: center; + width: 1.2rem; + height: 1.2rem; + border-radius: 50%; + background: hsl(var(--color-primary) / 0.1); + color: hsl(var(--color-primary)); + font-family: var(--font-mono); + font-size: 0.6rem; + font-weight: 700; + flex-shrink: 0; +} + +/* ── Section titles ── */ +.section-title { + font-family: var(--font-display); + font-size: clamp(1.1rem, 2.5vw, 1.35rem); + font-weight: 700; + color: hsl(var(--color-text)); + margin: 0 0 1.25rem; + padding-bottom: 0.5rem; + border-bottom: 2px solid hsl(var(--color-primary) / 0.15); +} + +/* ── Arguments ── */ +.args-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); + gap: 0.875rem; +} + +.arg-card { + padding: 1rem 1.1rem; + border-radius: 14px; + background: hsl(var(--color-surface)); + border: 1px solid hsl(var(--color-primary) / 0.08); + transition: transform 0.12s ease, box-shadow 0.12s ease; +} + +.arg-card:hover { + transform: translateY(-3px); + box-shadow: 0 8px 24px hsl(var(--color-primary) / 0.1); +} + +.arg-icon { + width: 2rem; + height: 2rem; + border-radius: 8px; + background: hsl(var(--color-primary) / 0.1); + color: hsl(var(--color-primary)); + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 0.6rem; +} + +.arg-title { + font-family: var(--font-display); + font-size: 0.9rem; + font-weight: 600; + color: hsl(var(--color-text)); + margin: 0 0 0.4rem; +} + +.arg-text { + font-size: 0.82rem; + line-height: 1.55; + color: hsl(var(--color-text-muted)); + margin: 0; +} + +/* ── Fiche steps ── */ +.fiche-steps { + display: flex; + flex-direction: column; + gap: 0; +} + +.fiche-step { + display: flex; + gap: 1rem; + padding: 1rem 0; + border-bottom: 1px solid hsl(var(--color-text) / 0.06); +} + +.fiche-step:last-child { + border-bottom: none; +} + +.step-num { + width: 2rem; + height: 2rem; + border-radius: 50%; + background: hsl(var(--color-primary) / 0.12); + color: hsl(var(--color-primary)); + font-family: var(--font-mono); + font-size: 0.8rem; + font-weight: 700; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + margin-top: 0.1rem; +} + +.step-body { + flex: 1; +} + +.step-title { + font-family: var(--font-display); + font-size: 0.95rem; + font-weight: 600; + color: hsl(var(--color-text)); + margin: 0 0 0.3rem; +} + +.step-text { + font-size: 0.85rem; + line-height: 1.55; + color: hsl(var(--color-text-muted)); + margin: 0; +} + +.step-tip { + margin: 0.5rem 0 0; + font-size: 0.78rem; + color: hsl(var(--color-accent)); + font-style: italic; +} + +/* ── Equivalents ── */ +.equiv-categories { + display: flex; + flex-direction: column; + gap: 1.5rem; +} + +.equiv-cat-label { + font-family: var(--font-mono); + font-size: 0.72rem; + font-weight: 600; + letter-spacing: 0.08em; + text-transform: uppercase; + color: hsl(var(--color-primary)); + margin: 0 0 0.5rem; +} + +.equiv-rows { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.equiv-row { + display: grid; + grid-template-columns: 1fr auto 1fr 1.5fr auto; + align-items: center; + gap: 0.5rem 0.75rem; + padding: 0.5rem 0.75rem; + border-radius: 10px; + background: hsl(var(--color-surface)); + border: 1px solid transparent; + text-decoration: none; + transition: border-color 0.12s, background 0.12s; +} + +.equiv-row:hover { + border-color: hsl(var(--color-primary) / 0.2); + background: hsl(var(--color-primary) / 0.04); +} + +.equiv-from { + font-size: 0.82rem; + color: hsl(var(--color-text-muted)); + text-decoration: line-through; + text-decoration-color: hsl(var(--color-text) / 0.2); +} + +.equiv-arrow { + font-size: 0.75rem; + color: hsl(var(--color-primary) / 0.4); +} + +.equiv-to { + font-size: 0.85rem; + font-weight: 600; + color: hsl(var(--color-primary)); +} + +.equiv-note { + font-size: 0.78rem; + color: hsl(var(--color-text-muted)); +} + +.equiv-ext { + color: hsl(var(--color-primary) / 0.4); + flex-shrink: 0; +} + +@media (max-width: 600px) { + .equiv-row { + grid-template-columns: 1fr auto 1fr; + grid-template-rows: auto auto; + } + .equiv-note { grid-column: 1 / -1; font-size: 0.74rem; } + .equiv-ext { display: none; } +} + +/* ── LLM ── */ +.llm-intro { + font-size: 0.9rem; + line-height: 1.6; + color: hsl(var(--color-text-muted)); + margin: 0 0 1rem; +} + +.llm-meta { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + margin-bottom: 1rem; +} + +.llm-badge { + display: inline-flex; + align-items: center; + gap: 0.35rem; + padding: 0.25rem 0.7rem; + border-radius: 20px; + font-size: 0.78rem; + font-weight: 500; + font-family: var(--font-mono); + background: hsl(var(--color-primary) / 0.1); + color: hsl(var(--color-primary)); +} + +.llm-commands { + display: flex; + flex-direction: column; + gap: 0.35rem; + margin-bottom: 1rem; +} + +.llm-cmd { + display: block; + padding: 0.5rem 0.875rem; + border-radius: 10px; + background: hsl(var(--color-bg)); + border: 1px solid hsl(var(--color-surface-light)); + font-family: var(--font-mono); + font-size: 0.78rem; + color: hsl(var(--color-text)); + white-space: pre; + overflow-x: auto; +} + +.llm-rules { + list-style: none; + padding: 0; + margin: 0; + display: flex; + flex-direction: column; + gap: 0.4rem; +} + +.llm-rule { + display: flex; + align-items: flex-start; + gap: 0.5rem; + font-size: 0.82rem; + color: hsl(var(--color-text-muted)); + line-height: 1.5; +} + +.llm-rule .i-lucide-shield-check { + color: hsl(var(--color-accent)); +} + +/* ── Atelier ── */ +.atelier-text { + font-size: 0.9rem; + line-height: 1.6; + color: hsl(var(--color-text-muted)); + margin: 0 0 0.75rem; +} + +.atelier-format { + font-size: 0.82rem; + font-family: var(--font-mono); + color: hsl(var(--color-primary)); + margin: 0 0 1rem; +} + +.atelier-programme { + list-style: none; + padding: 0; + margin: 0; + display: flex; + flex-direction: column; + gap: 0; +} + +.atelier-item { + display: flex; + align-items: flex-start; + gap: 0.625rem; + padding: 0.625rem 0; + border-bottom: 1px solid hsl(var(--color-text) / 0.06); + font-size: 0.85rem; + color: hsl(var(--color-text)); +} + +.atelier-item:last-child { border-bottom: none; } + +/* ── Links ── */ +.links-list { + list-style: none; + padding: 0; + margin: 0; + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.link-row { + display: grid; + grid-template-columns: 9rem 1fr auto; + align-items: center; + gap: 0.75rem; + padding: 0.625rem 0.875rem; + border-radius: 10px; + text-decoration: none; + background: hsl(var(--color-surface)); + border: 1px solid transparent; + transition: border-color 0.12s, background 0.12s; +} + +.link-row:hover { + border-color: hsl(var(--color-primary) / 0.2); + background: hsl(var(--color-primary) / 0.04); +} + +.link-label { + font-size: 0.85rem; + font-weight: 600; + color: hsl(var(--color-primary)); +} + +.link-desc { + font-size: 0.8rem; + color: hsl(var(--color-text-muted)); +} + +@media (max-width: 480px) { + .link-row { grid-template-columns: 1fr auto; grid-template-rows: auto auto; } + .link-desc { grid-column: 1; font-size: 0.74rem; } +} + +/* ── Insight ── */ +.insight-box { + padding: 1.25rem 1.5rem; + border-radius: 14px; + background: hsl(var(--color-surface)); + border-left: 3px solid hsl(var(--color-primary) / 0.5); +} + +.insight-box--warning { + border-left-color: hsl(var(--color-accent) / 0.6); + background: hsl(var(--color-accent) / 0.05); +} + +.insight-header { + display: flex; + align-items: flex-start; + gap: 0.6rem; + margin-bottom: 0.75rem; + color: hsl(var(--color-primary)); +} + +.insight-box--warning .insight-header { + color: hsl(var(--color-accent)); +} + +.insight-title { + font-family: var(--font-display); + font-size: 1rem; + font-weight: 700; + color: inherit; + margin: 0; + line-height: 1.3; +} + +.insight-text { + font-size: 0.875rem; + line-height: 1.6; + color: hsl(var(--color-text-muted)); + margin: 0 0 0.75rem; +} + +.insight-points { + list-style: none; + padding: 0; + margin: 0; + display: flex; + flex-direction: column; + gap: 0.35rem; +} + +.insight-points li { + font-size: 0.82rem; + color: hsl(var(--color-text-muted)); + padding-left: 1rem; + position: relative; + line-height: 1.5; +} + +.insight-points li::before { + content: '·'; + position: absolute; + left: 0; + color: hsl(var(--color-primary) / 0.5); + font-weight: 700; +} + +/* ── Tiers ── */ +.tiers-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 1rem; +} + +@media (max-width: 768px) { + .tiers-grid { grid-template-columns: 1fr; } +} + +.tier-card { + padding: 1.25rem; + border-radius: 14px; + background: hsl(var(--color-surface)); + border: 1px solid hsl(var(--color-primary) / 0.08); + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.tier-top { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 0.25rem; +} + +.tier-level { + font-family: var(--font-mono); + font-size: 0.7rem; + font-weight: 600; + color: hsl(var(--color-text-muted)); + text-transform: uppercase; + letter-spacing: 0.06em; +} + +.tier-badge { + font-size: 0.7rem; + font-weight: 500; + padding: 0.15rem 0.5rem; + border-radius: 20px; + background: hsl(var(--color-primary) / 0.1); + color: hsl(var(--color-primary)); +} + +.tier-icon { + width: 2rem; + height: 2rem; + border-radius: 8px; + background: hsl(var(--color-primary) / 0.1); + color: hsl(var(--color-primary)); + display: flex; + align-items: center; + justify-content: center; +} + +.tier-title { + font-family: var(--font-display); + font-size: 0.95rem; + font-weight: 700; + color: hsl(var(--color-text)); + margin: 0; +} + +.tier-text { + font-size: 0.8rem; + line-height: 1.55; + color: hsl(var(--color-text-muted)); + margin: 0; + flex: 1; +} + +.tier-tools { + list-style: none; + padding: 0; + margin: 0.25rem 0 0; + display: flex; + flex-direction: column; + gap: 0.2rem; + border-top: 1px solid hsl(var(--color-text) / 0.06); + padding-top: 0.5rem; +} + +.tier-tools li { + font-size: 0.76rem; + color: hsl(var(--color-text-muted)); + padding-left: 0.75rem; + position: relative; +} + +.tier-tools li::before { + content: '→'; + position: absolute; + left: 0; + color: hsl(var(--color-primary) / 0.4); + font-size: 0.65rem; +} + +/* ── Projet (gestation) ── */ +.projet-card { + padding: 1.75rem; + border-radius: 16px; + background: hsl(var(--color-surface)); + border: 1px solid hsl(var(--color-accent) / 0.2); + box-shadow: 0 0 32px hsl(var(--color-accent) / 0.05); +} + +.projet-header { + display: flex; + align-items: flex-start; + gap: 1rem; + margin-bottom: 1rem; +} + +.projet-icon { + width: 3rem; + height: 3rem; + border-radius: 12px; + background: hsl(var(--color-accent) / 0.12); + color: hsl(var(--color-accent)); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +.projet-header-text { + flex: 1; +} + +.projet-kicker { + font-family: var(--font-mono); + font-size: 0.7rem; + font-weight: 600; + letter-spacing: 0.1em; + text-transform: uppercase; + color: hsl(var(--color-accent)); + margin: 0 0 0.2rem; +} + +.projet-title { + font-family: var(--font-display); + font-size: clamp(1.25rem, 3vw, 1.6rem); + font-weight: 800; + color: hsl(var(--color-text)); + margin: 0; +} + +.projet-badge { + display: inline-flex; + align-items: center; + gap: 0.25rem; + padding: 0.2rem 0.6rem; + border-radius: 20px; + background: hsl(var(--color-accent) / 0.12); + color: hsl(var(--color-accent)); + font-size: 0.7rem; + font-weight: 500; + font-family: var(--font-mono); + white-space: nowrap; + flex-shrink: 0; +} + +.projet-text { + font-size: 0.875rem; + line-height: 1.65; + color: hsl(var(--color-text-muted)); + margin: 0 0 1.25rem; +} + +.projet-features { + list-style: none; + padding: 0; + margin: 0; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); + gap: 0.5rem; + border-top: 1px solid hsl(var(--color-text) / 0.06); + padding-top: 1rem; +} + +.projet-feature { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 0.82rem; + color: hsl(var(--color-text-muted)); + padding: 0.4rem 0.6rem; + border-radius: 8px; + background: hsl(var(--color-bg) / 0.5); +} + +.projet-feature .i-lucide-hard-drive, +.projet-feature .i-lucide-video, +.projet-feature .i-lucide-message-circle, +.projet-feature .i-lucide-bot, +.projet-feature .i-lucide-globe-2, +.projet-feature .i-lucide-share-2 { + color: hsl(var(--color-accent)); +} + +/* ── Territoire ── */ +.territoire-card { + border-radius: 16px; + background: hsl(var(--color-surface)); + border: 1px solid hsl(var(--color-primary) / 0.12); + overflow: hidden; +} + +.territoire-header { + display: flex; + align-items: flex-start; + gap: 1rem; + padding: 1.75rem 1.75rem 1.25rem; +} + +.territoire-icon { + width: 3rem; + height: 3rem; + border-radius: 12px; + background: hsl(var(--color-primary) / 0.1); + color: hsl(var(--color-primary)); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + margin-top: 0.1rem; +} + +.territoire-title { + font-family: var(--font-display); + font-size: clamp(1.15rem, 2.5vw, 1.4rem); + font-weight: 800; + color: hsl(var(--color-text)); + margin: 0 0 0.5rem; +} + +.territoire-text { + font-size: 0.875rem; + line-height: 1.65; + color: hsl(var(--color-text-muted)); + margin: 0; +} + +/* Modèles économiques */ +.territoire-economies { + display: flex; + gap: 0.75rem; + padding: 0 1.75rem 1.5rem; + flex-wrap: wrap; +} + +.territoire-eco { + flex: 1; + min-width: 220px; + display: flex; + align-items: flex-start; + gap: 0.75rem; + padding: 0.875rem 1rem; + border-radius: 12px; + background: hsl(var(--color-bg) / 0.6); + border: 1px solid hsl(var(--color-primary) / 0.1); +} + +.territoire-eco-icon { + width: 2rem; + height: 2rem; + border-radius: 8px; + background: hsl(var(--color-primary) / 0.12); + color: hsl(var(--color-primary)); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +.territoire-g1 { + font-family: var(--font-display); + font-weight: 700; + font-size: 1rem; +} + +.territoire-eco-label { + font-size: 0.82rem; + font-weight: 700; + color: hsl(var(--color-text)); + margin: 0 0 0.2rem; +} + +.territoire-eco-desc { + font-size: 0.78rem; + line-height: 1.5; + color: hsl(var(--color-text-muted)); + margin: 0; +} + +/* Bouquet */ +.territoire-bouquet { + padding: 1.25rem 1.75rem; + border-top: 1px solid hsl(var(--color-text) / 0.06); +} + +.territoire-bouquet-title { + display: flex; + align-items: center; + gap: 0.5rem; + font-family: var(--font-mono); + font-size: 0.75rem; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; + color: hsl(var(--color-primary)); + margin: 0 0 1rem; +} + +.territoire-bouquet-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); + gap: 0.75rem; +} + +.territoire-bouquet-cat { + background: hsl(var(--color-bg) / 0.5); + border-radius: 10px; + padding: 0.75rem; +} + +.territoire-bouquet-cat-header { + display: flex; + align-items: center; + gap: 0.375rem; + font-size: 0.75rem; + font-weight: 700; + color: hsl(var(--color-accent)); + margin-bottom: 0.5rem; +} + +.territoire-bouquet-items { + list-style: none; + padding: 0; + margin: 0; + display: flex; + flex-direction: column; + gap: 0.2rem; +} + +.territoire-bouquet-items li { + font-size: 0.76rem; + color: hsl(var(--color-text-muted)); + line-height: 1.4; + padding-left: 0.6rem; + position: relative; +} + +.territoire-bouquet-items li::before { + content: '›'; + position: absolute; + left: 0; + color: hsl(var(--color-primary) / 0.5); +} + +/* Estimation toggled */ +.territoire-estimate { + border-top: 1px solid hsl(var(--color-text) / 0.06); +} + +.territoire-estimate-toggle { + display: flex; + align-items: center; + gap: 0.6rem; + padding: 1rem 1.75rem; + cursor: pointer; + list-style: none; + font-size: 0.85rem; + font-weight: 600; + color: hsl(var(--color-text) / 0.7); + transition: color 0.15s; + user-select: none; +} + +.territoire-estimate-toggle:hover { + color: hsl(var(--color-primary)); +} + +.territoire-estimate-toggle::-webkit-details-marker { display: none; } + +.territoire-chevron { + margin-left: auto; + transition: transform 0.2s; +} + +details[open] .territoire-chevron { + transform: rotate(180deg); +} + +.territoire-estimate-body { + padding: 0 1.75rem 1.75rem; +} + +.territoire-estimate-note { + font-size: 0.8rem; + color: hsl(var(--color-text-muted)); + font-style: italic; + margin: 0 0 1.25rem; + line-height: 1.55; +} + +/* HW table */ +.territoire-hw-table { + display: flex; + flex-direction: column; + gap: 0; + border-radius: 12px; + overflow: hidden; + border: 1px solid hsl(var(--color-text) / 0.06); + margin-bottom: 1.25rem; +} + +.territoire-hw-header { + display: grid; + grid-template-columns: 1.5fr 3fr 1.2fr; + gap: 0.75rem; + padding: 0.5rem 1rem; + background: hsl(var(--color-bg) / 0.8); + font-family: var(--font-mono); + font-size: 0.7rem; + font-weight: 700; + letter-spacing: 0.06em; + text-transform: uppercase; + color: hsl(var(--color-text-muted)); + border-bottom: 1px solid hsl(var(--color-text) / 0.06); +} + +.territoire-hw-row { + display: grid; + grid-template-columns: 1.5fr 3fr 1.2fr; + gap: 0.75rem; + padding: 0.75rem 1rem; + border-bottom: 1px solid hsl(var(--color-text) / 0.04); + align-items: start; +} + +.territoire-hw-row:last-child { border-bottom: none; } +.territoire-hw-row:nth-child(even) { background: hsl(var(--color-bg) / 0.3); } + +.territoire-hw-role { + font-size: 0.82rem; + font-weight: 600; + color: hsl(var(--color-text)); + line-height: 1.4; +} + +.territoire-hw-detail { + display: flex; + flex-direction: column; + gap: 0.15rem; +} + +.territoire-hw-detail span:first-child { + font-size: 0.82rem; + color: hsl(var(--color-text) / 0.85); +} + +.territoire-hw-usage { + font-size: 0.75rem; + color: hsl(var(--color-text-muted)); + line-height: 1.4; +} + +.territoire-hw-note { + font-size: 0.72rem; + color: hsl(var(--color-accent) / 0.8); + font-style: italic; + line-height: 1.4; +} + +.territoire-hw-cost { + font-family: var(--font-mono); + font-size: 0.8rem; + font-weight: 600; + color: hsl(var(--color-primary)); + white-space: nowrap; +} + +/* Totaux */ +.territoire-totals { + border-radius: 12px; + overflow: hidden; + border: 1px solid hsl(var(--color-primary) / 0.15); +} + +.territoire-total-row { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.6rem 1rem; + border-bottom: 1px solid hsl(var(--color-primary) / 0.08); +} + +.territoire-total-row:last-of-type { border-bottom: none; } + +.territoire-total-row--highlight { + background: hsl(var(--color-primary) / 0.06); +} + +.territoire-total-label { + font-size: 0.82rem; + color: hsl(var(--color-text-muted)); +} + +.territoire-total-value { + font-family: var(--font-mono); + font-size: 0.88rem; + font-weight: 700; + color: hsl(var(--color-primary)); +} + +.territoire-totals-note { + padding: 0.6rem 1rem; + font-size: 0.8rem; + color: hsl(var(--color-text-muted)); + font-style: italic; + border-top: 1px solid hsl(var(--color-primary) / 0.08); + margin: 0; + background: hsl(var(--color-primary) / 0.03); +} + +@media (max-width: 640px) { + .territoire-header { flex-direction: column; gap: 0.75rem; } + .territoire-hw-header { display: none; } + .territoire-hw-row { grid-template-columns: 1fr; gap: 0.25rem; } + .territoire-hw-cost { font-size: 0.85rem; } + .territoire-bouquet-grid { grid-template-columns: 1fr; } +} + +/* overflow:clip coupe sans créer de scroll container — préserve position:sticky */ +.page-outer { + position: relative; + overflow: clip; +} + +/* ── Shadoks décoratifs ── */ +.shadok-dl { + position: absolute; + pointer-events: none; + color: hsl(var(--color-primary)); +} + +.shadok-dl-pinguin { + left: 1%; + top: 18%; + width: clamp(65px, 9vw, 130px); + opacity: 0.22; + animation: shadokfloat-a 11s ease-in-out infinite; +} + +.shadok-dl-toile { + right: 1%; + top: 22%; + width: clamp(65px, 9vw, 140px); + opacity: 0.2; + color: hsl(var(--color-accent)); + animation: shadokfloat-b 13s ease-in-out infinite; +} + +.shadok-dl-nas { + left: 2%; + bottom: 6%; + width: clamp(65px, 9vw, 135px); + opacity: 0.22; + color: hsl(var(--color-accent)); + animation: shadokfloat-c 10s ease-in-out infinite; +} + +@keyframes shadokfloat-a { + 0%, 100% { transform: translateY(0) rotate(-2deg); } + 50% { transform: translateY(-8px) rotate(2deg); } +} +@keyframes shadokfloat-b { + 0%, 100% { transform: translateY(0) rotate(3deg); } + 50% { transform: translateY(-10px) rotate(-2deg); } +} +@keyframes shadokfloat-c { + 0%, 100% { transform: translateY(0) rotate(-1deg); } + 50% { transform: translateY(-7px) rotate(3deg); } +} +@keyframes shadokfloat-d { + 0%, 100% { transform: translateY(0) rotate(2deg); } + 50% { transform: translateY(-9px) rotate(-3deg); } +} +@keyframes shadokfloat-e { + 0%, 100% { transform: translateY(0) rotate(-3deg); } + 50% { transform: translateY(-6px) rotate(1deg); } +} +@keyframes shadokfloat-f { + 0%, 100% { transform: translateY(0) rotate(1deg); } + 50% { transform: translateY(-11px) rotate(-2deg); } +} + +.shadok-dl-debugger { + right: 1%; + bottom: 14%; + width: clamp(65px, 9vw, 140px); + opacity: 0.2; + color: hsl(var(--color-primary)); + animation: shadokfloat-d 12s ease-in-out infinite; +} + +.shadok-dl-duck { + left: 38%; + top: 6%; + width: clamp(65px, 9vw, 145px); + opacity: 0.2; + color: hsl(var(--color-accent)); + animation: shadokfloat-e 14s ease-in-out infinite; +} + +.shadok-dl-cafeine { + right: 2%; + top: 52%; + width: clamp(65px, 9vw, 132px); + opacity: 0.22; + color: hsl(var(--color-primary)); + animation: shadokfloat-f 9s ease-in-out infinite; +} + +@media (max-width: 768px) { + .shadok-dl { display: none; } +} + +/* equiv-row without link */ +.equiv-row--no-link { + cursor: default; + opacity: 0.75; +} + +.equiv-row--no-link:hover { + border-color: transparent; + background: hsl(var(--color-surface)); +} diff --git a/docker/docker-compose.umami.yml b/docker/docker-compose.umami.yml new file mode 100644 index 0000000..54abade --- /dev/null +++ b/docker/docker-compose.umami.yml @@ -0,0 +1,52 @@ +## Umami analytics — déployer avec le compose principal +## Usage : docker compose -f docker-compose.yml -f docker-compose.umami.yml up -d +## +## Variables à définir dans .env : +## UMAMI_DB_PASSWORD — mot de passe PostgreSQL Umami (générer avec openssl rand -hex 32) +## UMAMI_APP_SECRET — secret applicatif (générer avec openssl rand -hex 32) +## UMAMI_DOMAIN — ex: stats.librodrome.org + +name: librodrome + +services: + umami: + image: ghcr.io/umami-software/umami:postgresql-latest + environment: + DATABASE_URL: postgresql://umami:${UMAMI_DB_PASSWORD}@umami-db:5432/umami + DATABASE_TYPE: postgresql + APP_SECRET: ${UMAMI_APP_SECRET} + depends_on: + umami-db: + condition: service_healthy + restart: always + labels: + - "traefik.enable=true" + - "traefik.http.routers.umami.rule=Host(`${UMAMI_DOMAIN:-stats.librodrome.org}`)" + - "traefik.http.routers.umami.entrypoints=websecure" + - "traefik.http.routers.umami.tls.certresolver=letsencrypt" + - "traefik.http.services.umami.loadbalancer.server.port=3000" + networks: + - default + - traefik + + umami-db: + image: postgres:15-alpine + environment: + POSTGRES_DB: umami + POSTGRES_USER: umami + POSTGRES_PASSWORD: ${UMAMI_DB_PASSWORD} + volumes: + - umami-db-data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U umami"] + interval: 5s + timeout: 5s + retries: 10 + restart: always + +volumes: + umami-db-data: + +networks: + traefik: + external: true diff --git a/nuxt.config.ts b/nuxt.config.ts index 71d3856..b1ca95a 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -29,6 +29,12 @@ export default defineNuxtConfig({ 'i-lucide-rocket', 'i-lucide-flask-conical', 'i-lucide-arrow-right', // Decision page 'i-lucide-vote', 'i-lucide-scroll-text', 'i-lucide-git-branch', + // sweethomeCloud + territoire + 'i-lucide-home', 'i-lucide-hard-drive', 'i-lucide-video', + 'i-lucide-message-circle', 'i-lucide-bot', 'i-lucide-globe-2', + 'i-lucide-map-pin', 'i-lucide-euro', 'i-lucide-package', + 'i-lucide-settings', 'i-lucide-layout-grid', 'i-lucide-server', + 'i-lucide-chevron-down', 'i-lucide-info', ], }, @@ -56,8 +62,12 @@ export default defineNuxtConfig({ runtimeConfig: { adminPassword: '', adminSecret: '', + umamiApiKey: '', public: { siteUrl: 'https://librodrome.org', + tenantId: 'librodrome', + umamiUrl: '', + umamiWebsiteId: '', }, }, diff --git a/server/api/stats/index.get.ts b/server/api/stats/index.get.ts new file mode 100644 index 0000000..f153b76 --- /dev/null +++ b/server/api/stats/index.get.ts @@ -0,0 +1,43 @@ +/** + * GET /api/stats + * Public stats endpoint — proxies Umami for cross-instance federation / observatoires. + * Each librodrome instance exposes its own metrics here. + * Observatoires call this endpoint on each instance and aggregate. + * + * Env vars required (private, server-side): + * NUXT_UMAMI_API_KEY — Umami API key (read-only) + * NUXT_UMAMI_WEBSITE_ID — Umami website ID (internal, server-side) + * NUXT_PUBLIC_UMAMI_URL — Umami base URL + * NUXT_PUBLIC_TENANT_ID — e.g. "librodrome" or "librodrome-bordeaux" + */ +export default defineEventHandler(async () => { + const config = useRuntimeConfig() + const { umamiApiKey } = config + const { umamiUrl, umamiWebsiteId, tenantId } = config.public + + if (!umamiApiKey || !umamiUrl || !umamiWebsiteId) { + return { tenant: tenantId, configured: false } + } + + const endAt = Date.now() + const startAt = endAt - 30 * 24 * 60 * 60 * 1000 // 30 days + + const [stats, pageviews] = await Promise.all([ + $fetch>(`${umamiUrl}/api/websites/${umamiWebsiteId}/stats`, { + headers: { 'x-umami-api-key': umamiApiKey }, + query: { startAt, endAt }, + }).catch(() => null), + $fetch>(`${umamiUrl}/api/websites/${umamiWebsiteId}/pageviews`, { + headers: { 'x-umami-api-key': umamiApiKey }, + query: { startAt, endAt, unit: 'day', timezone: 'Europe/Paris' }, + }).catch(() => null), + ]) + + return { + tenant: tenantId, + configured: true, + period: '30d', + stats, + pageviews, + } +}) diff --git a/site/pages/home.yml b/site/pages/home.yml index 19209a0..ae27f52 100644 --- a/site/pages/home.yml +++ b/site/pages/home.yml @@ -42,7 +42,7 @@ axes: icon: monitor items: - label: Logiciel libre - description: Maîtriser le code source, c'est maîtriser l'outil. Le logiciel libre est la base de l'autonomie numérique. + description: "Passer à Linux, adopter des équivalents libres, un assistant shell local sans cloud — guide de migration et atelier au prochain Librodrome." to: /numerique/logiciel-libre gestation: true icon: code-2 @@ -50,7 +50,7 @@ axes: title: wishBounty text: Application pour le financement fléché des développements. - label: Authentification — WoT - description: Une toile de confiance décentralisée, sans autorité centrale. Chaque identité est certifiée par ses pairs. + description: "Une clé pour les accès, une signature pour les actes. Le seul système sans autorité centrale ni biométrie — DID W3C, Duniter, EUDI Wallet 2026." to: /numerique/authentification-wot gestation: true icon: share-2 @@ -58,13 +58,13 @@ axes: title: trustWallet text: Gestionnaire de confiances. - label: Cloud libre - description: Héberger ses propres services pour ne dépendre de personne. Serveurs, noms de domaine, infrastructure. + description: "Sortir des datacenters — auto-hébergement, web3, IPFS, local-first. Conformité RGPD et droit à l'oubli." to: /numerique/cloud-libre gestation: true icon: cloud presentation: - title: Bouquet de services - text: "Un bouquet de services complet : Drive, Visio, Forum, Wiki, CMS. IA frugale localisée." + title: sweethomeCloud + text: "Bouquet de services libres auto-hébergés — clé en main." economie: title: Autonomie économique icon: coins diff --git a/site/pages/numerique.yml b/site/pages/numerique.yml index e04daee..4e98e91 100644 --- a/site/pages/numerique.yml +++ b/site/pages/numerique.yml @@ -42,7 +42,7 @@ pillars: Un bouquet de services complet — Drive, Visio, Forum, Wiki, CMS — et demain, une IA frugale localisée. project: - name: Bouquet de services - text: "Drive, Visio, Forum, Wiki, CMS. IA frugale localisée." + name: sweethomeCloud + text: "Bouquet de services libres auto-hébergés — clé en main pour chaque territoire." gestation: true to: /numerique/cloud-libre diff --git a/site/pages/numerique/authentification-wot.yml b/site/pages/numerique/authentification-wot.yml index d3a9393..bd1057c 100644 --- a/site/pages/numerique/authentification-wot.yml +++ b/site/pages/numerique/authentification-wot.yml @@ -1,22 +1,208 @@ meta: - title: Authentification WoT — Autonomie numérique + title: Authentification WoT — Identité numérique décentralisée kicker: Autonomie numérique title: "Authentification — WoT" icon: share-2 -gestation: true description: > - Une toile de confiance décentralisée, sans autorité centrale. - Chaque identité est certifiée par ses pairs — pas par un serveur, - pas par une entreprise. C'est le fondement de la monnaie libre Ğ1 - et de toute gouvernance entre égaux. + Vous avez les outils, vous maîtrisez votre infrastructure. + Reste la pièce manquante : une identité numérique qui n'appartient qu'à vous. + Pas de biométrie, pas d'autorité centrale — une clé, et une toile de confiance. + C'est le seul système qui les évite tous les deux. project: name: trustWallet - text: Gestionnaire de confiances. + text: Gestionnaire de confiances — accès, permissions, DID/UCAN/VC sur clés certifiées Duniter. + gestation: true -content: > - La Web of Trust (toile de confiance) est un mécanisme d'authentification - décentralisé où chaque participant certifie l'identité des autres. - Aucune autorité centrale n'est nécessaire — la confiance émerge du réseau. +sections: + - type: arguments + title: Pourquoi l'authentification actuelle est un problème + items: + - icon: lock + title: Mots de passe + text: > + Stockés côté serveur, volés par millions. Have I Been Pwned recense + des milliards de comptes compromis. Ta sécurité dépend intégralement + de la sécurité d'un tiers que tu ne contrôles pas. + - icon: chrome + title: "Se connecter avec Google" + text: > + Déléguer l'authentification à Google ou Meta, c'est en faire l'infrastructure + d'identité mondiale. Un compte suspendu = toutes tes connexions coupées. + Ces entreprises savent quand, où et à quoi tu te connectes. + - icon: fingerprint + title: Biométrie — irrévocable + text: > + Un mot de passe compromis se change. Une empreinte digitale jamais. + Si tes données biométriques sont volées — et elles l'ont été + (OPM breach USA 2015, 5,6 millions d'empreintes) — la compromission est définitive. + - icon: building-2 + title: Autorités de Certification (X.509) + text: > + HTTPS repose sur ~130 CA mondiales. DigiNotar (2011), Symantec (2015) : + des CA compromises ont permis des attaques sur des millions d'utilisateurs. + La confiance sur le web est centralisée chez Google, Apple et Microsoft. + + - type: fiche + title: Comment fonctionne une Web of Trust + steps: + - n: 1 + title: Générer une paire de clés sur ta machine + text: > + Clé privée (secrète, ne quitte jamais ton appareil) et clé publique + (diffusée librement). Ce qui est signé avec la clé privée peut être + vérifié par n'importe qui avec la clé publique. + tip: "Algorithme recommandé : Ed25519 — clé courte, rapide, sans paramètres douteux" + - n: 2 + title: Publier ta clé publique + text: > + Dans un DID Document, sur un keyserver, dans ton profil Duniter. + N'importe qui peut vérifier tes signatures. Personne ne peut usurper + ton identité sans ta clé privée. + - n: 3 + title: Être certifié par des membres certifiés + text: > + Dans Duniter, 5 membres certifiés (sigQty=5) certifient que tu es une personne réelle, + dans un rayon de 3 sauts du nœud sentinelle (stepMax=3). + La confiance émerge du graphe — pas d'un serveur central. + - n: 4 + title: La confiance se propage dans le graphe + text: > + Plus un nœud est certifié par des membres eux-mêmes bien certifiés, + plus son identité est robuste. Théorie des graphes appliquée à l'identité — + sans juge, sans notaire, sans serveur. + - n: 5 + title: Une clé pour les accès, une signature pour les actes + text: > + La même clé permet de s'authentifier à des services + et de signer des actes (documents, transactions, votes). + Tout ce que tu fais est vérifiable. Rien n'est transmissible à ton insu. + + - type: insight + title: Le seul système sans autorité centrale ni biométrie + icon: shield-check + variant: info + text: > + Toute authentification mainstream dépend d'au moins une entité centrale : + mot de passe (le serveur), OAuth (Google ou Meta), biométrie (le fabricant ou l'État), + HTTPS (les Autorités de Certification). La Web of Trust distribue la confiance + dans le réseau lui-même — structurellement différent. + Les standards W3C (DID 2022, VC 2025) et l'EUDI Wallet européen (fin 2026) + montrent que cette architecture sort des cercles militants + pour entrer dans la politique numérique des États. + points: + - "DID v1.0 : Recommandation W3C finale — juillet 2022" + - "Verifiable Credentials v2.0 : Recommandation W3C finale — mai 2025" + - "eIDAS 2.0 (UE) : wallet d'identité numérique pour chaque citoyen européen avant fin 2026" + - "Duniter/Ğ1 : seule blockchain avec WoT intégrée comme mécanisme de gouvernance du protocole" + + - type: equivalents + title: De l'ancien modèle aux standards décentralisés + categories: + - label: Authentification + items: + - from: Mot de passe + to: "Clé Ed25519 + WebAuthn" + url: https://webauthn.io + note: Signature cryptographique — aucun secret côté serveur + - from: "Se connecter avec Google" + to: SIOPv2 + wallet DID + url: https://openid.net/specs/openid-connect-self-issued-v2-1_0.html + note: "S'authentifier avec son propre wallet, sans compte tiers" + - from: Certificat X.509 + to: "did:web / did:key" + url: https://www.w3.org/TR/did-1.0/ + note: Identifiant décentralisé résolu sans CA centrale + - label: Standards W3C + items: + - from: Registre central d'identités + to: "DID v1.0 (W3C)" + url: https://www.w3.org/TR/did-1.0/ + note: "Recommandation W3C finale — juillet 2022" + - from: Attestation papier ou numérique centralisée + to: "Verifiable Credentials v2.0" + url: https://www.w3.org/TR/vc-data-model-2.0/ + note: "Recommandation W3C finale — mai 2025. Divulgation sélective." + - from: "OAuth / OIDC classique" + to: "OpenID4VP + OpenID4VCI" + url: https://openid.net/specs/openid-4-verifiable-presentations-1_0.html + note: Pont entre wallets DID et services web existants + - label: Implémentations + items: + - from: Monnaie et identité centralisées + to: "Duniter / Ğ1" + url: https://duniter.fr + note: "WoT intégrée au protocole — 5 certifications, rayon 3" + - from: Wallet propriétaire + to: trustWallet + note: "Gestionnaire de confiances — accès, permissions, DID/UCAN/VC sur clés certifiées Duniter (en gestation)" + - from: SSI entreprise + to: "SpruceID / ssi (Rust)" + url: https://spruceid.com + note: Librairie open source pour DID et Verifiable Credentials + + - type: arguments + title: Ce que la WoT rend possible + items: + - icon: log-in + title: Connexion décentralisée + text: > + Via SIOPv2 + OpenID4VP, un wallet d'identité répond aux requêtes + d'authentification de n'importe quel service compatible. + Pas de compte Google. Une clé. Final depuis juillet 2025. + - icon: file-signature + title: Signature légale + text: > + La signature qualifiée (eIDAS QES) a la même valeur juridique + qu'une signature manuscrite dans l'UE. L'EUDI Wallet + inclura la signature qualifiée pour chaque citoyen européen. + - icon: bar-chart-2 + title: Vote vérifiable + text: > + Cryptographie asymétrique et Zero-Knowledge Proofs permettent + un décompte public vérifiable sans révéler le vote individuel. + La vérification est mathématique, pas institutionnelle. + - icon: coins + title: Création monétaire — Ğ1 + text: > + Le cas d'usage le plus radical : l'identité dans la WoT Duniter détermine + l'accès au Dividende Universel. La WoT est un mécanisme de justice économique. + Pas de WoT → pas de co-création monétaire. + - icon: building + title: Services et gouvernance + text: > + Accès aux services publics (eIDAS 2.0), gouvernance de DAOs, + contrats intelligents vérifiables, réseaux de confiance décentralisés. + Une identité → une clé pour tous les accès. + + - type: links + title: Ressources + items: + - label: "W3C DID v1.0" + url: https://www.w3.org/TR/did-1.0/ + desc: "Standard des identifiants décentralisés — Recommandation W3C finale (2022)" + - label: "W3C Verifiable Credentials v2.0" + url: https://www.w3.org/TR/vc-data-model-2.0/ + desc: "Standard des attestations vérifiables — Recommandation W3C finale (mai 2025)" + - label: Duniter + url: https://duniter.fr + desc: "Blockchain WoT pour la monnaie libre Ğ1 — gouvernance par toile de confiance" + - label: trustWallet (en gestation) + desc: "Gestionnaire de confiances — accès, permissions, signatures DID/UCAN/VC sur clés certifiées de la WoT Duniter" + - label: SpruceID + url: https://spruceid.com + desc: Librairie open source Rust pour DID et Verifiable Credentials + - label: "EUDI Wallet (eIDAS 2.0)" + url: https://ec.europa.eu/digital-building-blocks/sites/display/EUDIGITALIDENTITYWALLET/ + desc: "Wallet d'identité numérique européen — déploiement prévu fin 2026" + - label: "OpenID4VP" + url: https://openid.net/specs/openid-4-verifiable-presentations-1_0.html + desc: "Standard final (juillet 2025) — authentification avec wallet DID" + - label: KERI + url: https://keri.one + desc: "Key Event Receipt Infrastructure — identité décentralisée, IETF draft" + - label: SSI Meetup + url: https://www.ssimeetup.org + desc: Webinaires et ressources sur la Self-Sovereign Identity diff --git a/site/pages/numerique/cloud-libre.yml b/site/pages/numerique/cloud-libre.yml index aeb1c08..3add1f5 100644 --- a/site/pages/numerique/cloud-libre.yml +++ b/site/pages/numerique/cloud-libre.yml @@ -1,22 +1,340 @@ meta: - title: Cloud libre — Autonomie numérique + title: Cloud libre — Sortir des datacenters kicker: Autonomie numérique title: Cloud libre icon: cloud -gestation: true description: > - Héberger ses propres services pour ne dépendre de personne. - Serveurs, noms de domaine, infrastructure. - Un bouquet de services complet — Drive, Visio, Forum, Wiki, CMS — - et demain, une IA frugale localisée. + Tes données vivent dans des datacenters dont tu ne connais pas l'adresse, + sous des juridictions que tu ne contrôles pas. Sortir de là est possible — + en trois paliers : auto-hébergement, services fédérés, architectures décentralisées. + Ces dernières émergent à peine. project: - name: Bouquet de services - text: "Drive, Visio, Forum, Wiki, CMS. IA frugale localisée." + name: sweethomeCloud + text: Bouquet de services libres auto-hébergés — clé en main pour chaque bassin de vie. + gestation: true -content: > - L'auto-hébergement est la clé de voûte de l'autonomie numérique. - Il s'agit de maîtriser l'infrastructure sur laquelle reposent nos outils - de communication, de stockage et de collaboration. +sections: + - type: arguments + title: Pourquoi sortir des datacenters ? + items: + - icon: shield + title: RGPD — conformité structurelle + text: > + Google, Amazon, Microsoft stockent tes données sous juridiction américaine (CLOUD Act). + L'auto-hébergement ou un hébergeur associatif européen offre + une conformité RGPD structurelle — pas seulement déclarative. + - icon: eye-off + title: Vie privée des données + text: > + Dans un cloud commercial, tes documents, photos et communications + sont analysés, profilés, monétisés. Ce n'est pas une théorie — + c'est le modèle économique déclaré. + - icon: zap + title: Écologie numérique + text: > + Les datacenters consomment 1 à 2 % de l'électricité mondiale. + Un petit serveur domestique consomme 5 à 10 W. + Héberger chez soi ou mutualiser dans un hébergeur associatif + réduit l'empreinte réelle. + - icon: key + title: Propriété réelle de tes données + text: > + Un service cloud peut fermer, changer ses CGU, couper ton compte. + Tes données te reviennent quand tu les héberges toi-même — + portabilité réelle, pas juste un bouton "Exporter". + - icon: git-branch + title: Résilience décentralisée + text: > + Un réseau de services distribués n'a pas de point de défaillance unique. + Un nœud fermé, les autres continuent. + C'est l'architecture d'Internet telle qu'elle avait été conçue. + + - type: tiers + title: Trois niveaux d'architecture libre + tiers: + - level: Niveau 1 + title: Auto-hébergement + icon: server + badge: Maîtrise totale + text: > + Ton propre serveur chez toi ou chez un hébergeur associatif. + Contrôle absolu, RGPD pleinement compatible. + YunoHost installe plus de 200 applications libres en un clic. + tools: + - "Nextcloud — fichiers, agenda, contacts, visio" + - "YunoHost — auto-hébergement simplifié" + - "Syncthing — sync pair-à-pair sans serveur" + - "FreedomBox — serveur domestique clé-en-main" + - level: Niveau 2 + title: Services fédérés + icon: share-2 + badge: Interconnecté + text: > + Des instances indépendantes interconnectées via des protocoles ouverts + (ActivityPub, Matrix). Tu rejoins un serveur de confiance + ou héberges le tien. Les données restent chez l'opérateur choisi. + tools: + - "Mastodon — réseau social fédéré" + - "PeerTube — vidéo hébergée et fédérée" + - "Matrix + Element — messagerie décentralisée" + - "Pixelfed — galerie photo fédérée" + - "Funkwhale — musique fédérée" + - level: Niveau 3 + title: Architectures décentralisées + icon: globe-2 + badge: Émergent + text: > + Pas de serveur central, pas d'opérateur unique. Les fichiers sont + fragmentés, chiffrés côté client, distribués sur des nœuds indépendants mondiaux. + Ces architectures émergent à peine — prometteuses, pas encore grand public. + tools: + - "IPFS — protocole pair-à-pair (ipfs.tech)" + - "Filecoin — marché de stockage sur IPFS" + - "Storj — stockage distribué chiffré côté client" + - "Sia — stockage décentralisé (Sia Foundation)" + - "Arweave — stockage permanent (modèle endowment)" + + - type: equivalents + title: Vos services cloud — en version libre + categories: + - label: "Fichiers & synchronisation" + items: + - from: "Google Drive / Dropbox" + to: Nextcloud + url: https://nextcloud.com/fr + note: "Fichiers, agenda, contacts, photos, visio — auto-hébergeable" + - from: Dropbox + to: Syncthing + url: https://syncthing.net + note: "Sync pair-à-pair chiffré, sans serveur central" + - from: "Dropbox / Box" + to: Storj + url: https://storj.io + note: Stockage distribué chiffré côté client + - label: "Email & calendrier" + items: + - from: "Gmail / Outlook" + to: Proton Mail + url: https://proton.me/fr/mail + note: "Chiffrement bout-en-bout, hébergé en Suisse" + - from: Google Calendar + to: Nextcloud Calendar + url: https://nextcloud.com/fr + note: "CalDAV standard, auto-hébergeable" + - label: "Vidéo & média" + items: + - from: YouTube + to: PeerTube + url: https://joinpeertube.org + note: "Hébergement vidéo fédéré — choisir son instance" + - from: Google Photos + to: Nextcloud Photos + url: https://nextcloud.com/fr + note: Galerie auto-hébergée + - label: Réseaux sociaux + items: + - from: "Twitter / X" + to: Mastodon + url: https://joinmastodon.org + note: "Réseau social fédéré — 30 M+ comptes" + - from: Instagram + to: Pixelfed + url: https://pixelfed.org + note: Galerie photo fédérée + - from: "Slack / Teams" + to: "Matrix + Element" + url: https://element.io + note: Messagerie décentralisée et fédérée + - label: Auto-hébergement facile + items: + - from: Pas de serveur + to: YunoHost + url: https://yunohost.org + note: "Installe 200+ apps libres en un clic (Debian)" + - from: Infrastructure cloud + to: FreedomBox + url: https://freedombox.org + note: Serveur domestique clé-en-main (projet Debian) + - from: Node Web3 + to: Umbrel + url: https://umbrel.com + note: "App store décentralisé, nœud Bitcoin/Lightning" + + - type: insight + title: RGPD et droit à l'oubli — une tension structurelle + icon: scale + variant: warning + text: > + Le droit à l'oubli (RGPD art. 17) exige l'effacement des données personnelles sur demande. + Les architectures décentralisées y résistent structurellement : + une blockchain est un registre immuable répliqué sur tous les nœuds, + IPFS conserve les données tant qu'un seul nœud les héberge. + C'est une tension réelle, non résolue, que le législateur européen commence à instruire + (lignes directrices CEPD 02/2025). + points: + - "Auto-hébergement : conformité RGPD totale — tu effaces ce que tu veux" + - "Services fédérés : dépend de l'opérateur de l'instance — choisir un hébergeur CHATONS" + - "IPFS / blockchain : chiffrer + détruire la clé (la donnée devient inintelligible). Accepté par la CNIL sous conditions strictes." + - "Off-chain data : stocker uniquement un hash sur la chaîne, les données personnelles sur un serveur effaçable — approche la plus propre" + - "Référence officielle : guide CNIL blockchain et RGPD + lignes directrices CEPD 02/2025" + + - type: projet + title: sweethomeCloud + kicker: Prochain projet + icon: home + badge: En gestation + text: > + Un bouquet de services libres, auto-hébergés et prêts à l'emploi — + pour les collectivités, associations et collectifs qui veulent + maîtriser leur infrastructure numérique sans expertise technique. + sweethomeCloud s'appuie sur les briques documentées dans cette page : + Nextcloud, Matrix, Jitsi, YunoHost, Ollama — packagées, maintenues, + documentées ensemble. Une instance par territoire. + features: + - icon: hard-drive + label: "Drive, agenda, contacts — Nextcloud" + - icon: video + label: "Visioconférence — Jitsi / Galène" + - icon: message-circle + label: "Messagerie chiffrée souveraine" + - icon: bot + label: "IA locale — Ollama, aucune donnée ne sort" + - icon: globe-2 + label: "CMS, forum, wiki, sites web" + - icon: shield + label: "Décentralisé local-first — votre territoire, vos données" + + - type: territoire + title: Autonomie des bassins de vie + icon: map-pin + text: > + Un bassin de vie de 50 000 personnes peut déployer et maintenir son propre réseau + numérique souverain. Le matériel est accessible, les logiciels libres sont matures. + sweethomeCloud sera ce bouquet — packagé, documenté, maintenu ensemble. + Deux modèles économiques, au choix. + economies: + - label: "Euro non vénale" + desc: "Portage associatif ou coopératif — contribution libre, cotisation symbolique, financement public" + icon: euro + - label: "Monnaie libre Ğ1 — à 100%" + desc: "Services financés exclusivement en Ğ1, co-créée par les membres du territoire. Aligné avec l'économie du don." + icon: coins + bouquet: + title: "Le bouquet sweethomeCloud" + categories: + - label: Collaboration quotidienne + icon: users + items: + - "Drive, agenda, contacts, photos — Nextcloud" + - "Visioconférence — Jitsi / Galène" + - "Messagerie chiffrée souveraine" + - "Email hébergé — Postfix + Dovecot" + - label: "Web & publication" + icon: globe-2 + items: + - "CMS — WordUp" + - "Forum" + - "Wiki" + - "Sites web, pages publiques" + - label: "Infrastructure technique" + icon: settings + items: + - "Git — Forgejo" + - "Automatisation — n8n" + - "Mailer transactionnel — Postal" + - "DNS souverain" + - label: "Souveraineté protocole" + icon: shield + items: + - "Nœud Duniter — Ğ1" + - "Stockage IPFS" + - "Miroirs logiciels libres" + - label: "Intelligence artificielle locale" + icon: bot + items: + - "LLM généraliste en file — Ollama + Llama 8B" + - "LLM lourd sur demande — Llama 70B" + - "IA code — Codestral / DeepSeek" + - "Aucune donnée ne sort du territoire" + - label: "Applications du territoire" + icon: layout-grid + items: + - "librodrome — économie & autonomie" + - "libreDecision — décision collective" + - "Applications métier à venir" + estimate: + toggle: "Estimation matérielle pour 50 000 personnes" + note: > + Basé sur 5% d'utilisation simultanée au pic (2 500 connectés), + 20 Go de stockage par habitant (taux d'occupation réel 30%), + matériel reconditionné. Hypothèses conservatives et vérifiées. + hardware: + - role: "Serveurs principaux" + detail: "4× reconditionné — 2× Xeon 16 cœurs, 128 Go RAM, SSD NVMe" + usage: "Nextcloud, mail, forum, wiki, git, n8n, CMS, apps, Matrix" + cost: "10 000 – 14 000 €" + note: "Dell PowerEdge R740 / HPE DL380 Gen10 reconditionné" + - role: "Stockage NAS" + detail: "24× HDD 10 To RAID6 → 160 To utilisables" + usage: "Drive (100 To), email (40 To), IPFS cache, backups" + cost: "5 000 – 7 000 €" + note: "~20 Go/habitant, occupation réelle ~30% — largement suffisant au démarrage" + - role: "Visioconférence" + detail: "3× serveur 8 cœurs / 32 Go — load balancé (Jitsi Octo)" + usage: "250 participants simultanés — 75-100 max par nœud Jitsi" + cost: "6 000 – 9 000 €" + note: "1 seul serveur Jitsi ne peut pas dépasser 100 participants — chiffre vérifié" + - role: "IA légère — Llama 8B" + detail: "4× PC gamer avec RTX 4090 24 Go VRAM" + usage: "Ollama — Q&A, résumé, assistance — 1 requête simultanée/GPU" + cost: "8 000 – 10 000 €" + note: "Llama 3.1 8B Q4 : 6-8 Go VRAM, 100-150 tokens/s par RTX 4090" + - role: "IA lourde — Llama 70B" + detail: "1× serveur avec 2× RTX 4090 (48 Go VRAM cumulés)" + usage: "Llama 3.1 70B Q4 (42 Go VRAM min), IA code, analyse longue" + cost: "5 000 – 8 000 €" + note: "Le modèle est splitté sur 2 GPU — seule option abordable sans datacenter" + - role: "Réseau & DNS" + detail: "Fibre pro 1 Gbps symétrique + switch 10 Gbps + 2× mini-PC DNS" + usage: "Tous services, DNS souverain redondant (BIND9)" + cost: "2 000 € + 300 €/mois fibre" + note: "Le DNS est la pièce la plus critique — la redondance est obligatoire" + totals: + invest: "36 000 – 48 000 €" + annual: "8 000 – 12 000 €/an" + per_person: "~2 €/an par habitant" + note: "Moins cher qu'un café — pour une infrastructure numérique complète et souveraine." + + - type: links + title: Ressources + items: + - label: YunoHost + url: https://yunohost.org + desc: Auto-hébergement simplifié — installe 200+ apps libres en un clic + - label: CHATONS + url: https://www.chatons.org + desc: "96+ hébergeurs alternatifs éthiques et décentralisés (initié par Framasoft)" + - label: Nextcloud + url: https://nextcloud.com/fr + desc: Suite collaborative auto-hébergeable de référence + - label: Dégooglisons Internet + url: https://degooglisons-internet.org + desc: Alternatives libres aux services Google — par Framasoft + - label: IPFS + url: https://ipfs.tech + desc: Protocole de stockage pair-à-pair décentralisé + - label: Storj + url: https://storj.io + desc: Stockage distribué chiffré côté client + - label: Sia + url: https://sia.tech + desc: "Stockage décentralisé — Sia Foundation (non-profit, très actif)" + - label: CNIL — Blockchain et RGPD + url: https://www.cnil.fr/fr/blockchain-et-rgpd-quelles-solutions-pour-un-usage-responsable-en-presence-de-donnees-personnelles + desc: Guide officiel sur les enjeux RGPD des architectures décentralisées + - label: Switching.software + url: https://switching.software + desc: Annuaire d'alternatives éthiques aux logiciels propriétaires diff --git a/site/pages/numerique/logiciel-libre.yml b/site/pages/numerique/logiciel-libre.yml index d8d81cb..32e6a1e 100644 --- a/site/pages/numerique/logiciel-libre.yml +++ b/site/pages/numerique/logiciel-libre.yml @@ -1,23 +1,243 @@ meta: - title: Logiciel libre — Autonomie numérique + title: Logiciel libre — Migrer sur Linux kicker: Autonomie numérique title: Logiciel libre icon: code-2 -gestation: true description: > - Le logiciel libre n'est pas qu'une question technique. - C'est la condition d'existence d'outils qui nous appartiennent — - que l'on peut auditer, modifier, partager. - Sans logiciel libre, toute promesse de souveraineté numérique est creuse. + Passer à Linux, adopter LibreOffice, Signal, Nextcloud. + Un guide concret d'équivalents libres, une fiche de migration + étape par étape — et un atelier au prochain Librodrome. project: name: wishBounty text: Application pour le financement fléché des développements libres. + gestation: true -content: > - Le logiciel libre garantit quatre libertés fondamentales : utiliser, étudier, - modifier et redistribuer. Ces libertés sont le socle de toute autonomie numérique. - Sans elles, nous sommes dépendants d'éditeurs qui peuvent à tout moment modifier - les règles du jeu. +sections: + - type: arguments + title: Pourquoi migrer ? + items: + - icon: shield + title: Vie privée + text: > + Windows et macOS collectent vos données en permanence, sans possibilité + de désactiver entièrement la télémétrie. Linux ne le fait pas par défaut — + tout le code est auditable. + - icon: coins + title: "Coût réel : 0 €" + text: > + Windows 11 coûte 145 €, Office 365 70 €/an. + Linux + LibreOffice sont gratuits. Sur 5 ans pour une association, + l'écart devient un argument décisif. + - icon: recycle + title: Durabilité matérielle + text: > + Linux redonne 5 à 10 ans de vie à des machines abandonnées par Windows 11 + (qui exige TPM 2.0). Moins de déchets électroniques — argument écologique concret. + - icon: users + title: Bien commun + text: > + Le logiciel libre est un commun numérique. Tu n'es pas client, tu participes. + Cohérent avec l'économie du don — l'argent économisé sur les licences + peut financer des communs. + - icon: lock-open + title: Indépendance réelle + text: > + Pas de mise à jour forcée qui casse le système. Pas d'abonnement qui expire + et verrouille tes fichiers. Ton OS t'appartient vraiment. + - icon: bot + title: Assistance permanente gratuite + text: > + Un LLM open source installé localement (Ollama + phi3:mini, 4 Go de RAM) + peut rédiger les commandes shell dans ton terminal sur simple demande en français. + Sans connexion à aucun serveur. Sans abonnement. Sans envoyer tes données. + + - type: fiche + title: "Fiche de migration — 6 étapes" + steps: + - n: 1 + title: Sauvegarder ses données + text: > + Copie documents, photos, mails sur un disque externe ou clé USB. + Ne commence rien sans ça. + - n: 2 + title: Tester sans risque — Live USB + text: > + Démarre Linux Mint depuis une clé USB. Tu explores, tu testes LibreOffice, + tu vérifies le WiFi — sans toucher à ton Windows existant. + tip: "Créer la clé : balenaEtcher (gratuit) + image Linux Mint sur linuxmint.com" + - n: 3 + title: Choisir sa distribution + text: > + Linux Mint Cinnamon pour migrer depuis Windows (interface familière). + Ubuntu pour un maximum de ressources en ligne. + Les deux sont excellents pour démarrer. + - n: 4 + title: Installer — double-boot ou remplacement + text: > + Double-boot si tu veux garder Windows le temps de la transition. + Remplacement complet quand tu es prêt·e — c'est le vrai départ. + - n: 5 + title: Installer ses équivalents libres + text: > + LibreOffice est déjà là. Ajoute Thunderbird, VLC, GIMP, Signal Desktop + via le gestionnaire de paquets en un clic — pas de téléchargement manuel. + - n: 6 + title: Rejoindre une communauté + text: > + Forum ubuntu-fr.org, groupe local, ou atelier Librodrome. + Les questions trouvent toujours réponse. + + - type: equivalents + title: Vos logiciels propriétaires — en version libre + categories: + - label: Bureautique + items: + - from: Microsoft Office + to: LibreOffice + url: https://fr.libreoffice.org + note: Suite complète gratuite multiplateforme + - from: Microsoft Office + to: OnlyOffice + url: https://www.onlyoffice.com/fr + note: "Meilleure compat .docx/.xlsx" + - label: "Photo & graphisme" + items: + - from: Photoshop + to: GIMP + url: https://www.gimp.org + note: Retouche et manipulation d'images + - from: "Photoshop / Affinity" + to: Krita + url: https://krita.org/fr + note: Peinture numérique et illustration + - from: Lightroom + to: Darktable + url: https://www.darktable.org + note: Développement photo RAW + - from: Illustrator + to: Inkscape + url: https://inkscape.org/fr + note: Dessin vectoriel SVG + - from: Figma + to: Penpot + url: https://penpot.app + note: "Design UI/UX, auto-hébergeable" + - label: "Email & messagerie" + items: + - from: Outlook + to: Thunderbird + url: https://www.thunderbird.net/fr + note: Client mail desktop complet + - from: WhatsApp + to: Session + url: https://getsession.org + note: "Pas de numéro de téléphone, réseau Oxen décentralisé" + - from: "Slack / Teams" + to: "Element (Matrix)" + url: https://element.io + note: Protocole décentralisé et fédéré + - from: "Zoom / Teams" + to: Jitsi Meet + url: https://meet.jit.si + note: Visio sans compte requis + - label: "Navigateur & stockage" + items: + - from: Chrome + to: Firefox + url: https://www.mozilla.org/fr/firefox + note: Standard libre de référence + - from: Chrome + to: Librewolf + url: https://librewolf.net + note: Firefox durci pour la vie privée + - from: "Dropbox / Drive" + to: Nextcloud + url: https://nextcloud.com/fr + note: "Fichiers, agenda, contacts — auto-hébergeable" + - from: Dropbox + to: Syncthing + url: https://syncthing.net + note: "Sync pair-à-pair, sans serveur central" + - label: Développement + items: + - from: VSCode + to: VSCodium + url: https://vscodium.com + note: VSCode sans télémétrie Microsoft + - from: Spotify + to: Navidrome + url: https://www.navidrome.org + note: Serveur musique auto-hébergé + + - type: llm + title: Un assistant shell local — sans cloud + text: > + Un petit LLM open source sur ta machine répond à tes questions sur les commandes Linux + en langage naturel, sans envoyer aucune donnée à un serveur distant. + Il suggère. Toi tu décides. + tool: Ollama + tool_url: https://ollama.com + model: "phi3:mini" + ram: "4 Go de RAM suffisent" + commands: + - "curl -fsSL https://ollama.com/install.sh | sh" + - "ollama pull phi3:mini" + - "ollama run phi3:mini \"Comment trouver les fichiers modifiés depuis 7 jours ?\"" + rules: + - Lis chaque commande avant de l'exécuter — le LLM suggère, tu valides + - "Utilise --dry-run ou -n quand disponible (rsync, make…)" + - Pour les commandes root/sudo, vérification manuelle obligatoire + - "Préfère phi3:mini ou qwen2.5-coder — pas les modèles uncensored" + + - type: atelier + title: Atelier migration — prochain Librodrome + text: > + Une demi-journée pour passer à Linux en douceur, en groupe. + Chaque participant repart avec une clé USB Linux Mint bootable + et un plan de migration personnalisé. + format: "Demi-journée — 6 à 12 participants" + programme: + - icon: usb + label: Live USB — tester Linux sans risque sur sa propre machine + - icon: list + label: "Équivalents logiciels — chacun fait son inventaire personnel" + - icon: hard-drive + label: Installation guidée sur machine volontaire + - icon: package + label: "Gestionnaire de paquets — installer ce dont on a besoin" + - icon: users + label: Questions ouvertes et suivi post-atelier + + - type: links + title: Ressources + items: + - label: Framalibre + url: https://framalibre.org + desc: "Annuaire du logiciel libre — plus de 1000 logiciels référencés" + - label: Framasoft + url: https://framasoft.org/fr/ + desc: Écosystème et alternatives éthiques au numérique centralisé + - label: Soyez résolus + url: https://soyezresolu.org/ + desc: Guide pratique pour libérer les usages numériques (associations) + - label: Guide d'installation Linux Mint + url: https://linuxmint-installation-guide.readthedocs.io/en/latest/ + desc: Guide officiel Linux Mint + - label: Documentation Ubuntu francophone + url: https://doc.ubuntu-fr.org/debutant + desc: Guide débutant Ubuntu en français + - label: Forum ubuntu-fr + url: https://forum.ubuntu-fr.org + desc: Communauté d'entraide Linux en français + - label: April + url: https://www.april.org + desc: Association pour la promotion du logiciel libre depuis 1996 + - label: Ollama + url: https://ollama.com + desc: Installer et gérer des LLMs locaux open source + - label: Librezo + url: https://librezo.fr + desc: Collectif d'artisans numériques travaillant exclusivement en logiciel libre