Architecture
Stack
- Angular 20, standalone components (no NgModules).
- Signals for state.
- SCSS for styling — no Tailwind.
- FontAwesome via
@fortawesome/angular-fontawesome. @ngx-translatefor i18n.- Built with the
@angular/build:applicationbuilder; Bun as package manager.
Layout
Application source lives under src/app/:
app.ts,app.config.ts,app.routes.ts— root component, providers, routing.app.config.server.ts,app.routes.server.ts— server-side rendering config.components/— reusable UI pieces (hero,features,faq,screenshots,download,navigation,footer,legal,language-switcher,theme-toggle).pages/— routed views (home,not-found).services/— singleton services (language,theme).
Angular 20 coding conventions
These conventions are enforced for all contributions.
Components
- Standalone components only. Do not set
standalone: truein decorators — it is the default. - Use
input()/output()functions instead of@Input()/@Output()decorators. - Set
changeDetection: ChangeDetectionStrategy.OnPush. - Keep components small and single-responsibility; prefer inline templates for small ones.
- Prefer Reactive forms over template-driven forms.
- Put host bindings in the
hostobject of the decorator — do not use@HostBinding/@HostListener. - Use
classandstylebindings — notngClass/ngStyle. - Use
NgOptimizedImagefor static images (note: it does not work for inline base64 images). - Implement lazy loading for feature routes.
State
- Use signals for local component state and
computed()for derived state. - Do not use
mutateon signals — useupdateorset. - Keep state transformations pure and predictable.
Templates
- Use native control flow (
@if,@for,@switch) — not*ngIf/*ngFor/*ngSwitch. - Use the
asyncpipe for observables. Keep templates free of complex logic.
Services
- Single responsibility;
providedIn: 'root'for singletons. - Use the
inject()function instead of constructor injection.
TypeScript
- Strict type checking. Prefer type inference when obvious.
- Avoid
any; useunknownwhen the type is uncertain.