Skip to content
Platforms & CRMLive2026

The Alliance Hub

A multi-tenant culture-operations platform for a real-estate team's physical hub, built by hard-forking a sibling product and re-deriving its tenancy, security and design…

111 tables / 63 migrations
schema applied to production at go-live
124 routes
clean production build
829
passing tests at go-live
64 tables
carry an enforced Postgres RLS tenant_isolation policy
The Alliance Hub interface

Problem

A national brokerage's Orlando team runs a physical Culture Center, but had no software layer for it: no record of who shows up, who teaches a class, who covers a colleague's showing, or who is quietly disengaging. Recognition, attendance, and peer coverage all lived in group chats and memory, which meant none of it could be measured, credited, or acted on before someone drifted away. The team also needed the system to be licensable beyond one building, which meant designing for organizations that do not trust each other with each other's data from day one rather than retrofitting isolation later. The fastest honest starting point was not a blank repository: a sibling product already had the primitives this needed (auth, events, achievements, member profiles, a job worker, a design system) but was tied to a different live brand running on the same physical machine, which turned the build into a de-risking problem before it was a feature problem.

What was built

The Alliance Hub is a hard fork of a sibling Next.js platform, taken with full git history and then deliberately severed: every port, container name, Postgres volume, launchd label, R2 bucket, and hardcoded URL that could collide with the live sibling product on the same host was inventoried and changed, documented in FORK.md as a standing isolation contract rather than a one-time cleanup. From that base, 23 tables and their routes belonging to the old product's domain were pruned (about 24k lines), and a new Culture domain was added: check-ins, a Culture Score computed from attendance/participation/contribution, a Culture Passport, seasons, a Council, a Media Hub, and Culture Coins. A live LED-wall mode renders rotating room-state slides for a physical display, refreshing on a timer and gated by a salted per-hub token so the served page never leaks a real user id. A showings coverage board lets agents post and claim buyer/listing/transaction tasks for each other, with the dollar-offer field wired as display-only by design so the platform never becomes a payment rail under the brokerage's compliance rules. Every privileged mutation writes to an append-only audit log through a single typed helper, full name and TOTP secrets are AES-256-GCM encrypted with column-bound authentication tags, and the product ships in English, Spanish, and Brazilian Portuguese across every member-facing surface. A background worker on pg-boss runs nightly backup, retention, and Culture Score recompute jobs; the whole stack runs under launchd on the operator's own machine behind a Cloudflare tunnel, with 6-hourly encrypted off-host backups verified by an actual restore rather than assumed.

Technical approach

