From frontend-angular
Angular workspace structure including Angular CLI, Nx monorepos, feature module organization, shared/core conventions, lazy-loaded routes, library projects, environment config, and barrel exports.
How this skill is triggered — by the user, by Claude, or both
Slash command
/frontend-angular:angular-project-structureThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
A standard Angular CLI single-project workspace:
A standard Angular CLI single-project workspace:
my-app/
├── angular.json # workspace + project configuration
├── tsconfig.json # root TypeScript config
├── tsconfig.app.json # app-specific TS config
├── tsconfig.spec.json # test-specific TS config
├── jest.config.ts # Jest configuration
├── .frontend-agent.json # frontend agent config
├── src/
│ ├── main.ts # bootstrapApplication entry point
│ ├── styles.scss # global styles
│ ├── assets/ # static assets
│ ├── environments/ # environment configs (see below)
│ └── app/
│ ├── app.component.ts # root component
│ ├── app.routes.ts # top-level route config
│ ├── app.config.ts # ApplicationConfig (providers)
│ ├── core/ # singleton services, guards, interceptors
│ ├── shared/ # reusable components, directives, pipes
│ └── features/ # feature-specific code (lazy-loaded)
├── e2e/ # Playwright E2E tests
└── node_modules/
For large teams or multi-app organizations, use Nx:
my-workspace/
├── nx.json
├── angular.json (or project.json per app/lib)
├── tsconfig.base.json
├── apps/
│ ├── admin/ # Admin Angular app
│ │ ├── src/
│ │ └── project.json
│ └── customer-portal/ # Customer-facing Angular app
│ ├── src/
│ └── project.json
├── libs/
│ ├── shared/
│ │ ├── ui/ # Shared UI components
│ │ ├── data-access/ # Shared data services
│ │ └── util/ # Shared utilities
│ ├── admin/
│ │ ├── feature-dashboard/
│ │ └── feature-users/
│ └── customer/
│ ├── feature-catalog/
│ └── feature-checkout/
└── tools/
Use Nx generators to create apps and libraries, and Nx tags to enforce module boundaries:
// .eslintrc.json (nx boundary rules)
{
"rules": {
"@nx/enforce-module-boundaries": ["error", {
"depConstraints": [
{ "sourceTag": "scope:admin", "onlyDependOnLibsWithTags": ["scope:admin", "scope:shared"] },
{ "sourceTag": "scope:shared", "onlyDependOnLibsWithTags": ["scope:shared"] }
]
}]
}
}
Organize by feature (vertical slice), not by type (horizontal). Each feature is a self-contained directory.
src/app/features/
├── products/
│ ├── products.routes.ts # Feature route config (lazy-loaded)
│ ├── components/
│ │ ├── product-list/
│ │ │ ├── product-list.component.ts
│ │ │ ├── product-list.component.html
│ │ │ ├── product-list.component.scss
│ │ │ └── product-list.component.spec.ts
│ │ └── product-detail/
│ │ ├── product-detail.component.ts
│ │ └── ...
│ ├── services/
│ │ ├── product.service.ts
│ │ └── product.service.spec.ts
│ ├── state/ # NgRx or signal store (if needed)
│ │ ├── products.actions.ts
│ │ ├── products.reducer.ts
│ │ ├── products.effects.ts
│ │ └── products.selectors.ts
│ ├── models/
│ │ └── product.model.ts
│ └── index.ts # barrel export (public API)
├── users/
│ └── ...
└── checkout/
└── ...
// app.routes.ts
export const routes: Routes = [
{
path: 'products',
loadChildren: () =>
import('./features/products/products.routes').then(m => m.PRODUCTS_ROUTES),
},
{
path: 'users',
loadChildren: () =>
import('./features/users/users.routes').then(m => m.USERS_ROUTES),
},
];
// features/products/products.routes.ts
export const PRODUCTS_ROUTES: Routes = [
{ path: '', component: ProductListComponent },
{
path: ':id',
loadComponent: () =>
import('./components/product-detail/product-detail.component')
.then(m => m.ProductDetailComponent),
resolve: { product: productResolver },
},
];
The core/ directory holds app-wide singletons: services that should be provided once, guards, interceptors, and app-level resolvers.
src/app/core/
├── auth/
│ ├── auth.service.ts
│ ├── auth.guard.ts
│ └── auth.interceptor.ts
├── config/
│ └── app-config.service.ts
├── error/
│ └── error-handler.service.ts
├── layout/
│ ├── header/
│ │ └── header.component.ts
│ ├── sidebar/
│ │ └── sidebar.component.ts
│ └── footer/
│ └── footer.component.ts
└── index.ts
Services in core/ should use { providedIn: 'root' } or be provided once in app.config.ts.
The shared/ directory holds reusable, feature-agnostic components, directives, pipes, and utilities.
src/app/shared/
├── components/
│ ├── spinner/
│ │ └── spinner.component.ts
│ ├── empty-state/
│ │ └── empty-state.component.ts
│ └── confirmation-dialog/
│ └── confirmation-dialog.component.ts
├── directives/
│ ├── click-outside.directive.ts
│ └── auto-focus.directive.ts
├── pipes/
│ ├── truncate.pipe.ts
│ └── date-format.pipe.ts
├── utils/
│ ├── date.utils.ts
│ └── string.utils.ts
└── index.ts
Rules for shared/:
In multi-project workspaces, extract reusable code into Angular libraries.
# Generate a library with Angular CLI
ng generate library @my-org/shared-ui
# Or with Nx
nx generate @nx/angular:library shared-ui --directory=libs/shared/ui
Library structure:
libs/shared/ui/
├── src/
│ ├── lib/
│ │ ├── button/
│ │ │ └── button.component.ts
│ │ └── input/
│ │ └── input.component.ts
│ └── index.ts # public API barrel
├── package.json
├── ng-package.json # Angular Package Format config
└── tsconfig.lib.json
Consumers import from the library's public API only:
import { ButtonComponent } from '@my-org/shared-ui';
src/environments/
├── environment.ts # development defaults
└── environment.prod.ts # production overrides
// environment.ts
export const environment = {
production: false,
apiUrl: 'http://localhost:3000/api',
featureFlags: {
newCheckout: true,
},
};
Angular CLI replaces environment.ts with environment.prod.ts in production builds (configured in angular.json under fileReplacements).
Inject environments via a service rather than importing directly:
import { InjectionToken } from '@angular/core';
import { environment } from '../environments/environment';
export const ENVIRONMENT = new InjectionToken('ENVIRONMENT', {
providedIn: 'root',
factory: () => environment,
});
src/assets/
├── images/
├── icons/
├── fonts/
└── i18n/ # Translation files (if using ngx-translate or Angular i18n)
├── en.json
└── fr.json
Reference assets with absolute paths from src/:
<img src="assets/images/logo.svg" alt="Logo" />
Use barrel exports (index.ts) to define the public API of a feature or library. This decouples internal file organization from import paths.
// features/products/index.ts
export { ProductListComponent } from './components/product-list/product-list.component';
export { ProductDetailComponent } from './components/product-detail/product-detail.component';
export { ProductService } from './services/product.service';
export type { Product, CreateProductDto } from './models/product.model';
// Do NOT export internal implementation details
Barrel guidelines:
index.ts for libraries, shared/, and features (public API only)components/ or services/ sub-folders — this causes circular dependency risk{
"projects": {
"my-app": {
"architect": {
"build": {
"configurations": {
"production": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"budgets": [
{ "type": "initial", "maximumWarning": "500kB", "maximumError": "1MB" },
{ "type": "anyComponentStyle", "maximumWarning": "4kB" }
]
}
}
},
"test": {
"builder": "@angular-builders/jest:run"
}
}
}
}
}
Set bundle size budgets to catch regressions early. Tune thresholds per project.
To add a second app to the same workspace:
ng generate application admin-app
my-workspace/
├── angular.json # registers both projects
├── projects/
│ └── admin-app/ # second application
│ └── src/
└── src/ # default (first) app
Share code via a library rather than importing across app boundaries directly.
npx claudepluginhub gagandeepp/software-agent-teams --plugin frontend-angularGuides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Enforces test-driven development: write failing test first, then minimal code to pass. Use when implementing features or bugfixes.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.