Scaffold
Modèles de structure de projet et génération de code passe-partout pour les types de projets courants, avec des configurations par défaut suivant les meilleures pratiques.
Arbre de décision du type de projet
Que construisez-vous ?
│
├─ API / Service Backend
│ ├─ API REST
│ │ ├─ Python → FastAPI (asynchrone, documentation OpenAPI automatique)
│ │ ├─ Node.js → Express ou Fastify (Fastify pour les performances)
│ │ ├─ Go → Gin (ergonomique) ou Echo (riche en middleware)
│ │ └─ Rust → Axum (écosystème tower, asynchrone par défaut)
│ ├─ API GraphQL
│ │ ├─ Python → Strawberry + FastAPI
│ │ ├─ Node.js → Apollo Server ou Pothos + Yoga
│ │ ├─ Go → gqlgen (code-first)
│ │ └─ Rust → async-graphql + Axum
│ └─ Service gRPC
│ ├─ Python → grpcio + protobuf
│ ├─ Go → google.golang.org/grpc
│ └─ Rust → tonic
│
├─ Application Web
│ ├─ Full-stack avec SSR
│ │ ├─ Écosystème React → Next.js 14+ (App Router)
│ │ ├─ Écosystème Vue → Nuxt 3
│ │ ├─ Écosystème Svelte → SvelteKit
│ │ └─ Contenu lourd / multi-framework → Astro
│ ├─ SPA (côté client uniquement)
│ │ ├─ React → Vite + React + React Router
│ │ ├─ Vue → Vite + Vue + Vue Router
│ │ └─ Svelte → Vite + Svelte + svelte-routing
│ └─ Site Statique
│ ├─ Blog / documentation → Astro ou VitePress
│ └─ Marketing / page d'accueil → Astro ou Next.js (export statique)
│
├─ Outil CLI
│ ├─ Python → Typer (simple) ou Click (complexe)
│ ├─ Node.js → Commander + Inquirer
│ ├─ Go → Cobra + Viper
│ └─ Rust → Clap (API derive)
│
├─ Bibliothèque / Package
│ ├─ Package npm → TypeScript + tsup + Vitest
│ ├─ Package PyPI → uv + pyproject.toml + pytest
│ ├─ Module Go → go mod init + go test
│ └─ Crate Rust → cargo init --lib + cargo test
│
└─ Monorepo
├─ JavaScript/TypeScript → Turborepo + pnpm workspaces
├─ Full-stack JS → Nx
├─ Go → Go workspaces (go.work)
├─ Rust → Cargo workspaces
└─ Python → uv workspaces ou hatch
Matrice de sélection de la pile
| Type de projet | Langage | Framework | Base de données | ORM/Requêtes | Cible de déploiement |
|---|
| API REST | Python | FastAPI | PostgreSQL | SQLAlchemy + Alembic | Docker / AWS ECS |
| API REST | Node.js | Fastify | PostgreSQL | Prisma ou Drizzle | Docker / Vercel |
| API REST | Go | Gin | PostgreSQL | sqlx (brut) ou GORM | Docker / Fly.io |
| API REST | Rust | Axum | PostgreSQL | sqlx | Docker / Fly.io |
| Application Web | TypeScript | Next.js 14+ | PostgreSQL | Prisma ou Drizzle | Vercel / Docker |
| Application Web | TypeScript | Nuxt 3 | PostgreSQL | Prisma | Vercel / Netlify |
| Application Web | TypeScript | Astro | SQLite / aucun | Drizzle | Cloudflare / Netlify |
| Outil CLI | Python | Typer | SQLite | sqlite3 stdlib | PyPI |
| Outil CLI | Go | Cobra | SQLite / BoltDB | sqlx | GitHub Releases |
| Outil CLI | Rust | Clap | SQLite | rusqlite | crates.io |
| Bibliothèque | TypeScript | tsup | n/a | n/a | npm |
| Bibliothèque | Python | hatch/uv | n/a | n/a | PyPI |
Commandes de génération rapide
Python (API)
mkdir my-api && cd my-api
uv init --python 3.12
uv add fastapi uvicorn sqlalchemy alembic psycopg2-binary pydantic-settings
uv add --dev pytest pytest-asyncio httpx ruff mypy
Node.js (Application Web)
npx create-next-app@latest my-app --typescript --tailwind --eslint --app --src-dir --import-alias "@/*"
npm create vite@latest my-app -- --template react-ts
Go (API)
mkdir my-api && cd my-api
go mod init github.com/user/my-api
go get github.com/gin-gonic/gin
go get github.com/jmoiron/sqlx
go get github.com/lib/pq
Rust (CLI)
cargo init my-cli
cd my-cli
cargo add clap --features derive
cargo add serde --features derive
cargo add anyhow tokio --features tokio/full
Monorepo (Turborepo)
npx create-turbo@latest my-monorepo
mkdir my-monorepo && cd my-monorepo
npm init -y
npm install turbo --save-dev
mkdir -p apps/web apps/api packages/shared
Modèle de projet API
Structure des répertoires (Exemple FastAPI)
my-api/
├── src/
│ └── my_api/
│ ├── __init__.py
│ ├── main.py # Application FastAPI, durée de vie, middleware
│ ├── config.py # Configuration pydantic-settings
│ ├── database.py # Moteur SQLAlchemy, session
│ ├── dependencies.py # Dépendances partagées FastAPI
│ ├── routers/
│ │ ├── __init__.py
│ │ ├── health.py # Point de terminaison de vérification d'état
│ │ └── users.py # Points de terminaison CRUD utilisateur
│ ├── models/
│ │ ├── __init__.py
│ │ └── user.py # Modèles SQLAlchemy
│ ├── schemas/
│ │ ├── __init__.py
│ │ └── user.py # Schémas de requête/réponse Pydantic
│ └── services/
│ ├── __init__.py
│ └── user.py # Logique métier
├── alembic/
│ ├── alembic.ini
│ ├── env.py
│ └── versions/
├── tests/
│ ├── conftest.py # Fixtures : DB de test, client, factories
│ ├── test_health.py
│ └── test_users.py
├── pyproject.toml
├── Dockerfile
├── docker-compose.yml
├── .env.example
├── .gitignore
└── .dockerignore
Structure des répertoires (Exemple Express/Fastify)
my-api/
├── src/
│ ├── index.ts # Point d'entrée, démarrage du serveur
│ ├── app.ts # Configuration de l'application Express/Fastify
│ ├── config.ts # Configuration d'environnement avec validation zod
│ ├── database.ts # Client Prisma ou configuration Drizzle
│ ├── middleware/
│ │ ├── auth.ts
│ │ ├── error-handler.ts
│ │ └── request-logger.ts
│ ├── routes/
│ │ ├── health.ts
│ │ └── users.ts
│ ├── services/
│ │ └── user.service.ts
│ └── types/
│ └── index.ts
├── prisma/
│ └── schema.prisma
├── tests/
│ ├── setup.ts
│ └── routes/
│ └── users.test.ts
├── package.json
├── tsconfig.json
├── Dockerfile
├── docker-compose.yml
├── .env.example
└── .gitignore
Modèle de projet d'application Web
Structure des répertoires (Next.js App Router)
my-app/
├── src/
│ ├── app/
│ │ ├── layout.tsx # Mise en page racine
│ │ ├── page.tsx # Page d'accueil
│ │ ├── loading.tsx # Interface utilisateur de chargement globale
│ │ ├── error.tsx # Limite d'erreur globale
│ │ ├── not-found.tsx # Page 404
│ │ ├── globals.css # Styles globaux + Tailwind
│ │ ├── (auth)/
│ │ │ ├── login/page.tsx
│ │ │ └── register/page.tsx
│ │ ├── dashboard/
│ │ │ ├── layout.tsx
│ │ │ └── page.tsx
│ │ └── api/
│ │ └── health/route.ts
│ ├── components/
│ │ ├── ui/ # Primitives réutilisables
│ │ └── features/ # Composants spécifiques aux fonctionnalités
│ ├── lib/
│ │ ├── db.ts # Client de base de données
│ │ ├── auth.ts # Fonctions d'aide à l'authentification
│ │ └── utils.ts # Utilitaires partagés
│ └── types/
│ └── index.ts
├── public/
│ └── favicon.ico
├── tests/
│ ├── setup.ts
│ └── components/
├── next.config.ts
├── tailwind.config.ts
├── tsconfig.json
├── package.json
├── .env.local.example
└── .gitignore
Modèle de projet d'outil CLI
Structure des répertoires (Python / Typer)
my-cli/
├── src/
│ └── my_cli/
│ ├── __init__.py
│ ├── __main__.py # Point d'entrée python -m my_cli
│ ├── cli.py # Application Typer, groupes de commandes
│ ├── commands/
│ │ ├── __init__.py
│ │ ├── init.py # my-cli init
│ │ └── run.py # my-cli run
│ ├── config.py # Chargement du fichier de configuration (TOML/YAML)
│ └── utils.py
├── tests/
│ ├── conftest.py
│ └── test_commands.py
├── pyproject.toml # Point d'entrée [project.scripts]
├── .gitignore
└── README.md
Structure des répertoires (Go / Cobra)
my-cli/
├── cmd/
│ ├── root.go # Commande racine, flags globaux
│ ├── init.go # my-cli init
│ └── run.go # my-cli run
├── internal/
│ ├── config/
│ │ └── config.go # Chargement de la configuration Viper
│ └── runner/
│ └── runner.go # Logique principale
├── main.go # Point d'entrée, appelle cmd.Execute()
├── go.mod
├── go.sum
├── Makefile
└── .gitignore
Modèle de projet de bibliothèque
Structure des répertoires (Package npm)
my-lib/
├── src/
│ ├── index.ts # Exportations de l'API publique
│ ├── core.ts # Implémentation principale
│ └── types.ts # Définitions de types publics
├── tests/
│ └── core.test.ts
├── package.json # "type": "module", carte des exports
├── tsconfig.json # declaration: true, declarationMap: true
├── tsup.config.ts # Configuration de build : cjs + esm
├── vitest.config.ts
├── .npmignore
├── .gitignore
├── CHANGELOG.md
└── LICENSE
Structure des répertoires (Package PyPI)
my-lib/
├── src/
│ └── my_lib/
│ ├── __init__.py # API publique, __version__
│ ├── core.py
│ └── py.typed # Marqueur PEP 561
├── tests/
│ ├── conftest.py
│ └── test_core.py
├── pyproject.toml # Système de build, métadonnées, configuration des outils
├── .gitignore
├── CHANGELOG.md
└── LICENSE
Modèle de Monorepo
Turborepo + pnpm Workspaces
my-monorepo/
├── apps/
│ ├── web/ # Frontend Next.js
│ │ ├── src/
│ │ ├── package.json # dépend de @repo/shared
│ │ └── tsconfig.json # étend ../../tsconfig.base.json
│ └── api/ # Backend Fastify
│ ├── src/
│ ├── package.json
│ └── tsconfig.json
├── packages/
│ ├── shared/ # Types, utilitaires, validateurs partagés
│ │ ├── src/
│ │ ├── package.json # "name": "@repo/shared"
│ │ └── tsconfig.json
│ ├── ui/ # Composants React partagés
│ │ ├── src/
│ │ └── package.json # "name": "@repo/ui"
│ └── config/ # Configurations partagées
│ ├── eslint/
│ ├── typescript/
│ └── package.json
├── turbo.json # Pipeline : build, test, lint
├── pnpm-workspace.yaml # packages: ["apps/*", "packages/*"]
├── package.json # devDeps racine : turbo
├── tsconfig.base.json # Configuration TypeScript partagée
├── .gitignore
└── .npmrc
Cargo Workspaces (Rust)
my-workspace/
├── crates/
│ ├── my-core/ # Bibliothèque principale
│ │ ├── src/lib.rs
│ │ └── Cargo.toml
│ ├── my-cli/ # Binaire CLI
│ │ ├── src/main.rs
│ │ └── Cargo.toml # dépend de my-core
│ └── my-server/ # Binaire API
│ ├── src/main.rs
│ └── Cargo.toml
├── Cargo.toml # [workspace] members = ["crates/*"]
├── Cargo.lock
├── .gitignore
└── rust-toolchain.toml
Liste de contrôle des ajouts courants
Configuration du projet terminée ? Ajoutez ceci :
│
├─ Contrôle de version
│ ├─ [ ] .gitignore (spécifique au langage)
│ ├─ [ ] .gitattributes (fin de ligne, fichiers binaires)
│ └─ [ ] Règles de protection de branche
│
├─ CI/CD
│ ├─ [ ] Workflow GitHub Actions (test sur PR, déploiement sur merge)
│ ├─ [ ] Tests matriciels (OS, versions d'exécution)
│ └─ [ ] Automatisation des versions
│
├─ Docker
│ ├─ [ ] Dockerfile multi-étapes
│ ├─ [ ] docker-compose.yml (application + base de données + cache)
│ ├─ [ ] .dockerignore
│ └─ [ ] Point de terminaison de vérification d'état
│
├─ Qualité du code
│ ├─ [ ] Linter (ESLint, Ruff, golangci-lint, Clippy)
│ ├─ [ ] Formateur (Prettier, Black/Ruff, gofmt, rustfmt)
│ ├─ [ ] Hooks de pré-commit (Husky, pre-commit)
│ └─ [ ] Vérification des types (TypeScript strict, mypy, go vet)
│
├─ Tests
│ ├─ [ ] Framework de test configuré (Vitest, pytest, go test)
│ ├─ [ ] Rapport de couverture
│ ├─ [ ] Configuration de la base de données de test
│ └─ [ ] Pipeline de test CI
│
├─ Éditeur
│ ├─ [ ] .editorconfig
│ ├─ [ ] .vscode/settings.json
│ └─ [ ] .vscode/extensions.json
│
└─ Documentation
├─ [ ] README.md (description du projet, configuration, utilisation)
├─ [ ] AGENTS.md — inspiré des assets/AGENTS-template.md de la compétence repo-doctor
│ (la section Landmines est obligatoire ;
│ doctrine : rules/agentic-quality.md)
├─ [ ] CONTRIBUTING.md
└─ [ ] Documentation de l'API (OpenAPI, godoc, rustdoc)
Modèles de fichiers de configuration
.editorconfig (Universel)
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.{py,rs}]
indent_size = 4
[*.go]
indent_style = tab
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab
pyproject.toml (Python)
[project]
name = "my-project"
version = "0.1.0"
requires-python = ">=3.12"
[tool.ruff]
target-version = "py312"
line-length = 88
[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B", "SIM"]
[tool.pytest.ini_options]
testpaths = ["tests"]
asyncio_mode = "auto"
[tool.mypy]
strict = true
tsconfig.json (TypeScript - Strict)
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
Pièges courants
| Piège | Pourquoi cela arrive | Prévention |
|---|
| Mauvais .gitignore pour le langage | Modèle générique utilisé, entrées spécifiques au langage manquantes | Utilisez gitignore.io ou les modèles de GitHub pour votre pile |
| .env.example oublié | Les membres de l'équipe ne savent pas quelles variables d'environnement sont nécessaires | Créez .env.example avec chaque variable (valeurs vides) au début du projet |
| Aucun fichier de verrouillage validé | Versions de dépendances incohérentes entre les environnements | Validez package-lock.json, uv.lock, go.sum, Cargo.lock |
| Port/hôte codé en dur dans le code | Fonctionne localement, échoue dans Docker/le cloud | Lisez toujours à partir d'une variable d'environnement avec une valeur par défaut raisonnable |
| Tests couplés à une base de données réelle | Les tests échouent sans base de données en cours d'exécution, la configuration CI est complexe | Utilisez une base de données en mémoire ou une base de données de test conteneurisée (Testcontainers) |
| Absence de typage strict | Invite des bugs d'exécution qui auraient pu être détectés à la compilation | Activez strict: true dans tsconfig.json, utilisez mypy/my_py pour Python activé |
| Ignorer les paramètres régionaux Python | Les chemins de site-packages diffèrent ; pip installe par défaut à l'échelle du système | Utilisez toujours un environnement virtuel (venv, uv, poetry) ; ajoutez .python-version à .gitignore |
| Absence de Makefile générique | Les nouveaux arrivants ne savent pas comment exécuter/développer/tester | Créez des cibles Makefile pour les commandes courantes (make dev, make test, make build) |
| Absence de fichier docker-compose pour le support | Chaque développeur exécute des dépendances (DB, cache) différemment | Créez docker-compose.yml avec les services de développement dès le départ |
| Absence de contexte d'erreur dans les API | Les erreurs 500 ne fournissent aucun détail, le débogage est difficile | Utilisez des gestionnaires d'erreurs structurés avec journalisation ; ne divulguez pas les traces de pile en production |
| Notification de version manquante | Les dépendances peuvent avoir des failles de sécurité | Utilisez Dependabot ou Renovate pour les mises à jour automatisées des dépendances |
| Absence de licence | Utilisation peu claire par d'autres ; problèmes juridiques | Choisissez une licence OSI (MIT, Apache-2.0, GPL-3.0) en fonction de vos objectifs |
Meilleures pratiques
Règles générales
- La cohérence prime : le projet entier doit utiliser les mêmes conventions (dénomination, formatage, structure).
- Séparation des préoccupations : maintenez des couches distinctes pour le routage, la logique métier et l'accès aux données.
- Tout est asynchrone : pour les API et les E/S, utilisez async/await partout.
- Documentation en tant que code : utilisez OpenAPI, le typage et les docstrings comme documentation vivante.
- Dépendances minimales : n'ajoutez une dépendance que si elle résout un véritable problème.
Sécurité
- Validez toutes les entrées (schémas Pydantic, zod, validation express).
- Utilisez des requêtes paramétrées pour les bases de données (jamais de concaténation SQL).
- Stockez les secrets de manière sécurisée (variables d'environnement, coffre-fort de secrets).
- Activez CORS uniquement pour les origines nécessaires.
- Définissez des en-têtes de sécurité (Helmet pour Express, middleware de sécurité FastAPI).
- Rate-limitez les points de terminaison publics.
Tests
- Écrivez les tests en premier (TDD) lorsque cela est possible.
- Maintenez les tests rapides et indépendants.
- Utilisez des fixtures pour le contexte partagé (client de test, base de données, authentification).
- Testez les cas limites, pas seulement le chemin heureux.
- Visez >= 80 % de couverture de code sur les chemins principaux.
Gestion des erreurs
- Utilisez des exceptions personnalisées/classes d'erreur avec codes.
- Renvoyez des messages d'erreur structurés (code, message, détails).
- Enregistrez les erreurs avec le contexte (ID de requête, utilisateur, action).
- Ne divulguez jamais les détails internes dans les réponses en production.
Performances
- Utilisez la mise en cache (Redis, mise en cache en mémoire) pour les données fréquemment consultées.
- Implémentez la pagination pour les listes (curseur ou décalage+limite).
- Utilisez la compression (gzip) pour les réponses.
- Activez la connexion keep-alive pour les services backend.
- Profilez les requêtes lentes et optimisez les requêtes de base de données (index, sélection uniquement des champs nécessaires).
commandes d'initialisation spécifiques à la plateforme / au langage
| Language | Init Project | Ajouter des dépendances | Exécuter | Tester | Construire | Publier |
|---|
| Python | uv init | uv add pkg | uv run src/main.py | uv run pytest | uv build | uv publish |
| Node.js | npm init | npm install pkg | npm run dev | npm test | npm run build | npm publish |
| Go | go mod init | go get pkg | go run . | go test ./... | go build | (GitHub Release) |
| Rust | cargo init | cargo add pkg | cargo run | cargo test | cargo build | cargo publish |