The architectural decision that shaped the most work was tenancy. The inherited codebase carried an organization_id column on 60 tables but almost nothing read it — safe with one tenant, invisible as a defect, and explicitly the kind of gap that stays invisible until a second organization exists and starts seeing the first one's rows. Rather than hand-adding a filter to the 72 affected modules (judged certain to drift on module 73), the fix went to the database boundary: Postgres row-level security with a tenant_isolation policy on every organization-scoped table, enforced via SET LOCAL app.org_id inside a per-request transaction so a connection that forgets its context sees zero rows instead of every row - fail-closed rather than fail-open. Getting there required solving a real constraint problem first: the app's Postgres client was a shared, pool-level connection, SET LOCAL only holds inside a transaction, and one route already opened a dedicated long-lived connection per open server-sent-events stream, so naively reserving a connection per request would have collided with a 100-connection ceiling shared with other services on the same host. The chosen approach resolves the org from the session's JWT claim at the point each query needs it rather than threading a wrapper through every route, which a probe confirmed was necessary: an AsyncLocalStorage context opened in a parent layout does not survive into a child page under React Server Component streaming, but Next's own request context (cookies, session) does resolve correctly from any nested module, which removed roughly 200 planned wrapper call sites. The flip to enforcement was staged behind a soak test: a second instance on a scratch port ran with RLS enforced as a non-admin member across 20 routes and was diffed byte-for-byte against the production instance before the real deploy switched roles. Concurrency correctness for member-facing actions follows a single pattern throughout: a claim, cancel, or completion is a conditional UPDATE whose WHERE clause IS the permission check (status = 'open' AND requester_id != caller, for example), so there is no read-then-write race window; a separate pure function mirrors the same rule set with no database dependency so it can be exhaustively unit tested and used again to explain a denial in plain language after the fact. PII at rest uses AES-256-GCM with the column path baked into the additional authenticated data, so a ciphertext copied from one encrypted column into another fails verification instead of silently decrypting as the wrong field. The build carries its own fork-isolation regression tests (a stray filesystem default once pointed at the sibling product's 343MB media library) alongside 800+ application tests, and the production build is gated on a clean pnpm audit at high severity.

Creative approach

Craft

The inherited visual language is dark, gold-on-obsidian, serif-display over sans-UI, built for a different brand's story, and the work was to keep the system's discipline (three-layer card vocabulary, a locked accent palette, a single mono eyebrow style for section labels) while re-deriving every screen for a culture-operations product rather than the community product it came from. The LED-wall mode is a distinct design problem from the member app: a mounted, unattended display cycling room-state, Culture Impact, team standings, and week-in-atmosphere every 90 seconds, with oversized serif titles and slide-progress ticks sized for a room, not a lap. It reuses the same organ components as the member dashboard rather than a separate rendering path, so a fix to how a stat animates in one surface applies to both. Motion is treated as an information channel, not a texture: a documented pass ("Kill the dots and smears") removed every purely decorative particle layer across the component library — ambient drifting dust behind pages, wind-streak effects, random scatter fields — after direct feedback that they read as sloppy rather than crafted, and replaced the ones carrying real signal with structures that map to specific data (a tally mark per response, a hairline stem tying a mark to a time axis, one sweeping arc instead of dozens of floating dots). The rule that survived the pass, applied to the whole library going forward, is binary: a particle is either a rendering of a specific record or part of one coherent structure, never ambience.

Reframe

The non-obvious idea is that a culture platform's leaderboard is a governance problem before it is a UI problem, and the interesting engineering happened at the boundary between "recognition" and "payment." The showings coverage board lets one agent post a task and offer another agent a dollar amount to cover it, which is exactly the kind of feature that turns a recognition platform into a real-estate settlement platform if built carelessly — and Florida statute (475.42(1)(d)) restricts how commission-like payments between agents can flow through a third-party system. The fix was architectural, not a warning label: the offer amount is validated, displayed, and stored, and the code path for it stops there by construction — there is no charge, payout, or ledger entry tied to it anywhere in the module, and the comment at the top of the file states the constraint as a standing rule for future edits, not a one-time review note. The same instinct shows up in the tenancy decision: rather than trust future code review to keep 72 files honest, the fix was moved to a place (the database itself) where forgetting is structurally impossible rather than merely discouraged. The product's own north-star document makes the same move at the concept level — it explicitly rejects five-star agent ratings as "toxic" and replaces them with attribute tags, and rejects raw invitation-volume rewards in favor of rewarding guests who actually return - treating the incentive structure itself as the thing being designed, not just the interface on top of it.

Process and what failed

Three real reversals, not narrated as wins. First, a split-brain identity bug shipped with the fork itself: every inherited query still filtered on the old product's hardcoded organization id while the new domain's data was seeded under the new organization, so early manual testing against a live-looking app was reading and writing against an org row that didn't match anything — fixed by a dedicated migration that repointed 32 column defaults and deleted the old organization row so a stray reference now fails a foreign key instead of silently succeeding. Second, the row-level-security rollout was originally scoped as threading a tenant-context wrapper through roughly 200 call sites down from each page's root layout; a targeted probe proved that assumption wrong (the wrapper's context does not survive React Server Component streaming into a child page) and, in the same investigation, proved a much cheaper mechanism already worked in production for something else, which cut the plan by an order of magnitude — the original plan was abandoned entirely rather than partially executed. Third, on user feedback that the interface's ambient particle effects "looked sloppy," seven separate decorative animation layers that had already shipped across multiple pages were removed outright rather than tuned, with a new standing rule adopted specifically to prevent the same mistake from recurring in future components — a design decision reversed after users experienced it, not caught in review beforehand.

Outcome

The Alliance Hub is live in production at app.myalliancehub.com, verified through the public domain rather than only in local development: authenticated sign-in, role-gated redirects for non-admin members, and content rendering were each checked against the deployed build, and the /api/health endpoint distinguishes a genuinely healthy app from one serving cached pages while its database is down. Row-level security is enforced in production, not merely implemented and left dormant, following a byte-for-byte soak comparison against a parallel instance before the cutover. The showings coverage board and its Florida-statute-aware payment boundary are live and used by real team members to trade coverage, and the platform speaks three languages across every member-reachable surface. Two gaps are tracked openly rather than hidden: roughly 47 server-component-only modules still rely on the architectural RLS backstop rather than an explicit per-query filter (a deliberate, documented choice, not an oversight), and two lifecycle actions (media attachment, activity deletion) remain intentionally unbuilt pending an R2 storage decision.