Communitygithub.com

rbikbov/frontend-starter

Démarrage d'un nouveau projet frontend avec Next.js (App Router) + TypeScript : les fondations posées avant la première fonctionnalité.

Qu'est-ce que frontend-starter ?

Ce skill fournit une méthodologie complète et structurée pour initialiser un projet frontend moderne avec Next.js (App Router) et TypeScript. Il sert de guide détaillé pour les décisions architecturales (choix du routeur, mono-repo, micro-frontends), la configuration stricte de TypeScript et ESLint avec des règles de linting des frontières, la mise en place de la structure Feature-Sliced Design (FSD) adaptée au routage Next, la gestion des variables d'environnement validées avec Zod, la création d'un client API et d'un modèle d'erreurs normalisé, l'installation de tests (Vitest, Playwright) et l'intégration de git hooks et CI. Le skill est conçu pour être utilisé avec Claude Code, Cursor ou Codex afin d'automatiser et de standardiser la phase de démarrage d'un projet, évitant les décisions arbitraires et garantissant des bases robustes et évolutives. Il s'appuie sur des références externes (`references/configs.md`, `references/next-structure.md`) et précise que les instructions explicites de l'utilisateur et les fichiers d'agent du projet ont priorité sur ce document. L'objectif est de passer d'un projet généré par `create-next-app` à un projet professionnel, testé et prêt pour la production, en suivant une séquence d'étapes bien définie.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/rbikbov/frontend-starter/tree/HEAD/.claude/skills/frontend-bootstrap

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Démarrage d'un projet Next.js

Il est moins coûteux de poser les fondations le premier jour : chaque règle doit ensuite être appliquée sur un code qui la viole déjà. Si le modèle frontend-starter existe — commence par une copie du modèle : les étapes ci-dessous y sont déjà effectuées et vérifiées, ce document reste une explication des décisions et une checklist d'audit.

