Front-end Domain Map¶
Apps¶
front-mobile-app: App investisseur principale (Expo/React Native). iOS + Android + Webapp-pdp-financement: App porteur de projet (espace financement). Même stack, scope plus réduitstorybook: Storybook pour uimmo et composants partagés
Modules¶
| Module | Scope |
|---|---|
auth |
Login, signup, 2FA, auth social, reset password, invitation (token URL) |
home |
Dashboard, propriétés mises en avant, actions rapides, revenus |
project |
Détail d'un bien : overview, documents, news, charts, community |
projects |
Liste des biens, filtres, recherche, projets financés |
wallet |
Solde, top-up, retrait, historique transactions |
boostedBalance |
Fonctionnalité solde boosté (gift balance) |
onboarding |
KYC Lemonway, setup profil investisseur |
Structure standard d'un module — s'inspirer de projects/front-mobile-app/src/modules/project/ comme référence :
modules/{feature}/
screens/{Feature}Screen/
{Feature}Screen.tsx → Screen (compose les composants du module)
index.ts
components/{ComponentName}/
{ComponentName}.tsx → Smart (data fetching, hooks, logique)
{ComponentName}UI.tsx → Dumb (props only, présentation)
{ComponentName}Loading.tsx → Skeleton
{ComponentName}UI.stories.tsx
index.ts
services/
queryKeys.ts → Query keys scopées au module
use{DataHook}.ts → Hooks React Query
hooks/ → Hooks custom du module
store/ → Zustand stores locaux
types/
utils/
Pas tous les dossiers sont obligatoires — un module simple peut n'avoir que screens/ et services/.
Quand un module a plusieurs screens avec sous-routes imbriquées, les composants partagés entre ces screens vont dans components/ au niveau du module (pas dupliqués dans chaque screen).
Legacy screens¶
src/screens/ contient les écrans legacy pas encore migrés vers modules/ :
portfolio, purchaseBricks, wallet, marketplace, referral, giftCard, taxation, documents, account (information, security, about)
Nouvelles features = toujours dans src/modules/. Migration en cours.
Routes (Expo Router)¶
src/app/
_layout.tsx → RootProvider (15+ providers) + RootContent
(public)/ → Auth (login, signup, forgot-password, reset-password, invitation)
(authenticated)/
_layout.tsx → Providers authentifiés (user, feature flags, biometric)
(tabs)/ → Navigation bottom tabs
index.tsx → Home
properties.tsx → Liste biens
portfolio/[tab].tsx → Portfolio (onglets dynamiques)
marketplace.tsx → Marketplace
account/ → Paramètres compte (8 écrans)
wallet/ → Wallet (top-up, retrait, achat briques)
onboarding/ → Flow KYC Lemonway
properties/[id]/ → Détail bien (depuis liste)
portfolio-project/[id]/ → Détail bien (depuis portfolio)
Groupes () = pas de segment URL. [id] = route dynamique.
Provider stack¶
Root layout imbrique ~15 providers (ordre = outer → inner). Pas de provider de thème : Uniwind passe par l'import core/theme/global.css en tête de _layout.tsx :
Toast > SafeArea > ErrorBoundary > Datadog > ProductTracking > AdvertisingTracking > ReactQuery > GestureHandler > NavigationTracking > OTAUpdates > SessionGate > MandatoryLoader > Maintenance > ForceUpdate > NewVersion
Authenticated layout ajoute : User, FeatureFlags, Biometric, EmailVerification, NavigationModalCloser, FundingProgress, SensitiveAmounts
Impact : un hook n'est utilisable que dans le provider qui le fournit. L'ordre détermine les dépendances.
Packages partagés¶
| Package | Contenu |
|---|---|
@bricks-common/uimmo |
Design system : 74+ composants (Text, Button, BottomSheetModal, SafeAreaBox, Icon...), helpers (cn, useModals, useCloseModal, triggerHapticFeedback, LinearGradient, SafeAreaView) |
@bricks-common/api-communication |
Endpoints API, validators, types branded, ErrorCode. 28 domaines. Partagé front/back |
@bricks-common/helpers |
Helpers purs partagés (array, date, string, number, object). NE PAS importer formatCurrency/formatPercentage côté front |
@bricks-common-front/helpers |
Helpers front : schemaResolver, useCurrencyFormatter, usePercentageFormatter, Datadog, productTracking, i18n |
@bricks-common-front/theme |
Thème Uniwind : spacing, colors, shadows, fonts, z-index. Génère uniwind-theme.css |
Tokens du design system (source de vérité pour les valeurs disponibles) :
| Token | Fichier |
|---|---|
| Spacing | projects/common/front/theme/src/spacing.ts |
| Colors | projects/common/front/theme/src/colors/*.ts |
| Border radius | projects/common/front/theme/src/border-radius.ts |
| Shadows | projects/common/front/theme/src/shadow.ts |
| Fonts / Typography | projects/common/front/theme/src/fonts.ts |
| Z-index | projects/common/front/theme/src/z-index.ts |
| Breakpoints | projects/common/front/theme/src/breakpoints.ts |
Data flow¶
- API :
customAxios+processHttpResult(valide la réponse, affiche toast erreur, log Datadog) - Query keys : centralisées dans
allStaticQueryKeys(par domaine) - Hooks API :
src/api/{domain}/use{Action}.tsousrc/modules/{module}/services/use{Action}.ts - Endpoints : définis dans
@bricks-common/api-communication, partagés avec le backend - Auth : token JWT dans MMKV, vérifié dans
RootContentpour guard routes - Persistence queries : AsyncStorage (survit au restart app)
Import aliases (front-mobile-app)¶
Tous les aliases mobile-app sont prefixes @invest-* pour eviter les collisions avec app-pdp-financement.
| Alias | Cible |
|---|---|
@invest-modules/* |
src/modules/* (le plus courant) |
@invest-core/* |
src/core/* (providers, theme, i18n, api, config, storage, customerIO, biometric, date, logger) |
@invest-shared/* |
src/shared/* (hooks, utils, services, components) |
@invest-components/* |
src/shared/components/* (raccourci vers les composants partages) |
@invest-assets/* |
assets/* |
@invest-legacy/* |
src/legacy/* (ecrans pas encore migres vers modules/) |
Priorité d'import : module local → @invest-modules → @invest-shared / @invest-core → @bricks-common
PDP (app-pdp-financement) : @modules, @shared (code sous src/), @assets / @pdp-assets → assets/ a la racine du projet (convention Expo, hors src).
PDP — groupes de modules¶
Une aire de l'app (= un route group app/(…)) est un groupe de modules, pas un module plat. Ex. modules/financing-management/ regroupe un sous-module par feature (home/, requests/, news/, documents/, users/…) + un shell/ qui porte le cadre partagé : utils/ (dont useNavItems, source unique des onglets), providers/SelectedProjectProvider, components/ (NavBar, Sidebar, ProjectsDropdown), et les écrans utilitaires non-feature dans screens/ (MoreScreen, HelpScreen). Les features dépendent de shell/ (jamais entre elles) ; les _layout.tsx câblent shell/ + les navigators Expo (Stack/Tabs, qui restent dans les route files). users/ (BRI-1785) : page Utilisateurs (liste + invitations + rôles) entre Documents et Compte ; tab toujours enabled (pas de requiresFinancedProject) ; invite/relance stubbées jusqu'à BRI-1784. Page publique invitation (BRI-1865) : /(public)/invitation?token= sous modules/auth/screens/InvitationScreen — validate + submit stubbés jusqu'à BRI-1784 ; session gate gère le post-accept.
modules/financing-request/ suit le même moule en variante wizard : un sous-module par step (presentation/, documents/, borrower/, analysis/, offer/, finalization/, signature/) + un shell/. La racine d'un groupe ne contient que les sous-modules (steps/features) + shell/ — jamais de components//services//types//store//utils/ à plat. Le transverse partagé du groupe vit sous shell/ : shell/providers/ (ProjectProvider), shell/components/ (chrome consommée par les _layout.tsx comme ProjectHeader+ProjectStepsBar, building blocks partagés comme BackToFunnelBanner, et FinancingStepContainer — layout steps 1–3 + signature avec side brut optionnel et FAB → Modal locale sous 2xl ; CTAs portal dans StepsBar uniquement ≥2xl), shell/services/ (logique de groupe non rattachée à un step — ici useValidateStep/useInvalidateStep, la progression du wizard), shell/utils/ (projectSteps, source unique de progression). Chaque step porte sa propre archi de module (<step>/components/, <step>/services/ + son queryKeys.ts, <step>/providers/, <step>/utils/) : un service consommé par un seul step vit dans <step>/services/. Au niveau module, pas de découpage par typologie hors services/ : hooks, types et utils vivent à plat dans <step>/utils/ (pas de hooks/ ni types/ séparés). Pas de dépendance entre steps : un service partagé monte dans shell/, jamais importé d'un autre step. Ce qui dépasse le groupe (utilisé aussi par auth, financing-management, app shell…) remonte au niveau app : primitives projet (useGetProject, useCreateProject, projectsStorage, clé project de @shared/services/queryKeys) dans @shared/services/, type Project dans @shared/types/, composants génériques (FormField, ProjectHeroBase, CheckboxCard, SelectCategoryModal, SelectDateModal) dans @shared/components/. App modules/shell ne doit pas importer les steps financing-request/*.
La coquille de l'app entière vit dans modules/shell/ (top-level, frère des groupes, pas un group-shell niché) : providers/ (toute la stack root câblée par app/_layout.tsx — Theme, ReactQuery, Datadog, CustomerIO, ProductTracking, SessionGate, MandatoryLoader, Maintenance, User, UserTracking ; authenticated ajoute ApporteurAffairesProvider — fake toggle DEV jusqu'au rôle API), screens/MaintenanceScreen, screens/NewProjectScreen (route authentifiée /new — AuthLayout + form de création 0 projet ; form partagé components/NewProjectForm aussi monté par components/modals/NewProjectModal depuis le dropdown / HomeHeader), components/InfoBanner, services/ (useMaintenanceChecker, useGetInfoBanner + leur queryKeys.ts). Importé via @modules/shell/…. Distinction de couche : modules/shell/ = chrome/infra qui wrappe toutes les routes (y compris (public)) ; shared/ reste le réutilisable générique cross-groupe (utils api/config/storage/theme/i18n, primitives projet, composants génériques).
Dans financing-management, l'index /(financing-management) redirige vers projects[0]/dashboard, ou vers /new si la liste est vide. L'option « Tous les projets » du dropdown est masquée via showAllProjectsOption={false} (le scope kind: 'all' reste supporté pour deep links / guards screens). Création d'un projet supplémentaire → openModal(NewProjectModal).
Concepts clés¶
- Modules vs Screens :
src/modules/= architecture cible.src/screens/= legacy. Toujours créer dans modules - Smart/Dumb : Screen complexe =
Screen.tsx(smart, hooks, logique) +ScreenUI.tsx(dumb, props only, Storybook) - Uniwind : Système TailwindCSS-like pour React Native. Classes via
className.cn()pour merge avec résolution de conflits - processHttpResult : Valide la réponse API contre le validator de l'endpoint, affiche notification erreur, retourne données typées
- Montants : Toujours en centimes (cents). Les formatters (
useCurrencyFormatter) divisent par 100 pour l'affichage - Feature flags : Fetchés via API, fournis par
FeatureFlagsProvider. Vérifier le hook FF avant toute logique conditionnelle - Observabilité : Datadog. Erreurs auto-reportées via
processHttpResultetErrorBoundaryProvider. Sur web,beforeSenddrop le bruit navigateur opaque (Script error., Outlook hosted webview, ResizeObserver, MetaMask, abort réseau) —shouldDiscardBrowserNoiseLog - Design system : Vit dans Figma. Composants uimmo matchent les noms Figma. Toujours vérifier uimmo avant de créer un nouveau primitif UI
Maintenance¶
Quand tu modifies la structure des modules, les routes, ou les providers : mettre à jour ce fichier.