Scaffold
Gabarits de scaffolding de projet et génération de code de base pour les types de projets courants avec des configurations par défaut optimisées.
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 la performance)
│ │ ├─ Go → Gin (ergonomique) ou Echo (riche en middleware)
│ │ └─ Rust → Axum (écosystème tower, asynchrone d'abord)
│ ├─ 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 / docs → Astro ou VitePress
│ └─ Marketing / landing → 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 stack
| 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 scaffolding rapides
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 de répertoire (Exemple FastAPI)
my-api/
├── src/
│ └── my_api/
│ ├── __init__.py
│ ├── main.py # Application FastAPI, cycle de vie, middleware
│ ├── config.py # Configuration pydantic-settings
│ ├── database.py # Moteur et session SQLAlchemy
│ ├── dependencies.py # Dépendances FastAPI partagées
│ ├── routers/
│ │ ├── __init__.py
│ │ ├── health.py # Point de terminaison de santé
│ │ └── users.py # Points de terminaison CRUD utilisateur
│ ├── models/
│ │ ├── __init__.py
│ │ └── user.py # Modèles SQLAlchemy
│ ├── schemas/
│ │ ├── __init__.py
│ │ └── user.py # Schémas Pydantic de requête/réponse
│ └── services/
│ ├── __init__.py
│ └── user.py # Logique métier
├── alembic/
│ ├── alembic.ini
│ ├── env.py
│ └── versions/
├── tests/
│ ├── conftest.py # Fixtures : BD de test, client, factories
│ ├── test_health.py
│ └── test_users.py
├── pyproject.toml
├── Dockerfile
├── docker-compose.yml
├── .env.example
├── .gitignore
└── .dockerignore
Structure de répertoire (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 Application Web
Structure de répertoire (Next.js App Router)
my-app/
├── src/
│ ├── app/
│ │ ├── layout.tsx # Layout racine
│ │ ├── page.tsx # Page d'accueil
│ │ ├── loading.tsx # UI de chargement global
│ │ ├── error.tsx # Frontière 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 # Helpers d'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 Outil CLI
Structure de répertoire (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 de répertoire (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 configuration Viper
│ └── runner/
│ └── runner.go # Logique centrale
├── main.go # Point d'entrée, appelle cmd.Execute()
├── go.mod
├── go.sum
├── Makefile
└── .gitignore
Modèle de projet Bibliothèque
Structure de répertoire (Package npm)
my-lib/
├── src/
│ ├── index.ts # Exportations de l'API publique
│ ├── core.ts # Implémentation centrale
│ └── types.ts # Définitions de types publics
├── tests/
│ └── core.test.ts
├── package.json # "type": "module", carte exports
├── tsconfig.json # declaration: true, declarationMap: true
├── tsup.config.ts # Configuration de build : cjs + esm
├── vitest.config.ts
├── .npmignore
├── .gitignore
├── CHANGELOG.md
└── LICENSE
Structure de répertoire (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 centrale
│ │ ├── 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 vérification des ajouts courants
Configuration du projet terminée ? Ajoutez ceci :
│
├─ Contrôle de version
│ ├─ [ ] .gitignore (spécifique au langage)
│ ├─ [ ] .gitattributes (fins de ligne, fichiers binaires)
│ └─ [ ] Règles de protection des branches
│
├─ CI/CD
│ ├─ [ ] Workflow GitHub Actions (test sur PR, déploiement sur merge)
│ ├─ [ ] Tests matriciels (OS, versions d'exécution)
│ └─ [ ] Automatisation des releases
│
├─ Docker
│ ├─ [ ] Dockerfile multi-étapes
│ ├─ [ ] docker-compose.yml (application + base de données + cache)
│ ├─ [ ] .dockerignore
│ └─ [ ] Point de terminaison de santé
│
├─ Qualité du code
│ ├─ [ ] Linter (ESLint, Ruff, golangci-lint, Clippy)
│ ├─ [ ] Formateur (Prettier, Black/Ruff, gofmt, rustfmt)
│ ├─ [ ] Hooks de pré-commit (Husky, pre-commit)
│ └─ [ ] Vérification de type (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)
├─ [ ] 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 se produit | Prévention |
|---|
| Mauvais .gitignore pour le langage | Utilisation d'un modèle générique, absence d'entrées spécifiques au langage | Utilisez gitignore.io ou les modèles GitHub pour votre stack |
| Oubli du .env.example | Les membres de l'équipe ne connaissent pas les variables d'environnement nécessaires | Créez un .env.example avec chaque variable (valeurs vides) au début du projet |
| Aucun fichier de verrouillage (lockfile) commité | Versions de dépendances incohérentes entre les environnements | Commitez package-lock.json, uv.lock, go.sum, Cargo.lock |
| Port/hôte codé en dur dans le code | Fonctionne localement, plante dans Docker/cloud | Lisez toujours depuis 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 des conteneurs de test ou SQLite en mémoire pour les tests unitaires |
| Point de terminaison de santé manquant | L'orchestrateur de déploiement ne peut pas vérifier la disponibilité | Ajoutez un point de terminaison /health qui renvoie l'état de l'application |
Règles et recommandations
Bonnes pratiques générales
- Utilisez des outils de scaffolding officiels lorsque disponibles (create-next-app, create-vite, cargo init).
- Choisissez votre stack tôt – l'arbre de décision ci-dessus vous aide à sélectionner les bons outils pour votre projet.
- Verrouillez les versions des dépendances avec un fichier de verrouillage pour assurer la reproductibilité des builds.
- Structurez votre code par fonctionnalité (feature-first) plutôt que par type technique pour les projets complexes.
- Versionnez les configurations en tant que code (infrastructure as code).
- Ajoutez un point de terminaison de santé à chaque projet déployé.
Gestion des environnements
- Utilisez un fichier
.env.example comme source de vérité pour les variables d'environnement requises.
- Pour Python, utilisez
pydantic-settings avec validation.
- Pour Node.js, utilisez
zod avec validation de schéma.
- Pour Go, utilisez
Viper pour la configuration.
- Ne commitez jamais de secrets (clés API, mots de passe) dans le dépôt.
Tests
- Isoler les tests unitaires des tests d'intégration.
- Utilisez des containers de test (Testcontainers) pour les bases de données.
- Configurez un pipeline de test CI pour chaque PR.
- Maintenez une couverture de test minimum de 80% pour le code critique.
Dockerisation
- Utilisez des builds multi-étapes pour réduire la taille des images.
- Évitez d'exécuter en tant que root dans le container.
- Ajoutez des sondes de santé (
HEALTHCHECK) à chaque service.
- Utilisez
.dockerignore pour exclure les fichiers inutiles de l'image.
Sécurité
- Validez et assainissez toutes les entrées utilisateur.
- Utilisez des requêtes paramétrées ou un ORM pour éviter les injections SQL.
- Activez CORS de manière sélective, pas en '*' en production.
- Utilisez des en-têtes de sécurité HTTP (Helmet pour Node.js, etc.).