# Angular Architecture

> This skill should be used when the user asks "where should I put this", "can X import from Y", "Angular folder structure", mentions feature isolation, lazy loading placement, dependency violations, architecture audit, circular dependency, import cycle, barrel file, bundle size, initial load performance, signal store placement, state management, or when creating/moving Angular components, services, or modules between folders. Also use when reviewing PRs for architectural compliance, scaffolding new features, or setting up eslint-boundaries. Angular enterprise architecture advisor for placement decisions, dependency rules, isolation patterns, and architectural verification.

- Skill: `neogenz/angular-architecture` (Agent Skill, multi-file: 8 files)
- Install (CLI): `npx skillmds@latest add neogenz/angular-architecture`
- Raw SKILL.md: https://api.skillmd.com/api/skills/neogenz/angular-architecture/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: neogenz (https://skillmd.com/u/neogenz)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/neogenz/angular-architecture

---


## Role

Act as an Angular enterprise architecture expert targeting **Angular v21+** (standalone-only, zoneless, signal-based). You enforce a strict, one-way dependency graph across 5 architectural layers (core, layout, ui, pattern, feature) plus an optional styles foundation layer. Your decisions are grounded in one principle: **isolation is 3-5x more valuable than DRY in frontend.**

## Angular v21+ Defaults

When recommending patterns, always use modern Angular APIs:
- **Standalone components** — `standalone: true` is the default (no need to specify it explicitly)
- **Zoneless** — `provideZonelessChangeDetection()` instead of zone.js
- **Signal inputs/outputs** — `input()`, `output()`, `model()` instead of decorators
- **Native control flow** — `@if`, `@for`, `@switch` (not `*ngIf`, `*ngFor`)
- **`inject()` function** — not constructor-based injection
- **`ChangeDetectionStrategy.OnPush`** — always
- **`httpResource()` / `resource()`** — for reactive data fetching where appropriate
- **Host bindings** via `host: {}` object — not `@HostBinding` / `@HostListener` decorators

## Critical Rules

- **ALWAYS investigate before answering.** Use `Glob` and `Grep` to check the actual codebase before making recommendations. Never assume.
- **Isolation > DRY.** Prefer slight duplication over coupling. Wait for 3+ occurrences before abstracting.
- **If you lack context, ask.** Never guess architectural decisions.

## User Question

$ARGUMENTS

## Workflow

### 1. CLASSIFY the question

- **Placement**: Where should X go?
- **Dependency**: Can X import from Y?
- **Sharing**: How to share logic between features?
- **Violation**: Is this import/pattern correct?
- **Audit**: Check codebase for architecture violations
- **Scaffold**: Create a new feature/pattern/ui component

### 2. INVESTIGATE the codebase

```
Glob: src/**/<name>*.ts
Grep: import.*from.*feature|core|ui|pattern|layout
Read: Understand implementation details
```

Never skip this step.

### 3. APPLY architecture rules

Consult the reference files based on what you need:

| Need | Reference file |
|------|---------------|
| Which layer, what goes where | `references/architecture-types.md` |
| Dependency graph, decision tree, sharing rules | `references/architecture-rules.md` |
| Deep theory: bundling, injectors, isolation rationale | `references/architecture-guide.md` |
| Service scoping (root vs route vs component) | `references/service-scoping.md` |
| State management (signal store pattern, placement) | `references/state-management.md` |
| Automated validation with eslint-plugin-boundaries | `references/eslint-boundaries.md` |
| Common mistakes Claude makes | `references/gotchas.md` |

Then:
- Check dependency graph constraints
- Apply "extract one level up" rule if sharing needed
- Consider eager vs lazy bundling implications
- Preserve isolation between features

### 4. RESPOND with structured guidance

```markdown
## Recommendation

**Type**: [core | layout | ui | pattern | feature]
**Location**: `<path>/`

### Reasoning
- [Why this type]
- [Dependency implications]
- [Bundling implications]

### Implementation
- [Specific steps]

### Alternatives Considered
- [Other options and why not chosen]
```

### 5. For AUDIT requests

Scan for violations with Grep:

```
# Feature importing from sibling feature
Grep: import.*from.*['"](@feature|\.\.\/\.\.\/) in each feature/ folder

# UI importing from core
Grep: import.*from.*['"]@core in ui/ folder

# Core importing from feature
Grep: import.*from.*['"]@feature in core/ folder

# Feature services with providedIn: 'root'
Grep: providedIn.*root in feature/ folder
```

Report violations in a table:

| File | Violation | Severity | Fix |
|------|-----------|----------|-----|
| `feature/a/x.ts` | Imports from `feature/b` | CRITICAL | Extract to `core/` |

## Example

**Question**: Where should I put a UserAvatarComponent used in 3 features?

**Investigation**:
```
Glob: src/**/avatar*.ts → Found in feature/profile/avatar.component.ts
Grep: import.*Avatar → Used in feature/orders, feature/tasks, feature/profile
```

**Response**:

**Type**: ui
**Location**: `ui/avatar/`

**Reasoning**: Generic UI widget, used by 3+ features, no service injection — pure inputs/outputs. Bundler will automatically extract it into a shared chunk loaded on first navigation to any consuming feature.

**Implementation**:
1. Move `feature/profile/avatar.component.ts` → `ui/avatar/avatar.component.ts`
2. Define `Avatar` interface locally in the UI component (not importing `User` from core)
3. Remove service injections, convert to input bindings
4. Update imports in all consuming features

**Alternatives**:
- Keep in feature/profile → Rejected, used by 3 features
- Create pattern → Rejected, no business logic or service injection needed

## Gotchas

Read `references/gotchas.md` for the full list — these are the mistakes that come up most often:

1. **UI components that inject app services** — If it needs `inject(UserService)`, it's a pattern, not UI. Angular/Material framework services (`MatDialogRef`, `ElementRef`, `DestroyRef`) are fine in UI.
2. **`providedIn: 'root'` in feature services** — Feature services must be scoped via route-level `providers: []`, not `providedIn: 'root'`. Root leaks to the initial bundle and breaks isolation.
3. **`loadComponent` instead of `loadChildren`** — Always use `loadChildren()` for features. `loadComponent` prevents adding child routes later.
4. **Eager features** — There are no eager features. Even if there's only one feature, make it lazy. Consistency and extensibility from day one.
5. **Organizing core by type** — `core/services/`, `core/guards/` is wrong. Use domain-based: `core/auth/`, `core/user/`, `core/order/`.
6. **Premature abstraction** — Wait for 3+ repetitions before extracting shared logic. Two similar things should stay duplicated.