Ce document définit l'ordre des étapes et le socle minimal. La manière d'écrire le code lui-même est décrite dans le skill fsd-frontend (s'il existe dans le projet), l'authentification dans frontend-auth-session, et la vérification avant commit dans anti-slop-review.

Les configurations prêtes sont dans references/configs.md, la structure Next + FSD avec exemples de code dans references/next-structure.md.

Priorité des règles. Les instructions explicites de l'utilisateur et les fichiers d'agent du projet (AGENTS.md, CLAUDE.md) sont plus importants que ce document. Les versions des bibliothèques changent : avant de copier une configuration, vérifie-la avec la documentation de la version installée et ne l'affirme pas comme fonctionnelle tant que tu ne l'as pas exécutée.

Les faits sur Next.js viennent de la documentation dans le paquet, pas de ce document ni de la mémoire. Depuis la version 16.2, la documentation se trouve dans node_modules/next/dist/docs/, et le fichier AGENTS.md du projet y fait référence. En cas de divergence avec les exemples de ce document, la documentation de la version installée prévaut.

Notations : MUST — ne pas enfreindre ; SHOULD — par défaut oui, toute dérogation nécessite une justification.


1. Décisions avant le code

Chaque décision du tableau est consignée dans le README (section « Décisions ») ou dans un ADR, avec sa justification. Ne pas s'écarter de la valeur par défaut sans raison écrite.

QuestionPar défautSinon
Next.js ou SPANext.js si au moins un besoin parmi : SSR/SEO, BFF (secrets, HttpOnly-cookie), route handlersApplication interne derrière un login sans SEO ni BFF → Vite + React Router : build et déploiement plus simples
RouteurApp RouterPages Router — uniquement dans un projet existant
Mono-repoNon, une seule applicationUne deuxième application ou un paquet apparaît réellement → pnpm workspaces ; Nx/Turborepo — quand le build ou le CI commencent à ralentir
Multi-Zones, micro-frontendsNonÉquipes indépendantes avec des releases indépendantes
Données serveurServer Components pour le chargement initial ; TanStack Query pour les données client interactives et les mutationsApplication purement client → seulement TanStack Query
Textes et i18nModule de traduction dès le premier jour (next-intl ou équivalent), même pour une seule locale, si le projet suit fsd-frontendDécision explicite « sans i18n » consignée dans le README
Gestionnaire de paquetspnpm, version dans packageManager—
DéploiementDécider immédiatement : Vercel, serveur Node (output: "standalone") ou DockerLes env, le cache et le CI en dépendent

MUST : ne pas ajouter une technologie « pour le futur ». Le mono-repo, le deuxième routeur, Storybook, le state manager, MSW « comme un type de backend » apparaissent seulement quand ils ont leur premier consommateur réel.


2. Ordre des étapes

  1. Créer le projet (pnpm create next-app@latest) : TypeScript, ESLint, Tailwind, App Router. Figer packageManager, engines.node (Next 16 nécessite Node 20.9+) et .nvmrc.
  2. Supprimer immédiatement le modèle du générateur : la page d'accueil, les SVG dans public/, le README par défaut, les styles de démonstration. Remplacer le README par le squelette de references/configs.md. Un modèle laissé « pour plus tard » survit jusqu'en production. AGENTS.md et CLAUDE.md de create-next-app ne sont pas supprimés : le bloc entre <!-- BEGIN:nextjs-agent-rules --> et <!-- END:nextjs-agent-rules --> indique aux agents la documentation de la version installée, next dev le maintient automatiquement. Les règles propres au projet sont ajoutées en dehors de ces marqueurs.
  3. TypeScript strict (section 4 de references/configs.md) et script typecheck (tsc --noEmit).
  4. Structure FSD au-dessus de Next (section 3 ci-dessous).
  5. Linter et formatage : ESLint flat config de eslint-config-next + règles type-aware + linter des frontières + Prettier. Next 16 a supprimé next lint et ne lint pas lors d'un next build — le linter est exécuté via un script séparé et dans le CI.
  6. Configuration des variables d'environnement (section 4).
  7. Modèle d'erreurs et client API dans shared/api (section 5).
  8. Providers dans la couche _app : QueryClient, thème, i18n, services globaux (toast, confirm) comme port dans shared + implémentation dans _app.
  9. Base UI (section 6).
  10. Tests : Vitest + Testing Library + MSW, Playwright pour l'e2e (section 7).
  11. Git hooks : husky + lint-staged (eslint --fix, prettier) + commitlint.
  12. CI : lint, typecheck, test, build pour chaque push et PR (section 8).
  13. Sécurité par défaut (section 9).
  14. README rempli avec ce qui est vrai (section 10), et Definition of Done validée (section 11).

Les étapes 1 à 3 forment un commit séparé « scaffold » : ainsi l'historique montre ce que le générateur a fait et ce que tu as fait.


3. FSD au-dessus du routage Next

D'après le guide officiel FSD pour App Router : le dossier réservé Next app/ est à la racine du projet, les couches FSD sont dans src/, et les couches app et pages reçoivent le préfixe _ pour éviter toute confusion avec les dossiers réservés Next.

app/                         routage Next : uniquement les fichiers de routes
├── layout.tsx               layout racine → providers depuis src/_app
├── (auth)/sign-in/page.tsx  export { SignInPage as default } from "@/_pages/sign-in"
└── api/auth/login/route.ts  route handler (BFF), fin
proxy.ts                     Next 16+ (avant middleware.ts), à côté de app/
src/
├── _app/                    couche app : providers, styles globaux, implémentations des services
├── _pages/                  couche pages
├── widgets/                 (si le projet les utilise)
├── features/
├── entities/
└── shared/{ui,api,lib,config}

MUST :

  • Les fichiers dans app/ sont fins : réexport de la page depuis src/_pages, generateMetadata, parsing de params/searchParams (dans Next 15+ c'est une Promise, il faut await), et passage par props. Pas de logique.
  • Les route handlers et Server Actions sont fins : analyser et valider l'entrée → appeler une fonction depuis src → retourner la réponse. Chacun d'eux est un point d'entrée public : il vérifie l'autorisation lui-même, sans compter sur proxy.ts.
  • Ne pas créer src/app et src/pages : Next cherche les dossiers réservés aussi bien à la racine que dans src, et un dossier portant ce nom peut facilement devenir un deuxième routeur.
  • Le linter des frontières connaît les préfixes : motifs src/_app, src/_pages/* au lieu de src/app, src/pages/* (configuration — fsd-frontend, references/conventions.md, section 11).
  • "use client" est placé le plus bas possible dans l'arbre. La page est par défaut serveur ; les pages clientes sont des feuilles avec de l'interactivité.
  • Les modules contenant des secrets commencent par import "server-only", les modules avec window par import "client-only".

Voir references/next-structure.md pour plus de détails et de code.


4. Configuration de l'environnement

MUST :

  • Les variables sont lues dans deux modules : shared/config/env.server.ts (import "server-only") et shared/config/env.client.ts. Le schéma est en zod, la validation a lieu à l'import : une erreur de configuration se produit au démarrage, pas lors de la première requête. Dans le reste du code, process.env est interdit (règle du linter).
  • Les variables NEXT_PUBLIC_* sont intégrées dans le bundle lors de la compilation et uniquement lors d'un accès direct process.env.NEXT_PUBLIC_X : pas de déstructuration ni de process.env[name]. Il est impossible de construire une seule image pour plusieurs environnements avec des valeurs publiques différentes — ces valeurs sont lues sur le serveur et transmises vers le bas.
  • Les secrets sont uniquement sans le préfixe NEXT_PUBLIC_.
  • .env.example contient chaque variable avec un commentaire et une valeur sécurisée ; .env* est dans .gitignore, sauf .env.example. La compilation dans le CI se fait avec les valeurs de .env.example.

5. Modèle d'erreurs et client API

MUST :

  • Les erreurs sont normalisées en AppError avec un kind une seule fois, à la frontière de shared/api (modèle — fsd-frontend, references/conventions.md, section 1). Au-dessus de shared/api, personne ne parse le Response, les statuts ni les textes d'erreur.
  • Un seul request() au-dessus de fetch (ou un client généré, enveloppé de la même manière) : il transmet le signal, convertit une erreur réseau en network, le statut HTTP en kind, et valide le corps de la réponse avec un schéma. Exemple dans references/next-structure.md.
  • Le type d'erreur est déterminé par le code : statut, extensions.code (GraphQL répond avec 200 même en cas d'erreur), code dans le corps. Si le backend ne renvoie que du texte, la correspondance est faite par le texte dans un seul mapper, avec un commentaire de justification et des tests.
  • La réponse du backend est mappée vers un type domaine à la frontière ; les DTO ne remontent pas dans l'UI.
  • Les données utilisateur ne sont pas mises en cache entre les utilisateurs : pas de "use cache"/unstable_cache pour les réponses dépendant de la session.
  • Le client est généré à partir du schéma (OpenAPI, GraphQL) si celui-ci existe. Le schéma ou le code généré est dans le dépôt : le CI ne doit pas contacter le backend en direct.

SHOULD : une interface sur le transport (AuthApi + factory) — uniquement quand elle a déjà un deuxième consommateur (fsd-frontend, references/state-and-data.md, 2.1). On ne crée pas de valeur de configuration de type "mock" qui lance une exception "not implemented".


6. Base UI

  • Tokens de design — variables CSS dans :root (et pour le thème sombre), reliées à Tailwind v4 via @theme. Dans les composants, uniquement des tokens ; les valeurs brutes HEX et arbitraires (text-[#3a3a3a]) sont une exception ponctuelle avec commentaire.
  • Les classes existent. Les composants copiés depuis shadcn/ui et les exemples arrivent avec leurs propres tokens (bg-card, text-muted-foreground). Soit tu ajoutes ces tokens, soit tu remplaces les classes — sinon le composant reste silencieusement sans style.
  • Les primitives shared/ui sont construites sur une bibliothèque headless (Radix, React Aria) pour l'accessibilité ; les variantes sont gérées avec cva, la fusion de classes avec cn (clsx + tailwind-merge).
  • Polices — next/font, images — next/image avec dimensions, images.remotePatterns listé explicitement.
  • Storybook — seulement quand le kit UI est réutilisé par plusieurs applications ou équipes, pas avant.

7. Tests

  • Vitest + Testing Library + jsdom + MSW avec onUnhandledFrame: "error" (MSW 3 ; dans MSW 2, onUnhandledRequest). Configuration dans references/configs.md.
  • Vitest ne peut pas rendre les Server Components async. Extrais leur logique dans des fonctions et teste-les via des tests unitaires ; la page elle-même est testée en e2e.
  • Playwright pour 3 à 10 chemins critiques. Dans le CI, les e2e s'exécutent contre un backend prévisible (serveur mock, environnement avec base de données de test), pas contre un environnement partagé où les tests modifient les données des autres.
  • Le premier test est écrit le jour zéro : il vérifie que l'infrastructure de test fonctionne et définit un exemple.

8. CI

MUST : pour chaque push sur la branche principale et pour chaque PR : lint, typecheck, test, build. Le modèle GitHub Actions est dans references/configs.md. Pour les dépôts publics, Actions est gratuit ; pour les dépôts privés, un quota mensuel de minutes s'applique.

  • La compilation dans le CI se fait avec .env.example, sans secrets.
  • e2e — dans un job séparé, quand il existe un backend isolé ; sinon, mention explicite dans le README de la raison pour laquelle ils ne sont pas dans le CI.
  • Le badge CI dans le README apparaît en même temps que le workflow.

9. Sécurité par défaut

  • poweredByHeader: false ; en-têtes via headers() dans next.config.ts : X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, X-Frame-Options: DENY (ou frame-ancestors dans CSP). CSP avec nonce est une tâche distincte, mais la décision « présent / absent et pourquoi » est consignée immédiatement.
  • Server Actions et route handlers sont des points de terminaison publics : validation de l'entrée avec un schéma et vérification des droits dans chacun.
  • dangerouslySetInnerHTML — uniquement avec un assainisseur et un commentaire de justification.
  • Les données personnelles et les jetons ne sont pas journalisés.
  • Autorisation — selon frontend-auth-session.

10. README

Le squelette est dans references/configs.md. Une seule règle : dans le README, seulement ce qui est vrai pour le code de ce commit. Chaque section est mise à jour dans le même commit que le code qu'elle décrit. Les plans sont dans une section séparée « Suite », avec la mention qu'ils ne sont pas encore réalisés.


11. Definition of Done pour le démarrage

  • Le modèle du générateur est supprimé ; le README est un squelette rempli avec des informations vraies.
  • packageManager, engines.node, .nvmrc sont figés.
  • TS strict ; typecheck, lint, test, build passent en local (exécutés, pas supposés).
  • Structure FSD avec préfixes _app/_pages ; le linter des frontières détecte les imports vers le haut.
  • Variables d'environnement via deux modules avec schéma ; process.env en dehors de ceux-ci est interdit par le linter ; .env.example complet.
  • AppError et request() dans shared/api, couverts par des tests (réseau, statuts, schéma incorrect).
  • Providers dans _app ; QueryClient non partagé entre les utilisateurs sur le serveur.
  • Tokens de design en variables CSS ; toutes les classes utilisées existent.
  • Vitest + MSW + Playwright configurés, au moins un test vivant chacun.
  • Git hooks et commitlint fonctionnent.
  • CI vert.
  • En-têtes de sécurité et poweredByHeader: false.
  • Décisions de la section 1 consignées.

12. Quand tu hésites

  • Entre « ajouter maintenant » et « ajouter quand ce sera nécessaire » — quand ce sera nécessaire.
  • Entre « configurer manuellement » et « laisser comme create-next-app l'a généré » — laisse, tant qu'il n'y a pas de raison de changer, et note la raison quand tu changes.
  • Entre « une seule application » et « mono-repo » — une seule application.
  • Entre « configuration de mémoire » et « configuration de la documentation de la version actuelle » — de la documentation.

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

rbikbov/frontend-starter

Creates Architecture Decision Records documenting key technical decisions with context, alternatives considered, tradeoffs, consequences, and decision owners. Use when documenting "architecture decisions", "technical choices", "design decisions", or "ADRs".

rbikbov/frontend-starter

Проверка фронтенд-кода и документации на «нейрослоп» перед коммитом, PR или публикацией репозитория: остатки генераторов, мёртвые и недоделанные опции, утверждения в README и комментариях, не подтверждённые кодом, маркетинговый тон и эмодзи, лишние абстракции, хрупкая обработка ошибок, персональные данные в логах, несуществующие классы стилей. Использовать, когда просят проверить код или репозиторий «на слоп», подготовить проект к публикации или показу, сделать ревью кода, написанного с помощью ИИ, или перед тем как закоммитить собственную большую правку.

rbikbov/frontend-starter

Процесс разработки фичи с агентом: PRD с Non-Goals → компактная спецификация → задачи по одной на коммит → read-only исследование → tracer bullet → сборка с тестом сначала → независимое ревью субагентом → проверка в браузере. Использовать, когда просят сделать фичу, экран, пользовательский сценарий или заметное изменение поведения; когда нужно написать PRD, спецификацию или разбить работу на задачи; когда работа больше одного коммита. Не использовать для опечаток и однострочных правок.

rbikbov/frontend-starter

Авторизация и сессия во фронтенде на Next.js (App Router): где хранить токены, BFF на route handlers с HttpOnly-cookie, refresh токена без гонок, определение «не авторизован» (включая GraphQL, который отвечает 200), проверки в proxy.ts и Data Access Layer, безопасный редирект после входа, выход без утечки данных прошлого пользователя, токены в ссылках сброса пароля, формы входа и восстановления. Использовать, когда проектируешь или пишешь вход, регистрацию, восстановление пароля, защищённые страницы, API-клиент с refresh-токеном, или ревьюишь такой код.

Skills associés