尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Bilingual (FR/EN) website that teaches you to inspect, repair, clean and adjust your own bike. Next.js 16 + React Three Fiber + Prisma.
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
vélo-atelier est un site public et bilingue (français par défaut, anglais) qui apprend à contrôler, réparer, nettoyer et régler son propre vélo.查看完整 README ↗
vélo-atelier est un site public et bilingue (français par défaut, anglais) qui apprend à contrôler, réparer, nettoyer et régler son propre vélo.
localStorage) ; une fois connecté, un bandeau sur
« Mes vélos » propose d'importer ce vélo dans le compte (/import).Site en ligne : https://velo-atelier.vercel.app — la mise en ligne est décrite dans
docs/deploy.md.
Prérequis : nvm avec Node 24 (.nvmrc),
Docker Desktop en cours d'exécution, et npm — jamais pnpm, yarn ni bun.
La séquence est celle du critère d'acceptation §4.8 AC1 du plan, telle quelle :
rm -rf node_modules && env -i PATH="$PATH" HOME="$HOME" npm ci
nvm use && cp .env.example .env.local && npm run db:setup && npm run dev
postinstall
ne lance que prisma generate, qui n'a pas besoin de base.docker compose up -d --wait), applique les
migrations, charge le jeu de démonstration, puis lance le serveur sur
http://localhost:3000.DEMO_USER (ci-dessous) : 3 vélos, 1 contrôle
terminé avec exactement 2 points KO, 1 liste de réparations avec
2 lignes.npm run db:seed lancé
deux fois ne change aucun nombre de lignes.npm run db:seed
npm run db:seed
npx tsx scripts/db/count.ts # affiche : users=2 bikes=4
Si la base velo_atelier_test manque (volume Docker créé avant
docker/initdb/), npm run db:reset la recrée — en détruisant le volume, donc
aussi les données locales de velo_atelier.
Créés par le seed (prisma/seed-data.ts). Le seed refuse toujours
VERCEL_ENV=production (prisma/seed.ts), et tout hôte de base non local sauf
ALLOW_REMOTE_SEED=1 explicite (lib/db/guard.ts).
DEMO_USER (fr) | DEMO_USER_EN (en) | |
|---|---|---|
[email protected] | [email protected] | |
| Mot de passe | Demo-Velo-Atelier-2026! | Demo-Velo-Atelier-2026! |
| Contenu | 3 vélos (« Vélo de route », « Gravel », « VTT électrique ») ; sur le Gravel, un contrôle terminé et la liste « Révision printemps » | 1 vélo (« Gravel bike ») |
Avec NEXT_PUBLIC_DEMO_LOGIN=1 (déjà dans .env.example), la page de connexion
propose un bouton qui remplit DEMO_USER.
La liste commentée est .env.example ; leur répartition entre
les environnements Vercel est dans docs/deploy.md.
| Variable | En local (.env.example) | Sur Vercel | Rôle |
|---|---|---|---|
POSTGRES_URL | Postgres Docker | les trois environnements | connexion de l'application (pool) ; exigée sous ce nom exact (voir sous le tableau) |
POSTGRES_URL_NON_POOLING | Postgres Docker | les trois environnements | connexion directe : migrations, seed ; exigée sous ce nom exact, jamais l'URL poolée |
AUTH_SECRET | valeur de développement | les trois, une valeur par environnement | clé de signature Auth.js, au moins 32 caractères (npx auth secret) |
AUTH_URL | http://localhost:3000 | Production seulement | origine publique à partir de laquelle Auth.js construit ses URL de retour |
AUTH_TRUST_HOST | true | les trois (true) | faire confiance à l'hôte transmis par le proxy |
NEXT_PUBLIC_SITE_URL | http://localhost:3000 | les trois environnements | URL canonique, sitemap, hreflang, images OpenGraph — figée au build |
AUTH_GOOGLE_ID / AUTH_GOOGLE_SECRET | vides (voir ci-dessous) | Production seulement | connexion Google ; vides, seul le formulaire e-mail + mot de passe aboutit |
BCRYPT_COST | 12 | non définie (12 par défaut) | facteur de coût bcrypt, ramené entre 4 et 15 (.env.test utilise 4) |
NEXT_PUBLIC_DEMO_LOGIN | 1 | jamais | bouton « compte de démonstration » sur la page de connexion |
ENABLE_TEST_PAGES | 1 | jamais | ouvre /dev/bike3d et /dev/bike3d-perf (lu à chaque requête) |
NEXT_PUBLIC_TEST_HOOKS | 1 | jamais | compile les sondes Playwright window.__va dans le bundle (lu au build) |
Deux précisions, depuis que le contrat d'environnement (lib/env.ts) est
évalué à chaque démarrage de serveur (instrumentation.ts) et pendant le build
Vercel (scripts/check-env.ts) :
lib/db/env.ts, qui
ouvre la connexion (application, migrations, seed), accepte aussi
DATABASE_URL / DATABASE_URL_UNPOOLED en repli. Le contrat, lui, ne les lit
pas : avec les seuls noms de Neon, il refuse l'environnement alors que la
connexion fonctionnerait.npm run dev démarre avec la paire Google vide ; npm run start non.
Tout next start est un serveur de production, et il lui faut alors
AUTH_GOOGLE_ID et AUTH_GOOGLE_SECRET non vides (n'importe quelle valeur,
comme dans .env.test) ainsi que AUTH_URL. Sinon Next affiche quand même
« Ready », puis chaque page répond 500 ; la raison n'est écrite que dans le
journal du serveur : EnvValidationError, suivi du nom de la variable.| Commande | Ce qu'elle fait |
|---|---|
npm run dev | dessins de l'arbre, contrôle du contenu, puis serveur de développement Turbopack sur le port 3000 |
npm run build | dessins de l'arbre, contrôle du contenu, puis build de production |
npm run start | sert ce build en production ; refusé tant que la paire Google est vide (ci-dessus) |
npm run lint / npm run format:check | ESLint / Prettier |
npm run typecheck | génère le client Prisma et le contenu, puis tsc --noEmit |
npm run content:check | valide content/** (règles structurelles et règles du corpus, --strict) |
npm run content:new <kind>-<slug> | crée un guide dans les deux langues (voir CONTRIBUTING.md) |
npm run db:up / db:down | démarre / arrête le Postgres Docker |
npm run db:seed | recharge le jeu de démonstration (idempotent) |
npm run db:reset | détruit le volume, puis migrations et seed depuis zéro |
npm run ci:local | scripts/ci.sh : le miroir local de la CI (le hook pre-push le lance aussi) |
| Commande | Ce qu'elle lance |
|---|---|
npm test | toute la suite Vitest : unit, ui, bike3d, integration, security — si rien ne répond sur la base _test, integration est sauté avec un avertissement. boot s'y ajoute dès qu'un build est sur le disque (.next/BUILD_ID) : quatre next start sur ce build — pas sur l'arbre de travail —, qui exigent une base joignable (sans elle, deux cas échouent aussitôt sur un 503) |
npm run test:unit · test:ui · test:bike3d · test:integration · test:security | un seul projet Vitest ; integration utilise velo_atelier_test (.env.test) |
npm run test:coverage | Vitest avec la barrière de couverture : 80 % global, 100 % sur lib/domain/**, 100 % des instructions et branches de lib/checkup/**, et des seuils par dossier |
npm run e2e -- --project=desktop-chromium | Playwright sur un build de production, fait d'abord avec ENABLE_TEST_PAGES=1 NEXT_PUBLIC_TEST_HOOKS=1 bash scripts/ci/build.sh (pas npm run build, qui grave l'origine :3000 de .env.local dans les URL canoniques) ; sans --project, tous les projets tournent (WebKit et perf compris) |
npm run e2e:mobile | les projets mobiles : Pixel 7, paysage, 320 px et WebKit (npx playwright install webkit au besoin) |
npm run e2e:docker | Playwright dans l'image Linux amd64 de la CI, pour reproduire un échec propre à Linux (build sur l'hôte d'abord) |
npm run perf | projets perf et perf-mobile : compteurs WebGL (draw calls, triangles) |
npx tsx scripts/perf/bundle-budget.ts | JavaScript chargé au premier affichage, par route, contre perf.budgets.json (après un build) |
npm run lhci | Lighthouse CI, par bash scripts/ci/lighthouse.sh (après un build fait avec scripts/ci/build.sh) ; le serveur audité utilise la base de , sauf si le shell exporte et . ; les arguments placés après ne sont pas transmis à lhci |
| Document | Contenu |
|---|---|
docs/bike3d.md | le visualiseur 3D : couches, API publique, crochets de test, limites |
docs/bike3d-geometry.md | la géométrie du vélo : axes, solveur, tableau des tailles |
docs/bike3d-perf.md | la performance 3D et la vérification sur un vrai appareil |
docs/illustrations.md | dessiner une illustration, pour un guide ou pour l'arbre de décision |
docs/retailers.md | les liens vers les boutiques et leur vérification à la main |
docs/deploy.md | la mise en ligne (W5) : Neon, Vercel, Google, réglages GitHub |
docs/qa/google-oauth.md | la recette manuelle de « Continuer avec Google » |
docs/backlog.md | ce qui est volontairement reporté : W5, puis après le MVP |
content/README.md | écrire un guide : slugs, gabarit, règles du contrôle |
src/ — l'alias
@ désigne la racine du dépôt./fr/…, /en/… ; / mène à /fr), un fichier de messages par espace de
noms dans messages/.docs/bike3d.md.Les contrats qui tiennent le tout sont dans CLAUDE.md.
Code sous licence MIT. Contenu éditorial (content/**) sous
CC BY-SA 4.0. Voir aussi
THIRD_PARTY_NOTICES.md.
vélo-atelier is a public, bilingual (French by default, English) website that teaches you to inspect, repair, clean and adjust your own bike.
localStorage); once signed in, a banner on "My bikes"
offers to import that bike into the account (/import).Live site: https://velo-atelier.vercel.app — how it is deployed is described in
docs/deploy.md.
Requirements: nvm with Node 24 (.nvmrc), a
running Docker Desktop, and npm — never pnpm, yarn or bun.
This is the plan's acceptance criterion §4.8 AC1, verbatim:
rm -rf node_modules && env -i PATH="$PATH" HOME="$HOME" npm ci
nvm use && cp .env.example .env.local && npm run db:setup && npm run dev
postinstall only runs
prisma generate, which needs no database.docker compose up -d --wait), applies the
migrations, loads the demo data, then serves the site on
http://localhost:3000.DEMO_USER (below): 3 bikes, 1 completed checkup with
exactly 2 KO items, 1 build list with 2 items.npm run db:seed
twice leaves every row count unchanged.npm run db:seed
npm run db:seed
npx tsx scripts/db/count.ts # prints: users=2 bikes=4
If the velo_atelier_test database is missing (a Docker volume created before
docker/initdb/ existed), npm run db:reset recreates it — by destroying the
volume, so the local velo_atelier data goes too.
Created by the seed (prisma/seed-data.ts). The seed always refuses
VERCEL_ENV=production (prisma/seed.ts), and any non-local database host
unless ALLOW_REMOTE_SEED=1 is set explicitly (lib/db/guard.ts).
DEMO_USER (fr) | DEMO_USER_EN (en) | |
|---|---|---|
[email protected] | [email protected] | |
| Password | Demo-Velo-Atelier-2026! | Demo-Velo-Atelier-2026! |
| Holds | 3 bikes ("Vélo de route", "Gravel", "VTT électrique"); on the Gravel, one completed checkup and the "Révision printemps" list | 1 bike ("Gravel bike") |
With NEXT_PUBLIC_DEMO_LOGIN=1 (already in .env.example), the sign-in page
offers a button that fills in DEMO_USER.
The annotated list is .env.example; how they are split
across Vercel's environments is in docs/deploy.md.
| Variable | Local (.env.example) | On Vercel | Purpose |
|---|---|---|---|
POSTGRES_URL | Docker Postgres | all three environments | the app's (pooled) connection; required under this exact name (see below the table) |
POSTGRES_URL_NON_POOLING | Docker Postgres | all three environments | direct connection for migrations and the seed; required under this exact name, never the pooled URL |
AUTH_SECRET | a development value | all three, a distinct value in each | Auth.js signing key, at least 32 characters (npx auth secret) |
AUTH_URL | http://localhost:3000 | Production only | the public origin Auth.js builds its callback URLs from |
AUTH_TRUST_HOST | true | all three (true) | trust the host forwarded by the proxy |
NEXT_PUBLIC_SITE_URL | http://localhost:3000 | all three environments | canonical URLs, sitemap, hreflang, OpenGraph images — baked in at build time |
AUTH_GOOGLE_ID / AUTH_GOOGLE_SECRET | empty (see below) | Production only | Google sign-in; when empty, only the email + password form can sign in |
BCRYPT_COST | 12 | unset (defaults to 12) | bcrypt work factor, clamped to 4–15 (.env.test uses 4) |
NEXT_PUBLIC_DEMO_LOGIN | 1 | never | the "demo account" button on the sign-in page |
ENABLE_TEST_PAGES | 1 | never | unlocks /dev/bike3d and /dev/bike3d-perf (read on every request) |
NEXT_PUBLIC_TEST_HOOKS | 1 | never | compiles the window.__va Playwright hooks into the bundle (read at build time) |
Two things to know, now that the environment contract (lib/env.ts) is
evaluated every time a server starts (instrumentation.ts) and during the
Vercel build (scripts/check-env.ts):
lib/db/env.ts, which
opens the connection (the app, migrations, the seed), also accepts
DATABASE_URL / DATABASE_URL_UNPOOLED as a fallback. The contract does not
read them: with Neon's names only it refuses the environment, although the
connection itself would work.npm run dev starts with the Google pair empty; npm run start does not.
Every next start is a production server, and one needs a non-empty
AUTH_GOOGLE_ID and AUTH_GOOGLE_SECRET (any value, as .env.test has) and
AUTH_URL. Without them Next still prints "Ready", then every page answers
500; the reason is only in the server's log: EnvValidationError, followed
by the variable's name.| Command | What it does |
|---|---|
npm run dev | tree drawings, content check, then the Turbopack dev server on port 3000 |
npm run build | tree drawings, content check, then the production build |
npm run start | serves that build in production; refused while the Google pair is empty (above) |
npm run lint / npm run format:check | ESLint / Prettier |
npm run typecheck | generates the Prisma client and the content, then tsc --noEmit |
npm run content:check | validates content/** (structural and corpus rules, --strict) |
npm run content:new <kind>-<slug> | scaffolds a guide in both locales (see CONTRIBUTING.md) |
npm run db:up / db:down | starts / stops the Docker Postgres |
npm run db:seed | reloads the demo data (idempotent) |
npm run db:reset | destroys the volume, then migrates and seeds from scratch |
npm run ci:local | scripts/ci.sh: the local mirror of CI (the pre-push hook runs it too) |
| Command | What it runs |
|---|---|
npm test | the whole Vitest suite: unit, ui, bike3d, integration, security — when nothing answers on the _test database, integration is skipped with a warning. boot joins as soon as a build is on disk (.next/BUILD_ID): four next start against that build — not the working tree — which need a reachable database (without one, two cases fail at once on a 503) |
npm run test:unit · test:ui · test:bike3d · test:integration · test:security | one Vitest project; integration uses velo_atelier_test (.env.test) |
npm run test:coverage | Vitest with the coverage gate: 80 % overall, 100 % on lib/domain/**, 100 % of the statements and branches of lib/checkup/**, and per-folder floors |
npm run e2e -- --project=desktop-chromium | Playwright against a production build, made first with ENABLE_TEST_PAGES=1 NEXT_PUBLIC_TEST_HOOKS=1 bash scripts/ci/build.sh (not npm run build, which bakes .env.local's :3000 origin into the canonical URLs); without --project, every project runs (WebKit and perf included) |
npm run e2e:mobile | the mobile projects: Pixel 7, landscape, 320 px and WebKit (npx playwright install webkit if needed) |
npm run e2e:docker | Playwright in CI's amd64 Linux image, to reproduce a Linux-only failure (build on the host first) |
npm run perf | the perf and perf-mobile projects: WebGL counters (draw calls, triangles) |
npx tsx scripts/perf/bundle-budget.ts | first-load JavaScript per route against perf.budgets.json (after a build) |
npm run lhci | Lighthouse CI, through bash scripts/ci/lighthouse.sh (after a build made with scripts/ci/build.sh); the audited server uses .env.test's _test database unless the shell exports and . ; arguments after are not forwarded to lhci |
| Document | What is in it |
|---|---|
docs/bike3d.md | the 3D viewer: layers, public API, test hooks, known limitations |
docs/bike3d-geometry.md | bike geometry: axes, the solver, the size table |
docs/bike3d-perf.md | 3D performance and the real-device check |
docs/illustrations.md | drawing an illustration, for a guide or for the decision tree |
docs/retailers.md | the retailer links and how they are verified by hand |
docs/deploy.md | going live (W5): Neon, Vercel, Google, the GitHub settings |
docs/qa/google-oauth.md | the manual QA of "Continue with Google" |
docs/backlog.md | what is deliberately deferred: W5, then post-MVP |
content/README.md | writing a guide: slugs, template, the content check's rules |
src/ — the @
alias is the repository root./fr/…, /en/…; /
goes to /fr), one message file per namespace under messages/.docs/bike3d.md.The contracts that hold it together are in CLAUDE.md.
Code is MIT. Editorial content under content/** is
CC BY-SA 4.0. See also
THIRD_PARTY_NOTICES.md.
ALLOW_REMOTE_SEED | absente | jamais | laisse le seed écrire dans une base non locale |
_test.env.testPOSTGRES_URLPOSTGRES_URL_NON_POOLING.next/ absent), la commande affiche SKIP et sort en 0 sans avoir rien audité--CLAUDE.md| les contrats d'architecture, en anglais |
CONTRIBUTING.md | contribuer : branches, commits, barrières, ajout d'un guide |
SECURITY.md | signaler une faille en privé |
.debug/README.md | l'index des notes de débogage |
ALLOW_REMOTE_SEED| unset |
| never |
| lets the seed write to a non-local database |
POSTGRES_URLPOSTGRES_URL_NON_POOLING.next/ missing) it prints SKIP and exits 0, having audited nothing--CLAUDE.md| the architecture contracts |
CONTRIBUTING.md | contributing: branches, commits, gates, adding a guide |
SECURITY.md | reporting a vulnerability privately |
.debug/README.md | the index of debug notes |