Nothing Held Back
Full-stack community platform for one of the internet's most active marketing communities — rebuilt from Bubble into a modern TypeScript stack.
Alejah Sardiniola
available for work

Nothing Held Back Pro is a paid marketing community running at $500/month. Before the platform, the experience was fragmented — content in one place, community in another, coaching somewhere else, all stitched together with workarounds that couldn't scale.
We built one system to carry all of it. Then, when AI-assisted development changed the math, we made the call most no-code founders are afraid to make: we left Bubble and rebuilt the whole thing in code.
This is the live version. Real members, real subscriptions, real money moving through Stripe. 127 database tables, 230 migrations, 258 route segments across five role-based areas. I led four of the systems that decide what a member sees, what they can touch, who they can bring with them, and whether it works before they find out it doesn't.
The problem
NHB had built something real — a 60,000-member free community, a high-ticket paid tier, world-class coaches, weekly live training, and a content library that kept growing. But the infrastructure couldn't carry the vision.
Members were navigating between platforms to access what they paid for. Content wasn't searchable. Coaching had no workflow — just inboxes and manual coordination. The AI tools Alen wanted to give members didn't exist anywhere they could be plugged in without a full custom build.
The community was outgrowing every platform it was on.
It needed a home that was built for it — not borrowed from someone else's template.
The solution
The architecture started with the data model, not the canvas. Every data type, every relationship, every permission scenario mapped before a single page was built. Then the access layer. Then the integrations. Then the visible surface.
Members don't navigate between tools. They live inside one environment that knows who they are and what they have access to.
The Rebuild
Then the ground shifted.
AI-assisted development stopped being a novelty and became the way serious software gets built. The math on a real codebase — owned, typed, versioned — flipped from "too expensive for a community this size" to "why are we still renting?"
So we left Bubble and rebuilt NHB in code. Not a rewrite for its own sake. A move to a stack that could carry the next decade instead of the next launch.
Next.js 16 (App Router) on Vercel — server-rendered, auto-deploys on push.
Supabase (Postgres) — row-level security maps almost one-to-one to Bubble's privacy rules.
Drizzle, not Prisma — stays close to raw SQL; Prisma choked on serverless.
Inngest — replaces Bubble's backend workflows and scheduled events.
Stripe — live checkout, real webhooks.
Claude Code — the co-engineer that made a rebuild this size shippable by a small team.
Same platform. Same members. A foundation that finally matches the ambition. Here's what I owned inside it.
1. Personalization that earns its keep twice
The rails on every core member page aren't a feed. They're a recommendation engine.
It's precompute-then-serve. Four background jobs do the thinking on a schedule — one builds a taste vector per member every hour, one scores what's trending across the community, one maps item-to-item similarity nightly, one assembles the final ranked list every four hours. All of it lands in a table. The member page does a single indexed read. No ranking at request time on the warm path — a brand-new member with no history falls back to live community popularity until they've given the engine something to work with.
Each member gets content scored to their own taste — cosine similarity against their taste vector — blended with what's hot community-wide. The blend shifts as it learns you: day one it's 100% what's trending, and by twenty signals in it's 90% you.
Then it earns its keep a second time. Locked premium isn't hidden from the rails — it rides through and renders as a lock-badged upgrade CTA, capped at three per rail so it tempts without nagging. Click it and the paywall opens instead of the content. The rail that personalizes is the same rail that converts.
2. The rules that decide who sees what
Access control on NHB runs three axes at once: three plan tiers (free, Pro, Fast Forward), an eight-program coaching subscription, and five roles. A coach can sit on any tier. A free member can never be a coach. Most gates are tier decisions — some are both.
It's enforced in depth, not in one place. The exact same tier logic is written twice — once as Postgres functions that gate the data at the row level, once as a pure TypeScript entitlement library that gates the features and pages. Edge middleware is the authoritative page lock. And a CI gate fails the build if any query that bypasses row-level security ships without a matching access test. Unknown permission values fail closed.
All of it was mapped at the schema layer — migration zero — and carried across the migration intact. Bubble's plan system mapped straight onto the new tiers, so the gates worked before Stripe was even reconnected.
3. One plan, a whole team
A paying member can bring their team on. They send a tokenized invite, it lands in an inbox with a 14-day expiry, the invitee accepts, and they're in.
Sub-members inherit the primary member's tier — tier only, scoped deliberately: coaching programs don't transfer, and a seat sees content from around the time they joined forward. Seats are free within a cap — three on Pro, five on Fast Forward — and Stripe stays at one subscription per plan. No per-seat billing surprises.
It's all run from one surface, and the accept path is built to not break under pressure. Two people accepting the last seat at the same instant can't both get in — the transaction takes a row lock and a database-level unique index backs it up. The seat cap holds even in the race.
4. The net that catches it before members do
An automation platform that only its author can operate is a script with extra steps. Same is true of a community platform — if it breaks for the member and nobody caught it first, the feature didn't ship, it leaked.
The platform runs a layered net: 2,808 unit tests, 96 end-to-end specs including adversarial access-matrix and role-boundary tests, post-deploy smoke checks, a k6 load test, synthetic monitoring on the staging mirror, and Sentry on every deploy.
My part was the human layer the automated suites can't cover. Manual QA against real checklists, cross-viewport on desktop and mobile, real-device spot-checks on the installed iOS PWA, and the pre-launch readiness audit that hardened the platform through real bug fixes before members ever saw it. I ran the flows the way a first-time member would, not the way the person who built them would. That's the only version of testing that catches what actually stops people.
What was built
- Personalized Member Dashboard — a home base that surfaces relevant content, active calls, and community activity based on each member's tier and history. Not a generic feed. A view that responds to the member.
- Recommendation Engine — precompute-then-serve personalization rails across the core member surfaces (dashboard, library, resources, live calls, forum). Four scheduled jobs rank content per member into a table; the page does one hot read. Locked premium renders as a lock-badged upgrade CTA, so the rail that personalizes is the one that converts.
- Multi-Tier Access Control — three plan tiers, an eight-program coaching axis, and five roles, enforced in depth: identical rules in Postgres row-level-security functions and a pure TypeScript entitlement library, an authoritative middleware page gate, and a CI gate that blocks any RLS-bypassing read without an access test. Fails closed.
- Team Members (Seats) — a paying member invites others onto their plan via tokenized, expiring invites; sub-members inherit the tier (tier only), free within a per-plan cap, managed from one surface. The accept path is concurrency-safe so the seat cap holds even under simultaneous accepts.
- Community Forums — topic-organized discussion with nested replies, search, and read/unread state. Built to stay alive without becoming noise.
- Content Archive — every live training call organized, timestamped, and searchable with transcripts. Members who miss a session don't miss the value.
- Coaching Workflow Engine — structured intake, routing, and feedback that tracks every member-to-coach interaction inside the platform. No more managing coaching through inboxes.
- MindAI — an AI assistant connected to the NHB knowledge base, built into the platform. Members query it on demand for frameworks, coaching insights, and content without waiting for a live call.
Tech stack
Impact
This isn't a launch-day screenshot. It's a live platform that already carried a whole community across a migration most founders never attempt.
The rebuild moved the membership off Bubble and onto owned, typed, versioned code — one login, one permission architecture, one source of truth for every member interaction. 1,812 members migrated and 271 active subscriptions carried over without losing the community underneath them. Members access everything they pay for in one place. Coaches work through a structured system instead of an inbox. Content that used to disappear after a live call is now permanent and searchable.
The four systems I led are the ones a member touches every session without thinking about them: the rails that decide what they see the second they log in, the rules that quietly enforce what they can open, the seats that let one plan carry a team, and the QA net that catches the break before they do.
Scale you can check in the repo: 127 database tables, 230 migrations, 258 route segments across five role-based areas, and a recommendation engine wired into six member surfaces. This is what a community platform looks like when you build it for the community instead of adapting the community to the platform.
Reflections
The hardest part of this build wasn't the features.
It was the discipline to not build the features first.
The permission system alone — mapping every access state for every tier before touching a single element — saved weeks of rework that would have come later. Map the data, own the permissions, do the invisible work, and the visible work takes care of itself.
The spec is the strategy. The data model is the foundation. The visible surface is the easy part.
When NHB moved off Bubble and into code, I stopped building features and started owning them. I led the recommendation engine — the layer that decides what every member sees the second they log in. I led tier-based access, the rules that quietly enforce who gets what. I led Team Members — the seats that let one plan carry a whole team. And I led QA.
Here's the part I'll defend the loudest, because it ties all four together.
The recommendation engine I built once surfaced content that was tier-locked — items a member could see in the rail but not open. That's the exact kind of gap that ships in a demo and breaks in production. It got caught in QA, before members did, and fixed at the engine. That's not a story about a bug. It's the whole argument for the layered net: the access rules were written in enough places that the leak was detectable instead of silent.
Different tools than the Bubble build. Same discipline. Map the data, own the permissions, do the invisible work — and test it like the person who's going to find the bug, because if you don't, your members will.