Skip to content

V41 — le site dit ce qu'il est : docs indexables, vrai 404, accueil à jour, CHANGELOG extrait du plan - #73

Merged
dapiced merged 6 commits into
mainfrom
dapiced-labml-improvement-proposals
Sep 29, 2026
Merged

dapiced merged 6 commits into
mainfrom
dapiced-labml-improvement-proposals

Conversation

@dapiced

@dapiced dapiced commented Sep 29, 2026

Copy link
Copy Markdown
Owner

Pourquoi

Analyse du dépôt et du site en production (29/09/2026, curl). Rien à redire au labo lui-même ; en revanche, ce que le site déclare de lui-même ne correspondait plus à ce qu'il est :

  • Les 12 pages /docs/<slug> annoncées par le sitemap étaient servies par le fallback racine : titre et Open Graph de l'accueil, canonical pointant vers /, <div id="root"> vide. Pour un moteur de recherche, douze doublons de l'accueil ; pour un lien de tutoriel partagé, l'aperçu de la mauvaise page.
  • La description de l'accueil commençait au milieu d'une phrase (« entirely in your browser. Drop a dataset… »).
  • Toute URL inconnue répondait 200. wrangler pages dev révèle que la seule règle de _redirects (/* /index.html 200) était invalide et ignorée par Pages ; le 200 venait du fallback SPA par défaut.
  • L'accueil était la seule section peinte blanche avant JavaScript, et sa carte « Build status » parlait encore de « trois modules » — texte de V22.
  • Le journal existe (PLAN.md, 195 Ko) mais rien de lisible n'en sort ; package.json était à 1.0.0.

Ce que fait la PR

# Changement Vérifié par
A1 Une coquille prérendue par page de doc (dist/docs/<slug>.html, article compilé, titre, résumé, canonical propre) shells.spec.ts : chaque URL du sitemap répond avec sa canonical, un titre unique et un <h1> sans JavaScript
A2 Description de l'accueil complète idem
A3 Vrai 404.html, shell.html nu (noindex) pour les routes dynamiques, _redirects limité aux quatre routes sans fichier propre, fallback du service worker sur shell.html, héros de l'accueil dans index.html redirects.test.ts (dérive la liste attendue de router.tsx) ; nouveau projet Playwright pages qui rejoue routing.spec.ts contre wrangler pages dev — le seul serveur qui applique _redirects, _headers et 404.html comme la prod
A4 Carte « Quoi de neuf » : état actuel des cinq espaces, dernière vague lue depuis la version du build, lien vers le CHANGELOG HomePage.test.tsx
A5 Le « PS » sur la taille des fichiers quitte le lede de /ml pour la zone de dépôt ; doublon LIMITATION retiré du README —
B4 CHANGELOG.md extrait de PLAN.md (npm run changelog, 37 vagues), package.json aligné sur 1.<vague>.0 changelog.test.ts : comparaison octet par octet, version épinglée à la dernière vague

Détails et mesures dans la ligne V41 de PLAN.md §N.

Ce que la relecture a rattrapé

Une relecture indépendante de la branche a trouvé deux points importants, corrigés dans le dernier commit :

  • La ligne V32 de PLAN.md contenait un | non échappé dans du code inline ; le générateur lisait quatre cellules et publiait un fragment du contenu comme raison de la vague. Le pipe est échappé, et le générateur refuse désormais toute ligne de vague à plus de trois cellules ou au statut inconnu, plutôt que de la sauter en silence.
  • Le test de comparaison du CHANGELOG échouait sur un checkout Windows frais (CRLF). Les deux côtés sont normalisés.

Plus quelques énoncés remis d'aplomb : l'ordre réel de Pages (les règles avant les fichiers — une règle ne doit jamais recouvrir un fichier existant), l'eyebrow des coquilles aligné sur le composant <Eyebrow> (il était cuivre depuis V9 et repeint en teal au montage), les compteurs du README.

À vérifier sur la preview avant de fusionner

curl -sI https://dapiced-labml-improvement-proposals.labml.pages.dev/nope | head -1              # 404
curl -sI https://dapiced-labml-improvement-proposals.labml.pages.dev/ml/share | head -1          # 200
curl -s  https://dapiced-labml-improvement-proposals.labml.pages.dev/docs/premier-modele | grep canonical
curl -sI https://dapiced-labml-improvement-proposals.labml.pages.dev/shell.html | head -1        # 308

Mesures

817 tests unitaires (+29), 122 e2e (+11, dont le projet pages), build et Lighthouse inchangés. Précache du service worker : 97 entrées (+1, shell.html) — les douze coquilles de doc en sont exclues (~1,5 Mo évités, l'app les rend déjà hors-ligne depuis son module DOCS).

Volontairement laissé de côté

Traduire le CHANGELOG (les titres sont ceux du journal, en anglais — la carte n'affiche que le numéro), prérendre la doc en français (les coquilles sont anglaises comme les sections ; l'app bascule au montage), ajouter des hreflang (la langue est celle de l'app, pas de l'URL). Quelques points mineurs de la relecture sont notés dans la conversation de session et peuvent faire l'objet d'un suivi.

dapiced and others added 6 commits September 29, 2026 17:00
…atest wave

One entry per wave (V7 to V40, sub-waves included, V12 pending excluded), newest
first, generated by \
pm run changelog\ from the roadmap tables. A unit test
compares the committed file with the generator's output byte for byte, so the
changelog cannot drift from the plan in either direction; three plan rows
(V25-V27) have no rationale cell and are kept with an empty one rather than
dropped. package.json (and the lockfile's root entries) now read 1.40.0 -
major 1, minor = wave - which the home page will read to name the latest wave.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ibes itself

Measured on production (29 Sep 2026): the twelve /docs/<slug> URLs the sitemap
advertised were served by the root fallback - the home page's title, Open
Graph tags and canonical, and an empty root - so a crawler saw twelve
duplicates of the home page and a shared tutorial link previewed the wrong
page. Each doc page now gets its own prerendered shell (docs/<slug>.html,
served at the clean URL Pages and vite preview both resolve) carrying the
compiled article, its title, its summary and its canonical. The home page's
description opened mid-sentence because only the highlighted half of the
title was prepended; and / was the one section painting nothing before
JavaScript, so index.html now carries the home hero with HomePage's exact
classes. The doc shells stay out of the service worker precache (~1.5 MB the
app already renders offline from its DOCS module); docs/index.html remains.

shells.spec.ts now reads every URL the sitemap lists and asserts its own
canonical, og:url, a unique title and an <h1> in the HTML itself.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…uting under test

Measured with wrangler pages dev: the one rule in _redirects, /* /index.html
200, was INVALID and ignored - Pages strips /index.html from URLs, so the
rewrite would loop - and the 200 every unknown address answered came from the
default single-page fallback. A misspelled URL was a soft 404.

The build now emits 404.html (served with a 404 by Pages, painting the
not-found hero before JavaScript) and shell.html (the site card, an empty
root, noindex), and _redirects lists only the routes that have no file of
their own - a run, a comparison, a share link - rewritten to the clean URL
/shell with a 200, exact sources before splats. The service worker's
navigation fallback moves to shell.html so an offline run page no longer
flashes the home hero.

Two tests hold it together: src/app/redirects.test.ts derives the expected
rule set from router.tsx and the shell routes in vite.config.ts, so a route
added to one side and not the other fails; e2e/routing.spec.ts runs in a new
Playwright project against wrangler pages dev, the one server that applies
_redirects, _headers and 404.html the way production does - 404 on unknown
addresses and missing assets, 200 on dynamic routes, the CSP actually served.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…s to the drop zone

The status card said « the three modules are live » and listed them - a
sentence written at V22 and untouched through the eighteen waves that
followed (SQL, the local chat, forecasts, documentation, the privacy page).
It is now « What's new »: a current one-paragraph map of the five areas, the
latest delivered wave read from the build version (Vite define from
package.json, which the changelog test pins to PLAN.md's last wave) and a
link to the CHANGELOG. Both languages; HomePage.test.tsx checks the wave, the
link and that the old sentence is gone.

The « PS: » about dataset size leaves the /ml lede - a hero is not the place
for a postscript - and becomes a short note under the drop zone, where the
file arrives. The README carried the same LIMITATION line twice; once is
enough.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
PLAN.md section N records V41 - six corrections to what the site said about
itself, each measured on production first - and what the wave deliberately
leaves aside. \
pm run changelog\ picks the row up (37 waves, version 1.41.0),
so the home card now reads V41. The README counts what the suite measures
today (813 unit tests, 122 e2e across four projects), says every page has a
shell, lists the changelog script and points at CHANGELOG.md.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…claims that match the code

The V32 row of PLAN.md held an unescaped pipe inside inline code, so the
changelog generator read four cells and published the tail of the content as
the wave's rationale; the byte-for-byte test could not see it because the
generator agreed with itself. The pipe is escaped (and the spacing the same
defect had eaten restored), and extractWaves now refuses a wave row with more
than three cells or with a status other than delivered/pending - a row
skipped in silence would leave the version a wave behind with every test
green - while still ignoring the benchmark tables whose rows merely mention a
wave. The changelog comparison normalises line endings: a Windows checkout
with autocrlf hands the committed file back as CRLF, and the test failed on
every line for a \\r.

Statements corrected to what the code does: _redirects said Pages served
files before rules (it is the reverse - a rule must never overlap a real
file); a vite.config comment still called index.html the SPA fallback; the
shell eyebrow now uses <Eyebrow>'s own classes instead of a copper label the
app repainted teal on mount; the README counts twelve documentation URLs, not
twenty-four, and five Playwright projects, not four. One French sentence on
the drop zone reads like French now.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings September 29, 2026 21:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The service-worker fallback restores soft 404s for controlled clients, and several new guarantees are inaccurate or incompletely enforced.

Review effort: Balanced
Findings: 2 Medium severity · 2 Low severity

Open (4)
What changed in this PR

Adds accurate prerendering, routing metadata, 404 handling, and an automatically generated changelog.

Changes:

  • Prerenders home and documentation pages with page-specific metadata.
  • Adds Cloudflare Pages routing and 404 tests.
  • Generates CHANGELOG.md and synchronizes the application version.
File Description
vite.config.ts Generates shells, metadata, sitemap, and PWA fallback.
src/​types/​app.d.ts Declares the injected application version.
src/​locales/​fr.json Updates French status and upload guidance.
src/​locales/​en.json Updates English status and upload guidance.
src/​lib/​changelog.test.ts Tests changelog generation and version synchronization.
src/​features/​ml/​components/​DropZone.tsx Displays dataset-size guidance.
src/​features/​home/​HomePage.tsx Adds current-wave and changelog information.
src/​features/​home/​HomePage.test.tsx Tests the updated status card.
src/​app/​redirects.test.ts Validates redirects against application routes.
scripts/​changelog.mjs Generates the changelog and synchronizes versions.
scripts/​changelog.d.mts Types the changelog module.
README.md Updates capabilities, test counts, and scripts.
public/​_redirects Replaces the catch-all with dynamic-route rewrites.
playwright.config.ts Adds Cloudflare Pages routing tests.
PLAN.md Records V41 and repairs the V32 table row.
package.json Updates version and adds the changelog script.
package-lock.json Synchronizes the root package version.
e2e/​shells.spec.ts Verifies sitemap-page metadata and prerendering.
e2e/​routing.spec.ts Tests production-like routing, 404s, and headers.
CHANGELOG.md Adds the generated delivery history.
.prettierignore Excludes generated changelog formatting.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread scripts/changelog.mjs
Comment on lines +65 to +73
if (head[2] === 'pending') continue;
// An unescaped pipe inside a cell splits the row and turns the tail of the
// content into the « why » — measured on the V32 row, whose inline code
// held one. The byte-for-byte test cannot see it, so the generator refuses.
if (cells.length > 3) {
throw new Error(
`PLAN.md: wave V${head[1]} has ${cells.length} cells — an unescaped | inside a cell? Write it as \\|`,
);
}
Comment thread vite.config.ts
],
// V41 — the bare shell, not the home page: offline, a run or a share
// link must not flash the home hero for a frame before the app mounts.
navigateFallback: '/shell.html',
Comment thread src/locales/en.json
"noRequests": "runs locally · no requests",
"dropTitle": "Drop a CSV or Excel file",
"dropHint": "or click to browse — the file is read right here in your browser, nothing is uploaded",
"sizeNote": "Ideal size: 1–30 MB. Larger files still train, but the browser takes longer to answer.",
Comment thread src/locales/fr.json
"noRequests": "exécution locale · aucune requête",
"dropTitle": "Déposez un fichier CSV ou Excel",
"dropHint": "ou cliquez pour parcourir — le fichier est lu ici même, dans votre navigateur ; rien n'est téléversé",
"sizeNote": "Taille idéale : 1 à 30 Mo. Au-delà, l'entraînement fonctionne quand même, mais le navigateur met plus de temps à répondre.",
@dapiced
dapiced merged commit 6a53972 into main Sep 29, 2026
8 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants