• HTML 80.9%
  • Astro 14%
  • TypeScript 2.1%
  • CSS 1.8%
  • JavaScript 0.5%
  • Other 0.7%
Find a file
morgan e209945cdd
All checks were successful
Build and push / changes (push) Successful in 3s
Build and push / check (push) Successful in 26s
Build and push / build (push) Successful in 1m22s
Build and push / notify-komodo (push) Successful in 2s
content: fiche « Le sommeil » (Corps 03, reviewed)
Fiche 03 du parcours Le Corps (La maintenance). Architecture en cycles (visuel hypnogramme SVG inline), les 4 voleurs de récupération, 7-9 h + régularité comme levier n°1, ce qui abîme/améliore une nuit sans gadget, frontière médicale (quand consulter), 3 notes débattues (glymphatique, avant minuit, courbe en U). Passée par la gate secrétaire de rédaction (R1 PASS). Feuille rangée sous docs/recherche/corps/.
2026-06-24 23:38:33 +02:00
.claude/skills/secretaire-redaction skill(secretaire-redaction): sharpen the trigger description 2026-06-24 18:02:12 +02:00
.forgejo/workflows
docker feat(visuels): build-time diagram/chart/math/figure pipeline + template 2026-06-24 18:27:20 +02:00
docs content: fiche « Le sommeil » (Corps 03, reviewed) 2026-06-24 23:38:33 +02:00
web content: fiche « Le sommeil » (Corps 03, reviewed) 2026-06-24 23:38:33 +02:00
.gitignore
compose.yaml
justfile
LICENSE
README.md
Welcome to Life.html

Bienvenue dans la vie

A free, volunteer, French knowledge hub for young adults: the plain, sourced explanations of adult-life essentials that nobody hands you.

« La vie ne livre pas de mode d'emploi. Nous, si. »

Three pillars, Le Corps (body), L'Argent (money), Le Monde (world). Each topic is a fiche: a short, calibrated, sourced synthesis of one question or mental model.

Look and language. French only, served at /. Single light "riso zine" theme: warm paper, Bricolage / Hanken / Spline type, orange and teal accents. The repository, image and Komodo stack keep the slug welcome-to-life; documentation and tooling are in English.

Editorial source of truth (read before writing content):

  • Brand brief: docs/brand.md. Idea, audience, pillars, voice.
  • Editorial line: docs/editorial.md. Epistemics, tone, fiche architecture, vocabulary.
  • Research project: docs/recherche/. The Claude Project setup (brief.md) and the fiche template (fiche-modele.md) that turn a topic into a sourced knowledge sheet before a fiche is written.

Contents

Stack

Concern Choice
Framework Astro, plain, custom full-page layout (no Starlight)
Runtime Bun
Fonts Self-hosted (Bricolage Grotesque display, Hanken Grotesk body, Spline Sans Mono labels)
Search Pagefind, standalone post-build index over dist
Output Static HTML
Runtime img Rootless nginx-unprivileged
CI/CD Forgejo Actions, container registry, Komodo
Proxy Pangolin (TLS and routing, external pangolin network)

Project layout

.
├── web/                       # the Astro site (all app code)
│   ├── astro.config.mjs       # plain Astro, no Starlight, FR-only (served at /)
│   ├── src/
│   │   ├── content.config.ts  # `articles` collection + extended trust schema
│   │   ├── content/articles/  # the fiches (FR), entry id = pillar/slug
│   │   ├── layouts/           # Page (site shell), Prose (styleguide), Legal
│   │   ├── pages/             # home, [pillar], [pillar]/[slug], notre-methode,
│   │   │                      #   recherche, mentions-legales, confidentialite, template
│   │   ├── components/        # nav, hero, seal, ticker, pillar grid, ArticleView, sources
│   │   ├── lib/               # pillars.ts, schema.ts, trust.ts (+ unit tests)
│   │   └── styles/theme.css   # riso design tokens, fonts, per-pillar accents
│   └── scripts/make-stubs.ts  # generator for placeholder fiches
├── docs/
│   ├── brand.md               # brand brief (idea, audience, voice)
│   ├── editorial.md           # editorial line (epistemics, tone, fiche architecture)
│   ├── recherche/             # research project: brief.md, fiche-modele.md, sheets
│   └── superpowers/           # historical design specs and plans (archive)
├── docker/
│   ├── Dockerfile             # multi-stage: Bun build, then rootless nginx
│   ├── Dockerfile.dockerignore
│   └── nginx.conf             # security headers, CSP, healthz, caching
├── compose.yaml              # deploy unit (kept at root; Komodo expects it here)
├── justfile                  # dev / build / docker recipes
└── .forgejo/workflows/build.yml   # CI pipeline

