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.2 | Framework (standalone components, signals) |
| PrimeNG | 21 | UI component library (custom preset on Aura) |
| Tailwind CSS | 3.4 | Utility-first styling |
| NGRX ComponentStore | 21 | State management |
| @jsverse/transloco | 7.6 | Internationalization (Italian + English) |
| TipTap | 2.27 | 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 areas (lazy-loaded)
│ ├── auth/ # Login, register, password reset, email confirmation, unsubscribe
│ ├── catalogo/ # Public catalog (list + detail)
│ ├── dashboard/ # Main authenticated app
│ │ ├── account/ # Profile, studio subscriptions, plan commerce
│ │ ├── home/ # Dashboard landing widgets
│ │ ├── orari/ # Scheduling (weekly grid)
│ │ ├── prenotazioni/ # Booking management + payments
│ │ ├── profile/
│ │ ├── side-bar/ # Legacy sidebar
│ │ ├── side-bar-v2/ # Current sidebar (+ SidebarStore)
│ │ ├── upgrade-plan/
│ │ ├── web-analytics/ # Site analytics dashboard
│ │ └── amministrazione/ # Admin panel
│ │ ├── gestione-utenti/ # Users (detail, preferences, billing)
│ │ ├── gestione-professionisti/ # Team/professionals
│ │ ├── gestione-servizi/ # Activities/services
│ │ ├── gestione-prenotazioni/ # Bookings admin
│ │ ├── gestione-fatturazione/ # Invoicing, payments, commerce orders
│ │ ├── gestione-blogs/ # Blog admin (native + legacy shell)
│ │ ├── gestione-comunicazione/ # Communication + automations
│ │ ├── gestione-newsletter/ # Newsletter
│ │ ├── gestione-galleria/ # Galleries / dynamic contents
│ │ ├── gestione-contatti/ # Contacts
│ │ ├── gestione-forms/ # Public forms
│ │ ├── business-analytics/ # Business analytics
│ │ ├── brand-kit/ # Brand identity + assets
│ │ ├── localizzazione/ # Site languages
│ │ ├── impostazioni/ # System settings (logs, webhooks, ...)
│ │ └── ... # access-permissions, website-states, ...
│ ├── home/ # Public pages (privacy policy, terms, footer)
│ └── immobili/ # Real-estate entities (list, detail, matching)
├── components/ # 54 shared components
├── directives/ # Custom directives
├── guards/ # Auth, role, feature flag, access policy guards
├── mixins/
├── pipes/ # Custom pipes (branding, formatting)
├── services/ # API clients, stores, utilities
├── testing/
└── utils/ # Helper utilities
Translation files live in src/assets/i18n/ (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
- Web manifest served at
/manifest.webmanifest - 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 initialization (
provideAppInitializer) - Language preference persisted in
localStorage(preferredLang) - 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.