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 architecture

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
3.2 KB
---
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

Overview

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.

How this skill works

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.

When to use it

  • When starting a new Angular project or defining repository layout.
  • When deciding where to place a new component, service, pipe, or model.
  • When reviewing code to reduce duplication and improve reuse boundaries.
  • When establishing team-wide Angular style rules.
  • When generating files with schematics or CLI and mapping them to feature folders.

Best practices

  • Apply the Scope Rule consistently: feature-only items live under features/[feature]/components, cross-feature items go to features/shared/.
  • Name files without technical suffixes — the folder signals the role (e.g., user-profile.ts, cart.ts, user.ts).
  • Keep one concept per file and a single main file per feature named to match the folder (feature/feature.ts).
  • Prefer inject() for dependencies, use class/style bindings, mark template-only members protected, and use readonly for inputs/outputs/queries.
  • Keep lifecycle hooks thin; delegate to well-named methods and keep internal state encapsulated with private signals and readonly accessors.

Example use cases

  • Creating a product card used only by the products feature: features/products/components/product-card.ts.
  • Building a button used across checkout and shopping-cart: features/shared/components/button.ts.
  • Adding a feature-specific service: features/orders/services/order.ts (no .service suffix).
  • Setting up core singletons like an auth guard in core/guards/auth.ts.
  • Generating files with CLI and mapping them to feature or core folders using the provided commands.

FAQ

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.