Skip to main content

Frontend Overview

The Flo frontend is an Angular 21 SPA using standalone components, signals, OnPush change detection, and PrimeNG for UI.

Tech Stack​

TechnologyVersionPurpose
Angular21.2Framework (standalone components, signals)
PrimeNG21UI component library (custom preset on Aura)
Tailwind CSS3.4Utility-first styling
NGRX ComponentStore21State management
@jsverse/transloco7.6Internationalization (Italian + English)
TipTap2.27Rich text editor (WYSIWYG)
Leaflet1.9Interactive maps
Chart.js4.5Data visualization
GSAP3.13Animations (sidebar, mobile tab bar)
Vitevia @angular/buildBuild 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 client
  • src/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.