Skillshub angular-architecture
install
source · Clone the upstream repo
git clone https://github.com/ComeOnOliver/skillshub
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/Gentleman-Programming/Gentleman-Skills/architecture" ~/.claude/skills/comeonoliver-skillshub-angular-architecture && rm -rf "$T"
manifest:
skills/Gentleman-Programming/Gentleman-Skills/architecture/SKILL.mdsource content
The Scope Rule (REQUIRED)
"Scope determines structure" - Where a component lives depends on its usage.
| Usage | Placement |
|---|---|
| Used by 1 feature | |
| Used by 2+ features | |
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)
over constructor injectioninject()
andclass
bindings overstyle
/ngClassngStyle
for template-only membersprotected
for inputs, outputs, queriesreadonly- Name handlers for action (
) not event (saveUser
)handleClick - Keep lifecycle hooks simple - delegate to well-named methods
- One concept per file
@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 |
|---|---|---|
| | Redundant - folder tells context |
| | Same |
Commands
# 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