| name | angular-single-app-architecture |
|---|---|
| description | Enforce a strict Angular application folder structure built around src/app core, layout, ui, feature, and pattern areas. Use when creating, moving, or refactoring Angular files under src/app, deciding where components, services, routes, guards, interceptors, pipes, or models belong, or checking that imports follow the intended boundaries. |
Use this skill to keep an Angular application aligned with a strict standalone-first project structure focused on src/app.
Keep application code organized around these architecture areas:
src/app/coresrc/app/layoutsrc/app/uisrc/app/featuresrc/app/pattern
Treat the architecture as standalone-first. Do not fall back to SharedModule-style placement rules.
Before generating or editing files:
- Identify the artifact type and responsibility.
- Classify it using references/folder-map.md.
- Verify whether it belongs to the eager app shell or a lazy feature.
- Place the file in the narrowest valid folder, not in a catch-all bucket.
- Check intended imports against references/dependency-boundaries.md.
- Only then scaffold, move, or refactor files.
After changes:
- Confirm the file still lives in the correct architecture area.
- Confirm no
sharedcatch-all structure or ad hoc top-level folder was introduced. - Confirm imports still respect the allowed dependency direction.
core: app-wide singleton logic and cross-cutting infrastructure needed from startup.layout: app shell structure, page chrome, navigation, and layout composition.ui: generic reusable UI building blocks, directives, pipes, and helper view types.feature/<name>: route-oriented lazy feature implementation for a specific use case.pattern/<name>: reusable drop-in business patterns or non-routed data-bound building blocks shared by features.
Use ui instead of a generic shared folder for reusable presentation pieces.
Use pattern instead of shared feature for reusable, business-aware drop-in functionality.
- Put app-wide
providedIn: 'root'services, interceptors, guards, tokens, and startup logic incore. - Keep layout components free of direct feature imports.
- Keep generic presentational components in
ui, notfeature. - Keep route configs inside the owning feature folder as
*.routes.ts. - Treat lazy features as isolated black boxes. Share logic by extracting it one level up into
pattern,ui, orcore, depending on responsibility. - If a feature becomes reusable via sub-routing from multiple features, keep it as a feature and integrate it through routing instead of collapsing it into a generic shared folder.
- Root app routing belongs in app-level files such as
app.routes.ts. - Feature routes live in
src/app/feature/<feature-name>/<feature-name>.routes.tsor equivalent*.routes.tsfiles in that feature folder. - Prefer lazy feature entrypoints loaded with
loadChildren. - Keep feature-local components and services inside the owning feature folder.
coremay depend on itself and external libraries, but not onlayout,ui,pattern, orfeature.uimay depend on itself and external libraries, but not onfeature,pattern, orlayout.layoutmay depend oncore,ui, andpattern, but not onfeature.patternmay depend oncore,ui, and otherpatterncode.featuremay depend oncore,ui, andpattern.featurecode should not import other feature implementation files directly. Cross-feature reuse should happen through routing,pattern,ui, orcore.
- If the repo uses
eslint-plugin-boundaries, map folders to architecture types using the reference rules in references/dependency-boundaries.md. - If a new folder category is introduced, extend the boundaries configuration instead of bypassing it.
- If testing or tooling files fall outside the architecture types, either define a dedicated type or add a narrow ignore rule.