Flux de lucru profesional: proiect unghiular cu cursor de la configurare la implementare
Ați aflat despre Cursor, regulile sale, Modul Agent, Modul Plan, Hooks și protocolul MCP. Acum este momentul să punem totul împreună într-unul singur flux de lucru profesional real. Acest articol finalul seriei și un studiu de caz operațional: vom construi un proiect Angular complet folosind Cursor ca Copilot AI în fiecare etapă, de la inițializarea proiectului până la implementarea producției.
Aceasta nu este o colecție abstractă de bune practici. Fiecare secțiune arată comenzi reale, solicitări configurații eficiente, concrete și deciziile pe care le ia o echipă de profesioniști atunci când se integrează Cursor în procesul de dezvoltare zilnică. La sfârșitul acestui articol veți avea un manual complet și replicabil pentru orice proiect Angular.
Proiectul pe care îl vom construi este unul singur tabloul de bord pentru managementul sarcinilor cu Angular 19, SSR, semnale, componente autonome, testare automată și CI/CD cu GitHub Actions. Un proiect reprezentativ pentru complexitatea reală pe care o întâlnești în munca ta profesională de zi cu zi.
Ce veți învăța în acest articol
- Cum se structurează un fișier
.cursor/rules/optim pentru proiectele Angular - Configurarea inițială a proiectului cu modul Agent: de la zero până la structura completă în câteva minute
- Generare bazată pe inteligență artificială de componente independente cu semnale și forme reactive
- Configurare SSR și hidratare incrementală cu Cursor ca asistent
- Flux de lucru de testare: teste unitare cu Jest/Vitest și E2E cu Playwright, scrise cu AI
- Refactorizează inteligent modelele moștenite cu Modul Agent
- Optimizarea asistată a performanței: încărcare leneră, analiză de pachete, Core Web Vitals
- Conducta completă CI/CD generată cu Cursor pentru GitHub Actions și Firebase
- Studiu de caz de la capăt la capăt: o caracteristică completă de la idee până la implementarea în producție
- Sfaturi și trucuri exclusive pentru dezvoltatorii Angular care folosesc Cursor în fiecare zi
Cerințe tehnice
- Node.js 22+ și Angular CLI 19+
- Cursor IDE (plan Pro recomandat pentru modul agent nelimitat)
- Git și un cont GitHub pentru CI/CD
- Cunoștințe de bază de Angular, TypeScript și RxJS
- Opțional: cont Firebase pentru implementare, familiaritate cu SSR
Pasul 1 - Configurați regulile cursorului pentru un proiect unghiular
Primul pas pentru un flux de lucru profesional este configurarea Cursorului astfel încât să cunoască convențiile proiectului dvs. chiar înainte de a scrie prima linie de cod. Un dosar de regulile bine structurate transformă Cursorul dintr-un asistent generic într-un colaborator specializat în stiva dvs. Angular.
Cu Cursor 0.45+, regulile sunt în director .cursor/rules/ ca un dosar
.mdc. Puteți avea reguli globale care sunt întotdeauna active și reguli specifice care se declanșează
pe baza contextului. Pentru un proiect profesional Angular, recomand această structură:
# Struttura directory regole Angular
.cursor/
rules/
angular-core.mdc # Regole fondamentali sempre attive
angular-components.mdc # Regole per componenti standalone
angular-testing.mdc # Regole per la scrittura dei test
angular-performance.mdc # Regole per ottimizzazioni
angular-ssr.mdc # Regole per SSR e hydration
Iată conținutul complet al angular-core.mdc, cea mai importantă regulă care
stabilește bazele arhitecturale ale proiectului:
---
description: Regole fondamentali per progetti Angular 19+ con standalone components e signals
globs: ["**/*.ts", "**/*.html"]
alwaysApply: true
---
# Angular Core Rules
## Architettura e Struttura
- Usa SEMPRE standalone components (niente NgModules salvo casi eccezionali)
- Organizza per feature/dominio, non per tipo (no cartelle globali "components/", "services/")
- Struttura directory per feature: `src/app/features/[nome-feature]/`
- Ogni feature ha: components/, services/, models/, guards/ (se necessario)
- Shared components in `src/app/shared/`
- Core singleton services in `src/app/core/`
## TypeScript e Dependency Injection
- Usa SEMPRE `inject()` per l'iniezione delle dipendenze (non costruttore)
- TypeScript strict mode obbligatorio
- Evita `any` - usa `unknown` con type narrowing quando necessario
- Usa `readonly` per proprietà che non cambiano dopo l'inizializzazione
- Interface su Type per definire shape di oggetti
## State Management con Signals
- Usa signals per tutto lo stato locale del componente
- `computed()` per valori derivati, mai getters che chiamano funzioni
- `effect()` solo per side effects (DOM, chiamate API non-reactive, log)
- Per stato condiviso tra componenti: service con signals esposti come readonly
- RxJS per operazioni async complesse (HTTP, WebSocket), poi `toSignal()` per esporre nei template
## Template e Rendering
- Usa SEMPRE la nuova sintassi control flow: @if, @for, @switch (non *ngIf, *ngFor)
- `@for` richiede sempre il `track` expression - usa ID univoci, non index
- ChangeDetectionStrategy.OnPush per TUTTI i componenti (performance default)
- NgOptimizedImage per tutte le immagini (src → ngSrc)
## Naming Conventions
- File: kebab-case (`user-profile.component.ts`)
- Classi: PascalCase (`UserProfileComponent`)
- Signals: nome senza prefisso, non `
09 - Flux de lucru profesional: Proiect unghiular cu cursor | Federico Calò
09 - Flux de lucru profesional: Proiect unghiular cu cursor | Federico Calò
Salta al contenuto principaleBună! Sunt
Federico Calò
Sviluppatore Software | Divulgatore Tecnico
Creo applicazioni web moderne e strumenti digitali personalizzati per aiutare le attività a crescere attraverso l'innovazione tecnologica. La mia passione è unire informatica ed economia per generare valore reale.
Despre Mine
La mia passione per l'informatica è nata tra i banchi dell'Istituto Tecnico Commerciale di Maglie, dove ho scoperto il potere della programmazione e il fascino di creare soluzioni digitali. Fin da subito, ho capito che l'informatica non era solo codice, ma uno strumento straordinario per trasformare idee in realtà.
Durante gli studi superiori in Sistemi Informativi Aziendali, ho iniziato a intrecciare informatica ed economia, comprendendo come la tecnologia possa essere il motore della crescita per qualsiasi attività. Questa visione mi ha accompagnato all'Università degli Studi di Bari, dove ho conseguito la Laurea in Informatica, approfondendo le mie competenze tecniche e la mia passione per lo sviluppo software.
Oggi metto questa esperienza al servizio di imprese, professionisti e startup, creando soluzioni digitali su misura che automatizzano processi, ottimizzano risorse e aprono nuove opportunità di business. Perché la vera innovazione inizia quando la tecnologia incontra le esigenze reali delle persone.
Competențele Mele
Analisi Dati & Modelli Previsionali
Trasformo i dati in insights strategici con analisi approfondite e modelli predittivi per decisioni informate
Automatizarea Proceselor
Creo strumenti personalizzati che automatizzano operazioni ripetitive e liberano tempo per attività a valore aggiunto
Sisteme Personalizate
Sviluppo sistemi software su misura, dalle integrazioni tra piattaforme alle dashboard personalizzate
const federico = {
nome: "Federico Calò",
ruolo: "Sviluppatore Software",
città: "Bari, Italia",
missione: "Aiutare attraverso l'informatica",
passioni: [
"Codice Pulito",
"Innovazione",
"Crescita Continua"
]
};
Misiunea Mea
Credo fermamente che l'informatica sia lo strumento più potente per trasformare le idee in realtà e migliorare la vita delle persone.
Democratizarea Tehnologiei
La mia missione è rendere l'informatica accessibile a tutti: dalle piccole imprese locali alle startup innovative, fino ai professionisti che vogliono digitalizzare la propria attività. Ogni realtà merita di sfruttare le potenzialità del digitale.
Unirea IT și Economiei
Non è solo questione di scrivere codice: è capire come la tecnologia possa generare valore reale. Intrecciando competenze informatiche e visione economica, aiuto le attività a crescere, ottimizzare processi e raggiungere nuovi traguardi di efficienza e redditività.
Crearea de Soluții Personalizate
Ogni attività è unica, e così devono esserlo le soluzioni. Sviluppo strumenti personalizzati che rispondono alle esigenze specifiche di ciascun cliente, automatizzando processi ripetitivi e liberando tempo per ciò che conta davvero: far crescere il business.
Transformă-ți Afacerea cu Tehnologia
Che tu gestisca un negozio, uno studio professionale o un'azienda, posso aiutarti a sfruttare le potenzialità dell'informatica per lavorare meglio, più velocemente e in modo più intelligente.
Hai să Vorbim →Unisciti alla Community
Entra nella community di sviluppatori dove discutiamo di software, AI, architettura e DevOps. Condividi idee, fai domande e cresci insieme a noi.
CanaleFC Dev Blog
Ricevi notifiche su nuovi articoli, serie complete, tips settimanali e tool in evidenza. Contenuti bilingui IT/EN direttamente nel tuo Telegram.
Nuovi articoli appena pubblicati Tips e code snippets settimanali Sondaggi sugli argomenti futuri
Iscriviti al CanaleGruppoFC Dev Community
Una community bilingue IT/EN per sviluppatori. Discussioni, Q&A, aiuto reciproco e networking con altri professionisti del settore.
Discussioni su articoli e tecnologie Help coding e code review Opportunità di lavoro e collaborazione
Unisciti al GruppoTopic di Discussione
#general #articles #help-coding #ai-ml #devops-cloud #architecture #tools #jobs-opportunitiesFormazione & Competenze
Il mio percorso accademico e le tecnologie che padroneggio
Certificazioni Professionali
8 certificazioni conseguite
Linguaggi & Tecnologie
Java Python JavaScript Angular React TypeScript SQL PHP CSS/SCSS Node.js Docker GitContactează-mă
Ai un proiect în minte? Hai să vorbim! Completează formularul și îți voi răspunde curând.
* Campi obbligatori. I tuoi dati saranno utilizzati solo per rispondere alla tua richiesta.
come suffisso (`users`, non `users
09 - Flux de lucru profesional: Proiect unghiular cu cursor | Federico Calò
09 - Flux de lucru profesional: Proiect unghiular cu cursor | Federico Calò
Salta al contenuto principaleBună! Sunt
Federico Calò
Sviluppatore Software | Divulgatore Tecnico
Creo applicazioni web moderne e strumenti digitali personalizzati per aiutare le attività a crescere attraverso l'innovazione tecnologica. La mia passione è unire informatica ed economia per generare valore reale.
Despre Mine
La mia passione per l'informatica è nata tra i banchi dell'Istituto Tecnico Commerciale di Maglie, dove ho scoperto il potere della programmazione e il fascino di creare soluzioni digitali. Fin da subito, ho capito che l'informatica non era solo codice, ma uno strumento straordinario per trasformare idee in realtà.
Durante gli studi superiori in Sistemi Informativi Aziendali, ho iniziato a intrecciare informatica ed economia, comprendendo come la tecnologia possa essere il motore della crescita per qualsiasi attività. Questa visione mi ha accompagnato all'Università degli Studi di Bari, dove ho conseguito la Laurea in Informatica, approfondendo le mie competenze tecniche e la mia passione per lo sviluppo software.
Oggi metto questa esperienza al servizio di imprese, professionisti e startup, creando soluzioni digitali su misura che automatizzano processi, ottimizzano risorse e aprono nuove opportunità di business. Perché la vera innovazione inizia quando la tecnologia incontra le esigenze reali delle persone.
Competențele Mele
Analisi Dati & Modelli Previsionali
Trasformo i dati in insights strategici con analisi approfondite e modelli predittivi per decisioni informate
Automatizarea Proceselor
Creo strumenti personalizzati che automatizzano operazioni ripetitive e liberano tempo per attività a valore aggiunto
Sisteme Personalizate
Sviluppo sistemi software su misura, dalle integrazioni tra piattaforme alle dashboard personalizzate
const federico = {
nome: "Federico Calò",
ruolo: "Sviluppatore Software",
città: "Bari, Italia",
missione: "Aiutare attraverso l'informatica",
passioni: [
"Codice Pulito",
"Innovazione",
"Crescita Continua"
]
};
Misiunea Mea
Credo fermamente che l'informatica sia lo strumento più potente per trasformare le idee in realtà e migliorare la vita delle persone.
Democratizarea Tehnologiei
La mia missione è rendere l'informatica accessibile a tutti: dalle piccole imprese locali alle startup innovative, fino ai professionisti che vogliono digitalizzare la propria attività. Ogni realtà merita di sfruttare le potenzialità del digitale.
Unirea IT și Economiei
Non è solo questione di scrivere codice: è capire come la tecnologia possa generare valore reale. Intrecciando competenze informatiche e visione economica, aiuto le attività a crescere, ottimizzare processi e raggiungere nuovi traguardi di efficienza e redditività.
Crearea de Soluții Personalizate
Ogni attività è unica, e così devono esserlo le soluzioni. Sviluppo strumenti personalizzati che rispondono alle esigenze specifiche di ciascun cliente, automatizzando processi ripetitivi e liberando tempo per ciò che conta davvero: far crescere il business.
Transformă-ți Afacerea cu Tehnologia
Che tu gestisca un negozio, uno studio professionale o un'azienda, posso aiutarti a sfruttare le potenzialità dell'informatica per lavorare meglio, più velocemente e in modo più intelligente.
Hai să Vorbim →Unisciti alla Community
Entra nella community di sviluppatori dove discutiamo di software, AI, architettura e DevOps. Condividi idee, fai domande e cresci insieme a noi.
CanaleFC Dev Blog
Ricevi notifiche su nuovi articoli, serie complete, tips settimanali e tool in evidenza. Contenuti bilingui IT/EN direttamente nel tuo Telegram.
Nuovi articoli appena pubblicati Tips e code snippets settimanali Sondaggi sugli argomenti futuri
Iscriviti al CanaleGruppoFC Dev Community
Una community bilingue IT/EN per sviluppatori. Discussioni, Q&A, aiuto reciproco e networking con altri professionisti del settore.
Discussioni su articoli e tecnologie Help coding e code review Opportunità di lavoro e collaborazione
Unisciti al GruppoTopic di Discussione
#general #articles #help-coding #ai-ml #devops-cloud #architecture #tools #jobs-opportunitiesFormazione & Competenze
Il mio percorso accademico e le tecnologie che padroneggio
Certificazioni Professionali
8 certificazioni conseguite
Linguaggi & Tecnologie
Java Python JavaScript Angular React TypeScript SQL PHP CSS/SCSS Node.js Docker GitContactează-mă
Ai un proiect în minte? Hai să vorbim! Completează formularul și îți voi răspunde curând.
* Campi obbligatori. I tuoi dati saranno utilizzati solo per rispondere alla tua richiesta.
ne `usersSignal`)
- Observable: suffisso `
09 - Flux de lucru profesional: Proiect unghiular cu cursor | Federico Calò
09 - Flux de lucru profesional: Proiect unghiular cu cursor | Federico Calò
Salta al contenuto principaleBună! Sunt
Federico Calò
Sviluppatore Software | Divulgatore Tecnico
Creo applicazioni web moderne e strumenti digitali personalizzati per aiutare le attività a crescere attraverso l'innovazione tecnologica. La mia passione è unire informatica ed economia per generare valore reale.
Despre Mine
La mia passione per l'informatica è nata tra i banchi dell'Istituto Tecnico Commerciale di Maglie, dove ho scoperto il potere della programmazione e il fascino di creare soluzioni digitali. Fin da subito, ho capito che l'informatica non era solo codice, ma uno strumento straordinario per trasformare idee in realtà.
Durante gli studi superiori in Sistemi Informativi Aziendali, ho iniziato a intrecciare informatica ed economia, comprendendo come la tecnologia possa essere il motore della crescita per qualsiasi attività. Questa visione mi ha accompagnato all'Università degli Studi di Bari, dove ho conseguito la Laurea in Informatica, approfondendo le mie competenze tecniche e la mia passione per lo sviluppo software.
Oggi metto questa esperienza al servizio di imprese, professionisti e startup, creando soluzioni digitali su misura che automatizzano processi, ottimizzano risorse e aprono nuove opportunità di business. Perché la vera innovazione inizia quando la tecnologia incontra le esigenze reali delle persone.
Competențele Mele
Analisi Dati & Modelli Previsionali
Trasformo i dati in insights strategici con analisi approfondite e modelli predittivi per decisioni informate
Automatizarea Proceselor
Creo strumenti personalizzati che automatizzano operazioni ripetitive e liberano tempo per attività a valore aggiunto
Sisteme Personalizate
Sviluppo sistemi software su misura, dalle integrazioni tra piattaforme alle dashboard personalizzate
const federico = {
nome: "Federico Calò",
ruolo: "Sviluppatore Software",
città: "Bari, Italia",
missione: "Aiutare attraverso l'informatica",
passioni: [
"Codice Pulito",
"Innovazione",
"Crescita Continua"
]
};
Misiunea Mea
Credo fermamente che l'informatica sia lo strumento più potente per trasformare le idee in realtà e migliorare la vita delle persone.
Democratizarea Tehnologiei
La mia missione è rendere l'informatica accessibile a tutti: dalle piccole imprese locali alle startup innovative, fino ai professionisti che vogliono digitalizzare la propria attività. Ogni realtà merita di sfruttare le potenzialità del digitale.
Unirea IT și Economiei
Non è solo questione di scrivere codice: è capire come la tecnologia possa generare valore reale. Intrecciando competenze informatiche e visione economica, aiuto le attività a crescere, ottimizzare processi e raggiungere nuovi traguardi di efficienza e redditività.
Crearea de Soluții Personalizate
Ogni attività è unica, e così devono esserlo le soluzioni. Sviluppo strumenti personalizzati che rispondono alle esigenze specifiche di ciascun cliente, automatizzando processi ripetitivi e liberando tempo per ciò che conta davvero: far crescere il business.
Transformă-ți Afacerea cu Tehnologia
Che tu gestisca un negozio, uno studio professionale o un'azienda, posso aiutarti a sfruttare le potenzialità dell'informatica per lavorare meglio, più velocemente e in modo più intelligente.
Hai să Vorbim →Unisciti alla Community
Entra nella community di sviluppatori dove discutiamo di software, AI, architettura e DevOps. Condividi idee, fai domande e cresci insieme a noi.
CanaleFC Dev Blog
Ricevi notifiche su nuovi articoli, serie complete, tips settimanali e tool in evidenza. Contenuti bilingui IT/EN direttamente nel tuo Telegram.
Nuovi articoli appena pubblicati Tips e code snippets settimanali Sondaggi sugli argomenti futuri
Iscriviti al CanaleGruppoFC Dev Community
Una community bilingue IT/EN per sviluppatori. Discussioni, Q&A, aiuto reciproco e networking con altri professionisti del settore.
Discussioni su articoli e tecnologie Help coding e code review Opportunità di lavoro e collaborazione
Unisciti al GruppoTopic di Discussione
#general #articles #help-coding #ai-ml #devops-cloud #architecture #tools #jobs-opportunitiesFormazione & Competenze
Il mio percorso accademico e le tecnologie che padroneggio
Certificazioni Professionali
8 certificazioni conseguite
Linguaggi & Tecnologie
Java Python JavaScript Angular React TypeScript SQL PHP CSS/SCSS Node.js Docker GitContactează-mă
Ai un proiect în minte? Hai să vorbim! Completează formularul și îți voi răspunde curând.
* Campi obbligatori. I tuoi dati saranno utilizzati solo per rispondere alla tua richiesta.
(`users
09 - Flux de lucru profesional: Proiect unghiular cu cursor | Federico Calò
09 - Flux de lucru profesional: Proiect unghiular cu cursor | Federico Calò
Salta al contenuto principaleBună! Sunt
Federico Calò
Sviluppatore Software | Divulgatore Tecnico
Creo applicazioni web moderne e strumenti digitali personalizzati per aiutare le attività a crescere attraverso l'innovazione tecnologica. La mia passione è unire informatica ed economia per generare valore reale.
Despre Mine
La mia passione per l'informatica è nata tra i banchi dell'Istituto Tecnico Commerciale di Maglie, dove ho scoperto il potere della programmazione e il fascino di creare soluzioni digitali. Fin da subito, ho capito che l'informatica non era solo codice, ma uno strumento straordinario per trasformare idee in realtà.
Durante gli studi superiori in Sistemi Informativi Aziendali, ho iniziato a intrecciare informatica ed economia, comprendendo come la tecnologia possa essere il motore della crescita per qualsiasi attività. Questa visione mi ha accompagnato all'Università degli Studi di Bari, dove ho conseguito la Laurea in Informatica, approfondendo le mie competenze tecniche e la mia passione per lo sviluppo software.
Oggi metto questa esperienza al servizio di imprese, professionisti e startup, creando soluzioni digitali su misura che automatizzano processi, ottimizzano risorse e aprono nuove opportunità di business. Perché la vera innovazione inizia quando la tecnologia incontra le esigenze reali delle persone.
Competențele Mele
Analisi Dati & Modelli Previsionali
Trasformo i dati in insights strategici con analisi approfondite e modelli predittivi per decisioni informate
Automatizarea Proceselor
Creo strumenti personalizzati che automatizzano operazioni ripetitive e liberano tempo per attività a valore aggiunto
Sisteme Personalizate
Sviluppo sistemi software su misura, dalle integrazioni tra piattaforme alle dashboard personalizzate
const federico = {
nome: "Federico Calò",
ruolo: "Sviluppatore Software",
città: "Bari, Italia",
missione: "Aiutare attraverso l'informatica",
passioni: [
"Codice Pulito",
"Innovazione",
"Crescita Continua"
]
};
Misiunea Mea
Credo fermamente che l'informatica sia lo strumento più potente per trasformare le idee in realtà e migliorare la vita delle persone.
Democratizarea Tehnologiei
La mia missione è rendere l'informatica accessibile a tutti: dalle piccole imprese locali alle startup innovative, fino ai professionisti che vogliono digitalizzare la propria attività. Ogni realtà merita di sfruttare le potenzialità del digitale.
Unirea IT și Economiei
Non è solo questione di scrivere codice: è capire come la tecnologia possa generare valore reale. Intrecciando competenze informatiche e visione economica, aiuto le attività a crescere, ottimizzare processi e raggiungere nuovi traguardi di efficienza e redditività.
Crearea de Soluții Personalizate
Ogni attività è unica, e così devono esserlo le soluzioni. Sviluppo strumenti personalizzati che rispondono alle esigenze specifiche di ciascun cliente, automatizzando processi ripetitivi e liberando tempo per ciò che conta davvero: far crescere il business.
Transformă-ți Afacerea cu Tehnologia
Che tu gestisca un negozio, uno studio professionale o un'azienda, posso aiutarti a sfruttare le potenzialità dell'informatica per lavorare meglio, più velocemente e in modo più intelligente.
Hai să Vorbim →Unisciti alla Community
Entra nella community di sviluppatori dove discutiamo di software, AI, architettura e DevOps. Condividi idee, fai domande e cresci insieme a noi.
CanaleFC Dev Blog
Ricevi notifiche su nuovi articoli, serie complete, tips settimanali e tool in evidenza. Contenuti bilingui IT/EN direttamente nel tuo Telegram.
Nuovi articoli appena pubblicati Tips e code snippets settimanali Sondaggi sugli argomenti futuri
Iscriviti al CanaleGruppoFC Dev Community
Una community bilingue IT/EN per sviluppatori. Discussioni, Q&A, aiuto reciproco e networking con altri professionisti del settore.
Discussioni su articoli e tecnologie Help coding e code review Opportunità di lavoro e collaborazione
Unisciti al GruppoTopic di Discussione
#general #articles #help-coding #ai-ml #devops-cloud #architecture #tools #jobs-opportunitiesFormazione & Competenze
Il mio percorso accademico e le tecnologie che padroneggio
Certificazioni Professionali
8 certificazioni conseguite
Linguaggi & Tecnologie
Java Python JavaScript Angular React TypeScript SQL PHP CSS/SCSS Node.js Docker GitContactează-mă
Ai un proiect în minte? Hai să vorbim! Completează formularul și îți voi răspunde curând.
* Campi obbligatori. I tuoi dati saranno utilizzati solo per rispondere alla tua richiesta.
)
- Metodi privati: prefisso `_` quando servono chiarezza
## Forms
- Reactive Forms (ReactiveFormsModule) per tutti i form non banali
- Template-driven solo per form con 1-2 campi senza validazione complessa
- Typed forms obbligatori (`FormControl<string>`, non `FormControl`)
- Validators personalizzati come funzioni pure (non classi)
Această regulă oferă Cursorului un context arhitectural complet. Când cereți să generați un
componentă, un serviciu sau o caracteristică, Cursor știe automat pe care să o folosească
inject(), semnale și noua sintaxă a fluxului de control. Nu e nevoie
repetați-l de fiecare dată în prompt.
Greșeală comună: reguli prea generice
Multe echipe creează un singur fișier .cursorrules imens cu sute de rânduri.
Rezultatul este că Cursorul nu reușește să prioritizeze instrucțiunile cele mai relevante pentru
contextul actual. Utilizați fișiere separate cu modele glob specifice: o regulă pentru i
componentele se vor activa numai pornit *.component.ts, menținând contextul
răspunsuri concentrate și cele mai precise.
Regula pentru Componente: angular-components.mdc
---
description: Standard per la creazione di componenti Angular standalone
globs: ["**/*.component.ts", "**/*.component.html"]
alwaysApply: false
---
# Component Standards
## Struttura Component File (ordine canonico)
1. Imports Angular/librerie
2. Imports locali (services, models, altri components)
3. @Component decorator
4. export class ComponentName
a. inject() calls (services)
b. @Input() signals con input()
c. @Output() signals con output()
d. Signals interni (private)
e. Computed signals
f. Constructor (solo se necessario per logic inizializzazione)
g. ngOnInit (se necessario)
h. Metodi pubblici (chiamati dal template)
i. Metodi privati (logica interna)
## Template Best Practices
- Niente logica nel template oltre a binding semplici
- Usa pipe per trasformazioni di dati (DatePipe, CurrencyPipe, ecc.)
- Mantieni template sotto le 100 righe - estrai sub-component se necessario
- Usa `aria-*` per accessibilità (WCAG 2.1 AA)
## Input/Output con Signal API (Angular 17+)
- `input()` per input opzionali, `input.required()` per quelli obbligatori
- `output()` al posto di `EventEmitter`
- `model()` per two-way binding custom
## Component-Scoped Styles
- Usa `:host` per stili sul root element
- Evita deep selector `::ng-deep` - estrai stili globali se necessario
- Variabili CSS per colori e spacing (usa il design system del progetto)
Faza 2 - Configurarea proiectului cu modul agent
Cu regulile configurate, este timpul să creați proiectul. În loc să ruleze manual fiecare comandă și creăm fiecare fișier, folosim Modul Agent pentru a delega întreaga fază de bootstrap. Acesta este unul dintre cele mai puternice cazuri de utilizare a Cursorului: dați instrucțiuni de nivel înalt și plecați că agentul efectuează toate etapele operaționale.
Deschideți Cursor, creați un folder nou pentru proiect și lansați Modul Agent cu Cmd+Shift+I (sau Ctrl+Shift+I pe Windows/Linux). Apoi utilizați acest prompt:
Mod Prompt Agent: Proiect Bootstrap
Crea un nuovo progetto Angular 19 chiamato "task-dashboard" con le seguenti caratteristiche:
1. Angular CLI con SSR abilitato (--ssr flag)
2. TypeScript strict mode
3. Jest al posto di Karma per i test unitari (configura jest.config.ts)
4. ESLint con angular-eslint
5. Prettier configurato con .prettierrc
6. Struttura a feature:
- src/app/core/ (interceptors, guards, singleton services)
- src/app/shared/ (components e pipes condivisi)
- src/app/features/tasks/ (feature principale)
- src/app/features/auth/ (autenticazione)
7. Ambiente di sviluppo con proxy verso http://localhost:3000 (API backend)
8. Git inizializzato con .gitignore appropriato
Esegui i comandi necessari, installa le dipendenze e mostrami la struttura finale.
Cursorul va rula ng new, va instala dependențe, va configura Jest,
ESLint și Prettier, va crea structura de foldere și va inițializa Git, totul
în câteva minute. Ceea ce durează în mod normal 30-45 de minute de configurare manuală vine
completate cu acuratețe și consecvență.
Generarea sarcinilor caracteristice cu modul agent
După bootstrapping, generăm caracteristica principală. Acest prompt se afișează ca Agent Mode poate construi o întreagă secțiune verticală a aplicației, de la modelul de date la componente, respectând regulile noastre unghiulare:
Mod agent prompt: Funcții sarcini finalizate
Crea la feature "tasks" completa in src/app/features/tasks/ seguendo le regole in .cursor/rules/:
MODELLO DATI (src/app/features/tasks/models/task.model.ts):
- Interface Task con: id (string), title (string), description (string),
status ('todo' | 'in-progress' | 'done'), priority ('low' | 'medium' | 'high'),
createdAt (Date), dueDate (Date | null), assigneeId (string | null)
- Type TaskStatus e TaskPriority (union types)
- Interface CreateTaskRequest e UpdateTaskRequest (Partial<Task> senza id/createdAt)
SERVICE (src/app/features/tasks/services/task.service.ts):
- Usa inject(HttpClient)
- Signals: tasks = signal<Task[]>([]), loading = signal(false), error = signal<string | null>(null)
- Computed: completedTasks, pendingTasks, tasksByPriority
- Metodi: loadTasks(), createTask(), updateTask(), deleteTask(), updateStatus()
- Tutti i metodi aggiornano i signals dopo le chiamate HTTP
COMPONENTI STANDALONE:
1. TaskListComponent - lista tasks con filtri per status/priority
2. TaskCardComponent - card singola task con azioni
3. TaskFormComponent - form creazione/modifica con reactive forms tipizzati
4. TaskDetailComponent - vista dettaglio con routing
ROUTING: configura il routing lazy-loaded in tasks.routes.ts
Rispetta SEMPRE: standalone: true, inject(), signals, ChangeDetectionStrategy.OnPush,
@if/@for syntax, TypeScript strict mode.
Cursorul va genera toate fișierele respectând convențiile definite în reguli. Rezultatul și cod coerent pe care l-ai fi putut scrie singur, dar într-o fracțiune de timp.
Faza 3 - Componente cu semnale și forme reactive
Să vedem în detaliu cum Cursor generează componente moderne Angular. După ce a dat promptul
mai sus, să examinăm rezultatul pentru TaskFormComponent și cum să o rafinați:
// task-form.component.ts - Generato da Cursor con Agent Mode
import { Component, ChangeDetectionStrategy, inject, input, output } from '@angular/core';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { CreateTaskRequest, TaskPriority } from '../models/task.model';
import { TaskService } from '../services/task.service';
@Component({
selector: 'app-task-form',
standalone: true,
imports: [ReactiveFormsModule],
templateUrl: './task-form.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class TaskFormComponent {
// Dependency injection con inject()
private readonly fb = inject(FormBuilder);
private readonly taskService = inject(TaskService);
// Input signals (Angular 17+ API)
readonly initialData = input<Partial<CreateTaskRequest> | null>(null);
readonly isEdit = input(false);
// Output signals
readonly formSubmit = output<CreateTaskRequest>();
readonly formCancel = output<void>();
// Reactive form tipizzato
readonly form = this.fb.group({
title: this.fb.control('', {
validators: [Validators.required, Validators.minLength(3), Validators.maxLength(100)],
nonNullable: true
}),
description: this.fb.control('', { nonNullable: true }),
priority: this.fb.control<TaskPriority>('medium', { nonNullable: true }),
dueDate: this.fb.control<string | null>(null)
});
// Computed: stato di validita esposto al template
readonly isValid = this.form.statusChanges;
// Loading state dal service (readonly - no mutation)
readonly loading = this.taskService.loading;
onSubmit(): void {
if (this.form.invalid) return;
const value = this.form.getRawValue();
this.formSubmit.emit({
title: value.title,
description: value.description,
priority: value.priority,
dueDate: value.dueDate ? new Date(value.dueDate) : null,
assigneeId: null
});
}
onCancel(): void {
this.form.reset();
this.formCancel.emit();
}
}
Observați cum Cursorul respectă automat convențiile regulilor: inject()
pentru dependențe, input() e output() în loc de
@Input() e @Output(), readonly pe proprietăți
e ChangeDetectionStrategy.OnPush. Aceasta este valoarea reală a regulilor bine
configurat: AI produce cod care se conformează standardelor echipei fără a fi nevoie de revizuiri
constante.
TaskService cu semnale: model reactiv complet
// task.service.ts - Pattern signals per stato globale della feature
import { Injectable, inject, signal, computed } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Task, CreateTaskRequest, UpdateTaskRequest, TaskStatus } from '../models/task.model';
import { tap, catchError, EMPTY, finalize } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class TaskService {
private readonly http = inject(HttpClient);
private readonly API_URL = '/api/tasks';
// Signals privati (stato interno del service)
private readonly _tasks = signal<Task[]>([]);
private readonly _loading = signal(false);
private readonly _error = signal<string | null>(null);
// Signals pubblici (readonly - i consumatori non possono mutare)
readonly tasks = this._tasks.asReadonly();
readonly loading = this._loading.asReadonly();
readonly error = this._error.asReadonly();
// Computed signals - derivati dallo stato
readonly completedTasks = computed(() =>
this._tasks().filter(t => t.status === 'done')
);
readonly pendingTasks = computed(() =>
this._tasks().filter(t => t.status !== 'done')
);
readonly tasksByPriority = computed(() => {
const tasks = this._tasks();
return {
high: tasks.filter(t => t.priority === 'high'),
medium: tasks.filter(t => t.priority === 'medium'),
low: tasks.filter(t => t.priority === 'low')
};
});
readonly completionRate = computed(() => {
const total = this._tasks().length;
if (total === 0) return 0;
return Math.round((this.completedTasks().length / total) * 100);
});
loadTasks(): void {
this._loading.set(true);
this._error.set(null);
this.http.get<Task[]>(this.API_URL).pipe(
tap(tasks => this._tasks.set(tasks)),
catchError(err => {
this._error.set('Errore nel caricamento dei task. Riprova.');
console.error('[TaskService] loadTasks error:', err);
return EMPTY;
}),
finalize(() => this._loading.set(false))
).subscribe();
}
createTask(request: CreateTaskRequest): void {
this._loading.set(true);
this.http.post<Task>(this.API_URL, request).pipe(
tap(newTask => {
// Immutable update del signal
this._tasks.update(current => [...current, newTask]);
}),
catchError(err => {
this._error.set('Errore nella creazione del task.');
return EMPTY;
}),
finalize(() => this._loading.set(false))
).subscribe();
}
updateStatus(taskId: string, status: TaskStatus): void {
// Optimistic update: aggiorna UI immediatamente
this._tasks.update(current =>
current.map(t => t.id === taskId ? { ...t, status } : t)
);
this.http.patch<Task>(`${this.API_URL}/${taskId}`, { status }).pipe(
catchError(err => {
// Rollback in caso di errore
this.loadTasks();
this._error.set('Errore nell\'aggiornamento dello stato.');
return EMPTY;
})
).subscribe();
}
}
Faza 4 - SSR și hidratare incrementală cu cursor
Port unghiular 19 hidratare progresivă în stabil, o caracteristică care permite pentru a hidrata doar părțile paginii care devin vizibile sau interactive, reducând drastic JavaScript inițial. Configurarea corectă a SSR este una dintre cele mai multe domenii supuse unor erori subtile. Cursorul devine deosebit de util aici.
Utilizați această solicitare pentru a configura SSR cu hidratare incrementală și management adecvat a contextelor server/browser:
Solicitare: Configurați SSR cu hidratare incrementală
Configura SSR con hydration incrementale per questo progetto Angular 19. Fai queste modifiche:
1. In app.config.ts: aggiungi provideClientHydration(withIncrementalHydration())
2. Crea un service isPlatformBrowser (src/app/core/services/platform.service.ts)
che usa PLATFORM_ID per verificare il contesto di esecuzione
3. Nel TaskListComponent: avvolgi la lista task in un blocco @defer con
on viewport per il caricamento lazy + hydration incrementale
4. Aggiungi TransferState per evitare la doppia chiamata HTTP nel TaskService
(carica i dati lato server, trasferiscili al client senza refetch)
5. Gestisci il caso in cui localStorage non sia disponibile lato server
Cursorul va edita fișierele relevante și vă va explica orice modificări. Rezultatul va fi
a app.config.ts un serviciu corect și compatibil cu platforma:
// app.config.ts - Configurazione SSR completa
import { ApplicationConfig, provideZonelessChangeDetection } from '@angular/core';
import { provideRouter, withPreloading, PreloadAllModules } from '@angular/router';
import { provideClientHydration, withIncrementalHydration } from '@angular/platform-browser';
import { provideHttpClient, withFetch } from '@angular/common/http';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
// Zone-less change detection (Angular 18+, raccomandato con signals)
provideZonelessChangeDetection(),
// Router con preloading strategia
provideRouter(routes, withPreloading(PreloadAllModules)),
// HTTP con fetch API (compatibile con SSR nativo)
provideHttpClient(withFetch()),
// SSR Hydration incrementale (Angular 19 stable)
provideClientHydration(withIncrementalHydration()),
]
};
// platform.service.ts - Rilevamento contesto server/browser
import { Injectable, inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
@Injectable({ providedIn: 'root' })
export class PlatformService {
private readonly platformId = inject(PLATFORM_ID);
readonly isBrowser = isPlatformBrowser(this.platformId);
readonly isServer = isPlatformServer(this.platformId);
// Helper per operazioni browser-only
runInBrowser(fn: () => void): void {
if (this.isBrowser) fn();
}
// Safe localStorage access
getLocalStorage(key: string): string | null {
if (!this.isBrowser) return null;
return localStorage.getItem(key);
}
setLocalStorage(key: string, value: string): void {
if (!this.isBrowser) return;
localStorage.setItem(key, value);
}
}
TransferState pentru a evita preluarea dublă
Una dintre cele mai frecvente erori cu Angular SSR este că datele sunt încărcate de două ori: pe o parte
server în timpul redării și din nou pe partea client după hidratare. Cursorul poate adăuga
automat TransferState la serviciu:
// task.service.ts - Con TransferState per SSR ottimizzato
import { Injectable, inject, signal, computed, makeStateKey, TransferState } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { tap, catchError, EMPTY, finalize } from 'rxjs';
import { Task, CreateTaskRequest, TaskStatus } from '../models/task.model';
import { PlatformService } from '../../../core/services/platform.service';
const TASKS_KEY = makeStateKey<Task[]>('tasks');
@Injectable({ providedIn: 'root' })
export class TaskService {
private readonly http = inject(HttpClient);
private readonly transferState = inject(TransferState);
private readonly platform = inject(PlatformService);
private readonly _tasks = signal<Task[]>([]);
private readonly _loading = signal(false);
private readonly _error = signal<string | null>(null);
readonly tasks = this._tasks.asReadonly();
readonly loading = this._loading.asReadonly();
readonly error = this._error.asReadonly();
loadTasks(): void {
// Se i dati sono già nel TransferState (hydration), usali direttamente
if (this.transferState.hasKey(TASKS_KEY)) {
const cachedTasks = this.transferState.get(TASKS_KEY, []);
this._tasks.set(cachedTasks);
this.transferState.remove(TASKS_KEY);
return;
}
this._loading.set(true);
this.http.get<Task[]>('/api/tasks').pipe(
tap(tasks => {
this._tasks.set(tasks);
// Lato server: salva nel TransferState per il client
if (this.platform.isServer) {
this.transferState.set(TASKS_KEY, tasks);
}
}),
catchError(() => {
this._error.set('Errore nel caricamento.');
return EMPTY;
}),
finalize(() => this._loading.set(false))
).subscribe();
}
}
Faza 5 - Flux de lucru de testare bazată pe inteligență artificială
Testarea este adesea partea cea mai trecută cu vederea a dezvoltării profesionale, deoarece este percepută ca fiind oneroase. Cursorul modifică această ecuație: puteți genera o suită completă de teste în câteva minute, permițându-vă să vă concentrați pe revizuirea și finalizarea cazurilor marginea în loc să scrie boilerplate de la zero.
Test unitar cu Jest: Generare automată
Utilizați această solicitare pe un fișier de serviciu sau componentă pentru a obține o testare completă:
Solicitare: Generați teste unitare complete
Genera unit test completi per @task.service.ts usando Jest e Angular Testing Library.
Includi test per:
1. loadTasks(): successo (mock HTTP 200), errore (mock HTTP 500),
loading state durante la chiamata, utilizzo TransferState in hydration
2. createTask(): aggiornamento ottimista del signal, rollback su errore,
validazione che il nuovo task venga aggiunto in coda
3. updateStatus(): optimistic update, verifica che il signal venga aggiornato
immediatamente, rollback su errore HTTP
4. Computed signals: verifica che completedTasks e pendingTasks si aggiornino
correttamente al cambiamento di _tasks
Usa TestBed con provideHttpClientTesting, HttpTestingController per i mock HTTP.
Organizza con describe/it annidati. Aggiungi afterEach con httpMock.verify().
// task.service.spec.ts - Generato da Cursor
import { TestBed } from '@angular/core/testing';
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
import { provideHttpClient } from '@angular/common/http';
import { TaskService } from './task.service';
import { Task, TaskStatus } from '../models/task.model';
const mockTasks: Task[] = [
{ id: '1', title: 'Task 1', description: '', status: 'todo', priority: 'high',
createdAt: new Date(), dueDate: null, assigneeId: null },
{ id: '2', title: 'Task 2', description: '', status: 'done', priority: 'low',
createdAt: new Date(), dueDate: null, assigneeId: null }
];
describe('TaskService', () => {
let service: TaskService;
let httpMock: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
provideHttpClient(),
provideHttpClientTesting(),
TaskService
]
});
service = TestBed.inject(TaskService);
httpMock = TestBed.inject(HttpTestingController);
});
afterEach(() => httpMock.verify());
describe('loadTasks()', () => {
it('dovrebbe caricare i task e aggiornare il signal', () => {
service.loadTasks();
const req = httpMock.expectOne('/api/tasks');
expect(req.request.method).toBe('GET');
req.flush(mockTasks);
expect(service.tasks()).toEqual(mockTasks);
expect(service.loading()).toBe(false);
expect(service.error()).toBeNull();
});
it('dovrebbe impostare loading a true durante la chiamata', () => {
service.loadTasks();
expect(service.loading()).toBe(true);
httpMock.expectOne('/api/tasks').flush(mockTasks);
expect(service.loading()).toBe(false);
});
it('dovrebbe gestire errori HTTP e impostare error signal', () => {
service.loadTasks();
httpMock.expectOne('/api/tasks').flush(
{ message: 'Server Error' },
{ status: 500, statusText: 'Internal Server Error' }
);
expect(service.error()).toBe('Errore nel caricamento.');
expect(service.tasks()).toEqual([]);
expect(service.loading()).toBe(false);
});
});
describe('updateStatus()', () => {
beforeEach(() => {
// Pre-popola il service con task
service.loadTasks();
httpMock.expectOne('/api/tasks').flush(mockTasks);
});
it('dovrebbe fare optimistic update del signal immediatamente', () => {
service.updateStatus('1', 'done');
// Signal aggiornato prima della risposta HTTP
expect(service.tasks().find(t => t.id === '1')?.status).toBe('done');
httpMock.expectOne('/api/tasks/1').flush({...mockTasks[0], status: 'done'});
});
});
describe('Computed Signals', () => {
it('completedTasks dovrebbe filtrare solo i task con status done', () => {
service.loadTasks();
httpMock.expectOne('/api/tasks').flush(mockTasks);
expect(service.completedTasks()).toHaveLength(1);
expect(service.completedTasks()[0].id).toBe('2');
});
it('completionRate dovrebbe calcolare la percentuale corretta', () => {
service.loadTasks();
httpMock.expectOne('/api/tasks').flush(mockTasks);
expect(service.completionRate()).toBe(50);
});
});
});
Test E2E cu dramaturg
Pentru testarea end-to-end, Cursor excelează în a genera scenarii de dramaturg dintr-un singur descrierea în limbaj natural a fluxului de utilizator:
Solicitare: E2E Test Dramaturg
Genera test Playwright E2E per il flusso "Creazione e completamento di un Task".
Scenario:
1. L'utente apre la dashboard (/)
2. Clicca sul pulsante "Nuovo Task"
3. Compila il form: titolo "Test E2E Task", priorità "high", nessuna data scadenza
4. Clicca "Salva"
5. Verifica che il nuovo task appaia nella lista con status "todo"
6. Clicca sull'icona "segna come completato" sul task appena creato
7. Verifica che lo status diventi "done" e che il task appaia nella sezione completati
8. Verifica che completionRate mostri un valore > 0%
Usa page object pattern. Mock il backend con Playwright apiRoutes.
Aggiungi accessibility check con axe-core su ogni schermata.
// e2e/task-flow.spec.ts - Generato da Cursor
import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
test.describe('Task Creation and Completion Flow', () => {
test.beforeEach(async ({ page }) => {
// Mock API routes
await page.route('/api/tasks', async (route) => {
if (route.request().method() === 'GET') {
await route.fulfill({ json: [] });
} else if (route.request().method() === 'POST') {
const body = route.request().postDataJSON();
await route.fulfill({
json: { id: 'test-1', ...body, status: 'todo', createdAt: new Date().toISOString() }
});
}
});
await page.route('/api/tasks/test-1', async (route) => {
await route.fulfill({ json: { id: 'test-1', status: 'done' } });
});
});
test('dovrebbe creare un task e marcarlo come completato', async ({ page }) => {
await page.goto('/');
// Accessibility check sulla homepage
const a11yResults = await new AxeBuilder({ page }).analyze();
expect(a11yResults.violations).toEqual([]);
// Crea nuovo task
await page.click('[data-testid="new-task-btn"]');
await page.fill('[data-testid="task-title-input"]', 'Test E2E Task');
await page.selectOption('[data-testid="task-priority-select"]', 'high');
await page.click('[data-testid="task-form-submit"]');
// Verifica task in lista
const taskCard = page.locator('[data-testid="task-card-test-1"]');
await expect(taskCard).toBeVisible();
await expect(taskCard.locator('[data-testid="task-status"]')).toHaveText('todo');
// Completa il task
await taskCard.locator('[data-testid="complete-task-btn"]').click();
// Verifica aggiornamento status
await expect(taskCard.locator('[data-testid="task-status"]')).toHaveText('done');
const rate = page.locator('[data-testid="completion-rate"]');
await expect(rate).not.toHaveText('0%');
});
});
Faza 6 - Moștenirea modelului de refactorizare
Unul dintre cele mai frecvente cazuri de utilizare în echipe cu baze de cod existente și codul Angular care migrează
moștenire (cu NgModules, @Input()/@Output(),
*ngIf/*ngFor) la modele moderne. Cursorul excelează la asta
tip de refactorizare sistematică.
Solicitare: Migrare la Standalone și Signals
Esegui la migrazione del componente @legacy-user-profile.component.ts a:
1. Standalone component (rimuovi dal NgModule)
2. Sostituisci @Input() con input() signal
3. Sostituisci @Output() EventEmitter con output()
4. Converti il template da *ngIf/*ngFor a @if/@for
5. Aggiungi ChangeDetectionStrategy.OnPush
6. Se usa ngModel, converti a reactive form con FormControl tipizzato
7. Aggiorna lo spec file per riflettere i cambiamenti
Dopo ogni cambiamento spiega il ragionamento e i benefici di performance.
Refactorizarea cu modul Plan pentru migrații mari
Pentru migrarea la scară largă (module întregi sau aplicații), utilizați modul Plan înainte Modul agent. Acest lucru vă permite să revizuiți planul înainte ca Cursor să facă modificări ireversibil:
Solicitare: Modul de planificare pentru migrarea modulelor
[Attiva Plan Mode con Ctrl+Shift+P → "Plan Mode ON"]
Analizza il modulo UserModule (@src/app/modules/user/) e crea un piano dettagliato
per migrarlo a standalone components con signals. Il modulo ha:
- UserModule.ts (NgModule principale)
- 4 componenti: UserListComponent, UserCardComponent, UserDetailComponent, UserEditComponent
- 2 servizi: UserService, UserPreferencesService
- 1 guard: UserAuthGuard
Per ogni file:
1. Lista le modifiche necessarie
2. Identifica le dipendenze da aggiornare
3. Stima il rischio (Low/Medium/High) con motivazione
4. Suggerisci l'ordine di migrazione per minimizzare il rischio
NON apportare modifiche ancora - solo il piano.
Faza 7 - Optimizarea asistată a performanței
Performanța este un domeniu în care Cursorul poate face diferența, dar necesită acest lucru știe să pună întrebările potrivite. AI nu identifică automat toate problemele de performanță: trebuie să-l ghidați cu contextul specific asupra problemei pe care o rezolvați.
Analiza pachetului și împărțirea codului
Solicitare: analiza pachetului și încărcare leneră
Analizza @app.routes.ts e @app.config.ts. Ho eseguito "ng build --stats-json" e
il bundle principale e di 850KB (troppo grande).
Fai queste ottimizzazioni:
1. Converti tutte le route in lazy-loaded routes (usa loadComponent per standalone)
2. Aggiungi PreloadStrategy intelligente: PreloadAllModules per route principali,
nessun preload per route admin/settings raramente visitate
3. Identifica import heavy nel bundle principale da spostare nei chunk lazy
4. Aggiungi SplitChunksPlugin config personalizzata nel angular.json per
separare vendor chunks (rxjs, angular/core separati)
5. Configura budget nel angular.json: warning a 500KB, error a 1MB
// app.routes.ts - Ottimizzato da Cursor con lazy loading
import { Routes } from '@angular/router';
export const routes: Routes = [
{
path: '',
redirectTo: 'dashboard',
pathMatch: 'full'
},
{
path: 'dashboard',
loadComponent: () =>
import('./features/dashboard/dashboard.component').then(m => m.DashboardComponent),
title: 'Dashboard - Task Manager'
},
{
path: 'tasks',
loadChildren: () =>
import('./features/tasks/tasks.routes').then(m => m.TASKS_ROUTES),
title: 'Tasks - Task Manager'
},
{
path: 'settings',
loadComponent: () =>
import('./features/settings/settings.component').then(m => m.SettingsComponent),
// Non preloadare: accesso raro
data: { preload: false },
title: 'Impostazioni - Task Manager'
},
{
path: '**',
loadComponent: () =>
import('./shared/components/not-found/not-found.component').then(m => m.NotFoundComponent)
}
];
OnPush și semnale: Core Web Vitals
Cursorul vă poate ajuta să identificați componentele care cauzează redări inutile și a
convertiți-le în ChangeDetectionStrategy.OnPush:
Solicitare: Audit Detectare modificări
Analizza tutti i componenti in @src/app/features/tasks/ e identifica quelli che:
1. NON usano ChangeDetectionStrategy.OnPush (aggiungi OnPush a tutti)
2. Hanno @Input() che potrebbero diventare input() signals (converti)
3. Usano getters nel template che potrebbero causare re-render (converti a computed())
4. Usano async pipe su Observable (considera toSignal() per semplificare)
Per ogni modifica mostra il codice prima e dopo con spiegazione del beneficio.
Pasul 8 - Conducta CI/CD generată cu cursorul
Faza finală a fiecărui proiect profesional este automatizarea implementării. Cursorul poate generați pipeline GitHub Actions complete și optimizate, inclusiv strategii de stocare în cache, Testare paralelă și implementări condiționate pe ramuri.
Solicitare: Conducta de acțiuni GitHub finalizată
Crea una pipeline GitHub Actions completa per questo progetto Angular 19 con:
WORKFLOW CI (.github/workflows/ci.yml):
- Trigger: push su feature/*, pull_request verso main e develop
- Jobs paralleli: lint, unit-tests, build
- Cache node_modules con chiave basata su package-lock.json
- Unit test con Jest + coverage report (soglia minima: 80%)
- Upload coverage a Codecov
- Build production con --stats-json
- Comment sul PR con bundle size comparison vs base branch
WORKFLOW CD (.github/workflows/cd.yml):
- Trigger: push su main (dopo CI passata)
- Deploy staging su push develop
- Deploy production su push main con approval manuale
- Deploy su Firebase Hosting (usa secrets: FIREBASE_TOKEN)
- Smoke test post-deploy: verifica che / risponda 200 e che il bundle sia < 1MB
- Notifica Slack in caso di fallimento
Usa Node.js 22, npm ci per installazione deterministica.
# .github/workflows/ci.yml - Generato da Cursor
name: CI
on:
push:
branches: ['feature/**', 'fix/**']
pull_request:
branches: [main, develop]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- run: npm ci
- run: npm run lint
test:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- run: npm ci
- name: Run Jest with coverage
run: npm test -- --coverage --coverageThreshold='{"global":{"branches":80,"functions":80,"lines":80}}'
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
build:
name: Production Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- run: npm ci
- name: Build with stats
run: npm run build -- --stats-json
- name: Bundle size check
run: |
BUNDLE_SIZE=$(stat -c%s dist/browser/main.*.js)
echo "Bundle size: $BUNDLE_SIZE bytes"
if [ $BUNDLE_SIZE -gt 1048576 ]; then
echo "::error::Bundle size exceeds 1MB limit"
exit 1
fi
- uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
Studiu de caz: Caracteristici „Notificări în timp real” de la idee la implementare
Pentru a consolida tot ceea ce am văzut, să ne uităm la modul în care un dezvoltator profesionist completați întregul ciclu de viață al unei caracteristici folosind Cursor. Caracteristica: adăugați notificări în timp real când o sarcină este atribuită sau își schimbă starea.
Acest studiu de caz arată fluxul real, inclusiv atunci când AI-ul înțelege greșit și cum să o corectați, deoarece aceasta face parte din fluxul de lucru autentic.
Pasul 1 - Modul Plan: Arhitectura caracteristicilor
Modul Prompt Plan
[Plan Mode ON]
Voglio aggiungere notifiche in tempo reale usando WebSocket (Socket.io) per questi eventi:
- task_assigned: quando un task viene assegnato all'utente corrente
- task_status_changed: quando cambia lo stato di un task dell'utente
- task_due_soon: 24h prima della scadenza di un task
Crea un piano architetturale che includa:
1. WebSocket service (con gestione reconnect automatico)
2. NotificationCenter component (slide-in panel)
3. NotificationBadge component (icona navbar con counter)
4. Integration con TaskService esistente
5. Persistenza notifiche non lette in localStorage
6. Testing strategy
Considera: SSR (WebSocket non disponibile lato server),
performance (niente memory leak), accessibilità (screen reader per notifiche live).
Modul Plan produce un document structurat cu fiecare fișier care urmează să fie creat/modificat dependențe dintre ele și riscuri. După revizuire, trecem la execuție:
Pasul 2 - Modul agent: Implementare
// notification.service.ts - Generato dopo approvazione del piano
import { Injectable, inject, signal, computed, effect, OnDestroy } from '@angular/core';
import { PlatformService } from '../../../core/services/platform.service';
export interface Notification {
id: string;
type: 'task_assigned' | 'task_status_changed' | 'task_due_soon';
message: string;
taskId: string;
timestamp: Date;
read: boolean;
}
@Injectable({ providedIn: 'root' })
export class NotificationService implements OnDestroy {
private readonly platform = inject(PlatformService);
private socket: WebSocket | null = null;
private reconnectTimer: ReturnType<typeof setTimeout> | null = null;
private readonly _notifications = signal<Notification[]>([]);
readonly notifications = this._notifications.asReadonly();
readonly unreadCount = computed(() =>
this._notifications().filter(n => !n.read).length
);
readonly hasUnread = computed(() => this.unreadCount() > 0);
constructor() {
// Carica notifiche salvate da localStorage (solo browser)
if (this.platform.isBrowser) {
this._loadPersistedNotifications();
this._initWebSocket();
}
// Persisti automaticamente quando cambiano
effect(() => {
const notifications = this._notifications();
this.platform.setLocalStorage(
'notifications',
JSON.stringify(notifications.slice(0, 50)) // Mantieni max 50
);
});
}
markAsRead(notificationId: string): void {
this._notifications.update(current =>
current.map(n => n.id === notificationId ? { ...n, read: true } : n)
);
}
markAllAsRead(): void {
this._notifications.update(current =>
current.map(n => { ...n, read: true })
);
}
private _initWebSocket(): void {
this.socket = new WebSocket('wss://api.example.com/notifications');
this.socket.onmessage = (event) => {
const notification: Notification = {
...JSON.parse(event.data),
id: crypto.randomUUID(),
timestamp: new Date(),
read: false
};
this._notifications.update(current => [notification, ...current]);
};
this.socket.onclose = () => {
// Reconnect automatico con backoff esponenziale
this.reconnectTimer = setTimeout(() => this._initWebSocket(), 3000);
};
}
private _loadPersistedNotifications(): void {
const stored = this.platform.getLocalStorage('notifications');
if (stored) {
try {
this._notifications.set(JSON.parse(stored));
} catch {
// JSON malformato - ignora
}
}
}
ngOnDestroy(): void {
this.socket?.close();
if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
}
}
Pasul 3 - Cursorul Identificați o eroare: SSR și WebSocket
În timpul examinării, Cursor raportează o problemă potențială: crypto.randomUUID()
este posibil să nu fie disponibil în toate mediile SSR. Folosește chatul pentru a remedia problema:
Solicitare: Remediați eroarea SSR
Ho notato che crypto.randomUUID() potrebbe causare problemi in ambienti SSR o
browser molto vecchi. Nel NotificationService, sostituisci crypto.randomUUID()
con una funzione generaId() che:
1. Usa crypto.randomUUID() se disponibile
2. Fallback su una combinazione di Date.now() + Math.random() per compatibilità
Aggiungi un commento che spiega il perchè del fallback.
Pasul 4 - Testare și revizuire PR
Solicitare: Pregătiți PR și testați
La feature notifiche e completa. Aiutami a prepararla per la code review:
1. Genera test unit per NotificationService (includi test per:
- Caricamento notifiche persisted al bootstrap
- markAsRead() e markAllAsRead()
- Comportamento quando platform.isBrowser e false - verifica no WebSocket inizializzato)
2. Controlla il codice che abbiamo scritto per:
- Memory leak (WebSocket, timers non cleanup)
- Problemi di accessibilità nel NotificationCenter template
- Immutabilita (nessun array.push() o mutazione diretta)
- Typing TypeScript (nessun any)
3. Scrivi un CHANGELOG entry per questa feature
Rispondi solo se trovi problemi reali - non citare cose già corrette.
Sfaturi și trucuri pentru dezvoltatorii Angular
După luni de utilizare intensivă a Cursor cu Angular, iată cele mai eficiente modele pe care un dezvoltator profesionist ar trebui să le adopte din prima zi.
1. Folosiți @codebase pentru întrebări despre proiect
Înainte de a întreba „cum pot face X”, folosește @codebase pentru a-i face pe oameni să înțeleagă
Cursorează contextul proiectului tău. Diferența dintre răspunsuri este semnificativă:
Prompt Pattern: Context de bază de cod
// MENO EFFICACE
"Come aggiungo la paginazione ai task?"
// PIU EFFICACE
"@codebase Guardando TaskListComponent e TaskService,
come aggiungo la paginazione lato server (page + pageSize params sulla GET /api/tasks)
usando i pattern signals e il servizio HTTP già presenti nel progetto?"
2. Solicitarea „Revizuire și critică”.
Una dintre cele mai utile solicitări pe care le puteți oferi cursorului și cere o revizuire critică a codul pe care tocmai l-ați scris, specificând tipul de probleme pe care doriți să le găsiți:
Solicitare: Revizuirea codului specializat
Rivedi @task.service.ts come senior Angular developer con focus su:
- Performance: computed() non necessari, effect() che potrebbero causare loop,
signal updates che triggherano re-render inutili
- Memory: subscriptions non unsubscribed, timers non cleared,
reference circolari nei signals
- Sicurezza: XSS in template, injection nei parametri HTTP
- Best practices Angular 2025: c'è qualcosa di deprecato?
Dai SOLO feedback concreto con code snippet. Salta gli elogi.
3. Documentați cu cursorul, nu manual
Solicitare: Generați JSDoc și README
Per ogni metodo pubblico in @notification.service.ts aggiungi JSDoc con:
- @description: cosa fa il metodo
- @param: tipizzazione e scopo di ogni parametro
- @returns: cosa ritorna e in che condizioni
- @throws: se il metodo può sollevare errori e in quali condizioni
- @example: un esempio d'uso conciso
Poi genera un README.md per la feature notifications in
src/app/features/notifications/ che documenti il NotificationService
per un nuovo developer del team.
4. Agenți de fundal pentru sarcini lungi
Agenții de fundal Cursor 2.0 sunt ideali pentru sarcini care necesită mai mult timp, cum ar fi analizarea unei întregi baze de cod sau generarea de teste pentru zeci de componente. În timp ce agentul funcționează, puteți continua să dezvoltați în paralel:
Solicitare: Agent de fundal pentru acoperirea testului
[Background Agent]
Analizza tutti i componenti in src/app/features/ che hanno copertura test inferiore
all'80% (controlla i file .spec.ts esistenti o crea test dove mancano).
Per ogni componente con coverage insufficiente:
1. Identifica i casi non coperti (branch, funzioni pubbliche, casi di errore)
2. Scrivi i test mancanti
3. Verifica che npm test passi dopo ogni aggiunta
Lavora in ordine di priorità: prima i componenti con 0% coverage,
poi quelli sotto il 50%, poi quelli tra 50% e 80%.
Notificami quando hai finito con un riepilogo delle coperture raggiunte.
5. Cârlige cursor pentru calitate automată
Configurați cârligele cursorului pentru a efectua verificări automate la fiecare modificare a fișierului unghiular. Acest lucru elimină nevoia de a vă aminti să rulați scame și teste manual:
// .cursor/hooks/post-edit.sh
#!/bin/bash
# Eseguito automaticamente dopo ogni salvataggio di file Angular
CHANGED_FILE="$1"
# Lint solo il file modificato (veloce)
if [[ "$CHANGED_FILE" == *.ts ]]; then
npx eslint "$CHANGED_FILE" --fix
fi
# Type check incrementale
if [[ "$CHANGED_FILE" == *.ts ]]; then
npx tsc --noEmit --incremental 2>&1 | head -20
fi
Valori reale de productivitate
O întrebare legitimă este: „Cât timp economisesc cu adevărat cu Cursor?”. Bazat pe experiențele documentate ale echipelor care au adoptat Cursor pentru proiecte profesionale Angular, Iată câteva măsurători concrete:
Benchmark: proiect unghiular cu și fără cursor
| Activitate | Fără Cursor | Cu Cursor | Economii |
|---|---|---|---|
| Proiect Bootstrap (CLI + config Jest/ESLint/Prettier) | 45-60 min | 5-10 min | ~85% |
| Generare completă de caracteristici (model + serviciu + 4 componente + rutare) | 3-4 ore | 30-45 min | ~80% |
| Scrierea testelor unitare (acoperire 80%) | 2 ore pe serviciu | 20-30 min | ~75% |
| Migrarea componentei moștenite la semnale de sine stătătoare | 30-45 min | 5-10 min | ~80% |
| Configurați acțiuni CI/CD GitHub | 2-3 ore | 20-30 min | ~85% |
| Depanarea unui bug complex | 1-2 ore | 20-40 min | ~60% |
Este important de reținut că aceste numere reprezintă timpul de producerea codului, nu vremea gândirii arhitecturale. Cursorul accelerează scrierea mecanică a codului, lăsând mai mult timp pentru decizii la nivel înalt care necesită expertiză umană.
Când cursorul nu este suficient
Cursorul este un multiplicator de productivitate, nu un substitut al expertizei. Există situații în care AI își arată limitele în contextul Angular:
- Deciziile arhitecturale strategice: Cursorul poate propune opțiuni, dar alegerea strategiei corecte de management al statului (semnale vs NgRx vs Akita) Depinde de factori de afaceri pe care doar tu îi cunoști.
- Depanare avansată a performanței: Identificați o scurgere de memorie cauzată de la o închidere într-un efect () sau o redare ciclică între semnale necesită înțelegere adâncimea detectării schimbării Angular.
- Integrare cu biblioteci complexe: Cursorul cunoaște bine Angular, dar poate avea cunoștințe limitate despre biblioteci terțe foarte specifice sau actualizat recent.
- Revizuirea securității: Nu aveți încredere orbește în codul generat fără el o evaluare a siguranței. Cursorul poate introduce vulnerabilități subtile, mai ales în domenii precum managementul autentificării și igienizarea intrărilor.
Anti-modele de evitat cu cursorul și unghiular
Anti-Pattern 1: Acceptarea codului fără a citi
Cel mai mare risc în utilizarea Cursorului este de a deveni dependent de AI până la punctul de accepta codul generat fără a-l înțelege. Acest lucru duce la baze de cod inconsistente, erori greu de depanat și dezvoltatori care nu își înțeleg propriul cod.
Regula generală: Dacă nu poți explica unui coleg de ce codul generated face ceea ce face, nu-l accepta până nu înțelegi. Folosiți cursorul pentru a accelera, nu pentru a înlocui înțelegerea.
Anti-Pattern 2: Vagi sugestii privind problemele complexe
// PROMPT VAGO - risultato mediocre
"La lista task non si aggiorna dopo aver modificato uno status"
// PROMPT SPECIFICO - risultato accurato
"@task-list.component.ts @task.service.ts
Quando chiamo updateStatus() nel TaskService, il signal _tasks viene aggiornato
(ho verificato con un debugger che il valore cambia), ma TaskListComponent NON
mostra il cambiamento. Il componente usa OnPush. Ho verificato che l'input
[tasks] viene passato da un componente padre con async pipe.
Il problema potrebbe essere nella reference immutability?"
Anti-Pattern 3: Reguli opuse
Dacă aveți reguli care se contrazic între ele (de exemplu, o regulă spune „folosește semnale” și altul spune „utilizați BehaviorSubject pentru stare”), Cursorul produce cod inconsecvent. Faceți un audit periodic al regulilor dvs. pentru a elimina conflictele și a le actualiza depășit când migrați baza de cod.
Anti-Pattern 4: Ignorarea ferestrei de context
Cursorul are o limită de context. Dacă aveți o conversație foarte lungă, mesaje cei mai mari sunt „uitati”. Pentru sarcini complexe care durează ore, este mai bine să deschideți noi conversații tematice, mai degrabă decât a continua o sesiune nesfârșită. Salvați solicitările eficiente ca Amintirile cursorului pentru a le reutiliza.
Concluzii: Fluxul de lucru pentru dezvoltatori angular în 2026
Ajungem la sfârșitul acestui articol și a întregii serii despre Cursor IDE. Fluxul de lucru pe care le-am construit reprezintă stadiul artei dezvoltării profesionale Angular în 2026: o abordare AI nativ, dar controlat de dezvoltator, unde inteligența tehnologia artificială accelerează fiecare fază fără a înlocui judecata umană.
Pentru a rezuma fluxul de lucru complet:
- Configurarea regulilor: Investește timp în crearea unor reguli specifice pentru stiva ta. Acesta este cel mai mare multiplicator: fiecare regulă bine scrisă se îmbunătățește fiecare interacțiune viitoare cu AI.
- Modul Plan înainte de Modul Agent: pentru caracteristici complexe sau migrari, Întotdeauna planificați înainte de a executa. Un plan revizuit este mai rapid decât o implementare proastă.
- Modul agent pentru bootstrapping: Lasă AI să se ocupe de crearea structuri, componente și configurații. Timpul tău valorează prea mult pentru tărie.
- Testarea cu AI: Generați teste cu Cursor, revizuiți cazuri marginale, adăugați cazurile pe care AI nu le-a luat în considerare. Obțineți o acoperire de 80% într-un sfert din timp.
- Refactorizare asistată: Utilizați Cursorul pentru migrarea sistematică a modelelor modern (semnale, autonom, sintaxă nouă). Scalați la module întregi cu agenți de fundal.
- CI/CD generat: Nu scrie pipeline YAML manual. Descrieți cerințele și lăsați Cursorul să genereze configurații corecte și optimizate.
Dezvoltatorul care îmbrățișează acest flux de lucru nu devine mai puțin expert: el devine exponențial mai productiv. Expertiza rămâne fundamentală pentru evaluează codul generat, ia decizii arhitecturale și menține calitatea a proiectului. Cursorul nu este un nivelator: extinde capacitățile celor care sunt deja buni.
Cursor IDE și AI-Native Development Series Rezumat
| # | Articol | Focus principal |
|---|---|---|
| 1 | Cursor IDE: Ghid complet | Prezentare generală, instalare, caracteristici de bază |
| 2 | Regulile cursorului | Configurare AI pentru proiectul dvs |
| 3 | Modul agent | Schimbați baza de cod cu o comandă |
| 4 | Modul Plan și agenți de fundal | Planificare și paralelism |
| 5 | Cârlige pentru cursor | Automatizarea fluxului de lucru |
| 6 | MCP și Cursor | Conexiune la baze de date și API-uri |
| 7 | Depanare cu Cursor AI | Remedierea erorilor de 3 ori mai rapidă |
| 8 | Cursor vs Windsurf vs Copilot | Comparația instrumentelor în 2026 |
| 9 | Sunteți aici - Professional Angular Workflow | Studiu de caz complet de la configurare până la implementare |
Serii similare de explorat
- Angular modern (ID-urile 224-233): Aflați mai multe despre semnale, de sine stătătoare componente, SSR și cele mai recente caracteristici Angular cu ghidaje dedicate.
- MCP și cursor (ID-urile 64-77): Explorați modelul de protocol de context în detalii pentru a conecta Cursor la baze de date, API-uri și instrumente externe.
- Codare Vibe: Aflați cum folosesc dezvoltatorii AI pentru a crea prototipuri idei rapid, cu Claude Code, sisteme multi-agent și testarea codului AI.
Mulțumesc că urmărești toată seria. Dacă aveți întrebări, feedback sau doriți să împărtășiți fluxul de lucru Angular cu Cursor, scrieți în comentarii. Contribuția ta ajută îmbunătățiți aceste ghiduri pentru întreaga comunitate de dezvoltatori italieni.







