Applies modern Angular fundamentals — dependency injection, the typed-configuration (provide) pattern, environment/runtime configuration, and modern TypeScript/Angular idioms. Use when registering providers in any Angular app or library, defining InjectionToken-based configuration, choosing a provider scope, setting up environments and runtime config, or applying standalone APIs, signals, inject(), strict null checks, and DestroyRef-based teardown.
Installation
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Applies modern Angular fundamentals — dependency injection, the typed-configuration (provide) pattern, environment/runtime configuration, and modern TypeScript/Angular idioms. Use when registering providers in any Angular app or library, defining InjectionToken-based configuration, choosing a provider scope, setting up environments and runtime config, or applying standalone APIs, signals, inject(), strict null checks, and DestroyRef-based teardown.
Modern Angular Fundamentals
When to Use
Working with Angular/TypeScript code
Registering providers (providedIn, providers: [...], provideXxx()) in any app, route, or component injector
Choosing a provider scope (root singleton, route/lazy scope, component instance)
Defining InjectionToken-based configuration and provideXxx(config) library APIs
Setting up environment.ts files, build-time file replacement, or runtime config loaded at bootstrap
Adopting standalone components, inject(), signals, strict null checks, or DestroyRef/takeUntilDestroyed teardown in new code
Core Principles
This skill is agnostic across Angular surfaces — standalone apps, libraries, and lazy-loaded routes all sit on these fundamentals. angular-components and angular-state build on top of them.
Token-first registration — depend on an abstraction (an abstract class or InjectionToken<T>), not a concrete class, when the implementation should be substitutable for testing or decoration. TypeScript interfaces don't exist at runtime, so they cannot be DI tokens — use an abstract class or InjectionToken.
No service locator — never inject Injector to resolve dependencies manually in business logic. Use inject() (or constructor injection) for the dependencies you actually need.
Typed config over scattered lookups — model configuration as a typed object provided via an InjectionToken and a provideXxx(config) function; do not read loose string keys all over the app.
Fail fast — validate required configuration at bootstrap (via provideAppInitializer / APP_INITIALIZER) so misconfiguration surfaces at startup, not at first use.
Immutable configuration — config objects use readonly members and are not mutated after provisioning.
Teardown flows everywhere — long-lived subscriptions and async work are torn down with takeUntilDestroyed() / DestroyRef (Angular's analogue to threading a CancellationToken), and HTTP cancellation happens by unsubscribing.
Signal-first APIs — author component surfaces with input()/output()/model() and signal queries (viewChild()/contentChild()), not decorators. Mark Angular-initialized members (input, model, output, queries) readonly so the framework-assigned value cannot be overwritten.
typed-configuration.md — typed configuration objects, provideXxx(config) library APIs, validation at bootstrap, environment- vs runtime-loaded config
configuration.md — environment.ts files, build-time fileReplacements, runtime config from assets/config.json, and why front-end apps have no real secrets