Project: [Your App Name]
[One-paragraph description of what your application does.]
Tech Stack
- Angular [version] (standalone components, signals)
- TypeScript 5.x (strict mode)
- [UI library: Angular Material / PrimeNG / Tailwind CSS + DaisyUI / etc.]
- RxJS 7.x (HTTP only; prefer signals for state)
- [State management: signals / NgRx Store / NgRx SignalStore / etc.]
- [Backend: REST API at /api, GraphQL, etc.]
- [Testing: Jest / Vitest / Karma+Jasmine]
- [Build system: Angular CLI / Nx]
Commands
For Angular CLI projects:
bash
ng serve # Dev server at http://localhost:4200
ng build # Production build
ng test # Run unit tests
ng test --watch=false # Run unit tests once (CI)
ng lint # Lint with ESLint
ng e2e # End-to-end testsFor Nx monorepo projects:
bash
nx serve <app-name> # Dev server
nx build <app-name> # Production build
nx test <app-name> # Run unit tests for an app
nx test <lib-name> # Run unit tests for a library
nx lint <project-name> # Lint a specific project
nx run-many -t test # Run tests across all projects
nx run-many -t lint # Lint all projects
nx affected -t test # Run tests only for affected projectsProject Structure
Option A: Standard Angular CLI project
src/app/
core/ # Singleton services, guards, interceptors (app-wide)
shared/ # Reusable components, directives, pipes
features/ # Feature modules (lazy-loaded route groups)
feature-name/
components/
pages/ # Container (smart) components
views/ # Presentational (dumb) components
services/ # Feature-specific services
models/ # Interfaces and types
feature.routes.ts
app.component.ts
app.routes.ts
app.config.tsOption B: Nx monorepo project
apps/
<app-name>/
src/app/
components/
pages/ # Container (smart) components
views/ # Presentational (dumb) components
config/ # App-level configuration and constants
types/ # App-level types
app.component.ts
app.routes.ts
app.config.ts
libs/ui/
component-library/ # Reusable UI components (buttons, inputs, cards)
data-access/ # State management, API clients, HTTP services
src/lib/
api/ # REST API service layer
clients/ # HTTP and WebSocket clients
state/ # NgRx feature slices (actions, reducers, selectors, effects)
config/ # State configuration providers
shared-ui/ # Shared services, guards, directives, pipes
src/
components/ # Shared components
directives/ # Custom directives
guards/ # Route guards
services/ # Shared services (navigation, theme, dialogs)
pipes/ # Custom pipes
types/ # Shared types
features/ # Feature libraries (lazy-loaded)
feature-name/
src/lib/
components/
pages/ # Container components
views/ # Presentational components
feature.routes.tsAngular Conventions
Components
- All components are standalone (
standalone: true). Do NOT use NgModules. - Always use
ChangeDetectionStrategy.OnPush. - Use
input()andoutput()functions, not@Input()/@Output()decorators. - Use
computed()for derived state. - Use inline templates for components under ~30 lines of HTML; external files otherwise.
- Component selector prefix:
[prefix]-(e.g.,app-user-listorngx-app-user-list). - Distinguish between pages (container/smart components that manage state and routing) and views (presentational/dumb components that receive data via inputs and emit via outputs).
Templates
- Use
@if,@for,@switchcontrol flow. Do NOT use*ngIf,*ngFor,[ngSwitch]. - Always include
trackexpression in@forblocks. - Prefer
classandstylebindings overngClass/ngStyle. - No arrow functions or complex logic in templates.
- Use the
asyncpipe for observables that are not converted to signals.
State and Reactivity
Option A: Signal-based state (for simpler apps or per-component state)
- Use signals (
signal(),computed(),effect()) for component and service state. - Use
set()orupdate()to modify signals. Never usemutate(). - Keep signals private (
private readonly _state = signal(...)) with public readonly selectors. - Use RxJS for HTTP calls and event streams; convert to signals at service boundaries where appropriate.
Option B: NgRx Store (for complex apps with shared state)
- Use
createActionGroup()to define feature actions with typed events. - Use
createReducer()withon()handlers for immutable state transitions. - Use
createFeatureSelector()andcreateSelector()for memoized state selection. - Use injectable effects with
ActionsandcreateEffect()for side effects. - Use
EntityAdapterfor normalized collection state. - Dispatch
NotificationsActions(or equivalent) for user-facing error handling in effects. - Register state with
provideState()andprovideEffects()in app configuration.
Services
- Use
providedIn: 'root'for app-wide services. - Use
inject()function for dependency injection. Do NOT use constructor parameter injection. - One service per file, one responsibility per service.
Routing
- Use
loadComponentfor single-component routes andloadChildrenfor feature route groups. - Each feature folder has its own
*.routes.tsfile. - Use functional route guards (not class-based).
Forms
- Use reactive forms exclusively (
FormBuilder,FormGroup,FormControl). - Use
fb.nonNullable.group({...})for type-safe form creation. - Do NOT use template-driven forms.
HTTP
- Use functional interceptors (
HttpInterceptorFn). - Configure with
provideHttpClient(withInterceptors([...]))inapp.config.ts.
Images
- Use
NgOptimizedImagefor static images (not for base64 inline).
Styling
- Use Tailwind CSS utility classes for styling. Avoid writing custom CSS when utility classes suffice.
- Use DaisyUI component classes (e.g.,
btn,card,badge) for consistent design tokens. - Keep component-specific styles minimal; prefer utility composition.
Testing
- Place test files next to source files (
component.spec.tsalongsidecomponent.ts). - Use
TestBed.configureTestingModulewith standalone component imports. - Mock services with
jest.fn()/jest.spyOn()(Jest) orjasmine.createSpyObj(Jasmine). - Test signal state transitions (initial -> loading -> loaded/error).
- For NgRx: test reducers as pure functions, test selectors with mock state, test effects with
provideMockActions.
TypeScript Conventions
- Strict mode enabled (
strict: trueintsconfig.json). - Use
unknowninstead ofanyfor ambiguous types. - Rely on type inference when types are self-evident.
- Use
interfacefor data models, notclass. - Export types and interfaces from a
models/ortypes/folder within each feature.
Nx Conventions
- Respect module boundary constraints defined in ESLint (
@nx/enforce-module-boundaries). - Libraries use scope tags (e.g.,
scope:feature,scope:data-access,scope:component-lib) to enforce dependency rules. - Do not import directly from library
src/internals; use the public API (index.tsbarrel exports). - Use
nx affectedcommands for CI to only test/build what changed.
Domain Context
Do NOT
- Do not create NgModules.
- Do not use
*ngIf,*ngFor, or[ngSwitch]. - Do not use
@Input()/@Output()/@HostBinding()/@HostListener()decorators. - Do not use constructor injection.
- Do not use
anytype. - Do not use template-driven forms.
- Do not add comments unless the logic is non-obvious.
- Do not create abstractions for one-time operations.
- Do not use
trackBywith*ngFor(usetrackin@forblocks instead). - Do not import from library internal paths; use barrel exports.