cda-app-fullstack-react
Application fullstack pédagogique structurée en deux sous-projets (API Express/Prisma et client React/Parcel) avec authentification JWT, routage protégé et persistance MySQL. Le projet couvre le cycle complet de développement fullstack : modélisation de données, routes API sécurisées, gestion d'état côté client et documentation technique.
🎯 Contexte et objectifs
- Construire un socle pédagogique fullstack couvrant la chaîne complète backend + frontend.
- Implémenter un module utilisateur sécurisé (création, authentification, token) côté API.
- Mettre en place côté web une navigation publique/privée et des appels API centralisés.
🛠️ Réalisations
🧩 Conception
- La solution est découpée en
api/etweb/, avec stacks dédiées à chaque couche (Express/Prisma côté serveur, React/Redux/Router côté client). Source: cda-app-fullstack-react/api/package.json
{
"scripts": {
"watch": "npx tsc -w",
"build": "npx tsc",
"dev": "nodemon ./dist/index.js",
"start": "node ./dist/index.js"
},
"devDependencies": {
"@types/express": "^4.17.13",
"argon2": "^0.28.2",
"cors": "^2.8.5",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"prisma": "^2.29.0",
"typescript": "^4.3.5"
},
"dependencies": {
"@prisma/client": "^2.29.0"
}
}
Source: cda-app-fullstack-react/web/package.json
{
"scripts": {
"dev": "npx parcel ./src/index.html"
},
"devDependencies": {
"axios": "^0.21.1",
"parcel": "^2.0.0-rc.0",
"react-redux": "^7.2.4",
"react-router-dom": "^5.2.0",
"redux": "^4.1.1",
"redux-logger": "^3.0.6",
"typescript": "^4.3.5"
},
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
}
}
- La base Prisma modélise utilisateurs, profils et posts avec relations explicites (
User->Post[],User->Profile?). Source: cda-app-fullstack-react/api/src/database/schema.prisma
model Post {
id Int @default(autoincrement()) @id
title String @db.VarChar(255)
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
}
model User {
id Int @default(autoincrement()) @id
email String @unique
name String?
password String
username String?
posts Post[]
profile Profile?
}
💻 Développement
- Backend : Le serveur Express expose un routeur versionné et active CORS + parsing JSON avant délégation aux modules métier. Source: cda-app-fullstack-react/api/src/server.ts
export const createServer = async () => {
const server: express.Application = express();
server.use(express.json())
server.use(cors({
origin:"http://localhost:1234"
}))
server.use(APP_BASE_URL, mainRouter)
return server
}
Le routeur principal compose endpoints racine, lecture de posts et sous-routes utilisateurs. Source: cda-app-fullstack-react/api/src/router.ts
const mainRouter: Router = Router();
mainRouter.get("/", (_: Request,res: Response) => {
res.send('voici la racine')
})
mainRouter.get('/posts', async (_:Request, res:Response) => {
const posts = await prisma.post.findMany();
res.send(posts);
})
mainRouter.use('/users',userRouter)
Le use case de création utilisateur chiffre le mot de passe (Argon2) puis persiste via repository Prisma. Source: cda-app-fullstack-react/api/src/modules/user/useCases/createUser/createUser.ts
const userAlreadyExists = await this.userRepo.exists(props.email)
if (userAlreadyExists) {
return {
success: false,
message: 'User already exists'
}
}
const hashPassword = await argon2.hash(props.password);
props.password = hashPassword;
await this.userRepo.create(props);
return {
success: true,
message: 'User is correctly created'
}
L’authentification vérifie Argon2 et génère un JWT, ensuite renvoyé en cookie HTTP-only par le contrôleur. Source: cda-app-fullstack-react/api/src/modules/user/useCases/login/login.ts
const user = await this.userRepo.getUserByEmail(email);
if (!user) {
return {
success: false,
message: "Email or password missmatch"
}
}
const passwordMatches = await argon2.verify(user.password, password)
if (!passwordMatches) {
return {
success: false,
message: "Email or password missmatch"
}
}
const jwtToken = sign({ id: user.id }, JWT_PASSPHRASE)
- Frontend :
Le client React orchestre routes publiques (
/login,/register) et routes privées via un composantAuthRoute. Source: cda-app-fullstack-react/web/src/js/app.jsx
<Router>
<Switch>
<Route path="/register" component={Register} />
<Route path="/login" component={Login} />
<Layout>
<AuthRoute exact path="/" component={Posts} />
<AuthRoute path="/posts" component={Posts} />
</Layout>
</Switch>
</Router>
La garde AuthRoute lit la session depuis le stockage local et redirige les utilisateurs non authentifiés.
Source: cda-app-fullstack-react/web/src/js/components/authRoute.jsx
const AuthRoute = ({ component, path, exact, ...props }) => {
const Component = component;
const isLogged = useAuth();
if (!isLogged)
return <Redirect to="/login" />;
return <Route exact={exact} path={path} render={() => <Component {...props} />} />;
};
const useAuth = () => {
const auth = getLocalStorageItem('user');
return auth !== null;
};
🏗️ DevOps & Qualité
- Le projet s’appuie sur une compilation TypeScript stricte côté API et sur un store Redux instrumenté (
redux-logger) côté web pour faciliter le debug des transitions d’état. Source: cda-app-fullstack-react/api/tsconfig.json
{
"compilerOptions": {
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"experimentalDecorators": true,
"esModuleInterop": true
},
"include": ["./src/**/*.ts"]
}
Source: cda-app-fullstack-react/web/src/js/store/store.js
import { createStore, applyMiddleware } from "redux";
import { createLogger } from "redux-logger";
import rootReducer from "./root";
const loggerMiddleware = createLogger();
export default preloadedState => {
return createStore(
rootReducer,
preloadedState,
applyMiddleware(
loggerMiddleware,
)
);
};
📈 Résultats
- Sur la base de l’historique Git du dépôt analysé, le travail couvre la période 2021-08-09 -> 2026-02-14, avec 27 commits et 2 contributeurs. Le projet a permis de livrer une chaîne fullstack fonctionnelle: API Express/Prisma, création/connexion utilisateur sécurisée, et frontend React avec routes protégées. La séparation
api/webet l’introduction de patterns repository/use case améliorent la lisibilité des responsabilités techniques. Le bénéfice technique est un socle complet pour prototyper rapidement des applications métier avec authentification.
🔧 Environnement technique
- Backend: Node.js, Express, TypeScript, Prisma, MySQL, Argon2, JWT, CORS.
- Frontend: React 17, React Router v5, Redux, Redux Logger, Parcel, Axios.
- Architecture: séparation
api/web, router versionné, repository + use cases. - Sécurité: hash mot de passe, token JWT, cookie HTTP-only côté login.
- Qualité: compilation TS stricte, debug middleware Redux.