React Back-Office App
Fullfinity ships two distinct frontends, and it’s important not to confuse them:
- The React/Mantine back-office SPA (this page, and the other “React App” pages).
This is the authenticated admin application — every List, Kanban, Form, Calendar,
Pivot, report, wizard and dashboard you see after logging in. It is a single-page app
built with React, Mantine, TanStack Query,
and React Router. Its source lives under
app/src/. - The Preact islands framework (
window.fullfinity), documented by the rest of the pages in this section. That framework hydrates server-rendered pages — the portal, website, ecommerce storefront and themes. It is not the admin app, has its own registry/toast/event-bus, and never runs inside the SPA.
If you are building an admin screen — a new field widget, a new view type, an action button — you are working in the React app described here. If you are adding interactivity to a Jinja-rendered public page, you want the islands framework instead.
Where the code lives
Section titled “Where the code lives”app/├── src/│ ├── App.jsx # Root: theme, router, top-level providers│ ├── axiosInstance.js # The single axios client (interceptors, re-auth, timing)│ ├── theme.js # Mantine theme (createTheme) + cssVariablesResolver│ ├── contexts/ # React contexts (User, Navigation, Filter, Form, UI, …)│ │ ├── ShellProviders.jsx # Composes the context provider tree│ │ └── LoadingContext.jsx # The one global loading channel│ ├── data/ # TanStack Query layer│ │ ├── DataProvider.jsx # QueryClientProvider wrapper│ │ ├── queryClient.js # QueryClient config│ │ ├── keys.js # Cache-key factories│ │ └── hooks/ # useModelQuery, useExecuteMethod, useListData, …│ ├── hooks/ # UI hooks (useModalStack, useWizard, …)│ ├── views/ # View-type components + registry.js (capabilities)│ ├── components/│ │ └── ui/│ │ ├── fields/ # Field widgets + the widget registry│ │ └── misc/ # EmptyState, AsyncBoundary, loaders, …│ └── utils/ # actionResultHandler.jsx, etc.The built bundle is emitted to the repo-level static/ directory and served to the
browser; you edit the sources under app/src/.
The provider tree
Section titled “The provider tree”App.jsx mounts the top-level providers, and ShellProviders (contexts/ShellProviders.jsx)
composes the focused state contexts inside the shell. The nesting order is deliberate —
ConnectionProvider is outermost so a disconnected overlay can cover the whole UI, and
TranslationProvider is mounted at App.jsx level (above the shell) so that modals
rendered in portals still resolve t().
// Conceptual tree (see App.jsx + ShellProviders.jsx for the exact wiring)<DataProvider> {/* TanStack Query client */} <MantineProvider theme={theme} cssVariablesResolver={cssVariablesResolver}> <TranslationProvider> {/* i18n — above the shell so modals get t() */} <LoadingProvider> {/* the ONE loading bar + logo overlay */} <ShellProviders modelRegistry={...}> {/* ConnectionProvider > UserProvider > NotificationProvider > ChatProvider > UIProvider > NavigationProvider > PaginationProvider > FilterProvider > FormProvider > AnalyticsProvider > ImportProvider */} <Shell /> </ShellProviders> </LoadingProvider> </TranslationProvider> </MantineProvider></DataProvider>ShellProviders takes a modelRegistry prop and threads it into FilterProvider.
Context catalogue
Section titled “Context catalogue”Each context is single-responsibility, exported from contexts/index.js with a matching
hook. Import the hook, never reach into the context object directly.
| Context | Hook | Responsibility |
|---|---|---|
UserContext | useUser | Current user profile and permissions |
NavigationContext | useNavigation | URL params, the active action, breadcrumbs, menu |
FilterContext | useFilter | Filter sets, search terms, grouping, saved filters |
PaginationContext | usePagination | Page number, rows per page, total count |
FormContext | useFormContext | Edit mode, form values, submit |
UIContext | useUI | Loading flags, modals, theme, responsive state |
AnalyticsContext | useAnalytics | Chart / pivot configuration |
ImportContext | useImport | File-import state |
RowSelectionContext | useRowSelection | Table row selection |
TranslationContext | useTranslation / useT | i18n + locale formatting |
ErrorContext | useError | Error-modal display |
PreviewContext | usePreview | Builder preview mode (mock values) |
Additional providers wired into ShellProviders but not re-exported from
contexts/index.js include ConnectionProvider, NotificationProvider and
ChatProvider.
Two cross-cutting concerns are deliberately not in this catalogue because they have their own dedicated pages:
- Loading / empty state → the single global loading channel. See React Conventions.
- Data fetching → the TanStack Query hooks and axios client. See Data Layer.
Where module authors plug in
Section titled “Where module authors plug in”Two registries are the supported extension points for the SPA — both live under
app/src/ (this is React code, not islands code):
- Field widgets →
components/ui/fields/registry.jsx. Register a widget withcreateWidget/registerWidget; awidget:name in a backend view arch resolves to it. - View types →
views/registry.js. Each view type is declared once as a capability record; a component is dispatched by theViewRenderer.
Both are covered in detail in Widget & View Registries.
Do not add admin-app widgets through the islands framework’s
window.fullfinity.registry— that registry is for server-rendered pages only. The two systems are separate.