Develop

Easiest path: just (run just with no argument to list every recipe).

just install       # install dependencies
just dev           # dev server (http://localhost:4321)
just build         # static build (web/dist)
just lint          # format check + types + the no-em-dash house rule (read-only)
just check         # lint + tests (local gate)
just clean         # remove dist/.astro/node_modules

just docker-build  # build the image
just docker-run    # build + run the image detached (http://localhost:8080)
just docker-logs   # follow the running container's logs
just docker-clean  # remove the local container + image

Without just, the equivalent commands live in the justfile (all cd web && bun ...).

Content and trust model

The reader-facing unit is a fiche: a short, calibrated synthesis of one question or mental model. Fiches live in web/src/content/articles/{corps,argent,monde}/. The Astro collection is named articles internally; the word "article" never appears on screen. Each entry id is pillar/slug, rendered by the [pillar]/[slug] route through ArticleView.

Because the content is AI-assisted, credibility is an explicit, visible system, and the trust signals are deliberately modest (the schema lives in src/lib/schema.ts, the logic in src/lib/trust.ts, both unit-tested):

  • Status (status: draft | reviewed). Drafts show an « En rédaction » pill. There is no "human-reviewed" claim: it would promise more than a solo, non-expert process can back.
  • Freshness (lastReviewed). Shown as « Mis à jour le ... ». A fiche can age, and the date says when it was last touched.
  • Evidence strength (confiance: solide | debattu | incertain). A coloured badge for the central claim. It is the author's read of the evidence, not an expert validation.
  • Sources (typed study | official | press | book, Zod-validated). Rendered as a Sources block. No source is ever invented.

The « Comment on vérifie » page (/notre-methode/) states the method and its honest limits in public. docs/editorial.md holds the full editorial line, and docs/recherche/ the workflow that turns a topic into vetted sources before a fiche is written.

How deployment works

  git push (main)
        │
        ▼
┌──────────────────────────────────────────────────────────────┐
│ Forgejo Actions  (.forgejo/workflows/build.yml)              │
│                                                              │
│  changes ──► check ──► build ──► notify-komodo               │
│  (diff)     (lint/    (buildx    (signed webhook)            │
│             test)      push)                                 │
└───────┬───────────────────┬──────────────────┬──────────────┘
        │                   │                  │
        │            push image to       POST signed webhook
        │            container registry   (HMAC-SHA256)
        │                   │                  │
        ▼                   ▼                  ▼
   (skips build      git.libresoftware    Pangolin ──► Komodo
    if only           .cloud/morgan/       (Basic auth)  │
    compose.yaml      welcome-to-life                    │ pull :latest
    changed)          :latest + :<sha>                   ▼ + recreate
                                                    compose.yaml
                                                    (rootless nginx,
                                                     pangolin network)
  1. Push to main triggers the pipeline.
  2. CI runs checks, builds the image, and pushes it to the Forgejo container registry.
  3. CI notifies Komodo with a signed HTTP webhook.
  4. Komodo pulls the new :latest image and recreates the container from compose.yaml.
  5. Pangolin (reverse proxy on the external pangolin network) terminates TLS and routes public traffic to the container's port 8080.

CI pipeline

