Nuovo progetto compatibile con lo stack globale
Questa guida definisce il baseline tecnico per creare un nuovo repository EXPERIENCE compatibile con il workspace cs-repository.
Il modello assume un monorepo npm con API NestJS, frontend React/Vite e package condiviso locale. Se il progetto diventa parte ufficiale dello stack operativo, deve essere aggiunto anche a platform-local-stack, platform-status-service e al catalogo della wiki.
Layout standard
text
new-project/
apps/
api/
src/
prisma/
test/
package.json
web/
src/
public/
package.json
packages/
shared/
src/
package.json
package.json
tsconfig.base.jsonRegole di ownership:
apps/webchiama solo endpoint same-origin/api/*.apps/apifa da BFF e integra i servizi CORE tramite client piccoli e dedicati.packages/sharedcontiene solo tipi, costanti e validatori riusabili dentro il progetto.- I contratti consumati da piu repository vanno promossi in
platform-shared-packages. - Componenti, controller, service, client HTTP e utility devono restare piccoli, modulari e riusabili.
Bootstrap rapido
Il bootstrap puo partire dai generatori standard, poi va normalizzato sul layout e sulle regole del workspace.
bash
mkdir new-project
cd new-project
npm init -y
npm pkg set private=true
npm pkg set type=module
npm pkg set 'workspaces[0]=apps/*'
npm pkg set 'workspaces[1]=packages/*'
mkdir -p apps packages packages/shared/src
npm create vite@latest apps/web -- --template react-ts
npx @nestjs/cli@latest new apps/api --package-manager npm --skip-git
npm init -w packages/shared -yInstalla poi le dipendenze per workspace, fissando nel lockfile i major approvati:
bash
npm install -D concurrently eslint @eslint/js typescript-eslint eslint-config-prettier prettier eslint-plugin-react-hooks eslint-plugin-react-refresh globals
npm install -w apps/api @nestjs/common@^11 @nestjs/core@^11 @nestjs/platform-express@^11 @nestjs/config @nestjs/jwt @prisma/client@^7 @prisma/adapter-pg@^7 pg class-validator class-transformer argon2 helmet cookie-parser reflect-metadata rxjs dotenv
npm install -D -w apps/api prisma@^7 jest ts-jest supertest testcontainers @nestjs/cli tsx ts-node typescript
npm install -w apps/web react@^19 react-dom@^19 react-router-dom@^7 @reduxjs/toolkit react-redux react-intl react-hook-form @hookform/resolvers zod class-variance-authority clsx tailwind-merge lucide-react tailwindcss-animate @radix-ui/react-slot @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-tooltip @radix-ui/react-popover @radix-ui/react-tabs @radix-ui/react-checkbox @radix-ui/react-select @radix-ui/react-label
npm install -D -w apps/web vite @vitejs/plugin-react tailwindcss @tailwindcss/vite vitest jsdom @testing-library/react @testing-library/jest-dom @testing-library/user-event typescript
npm install -D -w packages/shared typescript
npm install -w packages/shared zodSe packages/shared non espone validatori condivisi, rimuovi zod dal package.
Root workspace
Il root deve orchestrare i workspace npm e i comandi comuni.
Dipendenze:
- Monorepo:
npm workspaces,concurrently - Lint/format:
eslint,@eslint/js,typescript-eslint,eslint-config-prettier,prettier - React lint:
eslint-plugin-react-hooks,eslint-plugin-react-refresh - Globals:
globals
Esempio minimo di package.json:
json
{
"private": true,
"type": "module",
"workspaces": ["apps/*", "packages/*"],
"scripts": {
"dev": "concurrently \"npm -w apps/api run dev\" \"npm -w apps/web run dev\"",
"lint": "npm -ws --if-present run lint",
"test": "npm -ws --if-present run test",
"build": "npm -ws --if-present run build"
},
"devDependencies": {
"@eslint/js": "^9.0.0",
"concurrently": "^9.0.0",
"eslint": "^9.0.0",
"eslint-config-prettier": "^10.0.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.0",
"globals": "^16.0.0",
"prettier": "^3.0.0",
"typescript-eslint": "^8.0.0"
}
}apps/api
Stack approvato:
- NestJS 11:
@nestjs/common,@nestjs/core,@nestjs/platform-express,@nestjs/config,@nestjs/jwt - Prisma 7 + Postgres:
prisma,@prisma/client,@prisma/adapter-pg,pg - Validazione/transform:
class-validator,class-transformer - Sicurezza/auth:
argon2,helmet,cookie-parser - Runtime TS:
reflect-metadata,rxjs,dotenv - Test:
jest,ts-jest,supertest,testcontainers - Tooling:
@nestjs/cli,tsx,ts-node,typescript
Struttura consigliata:
text
src/
main.ts
app.module.ts
config/
env.schema.ts
runtime-config.service.ts
health/
health.controller.ts
health.service.ts
prisma/
prisma.module.ts
prisma.service.ts
auth/
auth.module.ts
guards/
clients/
platform-auth.client.ts
platform-ai.client.ts
features/
example/
dto/
example.controller.ts
example.service.ts
example.repository.tsLinee guida API:
- Ogni modulo espone controller sottili, service applicativi piccoli e repository dedicati quando serve persistenza.
- Ogni client verso servizi CORE vive in
src/clientso nel modulo proprietario, con input tipizzati e risposta normalizzata. GET /healthdeve essere stabile e non dipendere da dettagli locali come PID o processi.- La validazione globale usa
ValidationPipecon DTO espliciti. - Prisma resta dietro un service dedicato; non passare
PrismaClientdirettamente nei controller.
Bootstrap tipico in main.ts:
ts
import cookieParser from "cookie-parser";
import helmet from "helmet";
import { ValidationPipe } from "@nestjs/common";
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
const app = await NestFactory.create(AppModule);
app.use(helmet());
app.use(cookieParser());
app.setGlobalPrefix("api");
app.useGlobalPipes(
new ValidationPipe({
transform: true,
whitelist: true,
forbidNonWhitelisted: true,
}),
);
await app.listen(process.env.PORT ?? 3001);Variabili minime da prevedere:
text
PORT=3001
DATABASE_URL=postgresql://...
JWT_SECRET=...
PLATFORM_INTERNAL_TOKEN=...
AUTH_SERVICE_URL=http://localhost:3100
AI_SERVICE_URL=http://localhost:3300Usa i servizi CORE esistenti quando il requisito risulta condiviso:
- Auth/sessioni:
platform-auth-service - AI provider-agnostic:
platform-ai-service - Agent asincroni:
platform-agent-service - Salesforce e datasource esterni:
platform-connectors-service - Pagamenti:
platform-payments-service - Scraping:
platform-scraper-service
apps/web
Stack approvato:
- React 19:
react,react-dom - Build/dev:
vite,@vitejs/plugin-react - Routing:
react-router-dom7 - UI: shadcn/ui generato localmente, Radix,
lucide-react - Styling: Tailwind CSS 4,
@tailwindcss/vite,tailwindcss-animate - State/data:
@reduxjs/toolkit,react-redux - i18n:
react-intl - Forms:
react-hook-form,@hookform/resolvers,zod - Test:
vitest,jsdom,@testing-library/react,@testing-library/jest-dom,@testing-library/user-event - Tooling:
typescript
Dipendenze UI base:
text
class-variance-authority
clsx
tailwind-merge
lucide-react
tailwindcss-animate
@radix-ui/react-slot
@radix-ui/react-dialog
@radix-ui/react-dropdown-menu
@radix-ui/react-tooltip
@radix-ui/react-popover
@radix-ui/react-tabs
@radix-ui/react-checkbox
@radix-ui/react-select
@radix-ui/react-labelshadcn/ui non va trattato come dipendenza runtime: genera componenti locali in src/components/ui.
bash
cd apps/web
npx shadcn@latest initStruttura consigliata:
text
src/
app/
router.tsx
providers.tsx
components/
ui/
domain/
layout/
features/
example/
components/
hooks/
state/
api/
i18n/
lib/
store/
test/Regole frontend:
src/components/uicontiene componenti generati da shadcn e piccoli wrapper generici.src/components/domaincontiene componenti business riusabili tra feature.- Le feature tengono insieme componenti, hook, slice Redux e client
/api/*del proprio dominio. - I componenti non devono accedere direttamente ai servizi CORE o a URL cross-origin.
- Usa
lucide-reactper icone di azione e Radix/shadcn per controlli accessibili.
Alias richiesto in tsconfig.json:
json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}Alias corrispondente in vite.config.ts:
ts
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [react(), tailwindcss()],
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
},
server: {
proxy: {
"/api": "http://localhost:3001",
},
},
});Tailwind deve includere almeno i sorgenti Vite/React:
ts
export default {
content: ["./index.html", "./src/**/*.{ts,tsx}"],
};packages/shared
Stack approvato:
typescriptzodsolo quando servono validatori condivisi traapps/apieapps/web
Struttura consigliata:
text
src/
index.ts
constants/
dto/
schemas/
types/Linee guida:
- Esporta tipi e funzioni pure, senza dipendenze da NestJS, React, Vite o Prisma.
- I validatori condivisi possono stare in
schemas, poiapps/apili adatta ai DTO se necessario. - Non usare questo package per logica applicativa, chiamate HTTP o stato UI.
Integrazione con lo stack globale
Quando il nuovo progetto entra nel workspace operativo:
- Aggiungi repository, porte e domini in
platform-local-stack/config/stack-paths.json. - Aggiungi il servizio ai profili interessati in
platform-local-stack/config/profiles/*.yaml. - Definisci comandi, env runtime e dipendenze infra in
platform-local-stack/scripts/stack-definitions.mjs. - Esponi route HTTP o WebSocket nel proxy locale in
platform-local-stack/scripts/dev-proxy.mjs. - Registra prodotto, health target e link nel catalogo
/productsdiplatform-status-service; aggiungi smoke test solo quando serve una suite core dedicata. - Documenta il modulo in
platform-wikie aggiorna il catalogo moduli. - Aggiorna
README.mdedocs/architecture-current.mdse cambiano boundary, dipendenze o flussi runtime.
Boundary da rispettare:
- I servizi CORE restano product-agnostic.
- Il nuovo progetto
EXPERIENCEcontiene dominio prodotto, BFF, flussi utente e UI. - I frontend chiamano il BFF tramite
/api/*, mai i servizi CORE direttamente. - Gli SDK vendor restano nei servizi CORE quando esiste gia un connector condiviso.
- I tool MCP vanno aggiunti in
platform-mcp-servicesolo con registrar, client HTTP, schema input e risposta normalizzata dedicati.
Checklist finale
Prima di considerare pronto il nuovo progetto:
npm installgenera un solo lockfile al root del repository.npm run lint,npm run testenpm run buildpassano dal root.apps/apiesponeGET /api/healthoGET /health, secondo convenzione scelta e documentata.apps/webusa proxy Vite verso il BFF e non contiene URL diretti ai servizi CORE.packages/sharednon importa framework runtime.- Le variabili richieste sono documentate in
.env.example. - Le pagine wiki e i profili local-stack sono aggiornati se il repository entra in esercizio operativo.