home / skills / gentleman-programming / gentleman-skills / architecture
This skill helps you structure Angular projects using the Scope Rule, project layout, and naming conventions to improve maintainability.
npx playbooks add skill gentleman-programming/gentleman-skills --skill architectureReview the files below or copy the command above to add this skill to your agents.
---
name: angular-architecture
description: >
Angular architecture: Scope Rule, project structure, file naming, style guide.
Trigger: When structuring Angular projects or deciding where to place components.
metadata:
author: gentleman-programming
version: "1.0"
---
## The Scope Rule (REQUIRED)
**"Scope determines structure"** - Where a component lives depends on its usage.
| Usage | Placement |
|-------|-----------|
| Used by 1 feature | `features/[feature]/components/` |
| Used by 2+ features | `features/shared/components/` |
### Example
```
features/
shopping-cart/
shopping-cart.ts # Main component = feature name
components/
cart-item.ts # Used ONLY by shopping-cart
cart-summary.ts # Used ONLY by shopping-cart
checkout/
checkout.ts
components/
payment-form.ts # Used ONLY by checkout
shared/
components/
button.ts # Used by shopping-cart AND checkout
modal.ts # Used by multiple features
```
---
## Project Structure
```
src/app/
features/
[feature-name]/
[feature-name].ts # Main component (same name as folder)
components/ # Feature-specific components
services/ # Feature-specific services
models/ # Feature-specific types
shared/ # ONLY for 2+ feature usage
components/
services/
pipes/
core/ # App-wide singletons
services/
interceptors/
guards/
app.ts
app.config.ts
routes.ts
main.ts
```
---
## File Naming (REQUIRED)
No `.component`, `.service`, `.model` suffixes. The folder tells you what it is.
```
✅ user-profile.ts
❌ user-profile.component.ts
✅ cart.ts
❌ cart.service.ts
✅ user.ts
❌ user.model.ts
```
---
## Style Guide
### What We Follow (from official docs)
- `inject()` over constructor injection
- `class` and `style` bindings over `ngClass`/`ngStyle`
- `protected` for template-only members
- `readonly` for inputs, outputs, queries
- Name handlers for action (`saveUser`) not event (`handleClick`)
- Keep lifecycle hooks simple - delegate to well-named methods
- One concept per file
```typescript
@Component({...})
export class UserProfileComponent {
// 1. Injected dependencies
private readonly userService = inject(UserService);
// 2. Inputs/Outputs
readonly userId = input.required<string>();
readonly userSaved = output<User>();
// 3. Internal state
private readonly _loading = signal(false);
readonly loading = this._loading.asReadonly();
// 4. Computed
protected readonly displayName = computed(() => ...);
// 5. Methods
save(): void { ... }
}
```
### What We Override
| Official Says | We Do | Why |
|---------------|-------|-----|
| `user-profile.component.ts` | `user-profile.ts` | Redundant - folder tells context |
| `user.service.ts` | `user.ts` | Same |
---
## Commands
```bash
# New project
ng new my-app --style=scss --ssr=false
# Component in feature
ng g c features/products/components/product-card --flat
# Service in feature
ng g s features/products/services/product --flat
# Guard in core
ng g g core/guards/auth --functional
```
---
## Resources
- https://angular.dev/style-guide
This skill codifies a pragmatic Angular architecture: scope-based placement, a clear project layout, concise file naming, and a focused style guide. It helps teams decide where components, services, and models belong and how to name and implement them. Use it to keep projects predictable, modular, and easy to navigate.
The skill inspects component usage and recommends placement based on the Scope Rule: if a component is used by a single feature, it belongs in that feature's components folder; if reused across two or more features, it moves to features/shared/components. It provides a canonical src/app project layout, enforces no-redundant suffixes in filenames, and offers style conventions for dependency injection, bindings, member visibility, and method naming.
Why remove .component and .service suffixes from filenames?
Suffixes are redundant because the folder structure communicates the role. Shorter names reduce noise and improve readability while preserving context via path.
When should I move something from a feature to shared?
Move an item to shared when two or more features consume it. If reuse grows, extract the item to features/shared to make dependencies explicit and avoid duplication.