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 |
Flow KYC Lemonway (profil + widget LemonwayKYCScreen) ; gates wall/banner sur investorIdentityStatus |
accountStatus |
UI KYC (banners, wall, auto-open) : match sur investorIdentityStatus + investorFormCompletedAt aux call-sites, pas de machine d'état parallèle. Freeze via transactionRights |
whats-new |
Nouveautés produit : liste, pastille unread, réactions par emoji |
fundraising-v2 |
Levée 2026 + actionnariat : page, dock, cards, modales d'intention et d'achat, shareholding, data layer. Traduction proto → Uniwind : /proto-to-uniwind |
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/ → helpers purs du module (pas de `business/`)
Pas tous les dossiers sont obligatoires — un module simple peut n'avoir que screens/ et services/.
DO NOT créer un dossier business/ dans un module front — la logique pure vit dans utils/.
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/ → Formulaire profil + widget `LemonwayKYCScreen` (`accountStatus`). Recertif KYC : même widget via `start-onboarding` ; overlay `update` / `outdated` sur `/me`
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, AccountStatus
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 : 75+ composants (Text, Button, Modal, ModalList, Tooltip, SafeAreaBox, Icon, ImageGallery, ImageViewerModal, EmojiReactions...), blocs feature (whats-new / GroupedHighlights), helpers (cn, useModals, useCloseModal, triggerHapticFeedback, LinearGradient, SafeAreaView) |
@bricks-common/api-communication |
Endpoints API, validators, types branded, ErrorCode. 28 domaines. Partagé front/back. What's New : investorWhatsNewEndpoints + projectOwnerWhatsNewEndpoints (même contrat, préfixe de path) |
@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 — modules¶
Architecture détaillée de app-pdp-financement (modules à plat, shell/, wizard
financing-request/, routing) : docs/architecture-overview/front-app-pdp-modules.md.
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
- Lemonway KYC widget :
LemonwayKYCScreen;onFinish/onMyAccountpostMessage native (ReactNativeWebView) +parent(iframe web). Compte doublon →openModal(HelpCenterModal) - Account status :
matchsurinvestorIdentityStatus+investorFormCompletedAtaux call-sites (pas d'enum overlay) ; freeze viatransactionRightsévalué avant l'identité ; questionnaire invalide (investorFormCompletedAtabsent) seulement si Lemonwayverified