.forgejo/workflows/build.yml runs on push to main (and workflow_dispatch). It is path-aware, to avoid rebuilding when only the deploy unit changes:

Job Runs when Does
changes always Diffs the push; sets code (web/ docker/ workflows) and compose.
check code == true bun install, bun test, bun run format:check, bun astro check.
build code == true Buildx build of docker/Dockerfile, push :latest + :<short-sha>, registry build cache.
notify-komodo build succeeded or compose-only change Sends the signed redeploy webhook (see below).

A compose-only change (editing compose.yaml) skips check and build and still triggers notify-komodo, so deploy-config tweaks redeploy without an image rebuild.

Komodo redeploy (webhook)

The notify-komodo job POSTs a small JSON body to a Komodo listener that sits behind Pangolin. Two layers of authentication are involved:

curl -u "$KOMODO_BASIC_AUTH"  \                         # 1. Pangolin Basic auth
     -H "X-Hub-Signature-256: sha256=<HMAC>"  \         # 2. Komodo HMAC check
     -H "Content-Type: application/json"  \
     -d '{"ref":"refs/heads/main","trigger":"forgejo-actions"}'  \
     "$KOMODO_WEBHOOK_URL"                               # URL ends in /main
  1. Pangolin Basic auth. Pangolin gates the webhook URL behind HTTP Basic auth. The user:password is sent via curl -u. With Pangolin's "Extended compatibility" enabled, it forwards the Authorization header to Komodo, which ignores it.
  2. Komodo HMAC verification. Komodo runs a GitHub-style listener. It reads ref from the body, strips refs/heads/, and compares it against the trailing URL segment (/main). The request must carry X-Hub-Signature-256: sha256=<hex>, where <hex> is the HMAC-SHA256 of the exact request body keyed with the listener's secret. The CI computes it with openssl dgst -sha256 -hmac "$KOMODO_WEBHOOK_SECRET".

On a valid call, Komodo's Stack for this repo pulls the new :latest image and recreates the service defined in compose.yaml.

Komodo side (configured once, outside this repo): a Stack pointing at this repo's compose.yaml, a webhook listener whose secret matches KOMODO_WEBHOOK_SECRET, and a URL ending in /main. The container joins the external pangolin network so Pangolin can route to it.

Configuration: repo variables and secrets

Set these in Forgejo: Repository, Settings, Actions, Variables / Secrets. Variables are plain text; secrets are masked in logs.

Name Kind Used by Purpose
SITE_URL Variable build Canonical site URL baked into the build (site: in astro.config.mjs, for sitemap, canonical, SEO).
KOMODO_WEBHOOK_URL Variable notify-komodo Komodo listener endpoint (behind Pangolin). Must end in /main.
REGISTRY_TOKEN Secret build Forgejo token for ${{ github.actor }} to log in and push packages to git.libresoftware.cloud. Package-write.
KOMODO_WEBHOOK_SECRET Secret notify-komodo HMAC-SHA256 key; must match the secret configured on the Komodo listener.
KOMODO_BASIC_AUTH Secret notify-komodo user:password for Pangolin's HTTP Basic auth in front of the Komodo URL.

Provided automatically by Forgejo Actions (no setup): github.actor (the pusher, used as the registry username), github.sha, github.ref, github.repository, github.server_url.

Runner requirements

The workflow targets runs-on: docker (a Forgejo Actions runner labelled docker). The build job uses Buildx against a Docker-in-Docker service reachable at tcp://docker:2376 with TLS certs under /certs/client, so make sure the runner provides a DinD service (the standard Forgejo docker-runner-with-DinD setup).

Run it locally with Docker

compose.yaml targets production (it pulls the registry image and joins the external pangolin network), so for a local smoke test, build and run the image directly:

just docker-run        # builds docker/Dockerfile, runs detached on http://localhost:8080
curl -fsS http://localhost:8080/healthz   # health check, prints "ok"
just docker-clean      # remove the local container and image