OfficeGest

OGMF

The OfficeGest Modular Frontend — the OfficeGest web client, embedded as a web component and built from self-contained modules.

What OGMF is

OGMF (the OfficeGest Modular Frontend) is the frontend of OfficeGest. It is not a standalone app: it ships as a web component built with a module-federation architecture, so the host application embeds it as a custom element rather than mounting it as a page. The primary element is <officegest-mf>; a second element, <officegest-document-chat>, exposes document collaboration. React is bridged to those custom elements with @r2wc/react-to-web-component.

Because it runs inside a host, OGMF boots from a global window.OG object the host provides — auth token, current user, API endpoints (ogUrls), feature flags, permissions, and the list of available modules (CORE, CRM, VENDAS, …). That global is what gates which modules and routes come alive at runtime.

OGMF renders inside the host's shadow DOM. Dark mode is driven by the :host(.dark) selector, and all colors use semantic theme tokens (bg-primary, text-muted-foreground) rather than raw values, so the embedded component stays themable.


Tech stack at a glance

LayerChoice
FrameworkReact 19 + TypeScript (strict mode)
BuildVite 6 with Module Federation
Global / feature stateZustand
Server stateTanStack Query (React Query)
FormsTanStack Form + Zod (see Form Builder)
UIshadcn/ui on Radix primitives, Tailwind CSS 4 + CSS variables
RoutingReact Router 7 with lazy() code splitting
i18ni18next (Portuguese primary; English / Spanish fallback)

The forms layer is mid-migration: legacy screens still use React Hook Form, while new work targets the schema-driven Form Builder on TanStack Form. Reach for the builder for anything new.


How the code is organized

Every feature lives under src/modules/{domain}/ as a self-contained module that owns its own components, stores, context, hooks, services, and types. Modules may depend on each other directly when one needs a specific component or service from another — that is a deliberate, declared dependency. The slot system is the separate mechanism for the opposite case: letting any module extend a given place without the extended module knowing who will contribute.

Routes are discovered dynamically — the main router globs import.meta.glob('./modules/**/routes.tsx'), so dropping a routes.tsx into a module wires it in without touching central config. The Module System page covers how modules are defined, licensed, discovered, and connected to routes, navigation, and slots.


Documentation