/` pour les tranches métier, `api/router.py` comme point d'agrégation unique, `tests/` qui reflète les modules d'exécution.
+- **Ajouter un domaine** : copier `items/`, renommer entité / schémas / classes, mettre à jour les réexportations de `__init__.py`, enregistrer le routeur dans `src/app/api/router.py`, ajouter un module de test. Aucune édition dans `main.py`.
diff --git a/docs/fr/tutorial/first-project.md b/docs/fr/tutorial/first-project.md
new file mode 100644
index 0000000..e1da807
--- /dev/null
+++ b/docs/fr/tutorial/first-project.md
@@ -0,0 +1,1252 @@
+# Votre premier projet
+
+Construisez une API de blog complète avec gestion des utilisateurs, création de billets et système de commentaires en utilisant FastAPI-fastkit.
+
+## Vue d'ensemble du projet
+
+Dans ce tutoriel, nous allons créer une **API de blog** avec les fonctionnalités suivantes :
+
+- **Gestion des utilisateurs** : inscription, authentification et profils utilisateur
+- **Gestion des billets** : créer, lire, mettre à jour et supprimer des billets de blog
+- **Système de commentaires** : ajouter des commentaires aux billets
+- **Validation des données** : validation robuste des entrées et gestion des erreurs
+- **Documentation d'API** : documentation OpenAPI automatique
+- **Tests** : suite de tests complète
+
+### Ce que vous apprendrez
+
+À la fin de ce tutoriel, vous comprendrez :
+
+- La structure avancée d'un projet FastAPI-fastkit
+- L'intégration de base de données avec SQLAlchemy
+- L'authentification et l'autorisation des utilisateurs
+- Les relations de données complexes
+- La gestion des erreurs et la validation
+- Les bonnes pratiques de tests
+
+## Prérequis
+
+Avant de commencer, assurez-vous d'avoir :
+
+- Terminé le tutoriel [Prise en main](getting-started.md)
+- Une compréhension de base des API REST
+- Python 3.12+ installé
+- Un éditeur de texte ou IDE prêt
+
+## Étape 1 : Créer le projet
+
+Commençons par créer un nouveau projet avec la pile **STANDARD** pour la prise en charge des bases de données :
+
+
+
+```console
+$ fastkit init
+Enter the project name: blog-api
+Enter the author name: Your Name
+Enter the author email: your.email@example.com
+Enter the project description: A complete blog API with users, posts, and comments
+
+ Project Information
+┌──────────────┬─────────────────────────────────────────┐
+│ Project Name │ blog-api │
+│ Author │ Your Name │
+│ Author Email │ your.email@example.com │
+│ Description │ A complete blog API with users, posts, │
+│ │ and comments │
+└──────────────┴─────────────────────────────────────────┘
+
+Available Stacks and Dependencies:
+ MINIMAL Stack
+┌──────────────┬───────────────────┐
+│ Dependency 1 │ fastapi │
+│ Dependency 2 │ uvicorn │
+│ Dependency 3 │ pydantic │
+│ Dependency 4 │ pydantic-settings │
+└──────────────┴───────────────────┘
+
+ STANDARD Stack
+┌──────────────┬───────────────────┐
+│ Dependency 1 │ fastapi │
+│ Dependency 2 │ uvicorn │
+│ Dependency 3 │ sqlalchemy │
+│ Dependency 4 │ alembic │
+│ Dependency 5 │ pytest │
+│ Dependency 6 │ pydantic │
+│ Dependency 7 │ pydantic-settings │
+└──────────────┴───────────────────┘
+
+Select stack (minimal, standard, full): standard
+
+Available Package Managers:
+ Package Managers
+┌────────┬────────────────────────────────────────────┐
+│ PIP │ Standard Python package manager │
+│ UV │ Fast Python package manager │
+│ PDM │ Modern Python dependency management │
+│ POETRY │ Python dependency management and packaging │
+└────────┴────────────────────────────────────────────┘
+
+Select package manager (pip, uv, pdm, poetry) [uv]: uv
+Do you want to proceed with project creation? [y/N]: y
+
+✨ FastAPI project 'blog-api' has been created successfully!
+```
+
+
+
+## Étape 2 : Configurer le projet
+
+Allez dans le projet et activez l'environnement virtuel :
+
+
+
+```console
+$ cd blog-api
+$ source .venv/bin/activate
+```
+
+
+
+## Étape 3 : Ajouter les routes nécessaires
+
+Ajoutons les ressources principales de notre API de blog :
+
+
+
+```console
+$ fastkit addroute users blog-api
+✨ Successfully added new route 'users' to project 'blog-api'
+
+$ fastkit addroute posts blog-api
+✨ Successfully added new route 'posts' to project 'blog-api'
+
+$ fastkit addroute comments blog-api
+✨ Successfully added new route 'comments' to project 'blog-api'
+```
+
+
+
+## Étape 4 : Concevoir les modèles de données
+
+Concevons nos schémas de données. Commençons par mettre à jour le schéma utilisateur pour qu'il soit plus réaliste.
+
+### Mettre à jour le schéma utilisateur
+
+Modifiez `src/schemas/users.py` :
+
+```python
+from typing import Optional, List
+from datetime import datetime
+from pydantic import BaseModel, EmailStr, Field
+
+class UserBase(BaseModel):
+ email: EmailStr
+ username: str = Field(..., min_length=3, max_length=50)
+ full_name: Optional[str] = None
+ bio: Optional[str] = Field(None, max_length=500)
+ is_active: bool = True
+
+class UserCreate(UserBase):
+ password: str = Field(..., min_length=8)
+
+class UserUpdate(BaseModel):
+ email: Optional[EmailStr] = None
+ username: Optional[str] = Field(None, min_length=3, max_length=50)
+ full_name: Optional[str] = None
+ bio: Optional[str] = Field(None, max_length=500)
+ is_active: Optional[bool] = None
+
+class User(UserBase):
+ id: int
+ created_at: datetime
+ posts_count: int = 0
+
+ class Config:
+ from_attributes = True
+
+class UserInDB(User):
+ hashed_password: str
+```
+
+### Créer le schéma de billet
+
+Modifiez `src/schemas/posts.py` :
+
+```python
+from typing import Optional, List
+from datetime import datetime
+from pydantic import BaseModel, Field
+
+class PostBase(BaseModel):
+ title: str = Field(..., min_length=1, max_length=200)
+ content: str = Field(..., min_length=1)
+ published: bool = True
+
+class PostCreate(PostBase):
+ pass
+
+class PostUpdate(BaseModel):
+ title: Optional[str] = Field(None, min_length=1, max_length=200)
+ content: Optional[str] = Field(None, min_length=1)
+ published: Optional[bool] = None
+
+class Post(PostBase):
+ id: int
+ author_id: int
+ created_at: datetime
+ updated_at: datetime
+ comments_count: int = 0
+
+ class Config:
+ from_attributes = True
+
+class PostWithAuthor(Post):
+ author: "User"
+
+class PostWithComments(Post):
+ comments: List["Comment"] = []
+
+# Import to avoid circular imports
+from src.schemas.users import User
+from src.schemas.comments import Comment
+PostWithAuthor.model_rebuild()
+PostWithComments.model_rebuild()
+```
+
+### Créer le schéma de commentaire
+
+Modifiez `src/schemas/comments.py` :
+
+```python
+from typing import Optional
+from datetime import datetime
+from pydantic import BaseModel, Field
+
+class CommentBase(BaseModel):
+ content: str = Field(..., min_length=1, max_length=1000)
+
+class CommentCreate(CommentBase):
+ post_id: int
+
+class CommentUpdate(BaseModel):
+ content: Optional[str] = Field(None, min_length=1, max_length=1000)
+
+class Comment(CommentBase):
+ id: int
+ post_id: int
+ author_id: int
+ created_at: datetime
+ updated_at: datetime
+
+ class Config:
+ from_attributes = True
+
+class CommentWithAuthor(Comment):
+ author: "User"
+
+# Import to avoid circular imports
+from src.schemas.users import User
+CommentWithAuthor.model_rebuild()
+```
+
+## Étape 5 : Implémenter des opérations CRUD avancées
+
+### CRUD utilisateur enrichi
+
+Mettez à jour `src/crud/users.py` :
+
+```python
+from typing import List, Optional
+from datetime import datetime
+import hashlib
+from src.schemas.users import UserCreate, UserUpdate, UserInDB
+
+class UsersCRUD:
+ def __init__(self):
+ self._users: List[UserInDB] = []
+ self._next_id = 1
+
+ def _hash_password(self, password: str) -> str:
+ """Simple password hashing (use bcrypt in production)"""
+ return hashlib.sha256(password.encode()).hexdigest()
+
+ def _verify_password(self, plain_password: str, hashed_password: str) -> bool:
+ """Verify password against hash"""
+ return self._hash_password(plain_password) == hashed_password
+
+ def get_all(self) -> List[UserInDB]:
+ """Get all users"""
+ return [user for user in self._users if user.is_active]
+
+ def get_by_id(self, user_id: int) -> Optional[UserInDB]:
+ """Get user by ID"""
+ return next((user for user in self._users if user.id == user_id), None)
+
+ def get_by_email(self, email: str) -> Optional[UserInDB]:
+ """Get user by email"""
+ return next((user for user in self._users if user.email == email), None)
+
+ def get_by_username(self, username: str) -> Optional[UserInDB]:
+ """Get user by username"""
+ return next((user for user in self._users if user.username == username), None)
+
+ def create(self, user: UserCreate) -> UserInDB:
+ """Create a new user with validation"""
+ # Check for duplicates
+ if self.get_by_email(user.email):
+ raise ValueError("Email already registered")
+ if self.get_by_username(user.username):
+ raise ValueError("Username already taken")
+
+ new_user = UserInDB(
+ id=self._next_id,
+ email=user.email,
+ username=user.username,
+ full_name=user.full_name,
+ bio=user.bio,
+ is_active=user.is_active,
+ created_at=datetime.now(),
+ posts_count=0,
+ hashed_password=self._hash_password(user.password)
+ )
+ self._next_id += 1
+ self._users.append(new_user)
+ return new_user
+
+ def update(self, user_id: int, user_update: UserUpdate) -> Optional[UserInDB]:
+ """Update an existing user"""
+ user = self.get_by_id(user_id)
+ if not user:
+ return None
+
+ # Check for duplicates on email/username changes
+ update_data = user_update.dict(exclude_unset=True)
+ if "email" in update_data and update_data["email"] != user.email:
+ if self.get_by_email(update_data["email"]):
+ raise ValueError("Email already registered")
+
+ if "username" in update_data and update_data["username"] != user.username:
+ if self.get_by_username(update_data["username"]):
+ raise ValueError("Username already taken")
+
+ for field, value in update_data.items():
+ setattr(user, field, value)
+
+ return user
+
+ def delete(self, user_id: int) -> bool:
+ """Soft delete user (deactivate)"""
+ user = self.get_by_id(user_id)
+ if user:
+ user.is_active = False
+ return True
+ return False
+
+ def authenticate(self, email: str, password: str) -> Optional[UserInDB]:
+ """Authenticate user by email and password"""
+ user = self.get_by_email(email)
+ if user and self._verify_password(password, user.hashed_password):
+ return user
+ return None
+
+users_crud = UsersCRUD()
+```
+
+### CRUD des billets
+
+Mettez à jour `src/crud/posts.py` :
+
+```python
+from typing import List, Optional
+from datetime import datetime
+from src.schemas.posts import PostCreate, PostUpdate, Post
+
+class PostsCRUD:
+ def __init__(self):
+ self._posts: List[Post] = []
+ self._next_id = 1
+
+ def get_all(self, skip: int = 0, limit: int = 100, published_only: bool = True) -> List[Post]:
+ """Get all posts with pagination"""
+ posts = self._posts
+ if published_only:
+ posts = [post for post in posts if post.published]
+ return posts[skip:skip + limit]
+
+ def get_by_id(self, post_id: int) -> Optional[Post]:
+ """Get post by ID"""
+ return next((post for post in self._posts if post.id == post_id), None)
+
+ def get_by_author(self, author_id: int, skip: int = 0, limit: int = 100) -> List[Post]:
+ """Get posts by author"""
+ author_posts = [post for post in self._posts if post.author_id == author_id]
+ return author_posts[skip:skip + limit]
+
+ def create(self, post: PostCreate, author_id: int) -> Post:
+ """Create a new post"""
+ now = datetime.now()
+ new_post = Post(
+ id=self._next_id,
+ title=post.title,
+ content=post.content,
+ published=post.published,
+ author_id=author_id,
+ created_at=now,
+ updated_at=now,
+ comments_count=0
+ )
+ self._next_id += 1
+ self._posts.append(new_post)
+
+ # Update author's post count
+ from src.crud.users import users_crud
+ author = users_crud.get_by_id(author_id)
+ if author:
+ author.posts_count += 1
+
+ return new_post
+
+ def update(self, post_id: int, post_update: PostUpdate, author_id: int) -> Optional[Post]:
+ """Update an existing post"""
+ post = self.get_by_id(post_id)
+ if not post or post.author_id != author_id:
+ return None
+
+ update_data = post_update.dict(exclude_unset=True)
+ for field, value in update_data.items():
+ setattr(post, field, value)
+
+ post.updated_at = datetime.now()
+ return post
+
+ def delete(self, post_id: int, author_id: int) -> bool:
+ """Delete a post"""
+ post = self.get_by_id(post_id)
+ if post and post.author_id == author_id:
+ self._posts.remove(post)
+
+ # Update author's post count
+ from src.crud.users import users_crud
+ author = users_crud.get_by_id(author_id)
+ if author:
+ author.posts_count = max(0, author.posts_count - 1)
+
+ return True
+ return False
+
+ def search(self, query: str, skip: int = 0, limit: int = 100) -> List[Post]:
+ """Search posts by title or content"""
+ query_lower = query.lower()
+ matching_posts = [
+ post for post in self._posts
+ if post.published and (
+ query_lower in post.title.lower() or
+ query_lower in post.content.lower()
+ )
+ ]
+ return matching_posts[skip:skip + limit]
+
+posts_crud = PostsCRUD()
+```
+
+### CRUD des commentaires
+
+Mettez à jour `src/crud/comments.py` :
+
+```python
+from typing import List, Optional
+from datetime import datetime
+from src.schemas.comments import CommentCreate, CommentUpdate, Comment
+
+class CommentsCRUD:
+ def __init__(self):
+ self._comments: List[Comment] = []
+ self._next_id = 1
+
+ def get_all(self) -> List[Comment]:
+ """Get all comments"""
+ return self._comments
+
+ def get_by_id(self, comment_id: int) -> Optional[Comment]:
+ """Get comment by ID"""
+ return next((comment for comment in self._comments if comment.id == comment_id), None)
+
+ def get_by_post(self, post_id: int, skip: int = 0, limit: int = 100) -> List[Comment]:
+ """Get comments for a specific post"""
+ post_comments = [comment for comment in self._comments if comment.post_id == post_id]
+ return post_comments[skip:skip + limit]
+
+ def get_by_author(self, author_id: int, skip: int = 0, limit: int = 100) -> List[Comment]:
+ """Get comments by author"""
+ author_comments = [comment for comment in self._comments if comment.author_id == author_id]
+ return author_comments[skip:skip + limit]
+
+ def create(self, comment: CommentCreate, author_id: int) -> Comment:
+ """Create a new comment"""
+ # Verify post exists
+ from src.crud.posts import posts_crud
+ post = posts_crud.get_by_id(comment.post_id)
+ if not post:
+ raise ValueError("Post not found")
+
+ now = datetime.now()
+ new_comment = Comment(
+ id=self._next_id,
+ content=comment.content,
+ post_id=comment.post_id,
+ author_id=author_id,
+ created_at=now,
+ updated_at=now
+ )
+ self._next_id += 1
+ self._comments.append(new_comment)
+
+ # Update post's comment count
+ post.comments_count += 1
+
+ return new_comment
+
+ def update(self, comment_id: int, comment_update: CommentUpdate, author_id: int) -> Optional[Comment]:
+ """Update an existing comment"""
+ comment = self.get_by_id(comment_id)
+ if not comment or comment.author_id != author_id:
+ return None
+
+ update_data = comment_update.dict(exclude_unset=True)
+ for field, value in update_data.items():
+ setattr(comment, field, value)
+
+ comment.updated_at = datetime.now()
+ return comment
+
+ def delete(self, comment_id: int, author_id: int) -> bool:
+ """Delete a comment"""
+ comment = self.get_by_id(comment_id)
+ if comment and comment.author_id == author_id:
+ self._comments.remove(comment)
+
+ # Update post's comment count
+ from src.crud.posts import posts_crud
+ post = posts_crud.get_by_id(comment.post_id)
+ if post:
+ post.comments_count = max(0, post.comments_count - 1)
+
+ return True
+ return False
+
+comments_crud = CommentsCRUD()
+```
+
+## Étape 6 : Implémenter des routes d'API avancées
+
+### Routes utilisateur enrichies
+
+Mettez à jour `src/api/routes/users.py` :
+
+```python
+from typing import List
+from fastapi import APIRouter, HTTPException, status, Depends, Query
+from src.schemas.users import User, UserCreate, UserUpdate
+from src.crud.users import users_crud
+
+router = APIRouter()
+
+# Helper function to get current user (simplified for tutorial)
+def get_current_user_id() -> int:
+ # In a real app, this would verify JWT token and return user ID
+ return 1 # For tutorial purposes
+
+@router.get("/", response_model=List[User])
+def read_users(
+ skip: int = Query(0, ge=0),
+ limit: int = Query(100, ge=1, le=100)
+):
+ """Get all users with pagination"""
+ users = users_crud.get_all()[skip:skip + limit]
+ return [User(**user.dict()) for user in users]
+
+@router.post("/", response_model=User, status_code=status.HTTP_201_CREATED)
+def create_user(user: UserCreate):
+ """Register a new user"""
+ try:
+ new_user = users_crud.create(user)
+ return User(**new_user.dict())
+ except ValueError as e:
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail=str(e)
+ )
+
+@router.get("/{user_id}", response_model=User)
+def read_user(user_id: int):
+ """Get a specific user"""
+ user = users_crud.get_by_id(user_id)
+ if not user:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail=f"User with id {user_id} not found"
+ )
+ return User(**user.dict())
+
+@router.put("/{user_id}", response_model=User)
+def update_user(
+ user_id: int,
+ user_update: UserUpdate,
+ current_user_id: int = Depends(get_current_user_id)
+):
+ """Update user profile"""
+ if user_id != current_user_id:
+ raise HTTPException(
+ status_code=status.HTTP_403_FORBIDDEN,
+ detail="You can only update your own profile"
+ )
+
+ try:
+ updated_user = users_crud.update(user_id, user_update)
+ if not updated_user:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail="User not found"
+ )
+ return User(**updated_user.dict())
+ except ValueError as e:
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail=str(e)
+ )
+
+@router.delete("/{user_id}", status_code=status.HTTP_204_NO_CONTENT)
+def delete_user(
+ user_id: int,
+ current_user_id: int = Depends(get_current_user_id)
+):
+ """Deactivate user account"""
+ if user_id != current_user_id:
+ raise HTTPException(
+ status_code=status.HTTP_403_FORBIDDEN,
+ detail="You can only delete your own account"
+ )
+
+ success = users_crud.delete(user_id)
+ if not success:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail="User not found"
+ )
+
+@router.post("/login")
+def login(email: str, password: str):
+ """Authenticate user"""
+ user = users_crud.authenticate(email, password)
+ if not user:
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Invalid email or password"
+ )
+
+ # In a real app, return JWT token
+ return {
+ "message": "Login successful",
+ "user_id": user.id,
+ "username": user.username
+ }
+```
+
+### Routes de billets enrichies
+
+Mettez à jour `src/api/routes/posts.py` :
+
+```python
+from typing import List, Optional
+from fastapi import APIRouter, HTTPException, status, Depends, Query
+from src.schemas.posts import Post, PostCreate, PostUpdate
+from src.crud.posts import posts_crud
+
+router = APIRouter()
+
+def get_current_user_id() -> int:
+ return 1 # Simplified for tutorial
+
+@router.get("/", response_model=List[Post])
+def read_posts(
+ skip: int = Query(0, ge=0),
+ limit: int = Query(100, ge=1, le=100),
+ search: Optional[str] = Query(None)
+):
+ """Get all posts with optional search"""
+ if search:
+ posts = posts_crud.search(search, skip, limit)
+ else:
+ posts = posts_crud.get_all(skip, limit)
+ return posts
+
+@router.post("/", response_model=Post, status_code=status.HTTP_201_CREATED)
+def create_post(
+ post: PostCreate,
+ current_user_id: int = Depends(get_current_user_id)
+):
+ """Create a new blog post"""
+ new_post = posts_crud.create(post, current_user_id)
+ return new_post
+
+@router.get("/{post_id}", response_model=Post)
+def read_post(post_id: int):
+ """Get a specific post"""
+ post = posts_crud.get_by_id(post_id)
+ if not post:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail="Post not found"
+ )
+ return post
+
+@router.put("/{post_id}", response_model=Post)
+def update_post(
+ post_id: int,
+ post_update: PostUpdate,
+ current_user_id: int = Depends(get_current_user_id)
+):
+ """Update a blog post"""
+ updated_post = posts_crud.update(post_id, post_update, current_user_id)
+ if not updated_post:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail="Post not found or you don't have permission to edit it"
+ )
+ return updated_post
+
+@router.delete("/{post_id}", status_code=status.HTTP_204_NO_CONTENT)
+def delete_post(
+ post_id: int,
+ current_user_id: int = Depends(get_current_user_id)
+):
+ """Delete a blog post"""
+ success = posts_crud.delete(post_id, current_user_id)
+ if not success:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail="Post not found or you don't have permission to delete it"
+ )
+
+@router.get("/author/{author_id}", response_model=List[Post])
+def read_posts_by_author(
+ author_id: int,
+ skip: int = Query(0, ge=0),
+ limit: int = Query(100, ge=1, le=100)
+):
+ """Get posts by a specific author"""
+ posts = posts_crud.get_by_author(author_id, skip, limit)
+ return posts
+```
+
+### Routes de commentaires enrichies
+
+Mettez à jour `src/api/routes/comments.py` :
+
+```python
+from typing import List
+from fastapi import APIRouter, HTTPException, status, Depends, Query
+from src.schemas.comments import Comment, CommentCreate, CommentUpdate
+from src.crud.comments import comments_crud
+
+router = APIRouter()
+
+def get_current_user_id() -> int:
+ return 1 # Simplified for tutorial
+
+@router.get("/", response_model=List[Comment])
+def read_comments(
+ skip: int = Query(0, ge=0),
+ limit: int = Query(100, ge=1, le=100)
+):
+ """Get all comments"""
+ comments = comments_crud.get_all()[skip:skip + limit]
+ return comments
+
+@router.post("/", response_model=Comment, status_code=status.HTTP_201_CREATED)
+def create_comment(
+ comment: CommentCreate,
+ current_user_id: int = Depends(get_current_user_id)
+):
+ """Create a new comment"""
+ try:
+ new_comment = comments_crud.create(comment, current_user_id)
+ return new_comment
+ except ValueError as e:
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail=str(e)
+ )
+
+@router.get("/{comment_id}", response_model=Comment)
+def read_comment(comment_id: int):
+ """Get a specific comment"""
+ comment = comments_crud.get_by_id(comment_id)
+ if not comment:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail="Comment not found"
+ )
+ return comment
+
+@router.put("/{comment_id}", response_model=Comment)
+def update_comment(
+ comment_id: int,
+ comment_update: CommentUpdate,
+ current_user_id: int = Depends(get_current_user_id)
+):
+ """Update a comment"""
+ updated_comment = comments_crud.update(comment_id, comment_update, current_user_id)
+ if not updated_comment:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail="Comment not found or you don't have permission to edit it"
+ )
+ return updated_comment
+
+@router.delete("/{comment_id}", status_code=status.HTTP_204_NO_CONTENT)
+def delete_comment(
+ comment_id: int,
+ current_user_id: int = Depends(get_current_user_id)
+):
+ """Delete a comment"""
+ success = comments_crud.delete(comment_id, current_user_id)
+ if not success:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail="Comment not found or you don't have permission to delete it"
+ )
+
+@router.get("/post/{post_id}", response_model=List[Comment])
+def read_comments_by_post(
+ post_id: int,
+ skip: int = Query(0, ge=0),
+ limit: int = Query(100, ge=1, le=100)
+):
+ """Get comments for a specific post"""
+ comments = comments_crud.get_by_post(post_id, skip, limit)
+ return comments
+
+@router.get("/author/{author_id}", response_model=List[Comment])
+def read_comments_by_author(
+ author_id: int,
+ skip: int = Query(0, ge=0),
+ limit: int = Query(100, ge=1, le=100)
+):
+ """Get comments by a specific author"""
+ comments = comments_crud.get_by_author(author_id, skip, limit)
+ return comments
+```
+
+## Étape 7 : Tester votre API de blog
+
+Démarrons le serveur et testons notre API de blog complète :
+
+
+
+```console
+$ fastkit runserver
+INFO: Uvicorn running on http://127.0.0.1:8000
+```
+
+
+
+### Tester l'inscription d'un utilisateur
+
+
+
+```console
+$ curl -X POST "http://127.0.0.1:8000/api/v1/users/" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "email": "john@example.com",
+ "username": "john_doe",
+ "full_name": "John Doe",
+ "bio": "Software developer and blogger",
+ "password": "securepassword123"
+ }'
+
+{
+ "id": 1,
+ "email": "john@example.com",
+ "username": "john_doe",
+ "full_name": "John Doe",
+ "bio": "Software developer and blogger",
+ "is_active": true,
+ "created_at": "2023-12-07T10:30:00",
+ "posts_count": 0
+}
+```
+
+
+
+### Tester la connexion d'un utilisateur
+
+
+
+```console
+$ curl -X POST "http://127.0.0.1:8000/api/v1/users/login" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "email": "john@example.com",
+ "password": "securepassword123"
+ }'
+
+{
+ "message": "Login successful",
+ "user_id": 1,
+ "username": "john_doe"
+}
+```
+
+
+
+### Tester la création d'un billet
+
+
+
+```console
+$ curl -X POST "http://127.0.0.1:8000/api/v1/posts/" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "title": "My First Blog Post",
+ "content": "This is the content of my first blog post. It'\''s about learning FastAPI with FastAPI-fastkit!",
+ "published": true
+ }'
+
+{
+ "id": 1,
+ "title": "My First Blog Post",
+ "content": "This is the content of my first blog post. It's about learning FastAPI with FastAPI-fastkit!",
+ "published": true,
+ "author_id": 1,
+ "created_at": "2023-12-07T10:35:00",
+ "updated_at": "2023-12-07T10:35:00",
+ "comments_count": 0
+}
+```
+
+
+
+### Tester la création d'un commentaire
+
+
+
+```console
+$ curl -X POST "http://127.0.0.1:8000/api/v1/comments/" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "content": "Great post! I learned a lot from this.",
+ "post_id": 1
+ }'
+
+{
+ "id": 1,
+ "content": "Great post! I learned a lot from this.",
+ "post_id": 1,
+ "author_id": 1,
+ "created_at": "2023-12-07T10:40:00",
+ "updated_at": "2023-12-07T10:40:00"
+}
+```
+
+
+
+### Tester la fonctionnalité de recherche
+
+
+
+```console
+$ curl "http://127.0.0.1:8000/api/v1/posts/?search=FastAPI"
+
+[
+ {
+ "id": 1,
+ "title": "My First Blog Post",
+ "content": "This is the content of my first blog post. It's about learning FastAPI with FastAPI-fastkit!",
+ "published": true,
+ "author_id": 1,
+ "created_at": "2023-12-07T10:35:00",
+ "updated_at": "2023-12-07T10:35:00",
+ "comments_count": 1
+ }
+]
+```
+
+
+
+## Étape 8 : Documentation de l'API
+
+Rendez-vous sur [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) pour voir la documentation complète de votre API. Vous devriez désormais voir :
+
+- **Users** : inscription, connexion, gestion du profil
+- **Posts** : opérations CRUD, recherche, filtrage par auteur
+- **Comments** : opérations CRUD, filtrage par billet / auteur
+- **Items** : points d'extrémité d'exemple d'origine
+
+La documentation présente :
+
+- Tous les points d'extrémité disponibles
+- Les schémas de requête / réponse
+- Les règles de validation des données
+- Les réponses d'erreur
+
+## Étape 9 : Écrire des tests
+
+Créons des tests complets pour notre API de blog. Créez `tests/test_blog_api.py` :
+
+```python
+from fastapi.testclient import TestClient
+from src.main import app
+
+client = TestClient(app)
+
+class TestUserAPI:
+ def test_create_user(self):
+ user_data = {
+ "email": "test@example.com",
+ "username": "testuser",
+ "full_name": "Test User",
+ "bio": "Test bio",
+ "password": "testpassword123"
+ }
+ response = client.post("/api/v1/users/", json=user_data)
+ assert response.status_code == 201
+ data = response.json()
+ assert data["email"] == user_data["email"]
+ assert data["username"] == user_data["username"]
+ assert "id" in data
+ assert "hashed_password" not in data # Should not expose password
+
+ def test_duplicate_email(self):
+ # First user
+ user_data1 = {
+ "email": "duplicate@example.com",
+ "username": "user1",
+ "password": "password123"
+ }
+ response1 = client.post("/api/v1/users/", json=user_data1)
+ assert response1.status_code == 201
+
+ # Second user with same email
+ user_data2 = {
+ "email": "duplicate@example.com",
+ "username": "user2",
+ "password": "password123"
+ }
+ response2 = client.post("/api/v1/users/", json=user_data2)
+ assert response2.status_code == 400
+ assert "Email already registered" in response2.json()["detail"]
+
+ def test_login(self):
+ # Create user first
+ user_data = {
+ "email": "login@example.com",
+ "username": "loginuser",
+ "password": "loginpassword123"
+ }
+ client.post("/api/v1/users/", json=user_data)
+
+ # Tester la connexion
+ login_data = {
+ "email": "login@example.com",
+ "password": "loginpassword123"
+ }
+ response = client.post("/api/v1/users/login", json=login_data)
+ assert response.status_code == 200
+ data = response.json()
+ assert "user_id" in data
+ assert data["username"] == "loginuser"
+
+class TestPostAPI:
+ def test_create_post(self):
+ post_data = {
+ "title": "Test Post",
+ "content": "This is a test post content",
+ "published": True
+ }
+ response = client.post("/api/v1/posts/", json=post_data)
+ assert response.status_code == 201
+ data = response.json()
+ assert data["title"] == post_data["title"]
+ assert data["content"] == post_data["content"]
+ assert "id" in data
+ assert "author_id" in data
+
+ def test_read_posts(self):
+ response = client.get("/api/v1/posts/")
+ assert response.status_code == 200
+ data = response.json()
+ assert isinstance(data, list)
+
+ def test_search_posts(self):
+ # Create a post with specific content
+ post_data = {
+ "title": "FastAPI Tutorial",
+ "content": "Learn how to build APIs with FastAPI",
+ "published": True
+ }
+ client.post("/api/v1/posts/", json=post_data)
+
+ # Search for the post
+ response = client.get("/api/v1/posts/?search=FastAPI")
+ assert response.status_code == 200
+ data = response.json()
+ assert len(data) > 0
+ assert any("FastAPI" in post["title"] or "FastAPI" in post["content"] for post in data)
+
+class TestCommentAPI:
+ def test_create_comment(self):
+ # Create a post first
+ post_data = {
+ "title": "Post for Comments",
+ "content": "This post will receive comments",
+ "published": True
+ }
+ post_response = client.post("/api/v1/posts/", json=post_data)
+ post_id = post_response.json()["id"]
+
+ # Create comment
+ comment_data = {
+ "content": "This is a test comment",
+ "post_id": post_id
+ }
+ response = client.post("/api/v1/comments/", json=comment_data)
+ assert response.status_code == 201
+ data = response.json()
+ assert data["content"] == comment_data["content"]
+ assert data["post_id"] == post_id
+
+ def test_get_comments_by_post(self):
+ # Create post and comment first
+ post_data = {
+ "title": "Post with Comments",
+ "content": "This post has comments",
+ "published": True
+ }
+ post_response = client.post("/api/v1/posts/", json=post_data)
+ post_id = post_response.json()["id"]
+
+ comment_data = {
+ "content": "Comment on post",
+ "post_id": post_id
+ }
+ client.post("/api/v1/comments/", json=comment_data)
+
+ # Get comments for the post
+ response = client.get(f"/api/v1/comments/post/{post_id}")
+ assert response.status_code == 200
+ data = response.json()
+ assert len(data) > 0
+ assert all(comment["post_id"] == post_id for comment in data)
+
+# Run the tests
+if __name__ == "__main__":
+ import pytest
+ pytest.main([__file__])
+```
+
+### Lancer les tests
+
+
+
+```console
+$ python -m pytest tests/test_blog_api.py -v
+======================== test session starts ========================
+tests/test_blog_api.py::TestUserAPI::test_create_user PASSED
+tests/test_blog_api.py::TestUserAPI::test_duplicate_email PASSED
+tests/test_blog_api.py::TestUserAPI::test_login PASSED
+tests/test_blog_api.py::TestPostAPI::test_create_post PASSED
+tests/test_blog_api.py::TestPostAPI::test_read_posts PASSED
+tests/test_blog_api.py::TestPostAPI::test_search_posts PASSED
+tests/test_blog_api.py::TestCommentAPI::test_create_comment PASSED
+tests/test_blog_api.py::TestCommentAPI::test_get_comments_by_post PASSED
+======================== 8 passed in 1.23s ========================
+```
+
+
+
+## Ce que vous avez construit
+
+Félicitations ! Vous avez construit avec succès une API de blog complète avec :
+
+### ✅ Fonctionnalités implémentées
+
+- **Gestion des utilisateurs**
+ - Inscription d'utilisateur avec validation
+ - Authentification des utilisateurs (connexion)
+ - Gestion du profil
+ - Prévention des doublons
+
+- **Billets de blog**
+ - Créer, lire, mettre à jour, supprimer des billets
+ - Filtrage par auteur
+ - Fonctionnalité de recherche
+ - Statut publié / brouillon
+
+- **Système de commentaires**
+ - Ajouter des commentaires aux billets
+ - Voir les commentaires par billet ou par auteur
+ - Gestion des commentaires
+
+- **Validation des données**
+ - Validation d'e-mail
+ - Exigences sur les mots de passe
+ - Limites de longueur du contenu
+ - Validation des champs requis
+
+- **Gestion des erreurs**
+ - Codes d'état HTTP appropriés
+ - Messages d'erreur explicites
+ - Erreurs de validation des entrées
+
+- **Documentation d'API**
+ - Génération automatique d'OpenAPI
+ - Interface de test interactive
+ - Schémas de requête / réponse
+
+- **Tests**
+ - Couverture de tests complète
+ - Tests unitaires pour tous les points d'extrémité
+ - Tests de cas limites
+
+## Étapes suivantes
+
+### Améliorations possibles
+
+1. **Authentification réelle**
+ - Implémenter des tokens JWT
+ - Ajouter le hachage de mot de passe avec bcrypt
+ - Permissions basées sur les rôles
+
+2. **Intégration de base de données**
+ - Utiliser PostgreSQL ou MySQL
+ - Implémenter de vrais modèles de base de données
+ - Ajouter des migrations de base de données
+
+3. **Fonctionnalités avancées**
+ - Téléversement de fichiers pour les images
+ - Notifications par e-mail
+ - Catégories / étiquettes de billets
+ - Système de like / dislike
+
+4. **Préparation à la production**
+ - Ajouter de la journalisation
+ - Implémenter la mise en cache
+ - Ajouter de la limitation de débit
+ - Configuration d'environnement
+
+### Continuer à apprendre
+
+1. **[Utiliser les modèles](../user-guide/using-templates.md)** : explorer le modèle `fastapi-psql-orm` pour l'intégration de base de données
+2. **[Ajouter des routes](../user-guide/adding-routes.md)** : apprendre des motifs de routage plus avancés
+3. **[Contribution](../contributing/development-setup.md)** : contribuer à FastAPI-fastkit
+
+!!! tip "Bonnes pratiques que vous avez apprises"
+ - **Architecture modulaire** : séparation des préoccupations entre schémas, CRUD et routes
+ - **Validation des données** : utilisation de Pydantic pour une validation robuste des entrées
+ - **Gestion des erreurs** : codes d'état HTTP et messages d'erreur appropriés
+ - **Tests** : couverture de tests complète pour toutes les fonctionnalités
+ - **Documentation** : exploitation de la génération automatique de documentation d'API
+
+Vous avez maintenant les compétences pour construire des API de qualité production avec FastAPI-fastkit ! 🚀
diff --git a/docs/fr/tutorial/getting-started.md b/docs/fr/tutorial/getting-started.md
new file mode 100644
index 0000000..1b75380
--- /dev/null
+++ b/docs/fr/tutorial/getting-started.md
@@ -0,0 +1,564 @@
+# Prise en main
+
+Un tutoriel complet et pas à pas pour démarrer avec FastAPI-fastkit. Ce guide vous mènera de l'installation à l'exécution de votre première API en 15 minutes environ.
+
+## Prérequis
+
+Avant de commencer, assurez-vous d'avoir :
+
+- **Python 3.12 ou supérieur** installé sur votre système
+- **Une connaissance de base de Python** (variables, fonctions, classes)
+- **L'accès au terminal / à la ligne de commande**
+- **Un éditeur de texte ou un IDE** (VS Code, PyCharm, etc.)
+
+## Étape 1 : Installation
+
+Commençons par installer FastAPI-fastkit. Nous recommandons d'utiliser un environnement virtuel pour isoler vos projets.
+
+### Option A : avec pip (traditionnel)
+
+
+
+```console
+$ pip install fastapi-fastkit
+---> 100%
+Successfully installed fastapi-fastkit
+```
+
+
+
+### Option B : avec UV (recommandé — plus rapide)
+
+UV est un gestionnaire de paquets Python rapide. Si vous n'avez pas UV installé :
+
+
+
+```console
+# Installez d'abord UV
+$ curl -LsSf https://astral.sh/uv/install.sh | sh
+
+# Installez ensuite FastAPI-fastkit
+$ uv pip install fastapi-fastkit
+---> 100%
+Successfully installed fastapi-fastkit
+```
+
+
+
+### Option C : avec un environnement virtuel
+
+
+
+```console
+$ python -m venv fastapi-env
+$ source fastapi-env/bin/activate # On Windows: fastapi-env\Scripts\activate
+$ pip install fastapi-fastkit
+```
+
+
+
+### Vérifier l'installation
+
+Vérifiez que FastAPI-fastkit est correctement installé :
+
+
+
+```console
+$ fastkit --version
+FastAPI-fastkit version 1.0.0
+```
+
+
+
+## Étape 2 : Créer votre premier projet
+
+Créons maintenant votre premier projet FastAPI avec la commande interactive `init` :
+
+
+
+```console
+$ fastkit init
+Enter the project name: my-first-api
+Enter the author name: Your Name
+Enter the author email: your.email@example.com
+Enter the project description: My first FastAPI project
+
+ Project Information
+┌──────────────┬─────────────────────────┐
+│ Project Name │ my-first-api │
+│ Author │ Your Name │
+│ Author Email │ your.email@example.com │
+│ Description │ My first FastAPI project│
+└──────────────┴─────────────────────────┘
+
+Available Stacks and Dependencies:
+ MINIMAL Stack
+┌──────────────┬───────────────────┐
+│ Dependency 1 │ fastapi │
+│ Dependency 2 │ uvicorn │
+│ Dependency 3 │ pydantic │
+│ Dependency 4 │ pydantic-settings │
+└──────────────┴───────────────────┘
+
+ STANDARD Stack
+┌──────────────┬───────────────────┐
+│ Dependency 1 │ fastapi │
+│ Dependency 2 │ uvicorn │
+│ Dependency 3 │ sqlalchemy │
+│ Dependency 4 │ alembic │
+│ Dependency 5 │ pytest │
+│ Dependency 6 │ pydantic │
+│ Dependency 7 │ pydantic-settings │
+└──────────────┴───────────────────┘
+
+Select stack (minimal, standard, full): minimal
+
+Available Package Managers:
+ Package Managers
+┌────────┬────────────────────────────────────────────┐
+│ PIP │ Standard Python package manager │
+│ UV │ Fast Python package manager │
+│ PDM │ Modern Python dependency management │
+│ POETRY │ Python dependency management and packaging │
+└────────┴────────────────────────────────────────────┘
+
+Select package manager (pip, uv, pdm, poetry) [uv]: uv
+Do you want to proceed with project creation? [y/N]: y
+
+Creating virtual environment...
+Installing dependencies...
+✨ FastAPI project 'my-first-api' has been created successfully!
+```
+
+
+
+!!! note "Sélection de la pile"
+ Nous avons choisi **MINIMAL** pour ce tutoriel afin de garder les choses simples. Pour de vrais projets, envisagez **STANDARD** (inclut la prise en charge des bases de données) ou **FULL** (inclut les tâches en arrière-plan).
+
+## Étape 3 : Aller dans votre projet
+
+Déplacez-vous dans le répertoire du projet nouvellement créé :
+
+
+
+```console
+$ cd my-first-api
+$ ls -la
+total 32
+drwxr-xr-x 8 user user 256 Dec 7 10:30 .
+drwxr-xr-x 3 user user 96 Dec 7 10:30 ..
+drwxr-xr-x 5 user user 160 Dec 7 10:30 .venv
+-rw-r--r-- 1 user user 156 Dec 7 10:30 README.md
+-rw-r--r-- 1 user user 243 Dec 7 10:30 requirements.txt
+drwxr-xr-x 3 user user 96 Dec 7 10:30 scripts
+-rw-r--r-- 1 user user 1245 Dec 7 10:30 setup.py
+drwxr-xr-x 8 user user 256 Dec 7 10:30 src
+drwxr-xr-x 3 user user 96 Dec 7 10:30 tests
+```
+
+
+
+## Étape 4 : Activer l'environnement virtuel
+
+Votre projet est livré avec un environnement virtuel préconfiguré. Activez-le :
+
+
+
+```console
+$ source .venv/bin/activate # Sous Windows : .venv\Scripts\activate
+(my-first-api) $
+```
+
+
+
+Notez que votre invite de terminal affiche désormais `(my-first-api)`, ce qui indique que l'environnement virtuel est actif.
+
+## Étape 5 : Démarrer le serveur de développement
+
+Voici la partie excitante — démarrons votre serveur FastAPI :
+
+
+
+```console
+$ fastkit runserver
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+INFO: Started reloader process [28720] using StatReload
+INFO: Started server process [28722]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+```
+
+
+
+🎉 **Félicitations !** Votre serveur FastAPI tourne désormais.
+
+## Étape 6 : Tester votre API
+
+Testons votre API de plusieurs manières :
+
+### Méthode 1 : navigateur
+
+Ouvrez votre navigateur web et visitez :
+
+- **Point d'extrémité principal de l'API** : [http://127.0.0.1:8000](http://127.0.0.1:8000)
+
+Vous devriez voir :
+```json
+{"message": "Hello World"}
+```
+
+### Méthode 2 : documentation interactive de l'API
+
+Visitez la documentation d'API générée automatiquement :
+
+- **Swagger UI** : [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)
+- **ReDoc** : [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)
+
+Swagger UI est particulièrement utile — vous pouvez :
+
+- Voir tous les points d'extrémité disponibles
+- Tester les points d'extrémité directement dans votre navigateur
+- Consulter les schémas de requête / réponse
+- Télécharger les spécifications OpenAPI
+
+### Méthode 3 : ligne de commande
+
+Ouvrez un nouveau terminal (gardez le serveur en marche) et testez avec curl :
+
+
+
+```console
+$ curl http://127.0.0.1:8000
+{"message":"Hello World"}
+
+$ curl http://127.0.0.1:8000/api/v1/items/
+[]
+
+$ curl -X POST "http://127.0.0.1:8000/api/v1/items/" \
+ -H "Content-Type: application/json" \
+ -d '{"title": "My First Item", "description": "This is a test item"}'
+{
+ "id": 1,
+ "title": "My First Item",
+ "description": "This is a test item"
+}
+```
+
+
+
+## Étape 7 : Comprendre la structure de votre projet
+
+Explorons ce que FastAPI-fastkit a généré pour vous :
+
+
+
+```console
+$ tree src
+src/
+├── __init__.py
+├── main.py # Point d'entrée de l'application FastAPI
+├── core/
+│ ├── __init__.py
+│ └── config.py # Configuration de l'application
+├── api/
+│ ├── __init__.py
+│ ├── api.py # Routeur API principal
+│ └── routes/
+│ ├── __init__.py
+│ └── items.py # Points d'extrémité de l'API des items
+├── crud/
+│ ├── __init__.py
+│ └── items.py # Logique métier des items
+├── schemas/
+│ ├── __init__.py
+│ └── items.py # Schémas de validation des données
+└── mocks/
+ ├── __init__.py
+ └── mock_items.json # Données d'exemple
+```
+
+
+
+### Fichiers clés expliqués
+
+**`src/main.py`** — le cœur de votre application :
+```python
+from fastapi import FastAPI
+from src.api.api import api_router
+from src.core.config import settings
+
+app = FastAPI(
+ title=settings.PROJECT_NAME,
+ version=settings.VERSION,
+ openapi_url=f"{settings.API_V1_STR}/openapi.json"
+)
+
+app.include_router(api_router, prefix=settings.API_V1_STR)
+
+@app.get("/")
+def read_root():
+ return {"message": "Hello World"}
+```
+
+**`src/core/config.py`** — paramètres de l'application :
+```python
+from pydantic_settings import BaseSettings
+
+class Settings(BaseSettings):
+ PROJECT_NAME: str = "my-first-api"
+ VERSION: str = "1.0.0"
+ API_V1_STR: str = "/api/v1"
+
+ class Config:
+ env_file = ".env"
+
+settings = Settings()
+```
+
+**`src/api/routes/items.py`** — points d'extrémité d'API :
+```python
+from typing import List
+from fastapi import APIRouter, HTTPException
+from src.schemas.items import Item, ItemCreate, ItemUpdate
+from src.crud.items import items_crud
+
+router = APIRouter()
+
+@router.get("/", response_model=List[Item])
+def read_items():
+ """Get all items"""
+ return items_crud.get_all()
+
+@router.post("/", response_model=Item)
+def create_item(item: ItemCreate):
+ """Create a new item"""
+ return items_crud.create(item)
+```
+
+## Étape 8 : Ajouter votre première route personnalisée
+
+Ajoutons une nouvelle route d'API pour pratiquer ce que vous avez appris :
+
+
+
+```console
+$ fastkit addroute users my-first-api
+ Adding New Route
+┌──────────────────┬──────────────────────────────────────────┐
+│ Project │ my-first-api │
+│ Route Name │ users │
+│ Target Directory │ ~/my-first-api │
+└──────────────────┴──────────────────────────────────────────┘
+
+Do you want to add route 'users' to project 'my-first-api'? [Y/n]: y
+
+✨ Successfully added new route 'users' to project 'my-first-api'
+```
+
+
+
+Le serveur va redémarrer automatiquement et vous disposez maintenant de nouveaux points d'extrémité :
+
+- `GET /api/v1/users/` — récupérer tous les utilisateurs
+- `POST /api/v1/users/` — créer un nouvel utilisateur
+- `GET /api/v1/users/{user_id}` — récupérer un utilisateur précis
+- Et plus encore…
+
+### Tester votre nouvelle route
+
+
+
+```console
+$ curl -X POST "http://127.0.0.1:8000/api/v1/users/" \
+ -H "Content-Type: application/json" \
+ -d '{"title": "John Doe", "description": "Software Developer"}'
+{
+ "id": 1,
+ "title": "John Doe",
+ "description": "Software Developer"
+}
+
+$ curl http://127.0.0.1:8000/api/v1/users/
+[
+ {
+ "id": 1,
+ "title": "John Doe",
+ "description": "Software Developer"
+ }
+]
+```
+
+
+
+## Étape 9 : Explorer et modifier le code
+
+Faisons une petite modification pour comprendre comment fonctionne le code.
+
+### Modifier le message d'accueil
+
+Ouvrez `src/main.py` dans votre éditeur de texte et modifiez le point d'extrémité racine :
+
+```python
+@app.get("/")
+def read_root():
+ return {"message": "Welcome to my first FastAPI application!"}
+```
+
+Enregistrez le fichier. Grâce au rechargement automatique, votre serveur redémarre automatiquement.
+
+### Tester la modification
+
+
+
+```console
+$ curl http://127.0.0.1:8000
+{"message":"Welcome to my first FastAPI application!"}
+```
+
+
+
+### Ajouter un nouveau point d'extrémité
+
+Ajoutons un point d'extrémité simple à `src/main.py` :
+
+```python
+@app.get("/hello/{name}")
+def say_hello(name: str):
+ return {"message": f"Hello, {name}!"}
+```
+
+### Tester le nouveau point d'extrémité
+
+
+
+```console
+$ curl http://127.0.0.1:8000/hello/World
+{"message":"Hello, World!"}
+
+$ curl http://127.0.0.1:8000/hello/FastAPI
+{"message":"Hello, FastAPI!"}
+```
+
+
+
+## Étape 10 : Lancer les tests
+
+Votre projet est livré avec des tests préconfigurés. Lançons-les :
+
+
+
+```console
+$ python -m pytest
+======================== test session starts ========================
+collected 5 items
+
+tests/test_items.py::test_create_item PASSED
+tests/test_items.py::test_read_items PASSED
+tests/test_items.py::test_read_item PASSED
+tests/test_items.py::test_update_item PASSED
+tests/test_items.py::test_delete_item PASSED
+
+======================== 5 passed in 0.45s ========================
+```
+
+
+
+## Comprendre les concepts clés
+
+### 1. Structure de l'application FastAPI
+
+FastAPI-fastkit suit une **architecture modulaire** :
+
+- **`main.py`** : point d'entrée de l'application et points d'extrémité globaux
+- **`api/`** : organisation des routes d'API
+- **`core/`** : configuration et paramètres de l'application
+- **`crud/`** : logique métier et opérations sur les données
+- **`schemas/`** : validation et sérialisation des données
+- **`tests/`** : tests automatisés
+
+### 2. Gestion des dépendances
+
+Votre projet utilise une gestion moderne des dépendances Python :
+
+- **Environnement virtuel** : environnement Python isolé
+- **requirements.txt** : liste toutes les dépendances
+- **Installation automatique** : dépendances installées lors de la création du projet
+
+### 3. Serveur de développement
+
+FastAPI-fastkit utilise **Uvicorn** comme serveur ASGI :
+
+- **Rechargement automatique** : redémarre automatiquement lors des changements de code
+- **Démarrage rapide** : itération de développement rapide
+- **Prêt pour la production** : même serveur que celui utilisé en production
+
+### 4. Documentation d'API
+
+FastAPI génère automatiquement :
+
+- **Spécification OpenAPI** : documentation d'API conforme aux standards de l'industrie
+- **Swagger UI** : interface de test interactive
+- **ReDoc** : vue alternative de la documentation
+
+## Étapes suivantes
+
+Félicitations ! Vous avez :
+
+✅ Installé FastAPI-fastkit
+✅ Créé votre premier projet
+✅ Démarré le serveur de développement
+✅ Testé vos points d'extrémité d'API
+✅ Ajouté une nouvelle route
+✅ Modifié du code existant
+✅ Lancé les tests
+
+### Continuer à apprendre
+
+1. **[Votre premier projet](first-project.md)** : construire une API de blog complète avec des fonctionnalités avancées
+2. **[Ajouter des routes](../user-guide/adding-routes.md)** : apprendre à créer des points d'extrémité d'API complexes
+3. **[Utiliser les modèles](../user-guide/using-templates.md)** : explorer les modèles de projet prêts à l'emploi
+
+### Expérimenter davantage
+
+Essayez ces défis :
+
+1. **Ajouter de la validation** : modifier les schémas pour ajouter des règles de validation des données
+2. **Réponses personnalisées** : changer les formats de réponse dans les routes
+3. **Variables d'environnement** : utiliser des fichiers `.env` pour la configuration
+4. **Ajouter un middleware** : implémenter CORS ou l'authentification
+5. **Intégration de base de données** : passer à la pile STANDARD pour la prise en charge des bases de données
+
+### Problèmes courants et solutions
+
+**Le serveur ne démarre pas :**
+
+- Vérifiez que vous êtes dans le répertoire du projet
+- Assurez-vous que l'environnement virtuel est activé
+- Vérifiez l'absence d'erreurs de syntaxe dans votre code
+
+**Erreurs d'import :**
+
+- Assurez-vous que tous les fichiers `__init__.py` existent
+- Vérifiez que vos chemins d'import sont corrects
+- Vérifiez que vous utilisez l'environnement virtuel
+
+**Port déjà utilisé :**
+```console
+$ fastkit runserver --port 8080
+```
+
+## Bonnes pratiques que vous avez apprises
+
+1. **Environnements virtuels** : toujours utiliser des environnements isolés
+2. **Structure de projet** : suivre une architecture modulaire organisée
+3. **Rechargement automatique** : utiliser le serveur de développement pour une itération rapide
+4. **Documentation d'API** : exploiter la génération automatique de documentation
+5. **Tests** : exécuter les tests régulièrement pendant le développement
+
+!!! tip "Astuces de développement"
+ - Gardez le serveur de développement en marche pendant que vous codez
+ - Utilisez la documentation interactive (`/docs`) pour tester vos API
+ - Consultez le terminal pour des messages d'erreur utiles
+ - Committez votre code dans un système de contrôle de version régulièrement
+
+Vous êtes maintenant prêt à construire de superbes API avec FastAPI-fastkit ! 🚀
diff --git a/docs/fr/tutorial/mcp-integration.md b/docs/fr/tutorial/mcp-integration.md
new file mode 100644
index 0000000..a93ddd7
--- /dev/null
+++ b/docs/fr/tutorial/mcp-integration.md
@@ -0,0 +1,1730 @@
+# Intégration MCP (Model Context Protocol)
+
+Apprenez à intégrer le Model Context Protocol (MCP) à FastAPI pour construire un système où les modèles d'IA peuvent utiliser les points d'extrémité d'API comme des outils. Nous allons implémenter une API complète intégrée à l'IA, incluant l'authentification, la gestion des permissions et l'implémentation d'un serveur MCP avec le modèle `fastapi-mcp`.
+
+## Ce que vous apprendrez dans ce tutoriel
+
+- Concepts et implémentation du Model Context Protocol (MCP)
+- Construire un système d'authentification basé sur JWT
+- Implémenter le contrôle d'accès basé sur les rôles (RBAC)
+- Exposer et gérer des outils MCP
+- Communication sécurisée d'API avec des modèles d'IA
+- Gestion des sessions et du contexte utilisateur
+
+## Prérequis
+
+- Tutoriel [Gestion des réponses personnalisées](custom-response-handling.md) terminé
+- Compréhension des concepts de base de JWT et OAuth2
+- Concepts de communication d'API avec les modèles d'IA / LLM
+- Connaissances de base du protocole MCP
+
+## Qu'est-ce que le Model Context Protocol (MCP) ?
+
+MCP est un protocole standardisé qui permet aux modèles d'IA d'interagir avec des systèmes externes.
+
+### Approche traditionnelle vs MCP
+
+**Approche traditionnelle (appels d'API directs) :**
+```
+AI Model → HTTP Request → API Server → Response
+```
+
+**Approche MCP :**
+```
+AI Model → MCP Client → MCP Server (FastAPI) → Safe Tool Execution → Response
+```
+
+### Avantages de MCP
+
+- **Sécurité** : authentification et gestion des permissions intégrées
+- **Standardisation** : fourniture d'une interface cohérente
+- **Gestion du contexte** : maintien de l'état basé sur les sessions
+- **Abstraction des outils** : exposer des API complexes en tant qu'outils simples
+
+## Étape 1 : Créer un projet d'intégration MCP
+
+Créez un projet avec le modèle `fastapi-mcp` :
+
+
+
+```console
+$ fastkit startdemo fastapi-mcp
+Enter the project name: ai-integrated-api
+Enter the author name: Developer Kim
+Enter the author email: developer@example.com
+Enter the project description: MCP-based API server integrated with AI models
+Deploying FastAPI project using 'fastapi-mcp' template
+
+ Project Information
+┌──────────────┬─────────────────────────────────────────────┐
+│ Project Name │ ai-integrated-api │
+│ Author │ Developer Kim │
+│ Author Email │ developer@example.com │
+│ Description │ MCP-based API server integrated with AI models │
+└──────────────┴─────────────────────────────────────────────┘
+
+ Template Dependencies
+┌──────────────┬────────────────┐
+│ Dependency 1 │ fastapi │
+│ Dependency 2 │ uvicorn │
+│ Dependency 3 │ pydantic │
+│ Dependency 4 │ python-jose │
+│ Dependency 5 │ passlib │
+│ Dependency 6 │ python-multipart│
+│ Dependency 7 │ mcp │
+└──────────────┴────────────────┘
+
+Select package manager (pip, uv, pdm, poetry) [uv]: uv
+Do you want to proceed with project creation? [y/N]: y
+
+✨ FastAPI project 'ai-integrated-api' from 'fastapi-mcp' has been created successfully!
+```
+
+
+
+## Étape 2 : Analyse de la structure du projet
+
+Examinons la structure du projet généré :
+
+```
+ai-integrated-api/
+├── src/
+│ ├── main.py # FastAPI application
+│ ├── auth/
+│ │ ├── __init__.py
+│ │ ├── models.py # Authentication-related data models
+│ │ ├── jwt_handler.py # JWT token processing
+│ │ ├── dependencies.py # Authentication dependencies
+│ │ └── routes.py # Authentication router
+│ ├── mcp/
+│ │ ├── __init__.py
+│ │ ├── server.py # MCP server implementation
+│ │ ├── tools.py # MCP tool definitions
+│ │ └── client.py # MCP client (for testing)
+│ ├── api/
+│ │ ├── __init__.py
+│ │ ├── api.py # Regroupement des routeurs API
+│ │ └── routes/
+│ │ ├── items.py # Item management API
+│ │ ├── users.py # User management API
+│ │ └── admin.py # Admin API
+│ ├── schemas/
+│ │ ├── __init__.py
+│ │ ├── auth.py # Authentication schemas
+│ │ ├── users.py # User schemas
+│ │ └── items.py # Item schemas
+│ └── core/
+│ ├── __init__.py
+│ ├── config.py # Configuration
+│ ├── database.py # Database (in-memory)
+│ └── security.py # Security configuration
+└── tests/
+ ├── test_auth.py # Authentication tests
+ ├── test_mcp.py # MCP tests
+ └── test_integration.py # Integration tests
+```
+
+## Étape 3 : Implémentation du système d'authentification
+
+### Traitement des tokens JWT (`src/auth/jwt_handler.py`)
+
+```python
+from datetime import datetime, timedelta
+from typing import Optional, Dict, Any
+from jose import JWTError, jwt
+from passlib.context import CryptContext
+
+from src.core.config import settings
+
+# Password hashing
+pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
+
+def verify_password(plain_password: str, hashed_password: str) -> bool:
+ """Password verification"""
+ return pwd_context.verify(plain_password, hashed_password)
+
+def get_password_hash(password: str) -> str:
+ """Password hashing"""
+ return pwd_context.hash(password)
+
+def create_access_token(data: Dict[str, Any], expires_delta: Optional[timedelta] = None) -> str:
+ """Access token generation"""
+ to_encode = data.copy()
+
+ if expires_delta:
+ expire = datetime.utcnow() + expires_delta
+ else:
+ expire = datetime.utcnow() + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
+
+ to_encode.update({"exp": expire, "iat": datetime.utcnow()})
+
+ encoded_jwt = jwt.encode(
+ to_encode,
+ settings.SECRET_KEY,
+ algorithm=settings.ALGORITHM
+ )
+
+ return encoded_jwt
+
+def create_refresh_token(user_id: str) -> str:
+ """Refresh token generation"""
+ data = {"sub": user_id, "type": "refresh"}
+ expire = datetime.utcnow() + timedelta(days=settings.REFRESH_TOKEN_EXPIRE_DAYS)
+
+ to_encode = data.copy()
+ to_encode.update({"exp": expire, "iat": datetime.utcnow()})
+
+ return jwt.encode(
+ to_encode,
+ settings.SECRET_KEY,
+ algorithm=settings.ALGORITHM
+ )
+
+def decode_token(token: str) -> Optional[Dict[str, Any]]:
+ """Token decoding"""
+ try:
+ payload = jwt.decode(
+ token,
+ settings.SECRET_KEY,
+ algorithms=[settings.ALGORITHM]
+ )
+ return payload
+ except JWTError:
+ return None
+
+def verify_token(token: str, token_type: str = "access") -> Optional[str]:
+ """Token verification and user ID return"""
+ payload = decode_token(token)
+
+ if not payload:
+ return None
+
+ # Token type verification
+ if token_type == "refresh" and payload.get("type") != "refresh":
+ return None
+
+ user_id = payload.get("sub")
+ if not user_id:
+ return None
+
+ return user_id
+
+class TokenManager:
+ """Token management class"""
+
+ def __init__(self):
+ self.blacklisted_tokens = set()
+
+ def blacklist_token(self, token: str):
+ """Add token to blacklist"""
+ self.blacklisted_tokens.add(token)
+
+ def is_blacklisted(self, token: str) -> bool:
+ """Check if token is blacklisted"""
+ return token in self.blacklisted_tokens
+
+ def create_token_pair(self, user_id: str, user_role: str) -> Dict[str, str]:
+ """Create access/refresh token pair"""
+ access_token_data = {
+ "sub": user_id,
+ "role": user_role,
+ "type": "access"
+ }
+
+ access_token = create_access_token(access_token_data)
+ refresh_token = create_refresh_token(user_id)
+
+ return {
+ "access_token": access_token,
+ "refresh_token": refresh_token,
+ "token_type": "bearer"
+ }
+
+# Global token manager
+token_manager = TokenManager()
+```
+
+### Modèles d'utilisateur et base de données (`src/auth/models.py`)
+
+```python
+from typing import List, Optional, Dict, Any
+from pydantic import BaseModel, EmailStr
+from enum import Enum
+from datetime import datetime
+
+class UserRole(str, Enum):
+ """User roles"""
+ ADMIN = "admin"
+ USER = "user"
+ AI_AGENT = "ai_agent"
+ READONLY = "readonly"
+
+class Permission(str, Enum):
+ """Permissions"""
+ READ_ITEMS = "read:items"
+ WRITE_ITEMS = "write:items"
+ DELETE_ITEMS = "delete:items"
+ MANAGE_USERS = "manage:users"
+ USE_MCP_TOOLS = "use:mcp_tools"
+ ADMIN_MCP = "admin:mcp"
+
+class User(BaseModel):
+ """User model"""
+ id: str
+ email: EmailStr
+ username: str
+ full_name: Optional[str] = None
+ role: UserRole
+ permissions: List[Permission]
+ is_active: bool = True
+ created_at: datetime
+ last_login: Optional[datetime] = None
+ api_key: Optional[str] = None # For MCP client
+
+class UserInDB(User):
+ """User model for database storage"""
+ hashed_password: str
+
+class UserCreate(BaseModel):
+ """User creation schema"""
+ email: EmailStr
+ username: str
+ password: str
+ full_name: Optional[str] = None
+ role: UserRole = UserRole.USER
+
+class UserUpdate(BaseModel):
+ """User update schema"""
+ email: Optional[EmailStr] = None
+ username: Optional[str] = None
+ full_name: Optional[str] = None
+ role: Optional[UserRole] = None
+ is_active: Optional[bool] = None
+
+class LoginRequest(BaseModel):
+ """Login request schema"""
+ username: str
+ password: str
+
+class TokenResponse(BaseModel):
+ """Token response schema"""
+ access_token: str
+ refresh_token: str
+ token_type: str = "bearer"
+ expires_in: int
+ user: User
+
+# Default permission mapping by role
+ROLE_PERMISSIONS = {
+ UserRole.ADMIN: [
+ Permission.READ_ITEMS,
+ Permission.WRITE_ITEMS,
+ Permission.DELETE_ITEMS,
+ Permission.MANAGE_USERS,
+ Permission.USE_MCP_TOOLS,
+ Permission.ADMIN_MCP
+ ],
+ UserRole.USER: [
+ Permission.READ_ITEMS,
+ Permission.WRITE_ITEMS,
+ Permission.USE_MCP_TOOLS
+ ],
+ UserRole.AI_AGENT: [
+ Permission.READ_ITEMS,
+ Permission.WRITE_ITEMS,
+ Permission.USE_MCP_TOOLS
+ ],
+ UserRole.READONLY: [
+ Permission.READ_ITEMS
+ ]
+}
+
+class UserDatabase:
+ """Memory-based user database"""
+
+ def __init__(self):
+ self.users: Dict[str, UserInDB] = {}
+ self._init_default_users()
+
+ def _init_default_users(self):
+ """Create default users"""
+ from src.auth.jwt_handler import get_password_hash
+ import uuid
+
+ # Admin account
+ admin_id = str(uuid.uuid4())
+ self.users[admin_id] = UserInDB(
+ id=admin_id,
+ email="admin@example.com",
+ username="admin",
+ full_name="System Administrator",
+ role=UserRole.ADMIN,
+ permissions=ROLE_PERMISSIONS[UserRole.ADMIN],
+ hashed_password=get_password_hash("admin123"),
+ created_at=datetime.utcnow(),
+ api_key=str(uuid.uuid4())
+ )
+
+ # AI agent account
+ ai_id = str(uuid.uuid4())
+ self.users[ai_id] = UserInDB(
+ id=ai_id,
+ email="ai@example.com",
+ username="ai_agent",
+ full_name="AI Assistant",
+ role=UserRole.AI_AGENT,
+ permissions=ROLE_PERMISSIONS[UserRole.AI_AGENT],
+ hashed_password=get_password_hash("ai123"),
+ created_at=datetime.utcnow(),
+ api_key=str(uuid.uuid4())
+ )
+
+ def get_user_by_username(self, username: str) -> Optional[UserInDB]:
+ """Get user by username"""
+ return next(
+ (user for user in self.users.values() if user.username == username),
+ None
+ )
+
+ def get_user_by_id(self, user_id: str) -> Optional[UserInDB]:
+ """Get user by ID"""
+ return self.users.get(user_id)
+
+ def get_user_by_api_key(self, api_key: str) -> Optional[UserInDB]:
+ """Get user by API key"""
+ return next(
+ (user for user in self.users.values() if user.api_key == api_key),
+ None
+ )
+
+ def create_user(self, user_create: UserCreate) -> UserInDB:
+ """Create user"""
+ import uuid
+ from src.auth.jwt_handler import get_password_hash
+
+ user_id = str(uuid.uuid4())
+ user = UserInDB(
+ id=user_id,
+ email=user_create.email,
+ username=user_create.username,
+ full_name=user_create.full_name,
+ role=user_create.role,
+ permissions=ROLE_PERMISSIONS[user_create.role],
+ hashed_password=get_password_hash(user_create.password),
+ created_at=datetime.utcnow(),
+ api_key=str(uuid.uuid4())
+ )
+
+ self.users[user_id] = user
+ return user
+
+ def update_user(self, user_id: str, user_update: UserUpdate) -> Optional[UserInDB]:
+ """Update user"""
+ if user_id not in self.users:
+ return None
+
+ user = self.users[user_id]
+ update_data = user_update.dict(exclude_unset=True)
+
+ for field, value in update_data.items():
+ setattr(user, field, value)
+
+ # Update permissions if role changed
+ if "role" in update_data:
+ user.permissions = ROLE_PERMISSIONS[user.role]
+
+ return user
+
+ def update_last_login(self, user_id: str):
+ """Update last login time"""
+ if user_id in self.users:
+ self.users[user_id].last_login = datetime.utcnow()
+
+# Global database instance
+user_db = UserDatabase()
+```
+
+## Étape 4 : Implémentation des dépendances d'authentification
+
+### Dépendances d'authentification (`src/auth/dependencies.py`)
+
+```python
+from typing import Optional, List
+from fastapi import Depends, HTTPException, status, Security
+from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials, APIKeyHeader
+from jose import JWTError
+
+from src.auth.jwt_handler import decode_token, token_manager
+from src.auth.models import User, UserInDB, Permission, user_db
+
+# Security schema
+security = HTTPBearer()
+api_key_header = APIKeyHeader(name="X-API-Key", auto_error=False)
+
+async def get_current_user(
+ credentials: HTTPAuthorizationCredentials = Security(security)
+) -> User:
+ """Get current authenticated user"""
+ credentials_exception = HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Could not validate credentials",
+ headers={"WWW-Authenticate": "Bearer"},
+ )
+
+ try:
+ token = credentials.credentials
+
+ # Check blacklist
+ if token_manager.is_blacklisted(token):
+ raise credentials_exception
+
+ payload = decode_token(token)
+ if payload is None:
+ raise credentials_exception
+
+ user_id: str = payload.get("sub")
+ if user_id is None:
+ raise credentials_exception
+
+ except JWTError:
+ raise credentials_exception
+
+ user = user_db.get_user_by_id(user_id)
+ if user is None:
+ raise credentials_exception
+
+ if not user.is_active:
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail="Inactive user"
+ )
+
+ return User(**user.dict())
+
+async def get_current_user_by_api_key(
+ api_key: Optional[str] = Security(api_key_header)
+) -> Optional[User]:
+ """Authenticate user by API key"""
+ if not api_key:
+ return None
+
+ user = user_db.get_user_by_api_key(api_key)
+ if not user or not user.is_active:
+ return None
+
+ return User(**user.dict())
+
+async def get_current_user_flexible(
+ token_user: Optional[User] = Depends(get_current_user),
+ api_key_user: Optional[User] = Depends(get_current_user_by_api_key)
+) -> User:
+ """Authenticate user by token or API key (flexible authentication)"""
+ user = token_user or api_key_user
+
+ if not user:
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Authentication required"
+ )
+
+ return user
+
+def require_permissions(*required_permissions: Permission):
+ """Dependency requiring specific permissions"""
+ def permission_checker(current_user: User = Depends(get_current_user_flexible)) -> User:
+ for permission in required_permissions:
+ if permission not in current_user.permissions:
+ raise HTTPException(
+ status_code=status.HTTP_403_FORBIDDEN,
+ detail=f"Permission '{permission}' required"
+ )
+ return current_user
+
+ return permission_checker
+
+def require_roles(*required_roles):
+ """Dependency requiring specific roles"""
+ def role_checker(current_user: User = Depends(get_current_user_flexible)) -> User:
+ if current_user.role not in required_roles:
+ raise HTTPException(
+ status_code=status.HTTP_403_FORBIDDEN,
+ detail=f"Role must be one of: {', '.join(required_roles)}"
+ )
+ return current_user
+
+ return role_checker
+
+# Common permission dependencies
+RequireAdmin = require_roles("admin")
+RequireReadItems = require_permissions(Permission.READ_ITEMS)
+RequireWriteItems = require_permissions(Permission.WRITE_ITEMS)
+RequireDeleteItems = require_permissions(Permission.DELETE_ITEMS)
+RequireMCPTools = require_permissions(Permission.USE_MCP_TOOLS)
+RequireAdminMCP = require_permissions(Permission.ADMIN_MCP)
+```
+
+### Routeur d'authentification (`src/auth/routes.py`)
+
+```python
+from datetime import timedelta
+from fastapi import APIRouter, Depends, HTTPException, status
+from fastapi.security import OAuth2PasswordRequestForm
+
+from src.auth.models import (
+ User, UserCreate, UserUpdate, LoginRequest, TokenResponse,
+ user_db, UserRole
+)
+from src.auth.jwt_handler import (
+ verify_password, token_manager, verify_token, create_access_token
+)
+from src.auth.dependencies import get_current_user, RequireAdmin
+from src.core.config import settings
+
+router = APIRouter(prefix="/auth", tags=["authentication"])
+
+@router.post("/register", response_model=User)
+async def register_user(user_create: UserCreate):
+ """Register user"""
+ # Check duplicate username
+ if user_db.get_user_by_username(user_create.username):
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail="Username already registered"
+ )
+
+ # First user is automatically set as admin
+ if not user_db.users:
+ user_create.role = UserRole.ADMIN
+
+ user = user_db.create_user(user_create)
+ return User(**user.dict())
+
+@router.post("/login", response_model=TokenResponse)
+async def login_user(form_data: OAuth2PasswordRequestForm = Depends()):
+ """User login"""
+ user = user_db.get_user_by_username(form_data.username)
+
+ if not user or not verify_password(form_data.password, user.hashed_password):
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Incorrect username or password",
+ headers={"WWW-Authenticate": "Bearer"},
+ )
+
+ if not user.is_active:
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail="Inactive user"
+ )
+
+ # Create token
+ tokens = token_manager.create_token_pair(user.id, user.role)
+
+ # Update last login time
+ user_db.update_last_login(user.id)
+
+ return TokenResponse(
+ access_token=tokens["access_token"],
+ refresh_token=tokens["refresh_token"],
+ token_type=tokens["token_type"],
+ expires_in=settings.ACCESS_TOKEN_EXPIRE_MINUTES * 60,
+ user=User(**user.dict())
+ )
+
+@router.post("/refresh", response_model=dict)
+async def refresh_token(refresh_token: str):
+ """Refresh token"""
+ user_id = verify_token(refresh_token, "refresh")
+
+ if not user_id:
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="Invalid refresh token"
+ )
+
+ user = user_db.get_user_by_id(user_id)
+ if not user or not user.is_active:
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail="User not found or inactive"
+ )
+
+ # Create new token pair
+ tokens = token_manager.create_token_pair(user.id, user.role)
+
+ return {
+ "access_token": tokens["access_token"],
+ "refresh_token": tokens["refresh_token"],
+ "token_type": tokens["token_type"],
+ "expires_in": settings.ACCESS_TOKEN_EXPIRE_MINUTES * 60
+ }
+
+@router.post("/logout")
+async def logout_user(current_user: User = Depends(get_current_user)):
+ """User logout"""
+ # In actual implementation, add token to blacklist
+ return {"message": "Successfully logged out"}
+
+@router.get("/me", response_model=User)
+async def get_current_user_info(current_user: User = Depends(get_current_user)):
+ """Get current user information"""
+ return current_user
+
+@router.put("/me", response_model=User)
+async def update_current_user(
+ user_update: UserUpdate,
+ current_user: User = Depends(get_current_user)
+):
+ """Update current user information"""
+ # Normal users cannot change role
+ if user_update.role and current_user.role != UserRole.ADMIN:
+ user_update.role = None
+
+ updated_user = user_db.update_user(current_user.id, user_update)
+ if not updated_user:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail="User not found"
+ )
+
+ return User(**updated_user.dict())
+
+@router.get("/users", response_model=list[User])
+async def list_users(admin_user: User = Depends(RequireAdmin)):
+ """Get user list (admin only)"""
+ return [User(**user.dict()) for user in user_db.users.values()]
+
+@router.post("/users/{user_id}/generate-api-key")
+async def generate_api_key(
+ user_id: str,
+ admin_user: User = Depends(RequireAdmin)
+):
+ """Create user API key (admin only)"""
+ import uuid
+
+ user = user_db.get_user_by_id(user_id)
+ if not user:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail="User not found"
+ )
+
+ # Create new API key
+ new_api_key = str(uuid.uuid4())
+ user.api_key = new_api_key
+
+ return {
+ "api_key": new_api_key,
+ "message": "API key generated successfully"
+ }
+```
+
+## Étape 5 : Implémentation du serveur MCP
+
+### Définition des outils MCP (`src/mcp/tools.py`)
+
+```python
+from typing import Dict, Any, List, Optional
+from pydantic import BaseModel, Field
+from enum import Enum
+
+class ToolCategory(str, Enum):
+ """Tool category"""
+ DATA_MANAGEMENT = "data_management"
+ SEARCH = "search"
+ ANALYSIS = "analysis"
+ ADMIN = "admin"
+
+class MCPTool(BaseModel):
+ """MCP tool definition"""
+ name: str = Field(..., description="Tool name")
+ description: str = Field(..., description="Tool description")
+ category: ToolCategory = Field(..., description="Tool category")
+ parameters: Dict[str, Any] = Field(default_factory=dict, description="Parameter schema")
+ required_permissions: List[str] = Field(default_factory=list, description="Required permissions")
+ examples: List[Dict[str, Any]] = Field(default_factory=list, description="Usage examples")
+
+class ToolRegistry:
+ """Tool registry"""
+
+ def __init__(self):
+ self.tools: Dict[str, MCPTool] = {}
+ self._register_default_tools()
+
+ def _register_default_tools(self):
+ """Register default tools"""
+
+ # Create item tool
+ self.register_tool(MCPTool(
+ name="create_item",
+ description="Create a new item",
+ category=ToolCategory.DATA_MANAGEMENT,
+ parameters={
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Item name"
+ },
+ "description": {
+ "type": "string",
+ "description": "Item description"
+ },
+ "price": {
+ "type": "number",
+ "description": "Item price",
+ "minimum": 0
+ },
+ "category": {
+ "type": "string",
+ "description": "Item category"
+ }
+ },
+ "required": ["name", "price"]
+ },
+ required_permissions=["write:items"],
+ examples=[
+ {
+ "name": "Notebook",
+ "description": "High-performance gaming notebook",
+ "price": 1500000,
+ "category": "electronics"
+ }
+ ]
+ ))
+
+ # Search item tool
+ self.register_tool(MCPTool(
+ name="search_items",
+ description="Search for items",
+ category=ToolCategory.SEARCH,
+ parameters={
+ "type": "object",
+ "properties": {
+ "query": {
+ "type": "string",
+ "description": "Search query"
+ },
+ "category": {
+ "type": "string",
+ "description": "Category filter"
+ },
+ "min_price": {
+ "type": "number",
+ "description": "Minimum price"
+ },
+ "max_price": {
+ "type": "number",
+ "description": "Maximum price"
+ },
+ "limit": {
+ "type": "integer",
+ "description": "Result count limit",
+ "default": 10,
+ "maximum": 100
+ }
+ },
+ "required": ["query"]
+ },
+ required_permissions=["read:items"],
+ examples=[
+ {
+ "query": "Notebook",
+ "category": "electronics",
+ "max_price": 2000000,
+ "limit": 5
+ }
+ ]
+ ))
+
+ # Analyze item tool
+ self.register_tool(MCPTool(
+ name="analyze_items",
+ description="Analyze item data",
+ category=ToolCategory.ANALYSIS,
+ parameters={
+ "type": "object",
+ "properties": {
+ "analysis_type": {
+ "type": "string",
+ "enum": ["price_distribution", "category_breakdown", "trend_analysis"],
+ "description": "Analysis type"
+ },
+ "date_range": {
+ "type": "object",
+ "properties": {
+ "start_date": {"type": "string", "format": "date"},
+ "end_date": {"type": "string", "format": "date"}
+ },
+ "description": "Analysis period"
+ }
+ },
+ "required": ["analysis_type"]
+ },
+ required_permissions=["read:items"],
+ examples=[
+ {
+ "analysis_type": "price_distribution",
+ "date_range": {
+ "start_date": "2024-01-01",
+ "end_date": "2024-12-31"
+ }
+ }
+ ]
+ ))
+
+ # Manage user tool (admin only)
+ self.register_tool(MCPTool(
+ name="manage_users",
+ description="Manage users",
+ category=ToolCategory.ADMIN,
+ parameters={
+ "type": "object",
+ "properties": {
+ "action": {
+ "type": "string",
+ "enum": ["list", "create", "update", "deactivate"],
+ "description": "Action to perform"
+ },
+ "user_data": {
+ "type": "object",
+ "description": "User data (create/update)"
+ },
+ "user_id": {
+ "type": "string",
+ "description": "User ID (update/deactivate)"
+ }
+ },
+ "required": ["action"]
+ },
+ required_permissions=["manage:users"],
+ examples=[
+ {
+ "action": "list"
+ },
+ {
+ "action": "create",
+ "user_data": {
+ "username": "newuser",
+ "email": "newuser@example.com",
+ "role": "user"
+ }
+ }
+ ]
+ ))
+
+ def register_tool(self, tool: MCPTool):
+ """Register tool"""
+ self.tools[tool.name] = tool
+
+ def get_tool(self, tool_name: str) -> Optional[MCPTool]:
+ """Get tool"""
+ return self.tools.get(tool_name)
+
+ def list_tools(self, user_permissions: List[str] = None) -> List[MCPTool]:
+ """List tools by user permissions"""
+ if user_permissions is None:
+ return list(self.tools.values())
+
+ available_tools = []
+ for tool in self.tools.values():
+ # Check permissions
+ if all(perm in user_permissions for perm in tool.required_permissions):
+ available_tools.append(tool)
+
+ return available_tools
+
+ def get_tools_by_category(self, category: ToolCategory, user_permissions: List[str] = None) -> List[MCPTool]:
+ """List tools by category"""
+ tools = self.list_tools(user_permissions)
+ return [tool for tool in tools if tool.category == category]
+
+# Global tool registry
+tool_registry = ToolRegistry()
+```
+
+### Implémentation du serveur MCP (`src/mcp/server.py`)
+
+```python
+from typing import Dict, Any, List, Optional
+from fastapi import HTTPException, status
+import asyncio
+import json
+
+from src.mcp.tools import tool_registry, ToolCategory
+from src.auth.models import User, Permission
+from src.api.routes.items import ItemCRUD
+from src.auth.models import user_db
+
+class MCPServer:
+ """Model Context Protocol server"""
+
+ def __init__(self):
+ self.item_crud = ItemCRUD()
+ self.active_sessions: Dict[str, Dict[str, Any]] = {}
+
+ async def create_session(self, user: User) -> str:
+ """Create MCP session"""
+ import uuid
+
+ session_id = str(uuid.uuid4())
+ self.active_sessions[session_id] = {
+ "user_id": user.id,
+ "user": user,
+ "created_at": datetime.utcnow(),
+ "context": {},
+ "tool_usage_count": 0,
+ "last_activity": datetime.utcnow()
+ }
+
+ return session_id
+
+ async def get_session(self, session_id: str) -> Optional[Dict[str, Any]]:
+ """Get session"""
+ session = self.active_sessions.get(session_id)
+ if session:
+ session["last_activity"] = datetime.utcnow()
+ return session
+
+ async def close_session(self, session_id: str):
+ """Close session"""
+ if session_id in self.active_sessions:
+ del self.active_sessions[session_id]
+
+ async def list_tools(self, user: User) -> List[Dict[str, Any]]:
+ """List tools available to user"""
+ user_permissions = [perm.value for perm in user.permissions]
+ tools = tool_registry.list_tools(user_permissions)
+
+ return [
+ {
+ "name": tool.name,
+ "description": tool.description,
+ "category": tool.category,
+ "parameters": tool.parameters,
+ "examples": tool.examples
+ }
+ for tool in tools
+ ]
+
+ async def execute_tool(
+ self,
+ tool_name: str,
+ parameters: Dict[str, Any],
+ user: User,
+ session_id: Optional[str] = None
+ ) -> Dict[str, Any]:
+ """Execute tool"""
+
+ # Check if tool exists
+ tool = tool_registry.get_tool(tool_name)
+ if not tool:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail=f"Tool '{tool_name}' not found"
+ )
+
+ # Check permissions
+ user_permissions = [perm.value for perm in user.permissions]
+ for required_perm in tool.required_permissions:
+ if required_perm not in user_permissions:
+ raise HTTPException(
+ status_code=status.HTTP_403_FORBIDDEN,
+ detail=f"Permission '{required_perm}' required for tool '{tool_name}'"
+ )
+
+ # Update session
+ if session_id:
+ session = await self.get_session(session_id)
+ if session:
+ session["tool_usage_count"] += 1
+
+ # Execute tool
+ try:
+ result = await self._execute_tool_logic(tool_name, parameters, user)
+
+ return {
+ "success": True,
+ "tool": tool_name,
+ "result": result,
+ "timestamp": datetime.utcnow().isoformat()
+ }
+
+ except Exception as e:
+ return {
+ "success": False,
+ "tool": tool_name,
+ "error": str(e),
+ "timestamp": datetime.utcnow().isoformat()
+ }
+
+ async def _execute_tool_logic(
+ self,
+ tool_name: str,
+ parameters: Dict[str, Any],
+ user: User
+ ) -> Any:
+ """Execute tool logic"""
+
+ if tool_name == "create_item":
+ return await self._create_item(parameters)
+
+ elif tool_name == "search_items":
+ return await self._search_items(parameters)
+
+ elif tool_name == "analyze_items":
+ return await self._analyze_items(parameters)
+
+ elif tool_name == "manage_users":
+ return await self._manage_users(parameters, user)
+
+ else:
+ raise ValueError(f"Tool '{tool_name}' implementation not found")
+
+ async def _create_item(self, parameters: Dict[str, Any]) -> Dict[str, Any]:
+ """Create item tool implementation"""
+ from src.schemas.items import ItemCreate
+
+ try:
+ item_create = ItemCreate(**parameters)
+ created_item = await self.item_crud.create(item_create)
+
+ return {
+ "action": "create_item",
+ "item": created_item.dict(),
+ "message": f"Item '{created_item.name}' created successfully"
+ }
+ except Exception as e:
+ raise ValueError(f"Failed to create item: {str(e)}")
+
+ async def _search_items(self, parameters: Dict[str, Any]) -> Dict[str, Any]:
+ """Search item tool implementation"""
+ query = parameters.get("query", "")
+ category = parameters.get("category")
+ min_price = parameters.get("min_price")
+ max_price = parameters.get("max_price")
+ limit = parameters.get("limit", 10)
+
+ # Search logic implementation
+ all_items = await self.item_crud.get_all()
+ filtered_items = []
+
+ for item in all_items:
+ # Text search
+ if query.lower() not in item.name.lower() and query.lower() not in (item.description or "").lower():
+ continue
+
+ # Category filter
+ if category and getattr(item, 'category', None) != category:
+ continue
+
+ # Price filter
+ if min_price is not None and item.price < min_price:
+ continue
+ if max_price is not None and item.price > max_price:
+ continue
+
+ filtered_items.append(item)
+
+ # Result limit
+ result_items = filtered_items[:limit]
+
+ return {
+ "action": "search_items",
+ "query": query,
+ "total_found": len(filtered_items),
+ "returned_count": len(result_items),
+ "items": [item.dict() for item in result_items]
+ }
+
+ async def _analyze_items(self, parameters: Dict[str, Any]) -> Dict[str, Any]:
+ """Analyze item tool implementation"""
+ analysis_type = parameters.get("analysis_type")
+ date_range = parameters.get("date_range", {})
+
+ all_items = await self.item_crud.get_all()
+
+ if analysis_type == "price_distribution":
+ prices = [item.price for item in all_items]
+ if not prices:
+ return {"analysis": "price_distribution", "result": "No items found"}
+
+ return {
+ "analysis": "price_distribution",
+ "result": {
+ "total_items": len(prices),
+ "min_price": min(prices),
+ "max_price": max(prices),
+ "average_price": sum(prices) / len(prices),
+ "price_ranges": {
+ "under_100k": len([p for p in prices if p < 100000]),
+ "100k_to_500k": len([p for p in prices if 100000 <= p < 500000]),
+ "500k_to_1m": len([p for p in prices if 500000 <= p < 1000000]),
+ "over_1m": len([p for p in prices if p >= 1000000])
+ }
+ }
+ }
+
+ elif analysis_type == "category_breakdown":
+ categories = {}
+ for item in all_items:
+ category = getattr(item, 'category', 'uncategorized')
+ categories[category] = categories.get(category, 0) + 1
+
+ return {
+ "analysis": "category_breakdown",
+ "result": {
+ "total_categories": len(categories),
+ "categories": categories
+ }
+ }
+
+ else:
+ raise ValueError(f"Unknown analysis type: {analysis_type}")
+
+ async def _manage_users(self, parameters: Dict[str, Any], requesting_user: User) -> Dict[str, Any]:
+ """Manage user tool implementation"""
+ action = parameters.get("action")
+
+ # Check admin permissions
+ if Permission.MANAGE_USERS not in requesting_user.permissions:
+ raise ValueError("Insufficient permissions for user management")
+
+ if action == "list":
+ users = [User(**user.dict()) for user in user_db.users.values()]
+ return {
+ "action": "list_users",
+ "total_users": len(users),
+ "users": [user.dict() for user in users]
+ }
+
+ elif action == "create":
+ user_data = parameters.get("user_data", {})
+ from src.auth.models import UserCreate
+
+ user_create = UserCreate(**user_data)
+ created_user = user_db.create_user(user_create)
+
+ return {
+ "action": "create_user",
+ "user": User(**created_user.dict()).dict(),
+ "message": f"User '{created_user.username}' created successfully"
+ }
+
+ else:
+ raise ValueError(f"Unknown user management action: {action}")
+
+# Global MCP server instance
+mcp_server = MCPServer()
+```
+
+## Étape 6 : Implémentation des points d'extrémité d'API MCP
+
+### Routeur d'API MCP (`src/api/routes/mcp.py`)
+
+```python
+from typing import Dict, Any, Optional
+from fastapi import APIRouter, Depends, HTTPException, status, BackgroundTasks
+from pydantic import BaseModel
+
+from src.auth.dependencies import get_current_user_flexible, RequireMCPTools
+from src.auth.models import User
+from src.mcp.server import mcp_server
+from src.mcp.tools import ToolCategory
+
+router = APIRouter(prefix="/mcp", tags=["MCP"])
+
+class ToolExecuteRequest(BaseModel):
+ """Tool execution request"""
+ tool_name: str
+ parameters: Dict[str, Any]
+ session_id: Optional[str] = None
+
+class SessionCreateResponse(BaseModel):
+ """Session creation response"""
+ session_id: str
+ message: str
+
+@router.post("/session", response_model=SessionCreateResponse)
+async def create_mcp_session(
+ current_user: User = Depends(RequireMCPTools)
+):
+ """Create MCP session"""
+ session_id = await mcp_server.create_session(current_user)
+
+ return SessionCreateResponse(
+ session_id=session_id,
+ message=f"MCP session created (User: {current_user.username})"
+ )
+
+@router.delete("/session/{session_id}")
+async def close_mcp_session(
+ session_id: str,
+ current_user: User = Depends(RequireMCPTools)
+):
+ """Close MCP session"""
+ session = await mcp_server.get_session(session_id)
+
+ if not session:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail="Session not found"
+ )
+
+ # Check session owner
+ if session["user_id"] != current_user.id:
+ raise HTTPException(
+ status_code=status.HTTP_403_FORBIDDEN,
+ detail="Cannot close another user's session"
+ )
+
+ await mcp_server.close_session(session_id)
+
+ return {"message": "Session closed successfully"}
+
+@router.get("/tools")
+async def list_mcp_tools(
+ category: Optional[ToolCategory] = None,
+ current_user: User = Depends(RequireMCPTools)
+):
+ """List available MCP tools"""
+ tools = await mcp_server.list_tools(current_user)
+
+ if category:
+ tools = [tool for tool in tools if tool["category"] == category]
+
+ return {
+ "user": current_user.username,
+ "total_tools": len(tools),
+ "tools": tools
+ }
+
+@router.post("/execute")
+async def execute_mcp_tool(
+ request: ToolExecuteRequest,
+ background_tasks: BackgroundTasks,
+ current_user: User = Depends(RequireMCPTools)
+):
+ """Execute MCP tool"""
+
+ # Check session (optional)
+ if request.session_id:
+ session = await mcp_server.get_session(request.session_id)
+ if not session:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail="Session not found"
+ )
+
+ if session["user_id"] != current_user.id:
+ raise HTTPException(
+ status_code=status.HTTP_403_FORBIDDEN,
+ detail="Cannot use another user's session"
+ )
+
+ # Execute tool
+ result = await mcp_server.execute_tool(
+ tool_name=request.tool_name,
+ parameters=request.parameters,
+ user=current_user,
+ session_id=request.session_id
+ )
+
+ # Log tool usage in background
+ background_tasks.add_task(
+ log_tool_usage,
+ current_user.id,
+ request.tool_name,
+ result["success"]
+ )
+
+ return result
+
+@router.get("/sessions")
+async def list_user_sessions(
+ current_user: User = Depends(RequireMCPTools)
+):
+ """List active user sessions"""
+ user_sessions = []
+
+ for session_id, session_data in mcp_server.active_sessions.items():
+ if session_data["user_id"] == current_user.id:
+ user_sessions.append({
+ "session_id": session_id,
+ "created_at": session_data["created_at"],
+ "tool_usage_count": session_data["tool_usage_count"],
+ "last_activity": session_data["last_activity"]
+ })
+
+ return {
+ "user": current_user.username,
+ "active_sessions": len(user_sessions),
+ "sessions": user_sessions
+ }
+
+@router.get("/stats")
+async def get_mcp_stats(
+ current_user: User = Depends(RequireMCPTools)
+):
+ """MCP usage statistics"""
+ total_sessions = len(mcp_server.active_sessions)
+ user_sessions = len([
+ s for s in mcp_server.active_sessions.values()
+ if s["user_id"] == current_user.id
+ ])
+
+ return {
+ "user_stats": {
+ "username": current_user.username,
+ "active_sessions": user_sessions,
+ "permissions": [perm.value for perm in current_user.permissions]
+ },
+ "server_stats": {
+ "total_active_sessions": total_sessions,
+ "available_tools": len(await mcp_server.list_tools(current_user))
+ }
+ }
+
+async def log_tool_usage(user_id: str, tool_name: str, success: bool):
+ """Log tool usage (background job)"""
+ import logging
+
+ logger = logging.getLogger("mcp.usage")
+ logger.info(
+ f"Tool usage - User: {user_id}, Tool: {tool_name}, Success: {success}"
+ )
+```
+
+## Étape 7 : Intégration applicative et tests
+
+### Application principale (`src/main.py`)
+
+```python
+from fastapi import FastAPI
+from fastapi.middleware.cors import CORSMiddleware
+
+from src.auth.routes import router as auth_router
+from src.api.routes.items import router as items_router
+from src.api.routes.mcp import router as mcp_router
+from src.core.config import settings
+
+app = FastAPI(
+ title="AI Integrated API",
+ description="AI model integrated MCP-based API server",
+ version="1.0.0"
+)
+
+# CORS settings
+app.add_middleware(
+ CORSMiddleware,
+ allow_origins=settings.ALLOWED_HOSTS,
+ allow_credentials=True,
+ allow_methods=["*"],
+ allow_headers=["*"],
+)
+
+# Inclure les routeurs
+app.include_router(auth_router)
+app.include_router(items_router, prefix="/api/v1")
+app.include_router(mcp_router, prefix="/api/v1")
+
+@app.get("/")
+async def root():
+ return {
+ "message": "AI Integrated API with MCP Support",
+ "version": "1.0.0",
+ "endpoints": {
+ "authentication": "/auth",
+ "items": "/api/v1/items",
+ "mcp": "/api/v1/mcp",
+ "docs": "/docs"
+ }
+ }
+
+@app.get("/health")
+async def health_check():
+ """Health check endpoint"""
+ return {
+ "status": "healthy",
+ "version": "1.0.0",
+ "services": {
+ "auth": "operational",
+ "mcp": "operational",
+ "database": "operational"
+ }
+ }
+```
+
+### Lancer le serveur et tester
+
+
+
+```console
+$ cd ai-integrated-api
+$ fastkit runserver
+Starting FastAPI server at 127.0.0.1:8000...
+
+# User login
+$ curl -X POST "http://localhost:8000/auth/login" \
+ -H "Content-Type: application/x-www-form-urlencoded" \
+ -d "username=admin&password=admin123"
+
+{
+ "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
+ "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
+ "token_type": "bearer",
+ "expires_in": 1800,
+ "user": {
+ "id": "123e4567-e89b-12d3-a456-426614174000",
+ "email": "admin@example.com",
+ "username": "admin",
+ "role": "admin",
+ "permissions": ["read:items", "write:items", ...]
+ }
+}
+
+# Create MCP session
+$ curl -X POST "http://localhost:8000/api/v1/mcp/session" \
+ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
+
+{
+ "session_id": "abc123-def456-ghi789",
+ "message": "MCP session created (User: admin)"
+}
+
+# List available tools
+$ curl "http://localhost:8000/api/v1/mcp/tools" \
+ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
+
+{
+ "user": "admin",
+ "total_tools": 4,
+ "tools": [
+ {
+ "name": "create_item",
+ "description": "Create a new item",
+ "category": "data_management",
+ "parameters": {...},
+ "examples": [...]
+ },
+ ...
+ ]
+}
+
+# Execute MCP tool (create item)
+$ curl -X POST "http://localhost:8000/api/v1/mcp/execute" \
+ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "tool_name": "create_item",
+ "parameters": {
+ "name": "AI generated item",
+ "description": "MCP through AI generated item",
+ "price": 500000,
+ "category": "ai_generated"
+ },
+ "session_id": "abc123-def456-ghi789"
+ }'
+
+{
+ "success": true,
+ "tool": "create_item",
+ "result": {
+ "action": "create_item",
+ "item": {
+ "id": 1,
+ "name": "AI generated item",
+ "description": "MCP through AI generated item",
+ "price": 500000,
+ "category": "ai_generated",
+ "created_at": "2024-01-01T12:00:00Z"
+ },
+ "message": "Item 'AI generated item' created successfully"
+ },
+ "timestamp": "2024-01-01T12:00:00.123456Z"
+}
+
+# Execute MCP tool (search item)
+$ curl -X POST "http://localhost:8000/api/v1/mcp/execute" \
+ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "tool_name": "search_items",
+ "parameters": {
+ "query": "AI",
+ "limit": 5
+ }
+ }'
+```
+
+
+
+## Étape 8 : Exemple de client IA
+
+### Exemple de client MCP en Python
+
+```python
+# client_example.py
+import asyncio
+import aiohttp
+from typing import Dict, Any, List
+
+class MCPClient:
+ """MCP client example"""
+
+ def __init__(self, base_url: str, api_key: str):
+ self.base_url = base_url
+ self.api_key = api_key
+ self.session_id = None
+ self.session = None
+
+ async def __aenter__(self):
+ self.session = aiohttp.ClientSession(
+ headers={"X-API-Key": self.api_key}
+ )
+ return self
+
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
+ if self.session_id:
+ await self.close_session()
+ if self.session:
+ await self.session.close()
+
+ async def create_session(self) -> str:
+ """Create MCP session"""
+ async with self.session.post(f"{self.base_url}/api/v1/mcp/session") as resp:
+ data = await resp.json()
+ self.session_id = data["session_id"]
+ return self.session_id
+
+ async def close_session(self):
+ """Close MCP session"""
+ if self.session_id:
+ async with self.session.delete(f"{self.base_url}/api/v1/mcp/session/{self.session_id}"):
+ pass
+ self.session_id = None
+
+ async def list_tools(self) -> List[Dict[str, Any]]:
+ """List available tools"""
+ async with self.session.get(f"{self.base_url}/api/v1/mcp/tools") as resp:
+ data = await resp.json()
+ return data["tools"]
+
+ async def execute_tool(self, tool_name: str, parameters: Dict[str, Any]) -> Dict[str, Any]:
+ """Execute tool"""
+ payload = {
+ "tool_name": tool_name,
+ "parameters": parameters,
+ "session_id": self.session_id
+ }
+
+ async with self.session.post(
+ f"{self.base_url}/api/v1/mcp/execute",
+ json=payload
+ ) as resp:
+ return await resp.json()
+
+ async def ai_assistant_workflow(self, user_request: str) -> str:
+ """AI assistant workflow simulation"""
+
+ # 1. Create session
+ await self.create_session()
+ print(f"Session created: {self.session_id}")
+
+ # 2. Analyze user request and select appropriate tool
+ if "Create item" in user_request or "Create" in user_request:
+ # Create item request
+ result = await self.execute_tool("create_item", {
+ "name": "AI recommended item",
+ "description": "AI generated item based on user request",
+ "price": 100000,
+ "category": "ai_recommended"
+ })
+
+ if result["success"]:
+ item_name = result["result"]["item"]["name"]
+ return f"✅ '{item_name}' item created successfully!"
+ else:
+ return f"❌ Item creation failed: {result.get('error', 'Unknown error')}"
+
+ elif "Search" in user_request or "Find" in user_request:
+ # Search request
+ search_query = "Item" # Actually extracted from NLP
+ result = await self.execute_tool("search_items", {
+ "query": search_query,
+ "limit": 5
+ })
+
+ if result["success"]:
+ items = result["result"]["items"]
+ item_list = "\n".join([f"- {item['name']} (₩{item['price']:,})" for item in items])
+ return f"🔍 Search results ({len(items)} items):\n{item_list}"
+ else:
+ return f"❌ Search failed: {result.get('error', 'Unknown error')}"
+
+ elif "Analyze" in user_request:
+ # Analyze request
+ result = await self.execute_tool("analyze_items", {
+ "analysis_type": "price_distribution"
+ })
+
+ if result["success"]:
+ analysis = result["result"]["result"]
+ return f"📊 Price analysis:\nAverage price: ₩{analysis['average_price']:,.0f}\nMinimum: ₩{analysis['min_price']:,} - Maximum: ₩{analysis['max_price']:,}"
+ else:
+ return f"❌ Analysis failed: {result.get('error', 'Unknown error')}"
+
+ else:
+ return "Sorry, I couldn't find a tool to handle that request."
+
+async def main():
+ """Client test"""
+ async with MCPClient("http://localhost:8000", "your-api-key-here") as client:
+
+ # List available tools
+ tools = await client.list_tools()
+ print(f"Available tools: {len(tools)}")
+ for tool in tools:
+ print(f"- {tool['name']}: {tool['description']}")
+
+ print("\n" + "="*50 + "\n")
+
+ # AI assistant simulation
+ test_requests = [
+ "Create a new item",
+ "Search for items",
+ "Analyze price distribution"
+ ]
+
+ for request in test_requests:
+ print(f"User request: {request}")
+ response = await client.ai_assistant_workflow(request)
+ print(f"AI response: {response}")
+ print("-" * 30)
+
+if __name__ == "__main__":
+ asyncio.run(main())
+```
+
+
+
+
+
+## Résumé
+
+Dans ce tutoriel, nous avons implémenté l'intégration MCP (Model Context Protocol) avec :
+
+- ✅ Construction d'un système d'authentification basé sur JWT
+- ✅ Implémentation du contrôle d'accès basé sur les rôles (RBAC)
+- ✅ Implémentation d'un serveur MCP et d'un système d'outils
+- ✅ Gestion du contexte basée sur les sessions
+- ✅ Communication sécurisée d'API avec des modèles d'IA
+- ✅ Gestion des permissions sur les outils et suivi de l'usage
+- ✅ Implémentation d'un véritable exemple de client IA
+
+Vous pouvez désormais construire un système complet basé sur MCP, dans lequel les modèles d'IA peuvent utiliser de manière sûre et efficace les fonctionnalités de votre API !
diff --git a/docs/fr/user-guide/adding-routes.md b/docs/fr/user-guide/adding-routes.md
new file mode 100644
index 0000000..cadc5d9
--- /dev/null
+++ b/docs/fr/user-guide/adding-routes.md
@@ -0,0 +1,581 @@
+# Ajouter des routes
+
+Apprenez à ajouter de nouvelles routes d'API à votre projet FastAPI existant.
+
+## Ajout de route basique
+
+### Utiliser la commande `addroute`
+
+La commande `addroute` de FastAPI-fastkit facilite l'ajout de nouvelles routes :
+
+
+
+```console
+$ fastkit addroute users my-awesome-api
+ Adding New Route
+┌──────────────────┬──────────────────────────────────────────┐
+│ Project │ my-awesome-api │
+│ Route Name │ users │
+│ Target Directory │ ~/my-awesome-api │
+└──────────────────┴──────────────────────────────────────────┘
+
+Do you want to add route 'users' to project 'my-awesome-api'? [Y/n]: y
+
+╭──────────────────────── Info ────────────────────────╮
+│ ℹ Updated main.py to include the API router │
+╰──────────────────────────────────────────────────────╯
+╭─────────────────────── Success ───────────────────────╮
+│ ✨ Successfully added new route 'users' to project │
+│ `my-awesome-api` │
+╰───────────────────────────────────────────────────────╯
+```
+
+
+
+## Ce qui est créé
+
+Lorsque vous ajoutez une route, FastAPI-fastkit crée automatiquement :
+
+### 1. Fichier de route : `src/api/routes/users.py`
+
+```python
+from typing import List
+from fastapi import APIRouter, HTTPException, status
+from src.schemas.users import User, UserCreate, UserUpdate
+from src.crud.users import users_crud
+
+router = APIRouter()
+
+@router.get("/", response_model=List[User])
+def read_users():
+ """Get all users"""
+ return users_crud.get_all()
+
+@router.post("/", response_model=User, status_code=status.HTTP_201_CREATED)
+def create_user(user: UserCreate):
+ """Create a new user"""
+ return users_crud.create(user)
+
+@router.get("/{user_id}", response_model=User)
+def read_user(user_id: int):
+ """Get a specific user"""
+ user = users_crud.get_by_id(user_id)
+ if user is None:
+ raise HTTPException(status_code=404, detail="User not found")
+ return user
+
+@router.put("/{user_id}", response_model=User)
+def update_user(user_id: int, user: UserUpdate):
+ """Update a user"""
+ updated_user = users_crud.update(user_id, user)
+ if updated_user is None:
+ raise HTTPException(status_code=404, detail="User not found")
+ return updated_user
+
+@router.delete("/{user_id}", status_code=status.HTTP_204_NO_CONTENT)
+def delete_user(user_id: int):
+ """Delete a user"""
+ success = users_crud.delete(user_id)
+ if not success:
+ raise HTTPException(status_code=404, detail="User not found")
+```
+
+### 2. Opérations CRUD : `src/crud/users.py`
+
+```python
+from typing import List, Optional
+from src.schemas.users import User, UserCreate, UserUpdate
+
+class UsersCRUD:
+ def __init__(self):
+ self._users: List[User] = []
+ self._next_id = 1
+
+ def get_all(self) -> List[User]:
+ """Get all users"""
+ return self._users
+
+ def get_by_id(self, user_id: int) -> Optional[User]:
+ """Get user by ID"""
+ return next((user for user in self._users if user.id == user_id), None)
+
+ def create(self, user: UserCreate) -> User:
+ """Create a new user"""
+ new_user = User(
+ id=self._next_id,
+ title=user.title,
+ description=user.description
+ )
+ self._next_id += 1
+ self._users.append(new_user)
+ return new_user
+
+ def update(self, user_id: int, user: UserUpdate) -> Optional[User]:
+ """Update an existing user"""
+ existing_user = self.get_by_id(user_id)
+ if existing_user:
+ update_data = user.dict(exclude_unset=True)
+ for field, value in update_data.items():
+ setattr(existing_user, field, value)
+ return existing_user
+ return None
+
+ def delete(self, user_id: int) -> bool:
+ """Delete a user"""
+ user = self.get_by_id(user_id)
+ if user:
+ self._users.remove(user)
+ return True
+ return False
+
+users_crud = UsersCRUD()
+```
+
+### 3. Schémas Pydantic : `src/schemas/users.py`
+
+```python
+from typing import Optional
+from pydantic import BaseModel
+
+class UserBase(BaseModel):
+ title: str
+ description: Optional[str] = None
+
+class UserCreate(UserBase):
+ pass
+
+class UserUpdate(BaseModel):
+ title: Optional[str] = None
+ description: Optional[str] = None
+
+class User(UserBase):
+ id: int
+
+ class Config:
+ from_attributes = True
+```
+
+### 4. Enregistrement du routeur
+
+La commande met automatiquement à jour `src/api/api.py` pour inclure le nouveau routeur :
+
+```python
+from fastapi import APIRouter
+from src.api.routes import items, users
+
+api_router = APIRouter()
+
+api_router.include_router(items.router, prefix="/items", tags=["items"])
+api_router.include_router(users.router, prefix="/users", tags=["users"])
+```
+
+## Points d'extrémité d'API générés
+
+Après avoir ajouté la route `users`, vous disposerez de ces points d'extrémité :
+
+| Méthode | Point d'extrémité | Description |
+|--------|----------|-------------|
+| `GET` | `/api/v1/users/` | Récupérer tous les utilisateurs |
+| `POST` | `/api/v1/users/` | Créer un nouvel utilisateur |
+| `GET` | `/api/v1/users/{user_id}` | Récupérer un utilisateur précis |
+| `PUT` | `/api/v1/users/{user_id}` | Mettre à jour un utilisateur |
+| `DELETE` | `/api/v1/users/{user_id}` | Supprimer un utilisateur |
+
+## Tester vos nouvelles routes
+
+### 1. Démarrer le serveur
+
+
+
+```console
+$ fastkit runserver
+INFO: Uvicorn running on http://127.0.0.1:8000
+```
+
+
+
+### 2. Consulter la documentation de l'API
+
+Rendez-vous sur [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) pour voir vos nouveaux points d'extrémité dans la documentation interactive.
+
+### 3. Tester avec curl
+
+**Créer un utilisateur :**
+
+
+```console
+$ curl -X POST "http://127.0.0.1:8000/api/v1/users/" \
+ -H "Content-Type: application/json" \
+ -d '{"title": "John Doe", "description": "Software Developer"}'
+
+{
+ "id": 1,
+ "title": "John Doe",
+ "description": "Software Developer"
+}
+```
+
+
+
+**Récupérer tous les utilisateurs :**
+
+
+```console
+$ curl http://127.0.0.1:8000/api/v1/users/
+
+[
+ {
+ "id": 1,
+ "title": "John Doe",
+ "description": "Software Developer"
+ }
+]
+```
+
+
+
+**Récupérer un utilisateur précis :**
+
+
+```console
+$ curl http://127.0.0.1:8000/api/v1/users/1
+
+{
+ "id": 1,
+ "title": "John Doe",
+ "description": "Software Developer"
+}
+```
+
+
+
+## Personnaliser le code généré
+
+Le code généré est entièrement personnalisable. Voici des modifications courantes :
+
+### 1. Schéma utilisateur enrichi
+
+Modifiez `src/schemas/users.py` pour des données utilisateur plus réalistes :
+
+```python
+from typing import Optional
+from datetime import datetime
+from pydantic import BaseModel, EmailStr, Field
+
+class UserBase(BaseModel):
+ email: EmailStr
+ username: str = Field(..., min_length=3, max_length=50)
+ full_name: Optional[str] = None
+ is_active: bool = True
+
+class UserCreate(UserBase):
+ password: str = Field(..., min_length=8)
+
+class UserUpdate(BaseModel):
+ email: Optional[EmailStr] = None
+ username: Optional[str] = Field(None, min_length=3, max_length=50)
+ full_name: Optional[str] = None
+ is_active: Optional[bool] = None
+
+class User(UserBase):
+ id: int
+ created_at: datetime
+
+ class Config:
+ from_attributes = True
+
+class UserInDB(User):
+ hashed_password: str
+```
+
+### 2. CRUD enrichi avec validation
+
+Mettez à jour `src/crud/users.py` avec une meilleure validation :
+
+```python
+from typing import List, Optional
+from datetime import datetime
+import hashlib
+from src.schemas.users import UserCreate, UserUpdate, UserInDB
+
+class UsersCRUD:
+ def __init__(self):
+ self._users: List[UserInDB] = []
+ self._next_id = 1
+
+ def _hash_password(self, password: str) -> str:
+ """Simple password hashing (use bcrypt in production)"""
+ return hashlib.sha256(password.encode()).hexdigest()
+
+ def get_by_email(self, email: str) -> Optional[UserInDB]:
+ """Get user by email"""
+ return next((user for user in self._users if user.email == email), None)
+
+ def get_by_username(self, username: str) -> Optional[UserInDB]:
+ """Get user by username"""
+ return next((user for user in self._users if user.username == username), None)
+
+ def create(self, user: UserCreate) -> UserInDB:
+ """Create a new user with validation"""
+ # Vérifier les doublons
+ if self.get_by_email(user.email):
+ raise ValueError("Email already registered")
+ if self.get_by_username(user.username):
+ raise ValueError("Username already taken")
+
+ new_user = UserInDB(
+ id=self._next_id,
+ email=user.email,
+ username=user.username,
+ full_name=user.full_name,
+ is_active=user.is_active,
+ created_at=datetime.now(),
+ hashed_password=self._hash_password(user.password)
+ )
+ self._next_id += 1
+ self._users.append(new_user)
+ return new_user
+
+users_crud = UsersCRUD()
+```
+
+### 3. Route enrichie avec gestion d'erreurs
+
+Mettez à jour `src/api/routes/users.py` avec une meilleure gestion des erreurs :
+
+```python
+from typing import List
+from fastapi import APIRouter, HTTPException, status
+from src.schemas.users import User, UserCreate, UserUpdate
+from src.crud.users import users_crud
+
+router = APIRouter()
+
+@router.post("/", response_model=User, status_code=status.HTTP_201_CREATED)
+def create_user(user: UserCreate):
+ """Create a new user"""
+ try:
+ new_user = users_crud.create(user)
+ # Retourner l'utilisateur sans son hash de mot de passe
+ return User(**new_user.dict())
+ except ValueError as e:
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail=str(e)
+ )
+
+@router.get("/{user_id}", response_model=User)
+def read_user(user_id: int):
+ """Get a specific user"""
+ user = users_crud.get_by_id(user_id)
+ if not user:
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND,
+ detail=f"User with id {user_id} not found"
+ )
+ return User(**user.dict())
+```
+
+## Ajouter plusieurs routes
+
+Vous pouvez ajouter plusieurs routes pour construire une API complète :
+
+
+
+```console
+# Ajouter d'autres routes de ressources (nom de route d'abord, répertoire du projet ensuite)
+$ fastkit addroute products my-awesome-api
+$ fastkit addroute orders my-awesome-api
+$ fastkit addroute categories my-awesome-api
+
+# Chaque commande crée une structure CRUD complète
+```
+
+
+
+Cela crée une API complète avec :
+
+- `/api/v1/users/` — gestion des utilisateurs
+- `/api/v1/products/` — catalogue de produits
+- `/api/v1/orders/` — traitement des commandes
+- `/api/v1/categories/` — gestion des catégories
+
+## Organisation des routes
+
+### Regrouper des points d'extrémité liés
+
+Vous pouvez organiser les routes par domaine :
+
+```python
+# src/api/api.py
+from fastapi import APIRouter
+from src.api.routes import users, products, orders, categories
+
+api_router = APIRouter()
+
+# Gestion des utilisateurs
+api_router.include_router(
+ users.router,
+ prefix="/users",
+ tags=["User Management"]
+)
+
+# E-commerce
+api_router.include_router(
+ products.router,
+ prefix="/products",
+ tags=["E-commerce"]
+)
+api_router.include_router(
+ orders.router,
+ prefix="/orders",
+ tags=["E-commerce"]
+)
+api_router.include_router(
+ categories.router,
+ prefix="/categories",
+ tags=["E-commerce"]
+)
+```
+
+### Ajouter des dépendances de route
+
+Ajoutez l'authentification ou d'autres dépendances :
+
+```python
+from fastapi import APIRouter, Depends
+from src.core.auth import get_current_user
+
+router = APIRouter()
+
+@router.get("/profile", response_model=User)
+def get_user_profile(current_user: User = Depends(get_current_user)):
+ """Get current user's profile"""
+ return current_user
+
+@router.post("/", response_model=User)
+def create_user(
+ user: UserCreate,
+ current_user: User = Depends(get_current_user)
+):
+ """Create a new user (admin only)"""
+ if not current_user.is_admin:
+ raise HTTPException(status_code=403, detail="Admin access required")
+ return users_crud.create(user)
+```
+
+## Bonnes pratiques
+
+### 1. Nommage cohérent
+
+Suivez des conventions de nommage cohérentes :
+
+- **Noms de routes** : utilisez des noms au pluriel (`users`, `products`, `orders`)
+- **Noms de schémas** : utilisez le singulier (`User`, `Product`, `Order`)
+- **Classes CRUD** : terminez par `CRUD` (`UsersCRUD`, `ProductsCRUD`)
+
+### 2. Gestion des erreurs
+
+Gérez toujours les erreurs proprement :
+
+```python
+@router.post("/", response_model=User)
+def create_user(user: UserCreate):
+ try:
+ return users_crud.create(user)
+ except ValueError as e:
+ raise HTTPException(status_code=400, detail=str(e))
+ except Exception as e:
+ raise HTTPException(status_code=500, detail="Internal server error")
+```
+
+### 3. Documentation
+
+Ajoutez des docstrings complètes :
+
+```python
+@router.get("/{user_id}", response_model=User)
+def read_user(user_id: int):
+ """
+ Get a specific user by ID.
+
+ Args:
+ user_id: The unique identifier for the user
+
+ Returns:
+ User: The user object with all details
+
+ Raises:
+ HTTPException: 404 if user not found
+ """
+ user = users_crud.get_by_id(user_id)
+ if not user:
+ raise HTTPException(status_code=404, detail="User not found")
+ return user
+```
+
+### 4. Tests
+
+Testez toujours vos nouvelles routes :
+
+```python
+# tests/test_users.py
+from fastapi.testclient import TestClient
+from src.main import app
+
+client = TestClient(app)
+
+def test_create_user():
+ user_data = {
+ "email": "test@example.com",
+ "username": "testuser",
+ "password": "securepassword123"
+ }
+ response = client.post("/api/v1/users/", json=user_data)
+ assert response.status_code == 201
+ assert response.json()["email"] == user_data["email"]
+
+def test_get_user():
+ response = client.get("/api/v1/users/1")
+ assert response.status_code == 200
+```
+
+## Dépannage
+
+### La route n'apparaît pas
+
+Si votre route n'apparaît pas dans la documentation de l'API :
+
+1. **Vérifiez l'enregistrement du routeur** dans `src/api/api.py`
+2. **Redémarrez le serveur** après avoir ajouté des routes
+3. **Recherchez d'éventuelles erreurs d'import** dans le fichier de route
+
+### Erreurs d'import
+
+Si vous obtenez des erreurs d'import :
+
+1. **Vérifiez que la structure des fichiers** correspond à la disposition attendue
+2. **Vérifiez les imports des schémas** dans les fichiers de route et de CRUD
+3. **Assurez-vous que tous les fichiers `__init__.py` existent**
+
+### Le serveur ne démarre pas
+
+Si le serveur ne démarre pas après l'ajout de routes :
+
+1. **Recherchez les erreurs de syntaxe** dans les fichiers générés
+2. **Vérifiez la compatibilité des schémas** entre les fichiers
+3. **Consultez les journaux** pour des messages d'erreur précis
+
+## Étapes suivantes
+
+Maintenant que vous savez ajouter des routes :
+
+1. **[Votre premier projet](../tutorial/first-project.md)** : construire une API de blog complète
+2. **[Référence CLI](cli-reference.md)** : découvrir toutes les commandes disponibles
+3. **[Utiliser les modèles](using-templates.md)** : explorer les modèles de projet prêts à l'emploi
+
+!!! tip "Astuces de développement de routes"
+ - Testez toujours les nouvelles routes dans la documentation interactive (`/docs`)
+ - Utilisez des codes d'état HTTP pertinents
+ - Implémentez une gestion d'erreurs correcte pour tous les points d'extrémité
+ - Gardez les gestionnaires de route simples et déléguez la logique métier aux classes CRUD
diff --git a/docs/fr/user-guide/choosing-a-starter.md b/docs/fr/user-guide/choosing-a-starter.md
new file mode 100644
index 0000000..7a0985f
--- /dev/null
+++ b/docs/fr/user-guide/choosing-a-starter.md
@@ -0,0 +1,145 @@
+# Quel starter choisir ?
+
+FastAPI-fastkit propose plusieurs façons d'amorcer un projet. Cette page est une **aide à la décision** pour les nouveaux venus : choisissez un chemin ici, puis allez sur [Démarrage rapide](quick-start.md) pour créer concrètement le projet.
+
+Si vous hésitez, la réponse courte est :
+
+> **Commencez par `fastkit init --interactive` et sélectionnez le préréglage `domain-starter`.** C'est l'option recommandée pour les projets d'API modernes.
+
+Le reste de cette page explique pourquoi, et quand opter pour autre chose.
+
+## TL;DR — choisir selon le profil d'utilisateur
+
+| Vous êtes... | Commencez avec |
+|---|---|
+| Nouveau sur FastAPI, vous voulez une démonstration guidée | `fastkit init --interactive` (préréglage : **`domain-starter`**) |
+| Vous voulez une démo CRUD fonctionnelle à lire et modifier | `fastkit startdemo fastapi-default` |
+| Vous voulez le squelette le plus minimal possible | `fastkit init --interactive` (préréglage : **`minimal`**) |
+| Vous écrivez un prototype rapide ou un script monofichier | `fastkit init --interactive` (préréglage : **`single-module`**) |
+| Vous avez besoin d'une vraie base de données (PostgreSQL + SQLAlchemy + Alembic) | `fastkit startdemo fastapi-psql-orm` |
+| Vous voulez une disposition orientée domaine pour une API de taille moyenne | `fastkit init --interactive` (préréglage : **`domain-starter`**) |
+
+## `startdemo` vs `init --interactive` — quelle différence ?
+
+Ce sont les deux points d'entrée principaux. Ils répondent à des besoins différents.
+
+### `fastkit startdemo `
+
+Dépose sur disque un projet d'**exemple complet et fonctionnel** basé sur l'un des modèles livrés (`fastapi-default`, `fastapi-async-crud`, `fastapi-psql-orm`, `fastapi-domain-starter`, …). Le code source du modèle est copié tel quel, avec les emplacements de métadonnées (``, etc.) remplis.
+
+- ✅ Le chemin le plus rapide vers une démo exécutable.
+- ✅ Tout le code est réel et lisible — idéal pour apprendre par l'exemple.
+- ❌ La pile et la structure du modèle sont fixes ; impossible de choisir CORS mais d'abandonner l'authentification au passage.
+
+```console
+$ fastkit list-templates # show what's available
+$ fastkit startdemo fastapi-default # generate a project from one
+```
+
+### `fastkit init --interactive`
+
+Vous guide à travers un **assistant pas à pas** : métadonnées du projet → préréglage d'architecture → sélections de fonctionnalités (base de données, authentification, tests, déploiement, …) → gestionnaire de paquets → confirmation. Le générateur choisit un modèle de base approprié par préréglage et superpose les fonctionnalités sélectionnées.
+
+- ✅ Vous assemblez exactement la pile que vous voulez.
+- ✅ Le préréglage d'architecture façonne la disposition du projet (monofichier, en couches, orientée domaine, …).
+- ❌ Les préréglages les plus complets qui conservent `main.py` (`classic-layered`, `domain-starter`) génèrent bien les modules de configuration, mais vous laissent les raccorder vous-même aux routeurs fournis. Consultez la [Matrice des préréglages d'architecture](../reference/preset-feature-matrix.md) pour voir précisément ce que couvre chaque préréglage et chaque fonctionnalité.
+
+```console
+$ fastkit init --interactive
+```
+
+## Les quatre préréglages d'architecture
+
+Ils apparaissent dans `fastkit init --interactive` après les invites de saisie des informations du projet. Utilisez cette section pour décider lequel choisir.
+
+### `minimal` — commencer au plus simple, étoffer plus tard
+
+L'application FastAPI la plus légère possible. On part d'un squelette vide avec un unique `src/main.py`, régénéré à partir des fonctionnalités que vous sélectionnez. CORS, limitation de débit et instrumentation Prometheus sont ajoutés automatiquement à `main.py` lorsqu'ils sont choisis.
+
+- 👤 **Pour qui** : les personnes qui veulent ajouter elles-mêmes de la structure au fur et à mesure, ou qui explorent FastAPI sans a priori sur la disposition.
+- 📦 **Modèle de base** : `fastapi-empty`.
+- 🧠 **Modèle mental** : « donnez-moi un seul fichier avec FastAPI importé et laissez-moi faire le reste. »
+
+### `single-module` — prototype façon script
+
+Tout vit dans un seul module. Même superposition de régénération de `main.py` que `minimal`.
+
+- 👤 **Pour qui** : écrire un script glue, un petit webhook ou un prototype d'une journée qui n'a pas besoin de frontières de package.
+- 📦 **Modèle de base** : `fastapi-single-module`.
+- 🧠 **Modèle mental** : « je veux un seul fichier Python que je peux exécuter et lire d'une traite. »
+
+### `classic-layered` — découpe en couches (api / crud / schemas / core)
+
+La disposition « à la Django » : le code est réparti horizontalement par rôle. Les routeurs vont dans `api/`, la logique CRUD dans `crud/`, les schémas Pydantic dans `schemas/` et la configuration dans `core/`. Le `main.py` fourni par le modèle est **conservé** (il gère déjà CORS) ; les fichiers de configuration générés pour la base de données et l'authentification sont placés dans `src/core/`.
+
+- 👤 **Pour qui** : équipes familières des dispositions de type Django/Rails, projets avec de nombreux petits points d'extrémité partageant une plomberie CRUD commune.
+- 📦 **Modèle de base** : `fastapi-default`.
+- 🧠 **Modèle mental** : « découper le code selon ce qu'il _est_. »
+
+### `domain-starter` — orienté domaine (option recommandée)
+
+Le code est organisé verticalement par **concept métier** : chaque domaine possède son propre routeur, son service, son dépôt et ses schémas dans `src/app/domains//`. Le modèle inclut aussi un endpoint `/health` et un domaine d'exemple `items`, que vous pouvez copier et renommer pour chaque nouveau concept. Le `main.py` fourni (sous `src/app/`) est conservé ; les fichiers de configuration générés sont placés dans `src/app/core/`.
+
+- 👤 **Pour qui** : les API de taille moyenne qui vont accueillir plusieurs concepts distincts (users, orders, billing, …). C'est l'option moderne recommandée.
+- 📦 **Modèle de base** : `fastapi-domain-starter`.
+- 🧠 **Modèle mental** : « découper le code selon ce qu'il _fait_ pour le métier. »
+
+## Matrice de comparaison
+
+Une vue côte à côte d'un coup d'œil.
+
+| | `minimal` | `single-module` | `classic-layered` | `domain-starter` |
+|---|---|---|---|---|
+| Modèle de base | `fastapi-empty` | `fastapi-single-module` | `fastapi-default` | `fastapi-domain-starter` |
+| Point d'entrée du projet | `src/main.py` | `src/main.py` | `src/main.py` | `src/app/main.py` |
+| Emplacement des routeurs | (vous les ajoutez) | (à l'intérieur de `main.py`) | `src/api/routes/` | `src/app/domains//router.py` |
+| Dossiers par domaine | ❌ | ❌ | ❌ | ✅ |
+| Point d'extrémité `/health` intégré | ✅ | ✅ | ❌ | ✅ |
+| `main.py` régénéré à partir des fonctionnalités | ✅ | ✅ | ❌ | ❌ |
+| CORS pré-câblé dans `main.py` | ajouté si sélectionné | ajouté si sélectionné | oui (piloté par env) | oui (piloté par env) |
+| pyproject d'abord | optionnel | optionnel | optionnel | ✅ |
+| Idéal pour | « je ferai évoluer ma propre structure » | « prototype monofichier » | « découper par préoccupation » | « découper par concept métier » |
+
+Pour le contrat complet par fonctionnalité (chemins cibles de configuration base de données / authentification, sélections nécessitant un câblage manuel vs automatique, déclenchement des avertissements), consultez la [Matrice des préréglages d'architecture](../reference/preset-feature-matrix.md).
+
+## Choisir un modèle `startdemo`
+
+`fastkit startdemo ` est idéal quand vous voulez un **exemple complet et exécutable** plutôt qu'un assemblage guidé. La plupart des modèles correspondent grossièrement à l'un des quatre préréglages ci-dessus, mais ils embarquent du code d'exemple supplémentaire (points d'extrémité CRUD sur un magasin factice, gestion de réponses personnalisée, outillage Docker, etc.).
+
+| Modèle | Préréglage le plus proche | Quand le choisir |
+|---|---|---|
+| `fastapi-default` | `classic-layered` | Démo CRUD fonctionnelle avec la disposition en couches. Bon point de départ. |
+| `fastapi-empty` | `minimal` | Squelette nu ; même forme que celle obtenue par `minimal`. |
+| `fastapi-single-module` | `single-module` | Démo monofichier. |
+| `fastapi-domain-starter` | `domain-starter` | Valeur par défaut moderne recommandée ; livré avec un exemple de domaine items. |
+| `fastapi-async-crud` | `classic-layered` | Équivalent asynchrone de `fastapi-default`. |
+| `fastapi-custom-response` | `classic-layered` | Illustre les enveloppes / formats de réponses personnalisés. |
+| `fastapi-dockerized` | `classic-layered` | Ajoute un Dockerfile prêt pour la production à la disposition par défaut. |
+| `fastapi-psql-orm` | (aucun préréglage direct) | PostgreSQL + SQLAlchemy + Alembic. À choisir lorsque vous avez besoin d'une vraie base de données. |
+| `fastapi-mcp` | (aucun préréglage direct) | Intégration du Model Context Protocol. |
+
+`fastkit list-templates` affiche la liste à jour avec une description en une ligne.
+
+## Questions fréquentes
+
+**Q. Faut-il choisir un préréglage / modèle dès le départ ?**
+Non — vous pouvez toujours réorganiser le code généré à la main par la suite. Les préréglages sont des points de départ, pas des contrats. Ne sur-réfléchissez pas ce choix.
+
+**Q. Quel est le choix « moderne » ?**
+`domain-starter`. Il adopte une approche pyproject-first, fournit un endpoint `/health` et suit la structure vers laquelle convergent la plupart des projets FastAPI de taille moyenne bien entretenus.
+
+**Q. Puis-je passer de `classic-layered` à `domain-starter` plus tard ?**
+Oui, mais c'est un refactoring manuel — il n'existe pas de commande de migration. Si vous pensez que votre projet grandira au point de nécessiter des dossiers par domaine, commencez directement par là.
+
+**Q. Et si je veux simplement apprendre FastAPI ?**
+Commencez avec `fastkit startdemo fastapi-default` — lisez le code, exécutez les tests, modifiez quelques points d'extrémité. Une fois à l'aise, `fastkit init --interactive` avec le préréglage `domain-starter` est l'étape suivante naturelle.
+
+**Q. Où voir les fichiers exacts générés par chaque préréglage ?**
+La [Matrice des préréglages d'architecture](../reference/preset-feature-matrix.md) est la page de référence à ce sujet.
+
+## Étapes suivantes
+
+- [Démarrage rapide](quick-start.md) — créer concrètement votre premier projet.
+- [Créer des projets](creating-projects.md) — visite plus approfondie des drapeaux du CLI.
+- [Tutoriel Projet orienté domaine](../tutorial/domain-starter.md) — si vous avez choisi `domain-starter`, vous y trouverez un parcours complet de l'arborescence générée, de l'exemple `items` fourni et de la façon d'ajouter votre prochain domaine.
+- [Matrice des préréglages d'architecture](../reference/preset-feature-matrix.md) — le contrat complet par préréglage / par fonctionnalité.
diff --git a/docs/fr/user-guide/cli-reference.md b/docs/fr/user-guide/cli-reference.md
new file mode 100644
index 0000000..c3943da
--- /dev/null
+++ b/docs/fr/user-guide/cli-reference.md
@@ -0,0 +1,832 @@
+# Référence CLI
+
+Référence complète de toutes les commandes de l'interface en ligne de commande de FastAPI-fastkit.
+
+## Options globales
+
+Toutes les commandes acceptent ces options globales :
+
+```console
+$ fastkit [GLOBAL_OPTIONS] COMMAND [COMMAND_OPTIONS]
+```
+
+### Options globales
+
+| Option | Description |
+|--------|-------------|
+| `--version` | Afficher la version de FastAPI-fastkit |
+| `--help` | Afficher le message d'aide |
+
+### Exemples
+
+
+
+```console
+$ fastkit --version
+FastAPI-fastkit version 1.0.0
+
+$ fastkit --help
+Usage: fastkit [OPTIONS] COMMAND [ARGS]...
+
+ FastAPI-fastkit CLI
+
+Options:
+ --version Show the version and exit.
+ --help Show this message and exit.
+
+Commands:
+ addroute Add a new route to FastAPI project
+ init Create a new FastAPI project
+ list-templates List available FastAPI templates
+ runserver Start FastAPI development server
+ startdemo Create FastAPI project from template
+```
+
+
+
+## Commandes
+
+### `init`
+
+Créer un nouveau projet FastAPI avec une configuration interactive.
+
+#### Syntaxe
+
+```console
+$ fastkit init [OPTIONS]
+```
+
+#### Options
+
+| Option | Description | Défaut |
+|--------|-------------|---------|
+| `--package-manager` | Gestionnaire de paquets à utiliser (pip, uv, pdm, poetry) | uv |
+| `--help` | Afficher l'aide de la commande | - |
+
+#### Invites interactives
+
+La commande `init` vous demandera :
+
+1. **Nom du projet** : nom de répertoire et nom du paquet
+2. **Nom de l'auteur** : informations sur l'auteur du paquet
+3. **E-mail de l'auteur** : adresse de contact du paquet
+4. **Description du projet** : brève description du projet
+5. **Sélection de la pile** : choisir parmi minimal, standard ou full
+6. **Sélection du gestionnaire de paquets** : choisir parmi pip, uv, pdm ou poetry (à moins de l'avoir spécifié avec `--package-manager`)
+
+#### Options de pile
+
+**Pile MINIMAL :**
+
+- `fastapi` — framework FastAPI
+- `uvicorn` — serveur ASGI
+- `pydantic` — validation des données
+- `pydantic-settings` — gestion de la configuration
+
+**Pile STANDARD :**
+
+- Tous les paquets de la pile MINIMAL
+- `sqlalchemy` — boîte à outils SQL et ORM
+- `alembic` — outil de migration de base de données
+- `pytest` — framework de test
+
+**Pile FULL :**
+
+- Tous les paquets de la pile STANDARD
+- `redis` — stockage de données en mémoire
+- `celery` — file de tâches distribuée
+
+#### Exemples
+
+
+
+```console
+$ fastkit init
+Enter the project name: my-api
+Enter the author name: John Doe
+Enter the author email: john@example.com
+Enter the project description: My awesome API
+
+Select stack (minimal, standard, full): standard
+Select package manager (pip, uv, pdm, poetry) [uv]: uv
+Do you want to proceed with project creation? [y/N]: y
+
+✨ FastAPI project 'my-api' has been created successfully!
+```
+
+
+
+#### Structure générée
+
+Crée un projet avec cette structure :
+
+```
+my-api/
+├── .venv/ # Environnement virtuel
+├── src/
+│ ├── __init__.py
+│ ├── main.py # Application FastAPI
+│ ├── core/
+│ │ ├── __init__.py
+│ │ └── config.py # Configuration
+│ ├── api/
+│ │ ├── __init__.py
+│ │ ├── api.py # Regroupement des routeurs API
+│ │ └── routes/
+│ │ ├── __init__.py
+│ │ └── items.py # Exemple de route
+│ ├── crud/
+│ │ ├── __init__.py
+│ │ └── items.py # Opérations CRUD
+│ ├── schemas/
+│ │ ├── __init__.py
+│ │ └── items.py # Schémas Pydantic
+│ └── mocks/
+│ ├── __init__.py
+│ └── mock_items.json # Données de test
+├── tests/
+├── scripts/
+├── requirements.txt
+├── setup.py
+└── README.md
+```
+
+### `addroute`
+
+Ajouter une nouvelle route d'API à un projet FastAPI existant.
+
+#### Syntaxe
+
+```console
+$ fastkit addroute ROUTE_NAME [PROJECT_DIR] [OPTIONS]
+```
+
+#### Arguments
+
+| Argument | Description | Requis |
+|----------|-------------|----------|
+| `ROUTE_NAME` | Nom de la nouvelle route (pluriel recommandé) | Oui |
+| `PROJECT_DIR` | Répertoire du projet sous votre espace de travail (par défaut `.`, le répertoire courant) | Non |
+
+#### Options
+
+| Option | Description | Défaut |
+|--------|-------------|---------|
+| `--help` | Afficher l'aide de la commande | - |
+
+#### Exemples
+
+
+
+```console
+$ cd my-api
+$ fastkit addroute users
+ Adding New Route
+┌──────────────────┬──────────────────────────────────────────┐
+│ Project │ my-api │
+│ Route Name │ users │
+│ Target Directory │ ~/my-api │
+└──────────────────┴──────────────────────────────────────────┘
+
+Do you want to add route 'users' to project 'my-api'? [Y/n]: y
+
+✨ Successfully added new route 'users' to project 'my-api'
+```
+
+
+
+Vous pouvez aussi cibler un projet sous votre espace de travail par son nom sans vous déplacer avec `cd` :
+
+
+
+```console
+$ fastkit addroute users my-api
+```
+
+
+
+#### Fichiers générés
+
+Crée ces fichiers dans le projet :
+
+- `src/api/routes/users.py` — gestionnaires de route
+- `src/crud/users.py` — opérations CRUD
+- `src/schemas/users.py` — schémas Pydantic
+
+Met aussi à jour `src/api/api.py` pour inclure le nouveau routeur.
+
+#### Points d'extrémité générés
+
+Crée des points d'extrémité CRUD complets :
+
+| Méthode | Point d'extrémité | Description |
+|--------|----------|-------------|
+| `GET` | `/api/v1/users/` | Récupérer tous les utilisateurs |
+| `POST` | `/api/v1/users/` | Créer un nouvel utilisateur |
+| `GET` | `/api/v1/users/{user_id}` | Récupérer un utilisateur précis |
+| `PUT` | `/api/v1/users/{user_id}` | Mettre à jour un utilisateur |
+| `DELETE` | `/api/v1/users/{user_id}` | Supprimer un utilisateur |
+
+### `startdemo`
+
+Créer un projet FastAPI à partir d'un modèle prêt à l'emploi.
+
+#### Syntaxe
+
+```console
+$ fastkit startdemo [OPTIONS]
+```
+
+#### Options
+
+| Option | Description | Défaut |
+|--------|-------------|---------|
+| `--package-manager` | Gestionnaire de paquets à utiliser (pip, uv, pdm, poetry) | uv |
+| `--help` | Afficher l'aide de la commande | - |
+
+#### Invites interactives
+
+La commande `startdemo` vous demandera :
+
+1. **Nom du projet** : nom de répertoire pour le nouveau projet
+2. **Nom de l'auteur** : informations sur l'auteur du paquet
+3. **E-mail de l'auteur** : adresse de contact
+4. **Description du projet** : brève description
+5. **Sélection du gestionnaire de paquets** : choisir parmi pip, uv, pdm ou poetry (à moins de l'avoir spécifié avec `--package-manager`)
+
+#### Modèles disponibles
+
+| Modèle | Description | Fonctionnalités |
+|----------|-------------|----------|
+| `fastapi-default` | Projet FastAPI simple | CRUD basique, données factices |
+| `fastapi-async-crud` | API asynchrone de gestion d'items | Async/await, performance |
+| `fastapi-custom-response` | Système de réponses personnalisées | Réponses personnalisées, pagination |
+| `fastapi-dockerized` | API FastAPI dockerisée | Docker, prêt pour la production |
+| `fastapi-psql-orm` | API FastAPI avec PostgreSQL | PostgreSQL, SQLAlchemy, Alembic |
+| `fastapi-empty` | Projet FastAPI minimal | Configuration minimale |
+
+#### Exemples
+
+
+
+```console
+$ fastkit startdemo fastapi-psql-orm
+Enter the project name: my-blog
+Enter the author name: Jane Smith
+Enter the author email: jane@example.com
+Enter the project description: Blog API with PostgreSQL
+
+Select package manager (pip, uv, pdm, poetry) [uv]: poetry
+Do you want to proceed with project creation? [y/N]: y
+
+✨ FastAPI project 'my-blog' from 'fastapi-psql-orm' has been created!
+```
+
+
+
+### `runserver`
+
+Démarrer le serveur de développement FastAPI.
+
+#### Syntaxe
+
+```console
+$ fastkit runserver [OPTIONS]
+```
+
+#### Options
+
+| Option | Court | Description | Défaut |
+|--------|-------|-------------|---------|
+| `--host` | `-h` | Hôte sur lequel se lier | `127.0.0.1` |
+| `--port` | `-p` | Port sur lequel se lier | `8000` |
+| `--reload` | `-r` | Activer le rechargement automatique | `True` |
+| `--workers` | `-w` | Nombre de workers | `1` |
+| `--help` | | Afficher l'aide de la commande | - |
+
+#### Exemples
+
+
+
+```console
+# Utilisation de base (paramètres par défaut)
+$ fastkit runserver
+INFO: Uvicorn running on http://127.0.0.1:8000
+
+# Hôte et port personnalisés
+$ fastkit runserver --host 0.0.0.0 --port 8080
+INFO: Uvicorn running on http://0.0.0.0:8080
+
+# Désactiver le rechargement automatique
+$ fastkit runserver --no-reload
+INFO: Uvicorn running on http://127.0.0.1:8000
+
+# Plusieurs workers (production)
+$ fastkit runserver --workers 4
+INFO: Uvicorn running on http://127.0.0.1:8000
+```
+
+
+
+#### Prérequis
+
+- Doit être exécuté depuis un répertoire de projet FastAPI
+- Le projet doit avoir `src/main.py` avec une app FastAPI
+- L'environnement virtuel doit être activé
+
+### `list-templates`
+
+Lister tous les modèles de projet FastAPI disponibles.
+
+#### Syntaxe
+
+```console
+$ fastkit list-templates [OPTIONS]
+```
+
+#### Options
+
+| Option | Description | Défaut |
+|--------|-------------|---------|
+| `--help` | Afficher l'aide de la commande | - |
+
+#### Exemples
+
+
+
+```console
+$ fastkit list-templates
+ Available Templates
+┌─────────────────────────┬───────────────────────────────────┐
+│ fastapi-custom-response │ Async Item Management API with │
+│ │ Custom Response System │
+│ fastapi-dockerized │ Dockerized FastAPI Item │
+│ │ Management API │
+│ fastapi-empty │ No description │
+│ fastapi-async-crud │ Async Item Management API Server │
+│ fastapi-psql-orm │ Dockerized FastAPI Item │
+│ │ Management API with PostgreSQL │
+│ fastapi-default │ Simple FastAPI Project │
+└─────────────────────────┴───────────────────────────────────┘
+```
+
+
+
+## Variables d'environnement
+
+FastAPI-fastkit prend en compte ces variables d'environnement :
+
+| Variable | Description | Défaut |
+|----------|-------------|---------|
+| `FASTKIT_CONFIG_DIR` | Répertoire de configuration | `~/.fastkit` |
+| `FASTKIT_TEMPLATES_DIR` | Répertoire de modèles personnalisés | Modèles intégrés |
+| `FASTKIT_LOG_LEVEL` | Niveau de journalisation | `INFO` |
+
+### Exemples
+
+
+
+```console
+# Répertoire de configuration personnalisé
+$ export FASTKIT_CONFIG_DIR=~/my-fastkit-config
+$ fastkit init
+
+# Répertoire de templates personnalisé
+$ export FASTKIT_TEMPLATES_DIR=~/my-templates
+$ fastkit list-templates
+
+# Journalisation en mode debug
+$ export FASTKIT_LOG_LEVEL=DEBUG
+$ fastkit init
+```
+
+
+
+## Fichiers de configuration
+
+FastAPI-fastkit peut utiliser des fichiers de configuration pour les paramètres par défaut.
+
+### Emplacement du fichier de configuration
+
+1. `$FASTKIT_CONFIG_DIR/config.yaml` (si `FASTKIT_CONFIG_DIR` est défini)
+2. `~/.fastkit/config.yaml` (par défaut)
+3. `./fastkit.yaml` (spécifique au projet)
+
+### Format de la configuration
+
+```yaml
+# ~/.fastkit/config.yaml
+default:
+ author:
+ name: "Votre nom"
+ email: "your.email@example.com"
+
+ project:
+ stack: "standard"
+ create_venv: true
+ install_deps: true
+
+ server:
+ host: "127.0.0.1"
+ port: 8000
+ reload: true
+
+templates:
+ custom_dir: "~/my-templates"
+
+logging:
+ level: "INFO"
+ file: "~/.fastkit/logs/fastkit.log"
+```
+
+## Flux de travail courants
+
+### 1. Créer un nouveau projet
+
+
+
+```console
+# Créer un nouveau projet
+$ fastkit init
+# Suivez les invites...
+
+# Aller dans le projet
+$ cd my-awesome-api
+
+# Activer l'environnement virtuel
+$ source .venv/bin/activate
+
+# Démarrer le serveur de développement
+$ fastkit runserver
+```
+
+
+
+### 2. Ajouter des fonctionnalités à un projet existant
+
+
+
+```console
+# Ajouter plusieurs routes (le nom du projet en deuxième argument positionnel vise le projet de l'espace de travail)
+$ fastkit addroute users my-api
+$ fastkit addroute products my-api
+$ fastkit addroute orders my-api
+
+# Tester l'API
+$ fastkit runserver
+# Ouvrir ensuite http://127.0.0.1:8000/docs
+```
+
+
+
+### 3. Utiliser des modèles pour des projets complexes
+
+
+
+```console
+# Lister les templates disponibles
+$ fastkit list-templates
+
+# Créer un projet à partir d'un template
+$ fastkit startdemo
+# Choisir fastapi-psql-orm pour un projet avec base de données
+
+# Préparer la base de données (pour le template PostgreSQL)
+$ cd my-project
+$ docker-compose up -d postgres
+$ source .venv/bin/activate
+$ alembic upgrade head
+$ fastkit runserver
+```
+
+
+
+## Dépannage
+
+### Commande introuvable
+
+Si la commande `fastkit` est introuvable :
+
+1. **Vérifiez l'installation :**
+
+ ```console
+ $ pip show fastapi-fastkit
+ ```
+
+
+2. **Réinstallez si nécessaire :**
+
+ ```console
+ $ pip uninstall fastapi-fastkit
+ $ pip install fastapi-fastkit
+ ```
+
+
+3. **Vérifiez le PATH :**
+
+ ```console
+ $ which fastkit
+ ```
+
+
+### Problèmes d'environnement virtuel
+
+Si la création de l'environnement virtuel échoue :
+
+1. **Vérifiez la version de Python :**
+
+ ```console
+ $ python --version # Doit être en 3.12+
+ ```
+
+
+2. **Vérifiez le module venv :**
+
+ ```console
+ $ python -m venv --help
+ ```
+
+
+3. **Environnement virtuel manuel :**
+
+ ```console
+ $ python -m venv .venv
+ $ source .venv/bin/activate
+ $ pip install -r requirements.txt
+ ```
+
+
+### Le serveur ne démarre pas
+
+Si `fastkit runserver` échoue :
+
+1. **Vérifiez que vous êtes dans le répertoire du projet**
+2. **Vérifiez que `src/main.py` existe**
+3. **Activez l'environnement virtuel :**
+
+ ```console
+ $ source .venv/bin/activate
+ ```
+
+
+4. **Recherchez les erreurs de syntaxe :**
+
+ ```console
+ $ python -c "from src.main import app"
+ ```
+
+
+### Port déjà utilisé
+
+Si le port 8000 est occupé :
+
+
+
+```console
+# Utiliser un autre port
+$ fastkit runserver --port 8080
+
+# Ou arrêter le processus déjà en cours
+$ lsof -ti:8000 | xargs kill -9
+```
+
+
+
+## Utilisation avancée
+
+### Modèles personnalisés
+
+Vous pouvez créer des modèles personnalisés en :
+
+1. **Créant un répertoire de modèle :**
+ ```
+ my-template/
+ ├── src/
+ │ └── main.py-tpl
+ ├── requirements.txt-tpl
+ └── setup.py-tpl
+ ```
+
+2. **Définissant la variable d'environnement :**
+
+ ```console
+ $ export FASTKIT_TEMPLATES_DIR=~/my-templates
+ ```
+
+
+3. **Utilisant le modèle personnalisé :**
+
+ ```console
+ $ fastkit startdemo
+ # Your custom templates will appear in the list
+ ```
+
+
+### Scripts avec FastAPI-fastkit
+
+Vous pouvez utiliser FastAPI-fastkit dans des scripts :
+
+```bash
+#!/bin/bash
+# create-microservices.sh
+
+for service in users products orders; do
+ echo "Creating $service service..."
+ fastkit init <
+
+```console
+$ fastkit init --package-manager uv
+# Crée un `pyproject.toml` configuré pour UV
+```
+
+
+
+#### PDM
+- **Moderne** : prise en charge de PEP 582 et PEP 621
+- **Avancé** : résolution sophistiquée des dépendances
+- **Flexible** : multiples dispositions de projet
+
+
+
+```console
+$ fastkit init --package-manager pdm
+# Crée un `pyproject.toml` configuré pour PDM
+```
+
+
+
+#### Poetry
+- **Établi** : mature et largement adopté
+- **Intégré** : prise en charge du build et de la publication
+- **Lockfile** : poetry.lock pour des builds reproductibles
+
+
+
+```console
+$ fastkit init --package-manager poetry
+# Crée un `pyproject.toml` configuré pour Poetry
+```
+
+
+
+#### PIP
+- **Standard** : intégré à Python
+- **Compatible** : fonctionne partout
+- **Simple** : gestion directe des dépendances
+
+
+
+```console
+$ fastkit init --package-manager pip
+# Crée un `requirements.txt`
+```
+
+
+
+### Travailler avec les projets
+
+Après avoir créé un projet avec un gestionnaire de paquets spécifique :
+
+#### Projets UV
+```console
+cd my-project
+uv sync # Installer les dépendances
+uv add requests # Ajouter une nouvelle dépendance
+uv run pytest # Exécuter des commandes dans l'environnement
+```
+
+#### Projets PDM
+```console
+cd my-project
+pdm install # Installer les dépendances
+pdm add requests # Ajouter une nouvelle dépendance
+pdm run pytest # Exécuter des commandes dans l'environnement
+```
+
+#### Projets Poetry
+```console
+cd my-project
+poetry install # Installer les dépendances
+poetry add requests # Ajouter une nouvelle dépendance
+poetry run pytest # Exécuter des commandes dans l'environnement
+```
+
+#### Projets PIP
+```console
+cd my-project
+source .venv/bin/activate # Linux/macOS
+.venv\Scripts\activate # Windows
+pip install -r requirements.txt
+pip install requests
+pytest
+```
+
+## Étapes suivantes
+
+Maintenant que vous comprenez le CLI :
+
+1. **[Démarrage rapide](quick-start.md)** : essayer les commandes en pratique
+2. **[Votre premier projet](../tutorial/first-project.md)** : construire une application complète
+3. **[Contribution](../contributing/development-setup.md)** : contribuer à FastAPI-fastkit
+
+!!! tip "Astuces CLI"
+ - Utilisez `--help` avec n'importe quelle commande pour une aide détaillée
+ - Configurez les paramètres par défaut pour accélérer la création de projet
+ - Utilisez les modèles pour des configurations de projet complexes
+ - Combinez les commandes pour créer des flux de travail puissants
diff --git a/docs/fr/user-guide/creating-projects.md b/docs/fr/user-guide/creating-projects.md
new file mode 100644
index 0000000..3a10035
--- /dev/null
+++ b/docs/fr/user-guide/creating-projects.md
@@ -0,0 +1,540 @@
+# Créer des projets
+
+Un guide détaillé sur la création de différents types de projets FastAPI avec FastAPI-fastkit.
+
+## Création de projet basique
+
+### 1. Création de projet en mode interactif
+
+La façon la plus basique de créer un projet en mode interactif :
+
+
+
+```console
+$ fastkit init
+Enter the project name: my-awesome-api
+Enter the author name: John Doe
+Enter the author email: john@example.com
+Enter the project description: Awesome FastAPI project
+
+ Project Information
+┌──────────────┬─────────────────────────┐
+│ Project Name │ my-awesome-api │
+│ Author │ John Doe │
+│ Author Email │ john@example.com │
+│ Description │ Awesome FastAPI project │
+└──────────────┴─────────────────────────┘
+```
+
+
+
+### 2. Sélection de la pile
+
+Choisissez la pile de dépendances à inclure dans votre projet :
+
+#### Pile MINIMAL (par défaut)
+
+Le projet FastAPI le plus basique :
+
+- `fastapi` — framework FastAPI
+- `uvicorn` — serveur ASGI
+- `pydantic` — validation des données
+- `pydantic-settings` — gestion des paramètres
+
+**Idéal pour :**
+
+- Apprendre FastAPI
+- API simples
+- Prototypes
+- Microservices
+
+#### Pile STANDARD
+
+Inclut la prise en charge des bases de données et des tests :
+
+- Toutes les dépendances MINIMAL
+- `sqlalchemy` — ORM pour les opérations en base de données
+- `alembic` — migrations de base de données
+- `pytest` — framework de test
+
+**Idéal pour :**
+
+- La plupart des applications web
+- API avec stockage en base de données
+- Applications prêtes pour la production
+- Projets en équipe
+
+#### Pile FULL
+
+Environnement de développement complet :
+
+- Toutes les dépendances STANDARD
+- `redis` — cache et stockage de session
+- `celery` — traitement des tâches en arrière-plan
+
+**Idéal pour :**
+
+- Applications de grande taille
+- Exigences de haute performance
+- Logique métier complexe
+- Applications d'entreprise
+
+## Options de projet avancées
+
+### Configuration personnalisée du projet
+
+Vous pouvez personnaliser votre projet lors de la création :
+
+
+
+```console
+$ fastkit init
+Enter the project name: advanced-api
+Enter the author name: Development Team
+Enter the author email: dev@company.com
+Enter the project description: Advanced FastAPI application with custom features
+
+# Choisissez la pile STANDARD pour le support de base de données
+Select stack (minimal, standard, full): standard
+Do you want to proceed with project creation? [y/N]: y
+```
+
+
+
+### Explication de la structure du projet
+
+Lorsque vous créez un projet, FastAPI-fastkit génère cette structure :
+
+```
+my-awesome-api/
+├── .venv/ # Environnement virtuel
+├── src/ # Code source
+│ ├── __init__.py
+│ ├── main.py # Point d'entrée de l'application
+│ ├── core/ # Configuration centrale
+│ │ ├── __init__.py
+│ │ └── config.py # Paramètres et configuration
+│ ├── api/ # Couche API
+│ │ ├── __init__.py
+│ │ ├── api.py # Routeur principal de l'API
+│ │ └── routes/ # Modules de routes individuels
+│ │ ├── __init__.py
+│ │ └── items.py # Endpoints d'exemple pour items
+│ ├── crud/ # Opérations sur les données
+│ │ ├── __init__.py
+│ │ └── items.py # Opérations CRUD pour items
+│ ├── schemas/ # Modèles Pydantic
+│ │ ├── __init__.py
+│ │ └── items.py # Schémas de validation des données
+│ └── mocks/ # Données de test
+│ ├── __init__.py
+│ └── mock_items.json # Données d'exemple pour le développement
+├── tests/ # Suite de tests
+│ ├── __init__.py
+│ ├── conftest.py # Configuration des tests
+│ └── test_items.py # Tests d'exemple
+├── scripts/ # Scripts utilitaires
+│ ├── test.sh # Lancer les tests
+│ ├── coverage.sh # Couverture de tests
+│ └── lint.sh # Vérification du code
+├── requirements.txt # Dépendances Python
+├── setup.py # Configuration du paquet
+└── README.md # Documentation du projet
+```
+
+### 3. Sélection du gestionnaire de paquets
+
+FastAPI-fastkit prend en charge plusieurs gestionnaires de paquets Python. Choisissez celui qui correspond le mieux à votre flux de développement :
+
+#### Gestionnaires de paquets disponibles
+
+
+
+```console
+Available Package Managers:
+ Package Managers
+┌────────┬────────────────────────────────────────────┐
+│ PIP │ Standard Python package manager │
+│ UV │ Fast Python package manager │
+│ PDM │ Modern Python dependency management │
+│ POETRY │ Python dependency management and packaging │
+└────────┴────────────────────────────────────────────┘
+
+Select package manager (pip, uv, pdm, poetry) [uv]: uv
+```
+
+
+
+Chaque gestionnaire de paquets a ses atouts :
+
+#### UV (par défaut — recommandé)
+
+**Gestionnaire de paquets rapide basé sur Rust**
+
+- ⚡ **Ultra-rapide** : 10 à 100 fois plus rapide que pip
+- 🔧 **Remplacement direct** : compatible avec les flux pip
+- 📦 **Moderne** : prise en charge complète de PEP 621
+- 🛠️ **Fiable** : résolution déterministe
+
+**Fichiers générés :**
+
+- `pyproject.toml` (format PEP 621)
+- `uv.lock` (fichier de verrouillage)
+
+**Utilisation après création :**
+```console
+cd my-project
+uv sync # Installer les dépendances
+uv add requests # Ajouter une dépendance
+uv run pytest # Lancer les tests
+```
+
+#### PDM
+
+**Gestion moderne des dépendances Python**
+
+- 🚀 **Moderne** : prise en charge de PEP 582 et PEP 621
+- 🧠 **Intelligent** : résolution avancée des dépendances
+- 💼 **Professionnel** : prise en charge des espaces de travail et des projets multiples
+- 📊 **Analytique** : outils d'analyse des dépendances
+
+**Fichiers générés :**
+
+- `pyproject.toml` (format PEP 621)
+- `pdm.lock` (fichier de verrouillage)
+
+**Utilisation après création :**
+```console
+cd my-project
+pdm install # Installer les dépendances
+pdm add requests # Ajouter une dépendance
+pdm run pytest # Lancer les tests
+```
+
+#### Poetry
+
+**Gestion mature des dépendances et packaging**
+
+- ✅ **Établi** : mature et largement adopté
+- 📦 **Intégré** : prise en charge du build et de la publication
+- 🔒 **Reproductible** : poetry.lock pour des versions exactes
+- 🏗️ **Complet** : gestion complète du cycle de vie d'un projet
+
+**Fichiers générés :**
+
+- `pyproject.toml` (format Poetry)
+- `poetry.lock` (fichier de verrouillage)
+
+**Utilisation après création :**
+```console
+cd my-project
+poetry install # Installer les dépendances
+poetry add requests # Ajouter une dépendance
+poetry run pytest # Lancer les tests
+```
+
+#### PIP
+
+**Gestionnaire de paquets Python standard**
+
+- 🏠 **Intégré** : livré avec Python
+- 🌍 **Universel** : fonctionne partout
+- 📚 **Familier** : la plupart des développeurs le connaissent
+- 🔧 **Simple** : flux de travail direct
+
+**Fichiers générés :**
+
+- `requirements.txt`
+
+**Utilisation après création :**
+```console
+cd my-project
+source .venv/bin/activate # Linux/macOS
+.venv\Scripts\activate # Windows
+pip install -r requirements.txt
+pip install requests
+pytest
+```
+
+#### Spécifier le gestionnaire de paquets
+
+Vous pouvez indiquer votre gestionnaire de paquets préféré :
+
+**Sélection interactive (par défaut) :**
+```console
+$ fastkit init
+# ... invite de sélection du gestionnaire de paquets
+```
+
+**Option en ligne de commande :**
+```console
+$ fastkit init --package-manager poetry
+$ fastkit init --package-manager pdm
+$ fastkit init --package-manager uv
+$ fastkit init --package-manager pip
+```
+
+### Comprendre chaque répertoire
+
+#### Répertoire `src/`
+
+Contient tout le code source de votre application selon une **organisation en `src/`**, une bonne pratique courante pour le packaging Python.
+
+#### Module `core/`
+
+- **config.py** : paramètres de l'application, variables d'environnement et configuration
+- Centralise toute la gestion de la configuration
+- Prend en charge le fichier `.env` pour les paramètres spécifiques à l'environnement
+
+#### Module `api/`
+
+- **api.py** : routeur principal d'API qui regroupe tous les sous-routeurs
+- **routes/** : modules de routes individuels pour différentes ressources
+- Séparation propre des préoccupations pour les différents points d'extrémité de l'API
+
+#### Module `crud/`
+
+- Opérations de base de données et logique métier
+- Opérations **C**reate, **R**ead, **U**pdate, **D**elete
+- Couche d'abstraction entre les routes d'API et le stockage des données
+
+#### Module `schemas/`
+
+- Modèles Pydantic pour la validation des données
+- Schémas de requête / réponse
+- Définitions de types et modèles de données
+
+#### Répertoire `tests/`
+
+- Suite de tests complète pour votre application
+- Inclut des tests unitaires et d'intégration
+- Préconfiguré avec pytest
+
+## Comparaison des piles
+
+| Fonctionnalité | MINIMAL | STANDARD | FULL |
+|---------|---------|----------|------|
+| FastAPI & Uvicorn | ✅ | ✅ | ✅ |
+| Validation des données | ✅ | ✅ | ✅ |
+| Prise en charge des bases de données | ❌ | ✅ | ✅ |
+| Migrations | ❌ | ✅ | ✅ |
+| Framework de test | ❌ | ✅ | ✅ |
+| Mise en cache (Redis) | ❌ | ❌ | ✅ |
+| Tâches en arrière-plan | ❌ | ❌ | ✅ |
+| **Idéal pour** | Apprentissage, API simples | La plupart des applications | Entreprise, applications complexes |
+
+## Exemples de création de projet
+
+### Exemple 1 : projet d'apprentissage
+
+
+
+```console
+$ fastkit init
+Enter the project name: fastapi-learning
+Enter the author name: Student
+Enter the author email: student@example.com
+Enter the project description: Learning FastAPI basics
+
+Select stack (minimal, standard, full): minimal
+Do you want to proceed with project creation? [y/N]: y
+```
+
+
+
+### Exemple 2 : API e-commerce
+
+
+
+```console
+$ fastkit init
+Enter the project name: ecommerce-api
+Enter the author name: E-commerce Team
+Enter the author email: team@ecommerce.com
+Enter the project description: E-commerce platform API
+
+Select stack (minimal, standard, full): standard
+Do you want to proceed with project creation? [y/N]: y
+```
+
+
+
+### Exemple 3 : application haute performance
+
+
+
+```console
+$ fastkit init
+Enter the project name: enterprise-api
+Enter the author name: Enterprise Team
+Enter the author email: enterprise@company.com
+Enter the project description: High-performance enterprise API
+
+Select stack (minimal, standard, full): full
+Do you want to proceed with project creation? [y/N]: y
+```
+
+
+
+## Après la création du projet
+
+### 1. Activer l'environnement virtuel
+
+
+
+```console
+$ cd my-awesome-api
+$ source .venv/bin/activate # Linux/macOS
+$ .venv\Scripts\activate # Windows
+```
+
+
+
+### 2. Vérifier l'installation
+
+
+
+```console
+$ pip list
+Package Version
+fastapi 0.104.1
+uvicorn 0.24.0
+pydantic 2.5.0
+...
+```
+
+
+
+### 3. Démarrer le développement
+
+
+
+```console
+$ fastkit runserver
+INFO: Uvicorn running on http://127.0.0.1:8000
+```
+
+
+
+## Gestion de la configuration
+
+### Variables d'environnement
+
+Votre projet prend en charge la configuration via des fichiers `.env` :
+
+Créez un fichier `.env` à la racine de votre projet :
+
+```env
+# .env
+APP_NAME=My Awesome API
+APP_VERSION=1.0.0
+DEBUG=True
+DATABASE_URL=sqlite:///./app.db
+SECRET_KEY=your-secret-key-here
+```
+
+### Configuration dans le code
+
+Le `src/core/config.py` généré charge automatiquement ces variables :
+
+```python
+from pydantic_settings import BaseSettings
+
+class Settings(BaseSettings):
+ APP_NAME: str = "FastAPI Application"
+ APP_VERSION: str = "1.0.0"
+ DEBUG: bool = False
+ DATABASE_URL: str = "sqlite:///./app.db"
+ SECRET_KEY: str = "dev-secret-key"
+
+ class Config:
+ env_file = ".env"
+
+settings = Settings()
+```
+
+## Options de personnalisation
+
+### Ajouter des dépendances personnalisées
+
+Après la création du projet, vous pouvez ajouter d'autres dépendances :
+
+
+
+```console
+$ pip install requests httpx python-jose
+$ pip freeze > requirements.txt
+```
+
+
+
+### Modifier la structure du projet
+
+La structure générée suit les bonnes pratiques, mais vous pouvez l'adapter :
+
+- Ajouter de nouveaux modules dans `src/`
+- Créer des fichiers de routes supplémentaires dans `api/routes/`
+- Étendre les opérations CRUD dans `crud/`
+- Ajouter d'autres schémas dans `schemas/`
+
+## Bonnes pratiques
+
+### 1. Environnement virtuel
+
+Utilisez toujours des environnements virtuels pour isoler les dépendances du projet :
+
+```bash
+# Create project with virtual environment
+$ fastkit init # Automatically creates .venv/
+
+# Activate when working
+$ source .venv/bin/activate
+```
+
+### 2. Gestion de versions
+
+Initialisez un dépôt git après la création du projet :
+
+
+
+```console
+$ cd my-awesome-api
+$ git init
+$ git add .
+$ git commit -m "Initial commit - FastAPI project setup"
+```
+
+
+
+### 3. Configuration de l'environnement
+
+- Utilisez des fichiers `.env` pour le développement local
+- Utilisez des variables d'environnement pour la production
+- Ne committez jamais de données sensibles dans le contrôle de version
+
+### 4. Tests
+
+Profitez du framework de test inclus :
+
+
+
+```console
+$ python -m pytest
+$ bash scripts/test.sh
+```
+
+
+
+## Étapes suivantes
+
+Après avoir créé votre projet :
+
+1. **[Ajouter des routes](adding-routes.md)** : apprenez à ajouter de nouveaux points d'extrémité d'API
+2. **[Référence CLI](cli-reference.md)** : maîtrisez toutes les commandes disponibles
+3. **[Tutoriel Votre premier projet](../tutorial/first-project.md)** : construire une application complète
+
+!!! tip "Astuces pour la création de projet"
+ - Choisissez la pile qui correspond aux besoins de votre projet
+ - Commencez par MINIMAL pour apprendre, utilisez STANDARD pour la plupart des projets
+ - La structure du projet est conçue pour l'évolutivité et la maintenabilité
+ - Tout le code généré suit les bonnes pratiques de FastAPI
diff --git a/docs/fr/user-guide/installation.md b/docs/fr/user-guide/installation.md
new file mode 100644
index 0000000..28f7129
--- /dev/null
+++ b/docs/fr/user-guide/installation.md
@@ -0,0 +1,209 @@
+# Installation
+
+Ce guide explique comment installer FastAPI-fastkit.
+
+## Prérequis
+
+Pour utiliser FastAPI-fastkit, vous devez remplir les conditions suivantes :
+
+- **Python** : 3.12 ou supérieur
+- **Système d'exploitation** : Windows, macOS, Linux pris en charge
+
+## Méthodes d'installation
+
+### Installation avec pip (recommandée)
+
+La méthode d'installation la plus simple :
+
+
+
+```console
+$ pip install FastAPI-fastkit
+---> 100%
+Successfully installed FastAPI-fastkit
+```
+
+
+
+### Installer une version spécifique
+
+Pour installer une version précise :
+
+
+
+```console
+$ pip install FastAPI-fastkit==1.0.0
+---> 100%
+Successfully installed FastAPI-fastkit-1.0.0
+```
+
+
+
+### Installer la version de développement
+
+Pour installer la dernière version de développement directement depuis GitHub :
+
+
+
+```console
+$ pip install git+https://github.com/bnbong/FastAPI-fastkit.git
+---> 100%
+Successfully installed FastAPI-fastkit
+```
+
+
+
+!!! warning "Avertissement sur la version de développement"
+ Les versions de développement peuvent être instables et ne sont pas recommandées pour les environnements de production.
+
+## Configuration d'un environnement virtuel (recommandée)
+
+Il est fortement recommandé d'utiliser un environnement virtuel pour éviter les conflits de dépendances :
+
+### Avec venv
+
+
+
+```console
+$ python -m venv fastapi-env
+$ source fastapi-env/bin/activate # Linux/macOS
+$ fastapi-env\Scripts\activate # Windows
+$ pip install FastAPI-fastkit
+```
+
+
+
+### Avec conda
+
+
+
+```console
+$ conda create -n fastapi-env python=3.12
+$ conda activate fastapi-env
+$ pip install FastAPI-fastkit
+```
+
+
+
+## Vérifier l'installation
+
+Après l'installation, vérifiez que FastAPI-fastkit est correctement installé :
+
+
+
+```console
+$ fastkit --version
+FastAPI-fastkit version 1.0.0
+```
+
+
+
+
+
+```console
+$ fastkit --help
+Usage: fastkit [OPTIONS] COMMAND [ARGS]...
+
+ FastAPI-fastkit CLI
+
+Options:
+ --version Show the version and exit.
+ --help Show this message and exit.
+
+Commands:
+ addroute Add a new route to FastAPI project
+ init Create a new FastAPI project
+ list-templates List available FastAPI templates
+ runserver Start FastAPI development server
+ startdemo Create FastAPI project from template
+```
+
+
+
+## Dépannage
+
+### Commande introuvable
+
+Si vous obtenez une erreur « command not found » :
+
+1. **Vérifiez que FastAPI-fastkit est bien installé** :
+
+
+ ```console
+ $ pip show FastAPI-fastkit
+ ```
+
+
+2. **Vérifiez votre environnement virtuel** :
+
+
+ ```console
+ $ which python
+ $ which pip
+ ```
+
+
+3. **Réinstallez FastAPI-fastkit** :
+
+
+ ```console
+ $ pip uninstall FastAPI-fastkit
+ $ pip install FastAPI-fastkit
+ ```
+
+
+### Erreurs de permission
+
+Si vous rencontrez des erreurs de permission lors de l'installation :
+
+**Sous Linux/macOS :**
+
+
+
+```console
+$ pip install --user FastAPI-fastkit
+```
+
+
+
+**Sous Windows (exécutez en tant qu'administrateur) :**
+
+
+
+```console
+$ pip install FastAPI-fastkit
+```
+
+
+
+### Compatibilité des versions de Python
+
+FastAPI-fastkit nécessite Python 3.12+. Vérifiez votre version de Python :
+
+
+
+```console
+$ python --version
+Python 3.12.0
+```
+
+
+
+Si vous avez une version plus ancienne, mettez Python à niveau :
+
+- **Python officiel** : [python.org/downloads](https://www.python.org/downloads/)
+- **Avec pyenv** : `pyenv install 3.12.0`
+- **Avec conda** : `conda install python=3.12`
+
+## Étapes suivantes
+
+Une fois l'installation terminée :
+
+1. **[Démarrage rapide](quick-start.md)** : créez votre premier projet en 5 minutes
+2. **[Tutoriel de prise en main](../tutorial/getting-started.md)** : tutoriel détaillé pas à pas
+3. **[Référence CLI](cli-reference.md)** : référence complète des commandes
+
+!!! tip "Astuces d'installation"
+ - Utilisez toujours des environnements virtuels pour isoler vos projets
+ - Maintenez FastAPI-fastkit à jour vers la dernière version
+ - Consultez le [dépôt GitHub](https://github.com/bnbong/FastAPI-fastkit) pour les mises à jour et les tickets
diff --git a/docs/fr/user-guide/quick-start.md b/docs/fr/user-guide/quick-start.md
new file mode 100644
index 0000000..ff9952c
--- /dev/null
+++ b/docs/fr/user-guide/quick-start.md
@@ -0,0 +1,368 @@
+# Démarrage rapide
+
+Créez votre premier projet FastAPI avec FastAPI-fastkit en moins de 5 minutes !
+
+!!! tip "Vous ne savez pas quel starter choisir ?"
+ Consultez [**Quel starter choisir ?**](choosing-a-starter.md) pour voir une comparaison pensée pour les débutants entre les modèles `startdemo` et les préréglages d'architecture interactifs (`minimal` / `single-module` / `classic-layered` / `domain-starter`). En bref : **`fastkit init --interactive` avec le préréglage `domain-starter` est l'option moderne recommandée.**
+
+## 1. Créer le projet
+
+Utilisez la commande `init` de FastAPI-fastkit pour créer un nouveau projet :
+
+
+
+```console
+$ fastkit init
+Enter the project name: my-first-app
+Enter the author name: Your Name
+Enter the author email: your.email@example.com
+Enter the project description: My first FastAPI application
+
+ Project Information
+┌──────────────┬─────────────────────────────┐
+│ Project Name │ my-first-app │
+│ Author │ Your Name │
+│ Author Email │ your.email@example.com │
+│ Description │ My first FastAPI application│
+└──────────────┴─────────────────────────────┘
+
+Available Stacks and Dependencies:
+ MINIMAL Stack
+┌──────────────┬───────────────────┐
+│ Dependency 1 │ fastapi │
+│ Dependency 2 │ uvicorn │
+│ Dependency 3 │ pydantic │
+│ Dependency 4 │ pydantic-settings │
+└──────────────┴───────────────────┘
+
+ STANDARD Stack
+┌──────────────┬───────────────────┐
+│ Dependency 1 │ fastapi │
+│ Dependency 2 │ uvicorn │
+│ Dependency 3 │ sqlalchemy │
+│ Dependency 4 │ alembic │
+│ Dependency 5 │ pytest │
+│ Dependency 6 │ pydantic │
+│ Dependency 7 │ pydantic-settings │
+└──────────────┴───────────────────┘
+
+ FULL Stack
+┌──────────────┬───────────────────┐
+│ Dependency 1 │ fastapi │
+│ Dependency 2 │ uvicorn │
+│ Dependency 3 │ sqlalchemy │
+│ Dependency 4 │ alembic │
+│ Dependency 5 │ pytest │
+│ Dependency 6 │ redis │
+│ Dependency 7 │ celery │
+│ Dependency 8 │ pydantic │
+│ Dependency 9 │ pydantic-settings │
+└──────────────┴───────────────────┘
+
+Select stack (minimal, standard, full): minimal
+
+Available Package Managers:
+ Package Managers
+┌────────┬────────────────────────────────────────────┐
+│ PIP │ Standard Python package manager │
+│ UV │ Fast Python package manager │
+│ PDM │ Modern Python dependency management │
+│ POETRY │ Python dependency management and packaging │
+└────────┴────────────────────────────────────────────┘
+
+Select package manager (pip, uv, pdm, poetry) [uv]: uv
+Do you want to proceed with project creation? [y/N]: y
+
+✨ FastAPI project 'my-first-app' has been created successfully!
+```
+
+
+
+## 2. Activer l'environnement virtuel
+
+Allez dans votre projet et activez l'environnement virtuel :
+
+
+
+```console
+$ cd my-first-app
+$ source .venv/bin/activate # Linux/macOS
+$ .venv\Scripts\activate # Windows
+```
+
+
+
+## 3. Démarrer le serveur de développement
+
+Démarrez le serveur de développement FastAPI :
+
+
+
+```console
+$ fastkit runserver
+INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
+INFO: Started reloader process [28720]
+INFO: Started server process [28722]
+INFO: Waiting for application startup.
+INFO: Application startup complete.
+```
+
+
+
+!!! success "Félicitations !"
+ Votre serveur FastAPI tourne maintenant ! Ouvrez votre navigateur pour le découvrir.
+
+## 4. Tester votre API
+
+Ouvrez votre navigateur et rendez-vous à ces URL :
+
+### Point d'extrémité principal
+
+Visitez [http://127.0.0.1:8000](http://127.0.0.1:8000)
+
+Vous verrez :
+
+```json
+{"message": "Hello World"}
+```
+
+### Documentation interactive de l'API
+
+Visitez [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)
+
+Il s'agit de la documentation **Swagger UI** générée automatiquement, où vous pouvez :
+
+- Voir tous vos points d'extrémité d'API
+- Tester les points d'extrémité directement dans le navigateur
+- Consulter les schémas de requête et de réponse
+
+### Documentation alternative
+
+Visitez [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc)
+
+Il s'agit de l'interface de documentation **ReDoc**, au design différent et épuré.
+
+## 5. Ajouter votre première route
+
+Ajoutons une nouvelle route d'API à votre projet :
+
+
+
+```console
+$ fastkit addroute users my-first-app
+ Adding New Route
+┌──────────────────┬──────────────────────────────────────────┐
+│ Project │ my-first-app │
+│ Route Name │ users │
+│ Target Directory │ ~/my-first-app │
+└──────────────────┴──────────────────────────────────────────┘
+
+Do you want to add route 'users' to project 'my-first-app'? [Y/n]: y
+
+╭──────────────────────── Info ────────────────────────╮
+│ ℹ Updated main.py to include the API router │
+╰──────────────────────────────────────────────────────╯
+╭─────────────────────── Success ───────────────────────╮
+│ ✨ Successfully added new route 'users' to project │
+│ `my-first-app` │
+╰───────────────────────────────────────────────────────╯
+```
+
+
+
+Le serveur va se recharger automatiquement, et vous disposez désormais de nouveaux points d'extrémité :
+
+- `GET /api/v1/users/` — récupérer tous les utilisateurs
+- `POST /api/v1/users/` — créer un nouvel utilisateur
+- `GET /api/v1/users/{user_id}` — récupérer un utilisateur précis
+- `PUT /api/v1/users/{user_id}` — mettre à jour un utilisateur
+- `DELETE /api/v1/users/{user_id}` — supprimer un utilisateur
+
+## 6. Tester la nouvelle API
+
+### Avec curl
+
+**Récupérer tous les utilisateurs :**
+
+
+
+```console
+$ curl http://127.0.0.1:8000/api/v1/users/
+[]
+```
+
+
+
+**Créer un nouvel utilisateur :**
+
+
+
+```console
+$ curl -X POST "http://127.0.0.1:8000/api/v1/users/" \
+ -H "Content-Type: application/json" \
+ -d '{"title": "John Doe", "description": "Software Developer"}'
+{
+ "id": 1,
+ "title": "John Doe",
+ "description": "Software Developer"
+}
+```
+
+
+
+### Avec la documentation interactive
+
+1. Rendez-vous sur [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)
+2. Dépliez la section **« users »**
+3. Cliquez sur **« POST /api/v1/users/ »**
+4. Cliquez sur **« Try it out »**
+5. Remplissez le corps de la requête :
+ ```json
+ {
+ "title": "Jane Smith",
+ "description": "Product Manager"
+ }
+ ```
+6. Cliquez sur **« Execute »**
+
+## 7. Explorer la structure de votre projet
+
+Votre projet généré a une structure claire et organisée :
+
+```
+my-first-app/
+├── .venv/ # Environnement virtuel
+├── src/
+│ ├── __init__.py
+│ ├── main.py # Point d'entrée de l'application FastAPI
+│ ├── core/
+│ │ ├── __init__.py
+│ │ └── config.py # Configuration de l'application
+│ ├── api/
+│ │ ├── __init__.py
+│ │ ├── api.py # Ensemble des routeurs de l'API
+│ │ └── routes/
+│ │ ├── __init__.py
+│ │ ├── items.py # Route items par défaut
+│ │ └── users.py # Votre nouvelle route users
+│ ├── crud/
+│ │ ├── __init__.py
+│ │ ├── items.py # Opérations CRUD pour items
+│ │ └── users.py # Opérations CRUD pour users
+│ ├── schemas/
+│ │ ├── __init__.py
+│ │ ├── items.py # Schémas Pydantic pour items
+│ │ └── users.py # Schémas Pydantic pour users
+│ └── mocks/
+│ ├── __init__.py
+│ └── mock_items.json # Données de test
+├── tests/ # Fichiers de test
+├── scripts/ # Scripts utilitaires
+├── requirements.txt # Dépendances Python
+├── setup.py # Configuration du paquet
+└── README.md # Documentation du projet
+```
+
+## 8. Options de gestionnaire de paquets
+
+FastAPI-fastkit prend en charge plusieurs gestionnaires de paquets Python adaptés à vos préférences :
+
+### Gestionnaires de paquets disponibles
+
+| Gestionnaire | Description | Idéal pour |
+|---------|-------------|----------|
+| **UV** | Gestionnaire de paquets Python rapide (par défaut) | La vitesse et la performance |
+| **PDM** | Gestion moderne des dépendances Python | La résolution avancée des dépendances |
+| **Poetry** | Gestion des dépendances et packaging Python | Les flux de travail basés sur Poetry |
+| **PIP** | Gestionnaire de paquets Python standard | Le développement Python traditionnel |
+
+### Spécifier le gestionnaire de paquets
+
+Vous pouvez indiquer votre gestionnaire de paquets préféré de plusieurs manières :
+
+#### 1. Sélection interactive (par défaut)
+
+Lorsque vous lancez `fastkit init` ou `fastkit startdemo`, vous serez invité à faire un choix :
+
+
+
+```console
+$ fastkit init
+# ... after project details and stack selection ...
+
+Available Package Managers:
+ Package Managers
+┌────────┬────────────────────────────────────────────┐
+│ PIP │ Standard Python package manager │
+│ UV │ Fast Python package manager │
+│ PDM │ Modern Python dependency management │
+│ POETRY │ Python dependency management and packaging │
+└────────┴────────────────────────────────────────────┘
+
+Select package manager (pip, uv, pdm, poetry) [uv]: uv
+```
+
+
+
+#### 2. Option en ligne de commande
+
+Évitez l'invite interactive en spécifiant directement le gestionnaire de paquets :
+
+
+
+```console
+$ fastkit init --package-manager poetry
+$ fastkit startdemo --package-manager pdm
+```
+
+
+
+### Fichiers de dépendances générés
+
+Chaque gestionnaire de paquets crée les fichiers de dépendances appropriés :
+
+- **UV/PDM** : `pyproject.toml` (format PEP 621)
+- **Poetry** : `pyproject.toml` (format Poetry)
+- **PIP** : `requirements.txt`
+
+## 9. Et ensuite ?
+
+Félicitations ! Vous avez :
+
+✅ Créé votre premier projet FastAPI
+✅ Démarré le serveur de développement
+✅ Ajouté une nouvelle route d'API
+✅ Testé vos API
+
+### Continuer à apprendre
+
+1. **[Votre premier projet](../tutorial/first-project.md)** : construire une API de blog plus complexe
+2. **[Créer des projets](creating-projects.md)** : découvrir les différentes piles et options
+3. **[Ajouter des routes](adding-routes.md)** : maîtriser l'art du développement d'API
+4. **[Utiliser les modèles](using-templates.md)** : explorer les modèles de projet déjà prêts à l'emploi
+
+### Expérimenter davantage
+
+Essayez ces commandes pour explorer d'autres fonctionnalités :
+
+
+
+```console
+# List available templates
+$ fastkit list-templates
+
+# Create a project from a template
+$ fastkit startdemo
+
+# Add more routes (route name first, project dir second)
+$ fastkit addroute products my-first-app
+$ fastkit addroute orders my-first-app
+```
+
+
+
+!!! tip "Astuces de développement"
+ - Le serveur se recharge automatiquement quand vous modifiez des fichiers
+ - Consultez toujours la documentation interactive à `/docs` lors de l'ajout de nouvelles fonctionnalités
+ - Utilisez l'environnement virtuel pour isoler vos dépendances
+ - Explorez le code généré pour comprendre la structure du projet
diff --git a/docs/fr/user-guide/using-templates.md b/docs/fr/user-guide/using-templates.md
new file mode 100644
index 0000000..b316e74
--- /dev/null
+++ b/docs/fr/user-guide/using-templates.md
@@ -0,0 +1,608 @@
+# Utiliser les modèles
+
+FastAPI-fastkit propose des modèles de projet prêts à l'emploi pour vous aider à démarrer rapidement avec différentes piles techniques.
+
+## Modèles disponibles
+
+Consultez les modèles disponibles avec la commande `list-templates` :
+
+
+
+```console
+$ fastkit list-templates
+ Available Templates
+┌─────────────────────────┬───────────────────────────────────┐
+│ fastapi-custom-response │ Async Item Management API with │
+│ │ Custom Response System │
+│ fastapi-dockerized │ Dockerized FastAPI Item │
+│ │ Management API │
+│ fastapi-empty │ No description │
+│ fastapi-async-crud │ Async Item Management API Server │
+│ fastapi-psql-orm │ Dockerized FastAPI Item │
+│ │ Management API with PostgreSQL │
+│ fastapi-default │ Simple FastAPI Project │
+└─────────────────────────┴───────────────────────────────────┘
+```
+
+
+
+## Descriptions des modèles
+
+### 1. `fastapi-default`
+
+**Projet FastAPI simple**
+
+- Configuration FastAPI basique avec les fonctionnalités essentielles
+- Gestion d'items avec des données factices
+- Idéal pour apprendre et pour les API simples
+- Inclut les opérations CRUD de base
+
+**Idéal pour :**
+
+- Débutants en FastAPI
+- API web simples
+- Apprentissage et prototypage
+
+### 2. `fastapi-async-crud`
+
+**Serveur d'API asynchrone de gestion d'items**
+
+- Application FastAPI entièrement asynchrone
+- Opérations CRUD avancées avec async/await
+- Meilleure performance pour les opérations d'E/S
+- Stockage de données factices avec motifs asynchrones
+
+**Idéal pour :**
+
+- Applications haute performance
+- Opérations intensives en E/S
+- Développement Python asynchrone moderne
+
+### 3. `fastapi-custom-response`
+
+**API asynchrone de gestion d'items avec système de réponse personnalisé**
+
+- Modèles de réponse personnalisés et formatage
+- Gestion avancée des erreurs
+- Prise en charge de la pagination
+- Codes d'état HTTP et réponses personnalisés
+
+**Idéal pour :**
+
+- API nécessitant des formats de réponse spécifiques
+- Besoins avancés en gestion d'erreurs
+- Logique métier personnalisée dans les réponses
+
+### 4. `fastapi-dockerized`
+
+**API FastAPI de gestion d'items conteneurisée avec Docker**
+
+- Conteneurisation Docker complète
+- Configuration de déploiement prête pour la production
+- Builds Docker multi-étapes
+- Configuration basée sur l'environnement
+
+**Idéal pour :**
+
+- Déploiements en production
+- Environnements conteneurisés
+- Pipelines DevOps et CI/CD
+
+### 5. `fastapi-psql-orm`
+
+**API FastAPI conteneurisée de gestion d'items avec PostgreSQL**
+
+- Intégration de la base de données PostgreSQL
+- ORM SQLAlchemy avec migrations Alembic
+- Docker Compose pour le développement local
+- Opérations CRUD complètes en base de données
+
+**Idéal pour :**
+
+- Applications pilotées par une base de données
+- Stockage de données de qualité production
+- Relations de données complexes
+
+### 6. `fastapi-empty`
+
+**Projet FastAPI minimal**
+
+- Configuration FastAPI minimale
+- Aucune fonctionnalité ajoutée à l'avance
+- Page blanche pour du développement personnalisé
+
+**Idéal pour :**
+
+- Démarrer de zéro
+- Dépendances minimales
+- Exigences d'architecture personnalisée
+
+## Créer un projet à partir d'un modèle
+
+Utilisez la commande `startdemo` pour créer un projet à partir d'un modèle :
+
+
+
+```console
+$ fastkit startdemo
+Enter the project name: my-blog-api
+Enter the author name: John Doe
+Enter the author email: john@example.com
+Enter the project description: Blog API with PostgreSQL
+
+Available Templates:
+ fastapi-default
+┌─────────────┬──────────────────────┐
+│ Description │ Simple FastAPI │
+│ │ Project │
+│ Stack │ FastAPI, Uvicorn │
+│ Database │ Mock Data │
+│ Features │ Basic CRUD │
+└─────────────┴──────────────────────┘
+
+ fastapi-psql-orm
+┌─────────────┬──────────────────────┐
+│ Description │ Dockerized FastAPI │
+│ │ Item Management API │
+│ │ with PostgreSQL │
+│ Stack │ FastAPI, PostgreSQL, │
+│ │ SQLAlchemy, Docker │
+│ Database │ PostgreSQL │
+│ Features │ Full ORM, Migrations │
+└─────────────┴──────────────────────┘
+
+Select template (fastapi-default, fastapi-async-crud, fastapi-custom-response, fastapi-dockerized, fastapi-psql-orm, fastapi-empty): fastapi-psql-orm
+
+ Project Information
+┌──────────────┬─────────────────────┐
+│ Project Name │ my-blog-api │
+│ Author │ John Doe │
+│ Author Email │ john@example.com │
+│ Description │ Blog API with │
+│ │ PostgreSQL │
+└──────────────┴─────────────────────┘
+
+ Template Dependencies
+┌──────────────┬───────────────────┐
+│ Dependency 1 │ fastapi │
+│ Dependency 2 │ uvicorn │
+│ Dependency 3 │ sqlalchemy │
+│ Dependency 4 │ alembic │
+│ Dependency 5 │ psycopg2-binary │
+│ Dependency 6 │ python-dotenv │
+│ Dependency 7 │ pytest │
+└──────────────┴───────────────────┘
+
+Available Package Managers:
+ Package Managers
+┌────────┬────────────────────────────────────────────┐
+│ PIP │ Standard Python package manager │
+│ UV │ Fast Python package manager │
+│ PDM │ Modern Python dependency management │
+│ POETRY │ Python dependency management and packaging │
+└────────┴────────────────────────────────────────────┘
+
+Select package manager (pip, uv, pdm, poetry) [uv]: uv
+Do you want to proceed with project creation? [y/N]: y
+
+✨ FastAPI project 'my-blog-api' from 'fastapi-psql-orm' has been created successfully!
+```
+
+
+
+## Comparaison des fonctionnalités des modèles
+
+| Fonctionnalité | Default | Async CRUD | Custom Response | Dockerized | PostgreSQL ORM | Empty |
+|---------|---------|------------|-----------------|------------|----------------|-------|
+| **FastAPI de base** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
+| **Données factices** | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
+| **Support asynchrone** | Basique | ✅ | ✅ | ✅ | ✅ | ❌ |
+| **Réponses personnalisées** | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
+| **Docker** | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
+| **Base de données** | Factice | Factice | Factice | Factice | PostgreSQL | Aucune |
+| **ORM** | ❌ | ❌ | ❌ | ❌ | SQLAlchemy | ❌ |
+| **Migrations** | ❌ | ❌ | ❌ | ❌ | Alembic | ❌ |
+| **Tests** | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
+| **Idéal pour** | Apprentissage | Performance | API personnalisées | Production | Applications avec base de données | Personnalisé |
+
+## Configuration spécifique à chaque modèle
+
+### Utiliser `fastapi-psql-orm`
+
+Ce modèle inclut une configuration PostgreSQL complète. Après la création :
+
+1. **Démarrer PostgreSQL avec Docker :**
+
+
+
+```console
+$ cd my-blog-api
+$ docker-compose up -d postgres
+Starting my-blog-api_postgres_1 ... done
+```
+
+
+
+2. **Exécuter les migrations de base de données :**
+
+
+
+```console
+$ source .venv/bin/activate
+$ alembic upgrade head
+INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
+INFO [alembic.runtime.migration] Will assume transactional DDL.
+INFO [alembic.runtime.migration] Running upgrade -> bedcdc35b64a, first alembic
+```
+
+
+
+3. **Démarrer le serveur d'API :**
+
+
+
+```console
+$ fastkit runserver
+INFO: Uvicorn running on http://127.0.0.1:8000
+```
+
+
+
+### Utiliser `fastapi-dockerized`
+
+Ce modèle offre un support Docker complet :
+
+1. **Construire l'image Docker :**
+
+
+
+```console
+$ cd my-dockerized-api
+$ docker build -t my-dockerized-api .
+Successfully built abc123def456
+Successfully tagged my-dockerized-api:latest
+```
+
+
+
+2. **Exécuter le conteneur :**
+
+
+
+```console
+$ docker run -p 8000:8000 my-dockerized-api
+INFO: Uvicorn running on http://0.0.0.0:8000
+```
+
+
+
+### Utiliser `fastapi-custom-response`
+
+Ce modèle inclut une gestion avancée des réponses :
+
+1. **Modèles de réponse personnalisés :**
+
+```python
+from src.helper.pagination import PaginatedResponse
+from src.schemas.base import StandardResponse
+
+@router.get("/", response_model=PaginatedResponse[Item])
+def read_items(skip: int = 0, limit: int = 10):
+ items = items_crud.get_multi(skip=skip, limit=limit)
+ total = items_crud.count()
+
+ return PaginatedResponse(
+ data=items,
+ total=total,
+ page=skip // limit + 1,
+ pages=(total + limit - 1) // limit
+ )
+
+@router.post("/", response_model=StandardResponse[Item])
+def create_item(item: ItemCreate):
+ new_item = items_crud.create(item)
+ return StandardResponse(
+ data=new_item,
+ message="Item created successfully",
+ status_code=201
+ )
+```
+
+2. **Gestion d'erreurs améliorée :**
+
+```python
+from src.helper.exceptions import ItemNotFoundError, ValidationError
+
+@router.get("/{item_id}", response_model=StandardResponse[Item])
+def read_item(item_id: int):
+ try:
+ item = items_crud.get(item_id)
+ return StandardResponse(data=item)
+ except ItemNotFoundError:
+ raise HTTPException(
+ status_code=404,
+ detail=f"Item with id {item_id} not found"
+ )
+```
+
+## Structure des projets de modèle
+
+Chaque modèle suit une structure cohérente mais adaptée :
+
+### Structure de `fastapi-default`
+```
+my-project/
+├── src/
+│ ├── main.py
+│ ├── core/config.py
+│ ├── api/
+│ │ ├── api.py
+│ │ └── routes/items.py
+│ ├── crud/items.py
+│ ├── schemas/items.py
+│ └── mocks/mock_items.json
+├── tests/
+├── scripts/
+└── requirements.txt
+```
+
+### Structure de `fastapi-psql-orm`
+```
+my-project/
+├── src/
+│ ├── main.py
+│ ├── core/
+│ │ ├── config.py
+│ │ └── db.py
+│ ├── api/
+│ │ ├── api.py
+│ │ ├── deps.py
+│ │ └── routes/items.py
+│ ├── crud/items.py
+│ ├── schemas/items.py
+│ ├── alembic/
+│ │ ├── env.py
+│ │ └── versions/
+│ └── utils/
+├── tests/
+├── scripts/
+├── docker-compose.yml
+├── Dockerfile
+├── alembic.ini
+└── requirements.txt
+```
+
+## Personnaliser les modèles
+
+Après avoir créé un projet à partir d'un modèle, vous pouvez le personnaliser :
+
+### 1. Ajouter de nouvelles routes
+
+
+
+```console
+$ fastkit addroute posts my-blog-api
+$ fastkit addroute users my-blog-api
+$ fastkit addroute comments my-blog-api
+```
+
+
+
+### 2. Modifier la configuration
+
+Modifiez `src/core/config.py` selon vos besoins :
+
+```python
+from pydantic_settings import BaseSettings
+
+class Settings(BaseSettings):
+ PROJECT_NAME: str = "My Blog API"
+ VERSION: str = "1.0.0"
+ API_V1_STR: str = "/api/v1"
+
+ # Database settings (for PostgreSQL templates)
+ DATABASE_URL: str = "postgresql://user:password@localhost/dbname"
+
+ # Security settings
+ SECRET_KEY: str = "your-secret-key-here"
+ ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
+
+ class Config:
+ env_file = ".env"
+
+settings = Settings()
+```
+
+### 3. Ajouter des variables d'environnement
+
+Créez un fichier `.env` à la racine de votre projet :
+
+```env
+# .env
+PROJECT_NAME=My Blog API
+VERSION=1.0.0
+DEBUG=True
+
+# Database (for PostgreSQL templates)
+DATABASE_URL=postgresql://user:password@localhost:5432/myblogdb
+POSTGRES_USER=user
+POSTGRES_PASSWORD=password
+POSTGRES_DB=myblogdb
+
+# Security
+SECRET_KEY=your-super-secret-key-here
+ACCESS_TOKEN_EXPIRE_MINUTES=30
+```
+
+## Tests des modèles
+
+Chaque modèle est livré avec des tests préconfigurés :
+
+
+
+```console
+$ cd my-blog-api
+$ source .venv/bin/activate
+$ python -m pytest
+
+======================== test session starts ========================
+tests/test_items.py::test_create_item PASSED
+tests/test_items.py::test_read_items PASSED
+tests/test_items.py::test_read_item PASSED
+tests/test_items.py::test_update_item PASSED
+tests/test_items.py::test_delete_item PASSED
+======================== 5 passed in 0.23s ========================
+```
+
+
+
+## Flux de développement avec les modèles
+
+### 1. Choisir le bon modèle
+
+- **Apprentissage / API simples** : `fastapi-default`
+- **Haute performance** : `fastapi-async-crud`
+- **Formats de réponse personnalisés** : `fastapi-custom-response`
+- **Déploiement en production** : `fastapi-dockerized`
+- **Applications avec base de données** : `fastapi-psql-orm`
+- **Architecture personnalisée** : `fastapi-empty`
+
+### 2. Créer et configurer
+
+
+
+```console
+$ fastkit startdemo
+# Follow the prompts
+$ cd your-project
+$ source .venv/bin/activate
+```
+
+
+
+### 3. Développement
+
+
+
+```console
+# Démarrer le serveur de développement
+$ fastkit runserver
+
+# Exécuter les tests
+$ python -m pytest
+
+# Ajouter de nouvelles fonctionnalités
+$ fastkit addroute new-resource your-project
+```
+
+
+
+### 4. Déploiement
+
+Pour les modèles destinés à la production (`fastapi-dockerized`, `fastapi-psql-orm`) :
+
+
+
+```console
+# Build for production
+$ docker build -t your-app .
+
+# Deploy with Docker Compose
+$ docker-compose up -d
+```
+
+
+
+## Bonnes pratiques
+
+### 1. Choisir les modèles judicieusement
+
+- Commencez par les modèles plus simples pour apprendre
+- Utilisez les modèles avec base de données pour les applications pilotées par les données
+- Utilisez les modèles Docker pour les déploiements en production
+
+### 2. Gestion de l'environnement
+
+- Utilisez toujours des fichiers `.env` pour la configuration
+- Ne committez jamais de données sensibles dans le contrôle de version
+- Utilisez des environnements différents pour développement / production
+
+### 3. Stratégie de personnalisation
+
+- Ajoutez de nouvelles routes avec `fastkit addroute`
+- Modifiez le code existant pour l'adapter à votre logique métier
+- Gardez la structure du projet organisée
+
+### 4. Tests
+
+- Exécutez les tests régulièrement pendant le développement
+- Ajoutez des tests pour les nouvelles fonctionnalités que vous implémentez
+- Utilisez la structure de tests fournie comme guide
+
+## Dépannage
+
+### Problèmes de connexion à la base de données (modèles PostgreSQL)
+
+Si vous n'arrivez pas à vous connecter à PostgreSQL :
+
+1. **Vérifiez que Docker tourne :**
+
+
+ ```console
+ $ docker ps
+ ```
+
+
+2. **Vérifiez le conteneur PostgreSQL :**
+
+
+ ```console
+ $ docker-compose logs postgres
+ ```
+
+
+3. **Vérifiez les variables d'environnement :**
+
+ ```env
+ DATABASE_URL=postgresql://user:password@localhost:5432/dbname
+ ```
+
+### Échecs de build Docker
+
+Si le build Docker échoue :
+
+1. **Vérifiez la syntaxe du Dockerfile**
+2. **Vérifiez que tous les fichiers sont présents**
+3. **Vérifiez que le démon Docker tourne**
+
+### Dépendances manquantes
+
+Si vous obtenez des erreurs d'import :
+
+1. **Activez l'environnement virtuel :**
+
+ ```console
+ $ source .venv/bin/activate
+ ```
+
+
+2. **Installez les dépendances :**
+
+ ```console
+ $ pip install -r requirements.txt
+ ```
+
+
+## Étapes suivantes
+
+Maintenant que vous comprenez les modèles :
+
+1. **[Votre premier projet](../tutorial/first-project.md)** : construire une application complète
+2. **[Ajouter des routes](adding-routes.md)** : étendre votre projet basé sur un modèle
+3. **[Référence CLI](cli-reference.md)** : maîtriser toutes les commandes disponibles
+
+!!! tip "Astuces sur les modèles"
+ - Les modèles sont d'excellents points de départ, pas des solutions finales
+ - Personnalisez les modèles pour qu'ils correspondent à vos besoins spécifiques
+ - Étudiez le code des modèles pour apprendre les bonnes pratiques de FastAPI
+ - Utilisez le contrôle de version pour suivre vos personnalisations
diff --git a/docs/ja/reference/translation-status.md b/docs/ja/reference/translation-status.md
index 271375b..3cee416 100644
--- a/docs/ja/reference/translation-status.md
+++ b/docs/ja/reference/translation-status.md
@@ -23,10 +23,10 @@ FastAPI-fastkit のドキュメントは複数の言語でビルドされます
| 🇯🇵 Japanese (`ja`) | ✅ 完了 | 26 / 26 | ロケール側のページはすべて存在します。Phase 1: トップレベル + コアの user-guide、Phase 2: 残りの user-guide + すべての tutorial、Phase 3: contributing + reference。`docs/ja/changelog.md` は英語の `CHANGELOG.md` を意図的に再利用しています。 |
| 🇨🇳 Chinese (`zh`) | 🔴 スケルトン | 0 / 26 | ビルドターゲットのみ。すべてのページが英語にフォールバックします。 |
| 🇪🇸 Spanish (`es`) | ✅ 完了 | 26 / 26 | ロケール側のページはすべて存在します。Phase 1: トップレベル + コアの user-guide、Phase 2: 残りの user-guide + すべての tutorial、Phase 3: contributing + reference。`docs/es/changelog.md` は英語の `CHANGELOG.md` を意図的に再利用しています。 |
-| 🇫🇷 French (`fr`) | 🔴 スケルトン | 0 / 26 | ビルドターゲットのみ。すべてのページが英語にフォールバックします。 |
+| 🇫🇷 French (`fr`) | ✅ 完了 | 26 / 26 | ロケール側のページはすべて存在します。Phase 1: トップレベル + コアの user-guide、Phase 2: 残りの user-guide + すべての tutorial、Phase 3: contributing + reference。`docs/fr/changelog.md` は英語の `CHANGELOG.md` を意図的に再利用しています。 |
| 🇩🇪 German (`de`) | 🔴 スケルトン | 0 / 26 | ビルドターゲットのみ。すべてのページが英語にフォールバックします。 |
-*スナップショット検証日: 2026-05-11。Phase 3 (contributing + reference) を反映した現在のブランチを基準に `es` 行を再集計しました。スペイン語はロケール側のページがすべてそろっており、`docs/es/changelog.md` は英語版 changelog をそのまま指しています。* この表は手動で管理されています。リポジトリルートで現在の状態を再カウントしたい場合は、次のコマンドを実行してください:
+*スナップショット検証日: 2026-05-15。Phase 3 (contributing + reference) を反映した現在のブランチを基準に `fr` 行を再集計しました。フランス語はロケール側のページがすべてそろっており、`docs/fr/changelog.md` は英語版 changelog をそのまま指しています。* この表は手動で管理されています。リポジトリルートで現在の状態を再カウントしたい場合は、次のコマンドを実行してください:
```console
$ for loc in en ko ja zh es fr de; do
diff --git a/docs/ko/reference/translation-status.md b/docs/ko/reference/translation-status.md
index 0dd1aea..c492e6c 100644
--- a/docs/ko/reference/translation-status.md
+++ b/docs/ko/reference/translation-status.md
@@ -23,10 +23,10 @@ FastAPI-fastkit 문서는 여러 언어로 빌드되지만, 모든 번역이 **
| 🇯🇵 일본어 (`ja`) | ✅ 완료 | 26 / 26 | 언어별 페이지는 모두 존재합니다. Phase 1: 최상위 + 핵심 user-guide, Phase 2: 나머지 user-guide + 모든 tutorial, Phase 3: contributing + reference. `docs/ja/changelog.md` 는 영문 기준 `CHANGELOG.md` 를 그대로 사용합니다. |
| 🇨🇳 중국어 (`zh`) | 🔴 기본 구조만 있음 | 0 / 26 | 빌드 대상만 설정되어 있으며, 모든 페이지는 영어 원문으로 표시됩니다. |
| 🇪🇸 스페인어 (`es`) | ✅ 완료 | 26 / 26 | 언어별 페이지는 모두 존재합니다. Phase 1: 최상위 + 핵심 user-guide, Phase 2: 나머지 user-guide + 모든 tutorial, Phase 3: contributing + reference. `docs/es/changelog.md` 는 영문 기준 `CHANGELOG.md` 를 그대로 사용합니다. |
-| 🇫🇷 프랑스어 (`fr`) | 🔴 기본 구조만 있음 | 0 / 26 | 빌드 대상만 설정되어 있으며, 모든 페이지는 영어 원문으로 표시됩니다. |
+| 🇫🇷 프랑스어 (`fr`) | ✅ 완료 | 26 / 26 | 모든 로케일 페이지가 존재합니다. Phase 1: 최상위 + 핵심 user-guide; Phase 2: 나머지 user-guide + 모든 tutorial; Phase 3: contributing + reference. `docs/fr/changelog.md` 는 영문 기준 `CHANGELOG.md` 를 그대로 재사용합니다. |
| 🇩🇪 독일어 (`de`) | 🔴 기본 구조만 있음 | 0 / 26 | 빌드 대상만 설정되어 있으며, 모든 페이지는 영어 원문으로 표시됩니다. |
-*스냅샷 검증 시점: 2026-05-11. Phase 3(contributing + reference) 작업이 반영된 현재 브랜치 기준으로 `es` 행을 다시 집계했습니다. 스페인어는 언어별 페이지가 모두 존재하며, `docs/es/changelog.md` 는 영문 기준 changelog를 그대로 가리킵니다.* 이 표는 수동으로 관리됩니다. 리포지토리 루트에서 현재 상태를 다시 세고 싶다면 다음 명령을 실행하세요:
+*스냅샷 검증 시점: 2026-05-15. Phase 3(contributing + reference) 작업이 반영된 현재 브랜치 기준으로 `fr` 행을 다시 집계했습니다. 프랑스어는 이제 모든 로케일 페이지를 보유하며 `docs/fr/changelog.md` 는 영문 기준 changelog를 그대로 가리킵니다.* 이 표는 수동으로 관리됩니다. 리포지토리 루트에서 현재 상태를 다시 세고 싶다면 다음 명령을 실행하세요:
```console
$ for loc in en ko ja zh es fr de; do