XOM is a statically exported Next.js application backed entirely by Firebase services. This page describes the shape of the system: what runs where, which store holds what, and the constraints that follow from the deployment model.
01The layers
Browser (static bundle)
│
├─ React client components ── React Context (auth, app state)
│
├─▶ Firebase Authentication ...... identity, MFA challenge
├─▶ Cloud Firestore .............. user documents, invite codes,
│ admin config, audit logs
├─▶ Realtime Database ............ posts, reactions, ad campaigns
│ and ad metrics, live/presence state
├─▶ Firebase Storage ............. uploaded media
└─▶ Cloud Functions .............. notifications, post processing,
admin callables, content proxy
The application is built with Next.js 14 using the App Router, written in a mix of TypeScript and JavaScript, styled with CSS Modules and SCSS, and deployed to Firebase Hosting.
02The constraint that shapes everything
next.config.js sets output: 'export'. XOM builds to a fully static bundle and there is no Node server at runtime. Three consequences follow directly, and they explain most of the architecture:
- No middleware and no server-side route protection. Route guarding is done client-side by a
ProtectedRoutecomponent that consults the auth context. - No server components. Every component is a client component.
- The browser talks to Firebase directly. Reads and writes go from the client SDK to Firestore and the Realtime Database, which makes the security rules — not application code — the enforcement boundary. Privileged operations that cannot be trusted to the client are implemented as Cloud Functions.
Because CSS Module class names are hashed at build time, features that need stable DOM targets (the onboarding spotlight, for example) key off data-* attributes instead of class names.
03Two databases, deliberately
Firestore and the Realtime Database are both in use and they are not interchangeable here. Firestore holds documents that need querying, indexing, and rule-based role checks: user records with role and status, invite codes, per-module admin configuration, and the admin audit log. The Realtime Database holds the high-churn, listener-driven data: post nodes, engagement counters, ad campaigns and their metrics, and live session state. Node-level rules govern each Realtime Database path.
04Authorization model
User documents carry a role and a status. The role hierarchy runs pending user, approved user, moderator, admin, super admin; status runs pending, active, suspended, rejected. Firestore rules implement the role checks server-side, which matters given that route protection is client-side.
05Where to read further
The internal architecture reference (PLATFORM_ARCHITECTURE.md) carries the full component-level breakdown: layout systems, the container taxonomy, the broadcast console, the gamification and rewards systems, the admin control modules, and the roadmap phases.