62e1b019a1474db13e4d25e52f249ee273830794
- useCategoriesAdmin : extract `HYDRA_NO_PAGINATION = 999` to a named
constant (was duplicated between fetchAll and fetchTypes) + comment
the post-M0 server-pagination debt.
- useCategoryForm + useApi + shared/utils/api : drop the local copy of
`extractErrorMessage` in useCategoryForm (it was duplicating the one
in useApi), and centralize Hydra error / violation extraction in
`shared/utils/api.ts` via two new helpers :
- extractApiErrorMessage(data) : tries hydra:description, detail,
description, message, error, title, hydra:title — used by both
useApi.onResponseError and useCategoryForm.handleApiError.
- extractApiViolations(data) : returns the ApiPlatform 422
violations as a typed array (handles `violations` and
`hydra:violations`), letting each caller map them onto its own
fields. useCategoryForm now uses this helper instead of an
inline loop, ready for the next form drawer to reuse.
handleApiError keeps a manual fallback toast on non-409/422 errors :
the native useApi toast is disabled by design (`toast: false`) to allow
fine-grained 409/422 mapping, so the catch-all branch must re-emit one
or a 500 would be silent.
No behavior change — 43/43 Vitest tests still pass.
Starseed
CRM/ERP — Symfony 8 (API Platform 4) + Nuxt 4
Stack
- Backend : PHP 8.4, Symfony 8, API Platform 4, Doctrine ORM, PostgreSQL 16
- Frontend : Nuxt 4 (SPA), Vue 3, Pinia, Tailwind CSS, @malio/layer-ui
- Auth : JWT HTTP-only cookie (Lexik)
- Infra : Docker Compose (dev + prod multi-stage)
- CI/CD : Gitea Actions (auto-tag + build Docker)
Quick Start
make start # Demarrer les containers Docker
make install # Composer, migrations, fixtures, build Nuxt
Dev frontend (hot reload) :
make dev-nuxt # Port 3003
Ports
| Service | Port |
|---|---|
| API (Nginx) | 8083 |
| Frontend | 3004 |
| PostgreSQL | 5437 |
Commandes
| Commande | Description |
|---|---|
make start |
Demarrer les containers |
make stop |
Arreter les containers |
make restart |
Redemarrer les containers |
make install |
Install complet |
make reset |
Tout supprimer et reinstaller |
make dev-nuxt |
Serveur dev Nuxt (hot reload) |
make shell |
Shell dans le container PHP |
make cache-clear |
Vider le cache Symfony |
make migration-migrate |
Lancer les migrations |
make fixtures |
Charger les fixtures |
make db-reset |
Reset BDD + migrations + fixtures |
make test |
PHPUnit (tests back) |
make nuxt-test |
Vitest (tests unitaires front) |
make test-e2e |
Playwright (tests E2E front) |
make test-e2e-ui |
Playwright UI interactive (debug) |
make seed-e2e |
Seed les 6 personas E2E |
make install-e2e-deps |
One-time : Chromium + libs systeme (sudo) |
make php-cs-fixer-allow-risky |
Fix code style PHP |
make logs-dev |
Tail logs Symfony |
Tests
- Back :
make test(PHPUnit). Fixtures dediees soustests/Fixtures/. - Front unitaire :
make nuxt-test(Vitest, happy-dom). Composables, utils, stores — rapide, <30s. - Front E2E :
make test-e2e(Playwright). Couvre login + matrice RBAC sidebar. Suite volontairement minimaliste (11 tests) — voir la regle d'or dansCLAUDE.md.
Bootstrap E2E (une fois par poste) :
make install-e2e-deps # Telecharge Chromium + libs systeme via apt (sudo)
Workflow E2E :
# Terminal 1 : containers + dev server
make start && make seed-e2e && make dev-nuxt
# Terminal 2 : tests
make test-e2e
Architecture
Modular Monolith DDD : chaque module est un bounded context autonome, activable/desactivable par tenant. Le backend est la seule source de verite pour l'activation et l'organisation de la sidebar.
config/modules.php— liste des modules actifsconfig/sidebar.php— structure de la sidebar (sections + items avec module owner)GET /api/sidebar— retourne les sections filtrees par les modules actifs + les routes desactivees- Frontend : chaque
frontend/modules/*/est auto-detecte comme layer Nuxt, la sidebar est fetchee de l'API
Pour desactiver un module : commenter sa ligne dans config/modules.php, clear cache. Ses items de sidebar disparaissent et ses routes sont bloquees par le middleware front.
Pour reorganiser la sidebar (ex: deplacer un item d'une section a l'autre) : editer config/sidebar.php uniquement, le code des modules n'est pas touche.
Structure
src/ # Backend Symfony
Kernel.php
Shared/ # Noyau technique partage
Domain/
ValueObject/ # Email, ...
Event/ # DomainEventInterface
Contract/ # Interfaces inter-modules
Application/
Bus/ # CommandBusInterface, QueryBusInterface
Infrastructure/
ApiPlatform/
Resource/ # AppVersion, ModulesResource, SidebarResource
State/ # AppVersionProvider, ModulesProvider, SidebarProvider
Module/
Core/ # Module obligatoire (auth, users)
CoreModule.php # Declaration (ID, LABEL, REQUIRED)
Domain/
Entity/ # User
Repository/ # UserRepositoryInterface
Event/ # UserCreated
Application/
DTO/ # UserOutput
Infrastructure/
Doctrine/ # DoctrineUserRepository, Migrations/
ApiPlatform/State/
Provider/ # MeProvider
Processor/ # UserPasswordHasherProcessor
Console/ # CreateUserCommand
DataFixtures/ # AppFixtures
Commercial/ # Autre module (exemple)
CommercialModule.php
config/
modules.php # Source de verite activation
sidebar.php # Source de verite navigation
version.yaml
packages/ # Config Symfony
jwt/ # Cles JWT
migrations/ # Anciennes migrations
frontend/ # App Nuxt 4 (SPA)
app/
layouts/ # default.vue, auth.vue
middleware/ # auth.global.ts, modules.global.ts
shared/ # Code partage (hors modules)
composables/ # useApi, useAppVersion, useSidebar
components/ui/ # AppTopNav, ...
stores/ # auth, ui
services/ # auth
types/ # SidebarSection, UserData
utils/ # api (Hydra)
modules/ # Modules auto-detectes comme layers Nuxt
core/
nuxt.config.ts # Marqueur layer
pages/ # index, login, logout
commercial/
nuxt.config.ts
pages/ # commercial.vue
app.vue
nuxt.config.ts # Scanne modules/*/ automatiquement
i18n/locales/ # Traductions (sidebar.*, etc.)
assets/ # CSS, images
public/ # Fichiers statiques
infra/
dev/ # Docker dev (Dockerfile, nginx, php.ini, xdebug)
prod/ # Docker prod (multi-stage, nginx, php-prod.ini)
.gitea/workflows/ # CI Gitea (auto-tag, build Docker)
.claude/
skills/create-module/ # Skill Claude Code pour scaffolder un module
CI/CD
- Auto Tag : push sur
develop→ bumpconfig/version.yaml→ tagvX.Y.Z - Build Docker : push tag
v*→ build image multi-stage → push Gitea Registry
Secrets requis dans Gitea :
RELEASE_TOKEN— PAT avec droitswrite:repositoryREGISTRY_TOKEN— token pour le registry Docker
Credentials (dev)
| Username | Password | Role |
|---|---|---|
| admin | admin | ROLE_ADMIN |
| alice | alice | ROLE_USER |
| bob | bob | ROLE_USER |
Conventions
Commits
<type>(<scope optionnel>) : <message>
Types : build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test
Description
Languages
PHP
67.2%
TypeScript
17.5%
Vue
12.3%
Makefile
1.5%
Dockerfile
0.6%
Other
0.9%