Frontend Overview
The Flo frontend is an Angular 21 SPA using standalone components, signals, OnPush change detection, and PrimeNG for UI.
Tech Stack
| Technology | Version | Purpose |
|---|---|---|
| Angular | 21 | Framework (standalone components, signals) |
| PrimeNG | 21 | UI component library (Lara theme) |
| Tailwind CSS | 3.4 | Utility-first styling |
| NGRX ComponentStore | 21 | State management |
| Transloco | 7.6 | Internationalization (Italian + English) |
| TipTap | 2.24 | Rich text editor (WYSIWYG) |
| Leaflet | 1.9 | Interactive maps |
| Chart.js | 4.5 | Data visualization |
| GSAP | 3.13 | Animations (sidebar, mobile tab bar) |
| Vite | via @angular/build | Build tool |
App Structure
src/app/
├── features/ # Feature modules (lazy-loaded)
│ ├── auth/ # Login, register, OTP, password reset
│ ├── dashboard/ # Main authenticated app
│ │ ├── prenotazioni/ # Booking management
│ │ ├── orari/ # Scheduling
│ │ ├── account/ # User profile & settings
│ │ └── amministrazione/ # Admin panel
│ │ ├── utenti/ # User management
│ │ ├── professionisti/ # Staff management
│ │ ├── servizi/ # Service/activity management
│ │ ├── locazioni/ # Locations
│ │ ├── chiusure/ # Studio closures
│ │ ├── blogs/ # Blog management (Strapi)
│ │ ├── newsletter/ # Newsletter management
│ │ ├── gallery/ # Media gallery
│ │ └── settings/ # App settings (SuperAdmin)
│ ├── immobili/ # Dynamic entity management
│ └── home/ # Privacy policy, terms
├── components/ # 33 shared components
├── services/ # API clients, stores, utilities
├── guards/ # Auth, role, feature flag guards
├── pipes/ # Custom pipes (branding, formatting)
├── directives/ # Custom directives
├── utils/ # Helper utilities
└── assets/i18n/ # Translation files (it.json, en.json)
Key Patterns
Standalone Components
All components are standalone (no NgModules):
@Component({
selector: 'app-feature',
standalone: true,
imports: [CommonModule, TranslocoModule, ButtonModule],
changeDetection: ChangeDetectionStrategy.OnPush
})
Signal-Based Reactivity
// Local component state
protected readonly loading = signal(false);
protected readonly searchTerm = signal('');
// Derived state
protected readonly hasFilters = computed(() => this.searchTerm().length > 0);
Thin Components
All business logic lives in stores/services. Components only handle:
- Template bindings
- UI event delegation to stores
- Local UI state (signals)
Dependency Injection
Use inject() function, never constructor injection:
private readonly store = inject(GlobalStore);
private readonly messageService = inject(MessageService);
Template Control Flow
Use new Angular control flow syntax:
@if (loading()) {
<p-progressSpinner />
} @else {
@for (item of items(); track item.id) {
<app-item [data]="item" />
}
}
Icons
Material Symbols only. PrimeIcons are forbidden:
<!-- Correct -->
<span class="material-symbols-outlined">add</span>
<!-- Forbidden -->
<i class="pi pi-plus"></i>
API Clients
Auto-generated from backend OpenAPI spec using NSwag:
npm run generate-proxies
Produces:
src/app/services/client.ts— Private API clientsrc/app/services/public-api-client.ts— Public API client
PWA
- Service worker enabled in production builds
- Separate manifests per brand
- Auto-update checks every 6 hours
- Install prompts via
@khmyznikov/pwa-install
Internationalization
Uses @jsverse/transloco with Italian as default:
- Translations pre-loaded during
APP_INITIALIZER - Language preference persisted in
localStorage - PrimeNG component translations updated on language change
- CI check validates both translation files have matching keys
All user-facing text must use the Transloco pipe:
{{ 'feature.title' | transloco }}
Translations must be added to both it.json and en.json.