Faith & Friction
A standalone Next.js membership platform for a men's brotherhood — invite-only application flow, gamified accountability, and a YouTube/podcast funnel into it.
- 5
- Drizzle migrations applied to the production database

Problem
The repo's build brief frames the platform as a solution to a specific gap: men who look successful on paper and are isolated underneath, with no room built for someone to tell them the truth and hold them to it. The founder's-note copy in the shipped product states this directly — good men drifting, "successful on paper, alone underneath," and no place strong enough to hold honest correction. Generic community platforms answer this with a chat app or a course; the repo's stated position, carried through both the CLAUDE.md hard rule and the HANDOFF.md identity notes, is that the product has to be a brotherhood with structure — an application gate, a visible accountability mechanism (streaks, standings), and a consistency framing rather than a leaderboard framing — not an open forum. A second, narrower problem the repo documents explicitly: the original build brief (docs/spec.md) specified a faith framing that included scripture, prayer-as-ritual, and church language, and CLAUDE.md records that this was reversed mid-build into a hard rule — "faith, not religion" — because the brand needed spiritual seriousness without functioning as a church, and the earlier copy is called out by name as dead. The platform also had to stand alone: no shared login, database, or brand framing with any other property the same owner runs, which shaped every infrastructure decision from the ground up.
What was built
The shipped product is a full membership platform on a single Next.js 15 codebase, deployed as one Cloudflare Worker via OpenNext with Cloudflare D1 as the database. Public marketing pages (home, the show hub, the Forge, the F.O.R.G.E. Method, a 7-day challenge, join, events, contact) sit in front of an authenticated member area reachable only through an admin-approved application: a visitor applies on /join, an admin approves or rejects from /admin, and approval issues a time-boxed activation link that lets the applicant set a password — there is no open signup route. Inside the gate, members get a dashboard (streak, XP/tier/badges, challenge progress, pod, next gathering, a first-run checklist), a community feed called "the Forge," a consistency-framed standings board, pods, a tracker, a gated content library, profiles, notifications and settings. A separate Cloudflare Worker runs the weekly digest cron independently of the app's own fetch handler, calling the app's authenticated digest endpoint on a Monday schedule. The public-facing show hub is pre-launch by design — the episode list is empty and the hub renders a coming-soon state with an email-capture funnel into the Forge, structured so that dropping episodes into a single content file and setting real channel URLs flips the whole experience live with no further code changes.
Technical approach
The most consequential engineering decision was reversed after it shipped: the build brief specified argon2id for password hashing, but native argon2 cannot run in Cloudflare's workerd runtime and a pure-JS implementation exceeds the free-plan CPU budget per request. The repo's locked-decisions log records the fallback to PBKDF2-SHA256 (100k iterations) via native WebCrypto, with the stored hash string versioned (pbkdf2$v1$…) specifically so a later move to argon2id on a paid plan or a separate auth service is a drop-in rather than a migration. The same log records a second infrastructure swap: the brief said Cloudflare Pages, but the repo moved to a Worker via OpenNext because @cloudflare/next-on-pages was already in maintenance mode and Workers+OpenNext was Cloudflare's current recommended target — the same pattern used elsewhere in the owner's stack, reused deliberately rather than invented fresh.
Two invariants are enforced by CLAUDE.md as hard rules because both were violated in development and caused real incidents. First, package.json's build script must stay next build — a version that called opennextjs-cloudflare build directly caused OpenNext to re-invoke that script internally, recursing roughly 172 levels deep and driving the 16GB build host into 27GB of swap before it was diagnosed and fixed. Second, next dev inherits the live Resend API key from the shell environment, so running the digest generator locally sends real email to whatever addresses sit in the local D1 database; a 2026-07-08 incident produced three bounces to fake seed addresses before local digest runs were restricted to deliverable test addresses for local digest runs.
The @mentions system is a small, self-contained design: raw @Firstname text is resolved server-side at post time against the member list, and only unambiguous single-first-name matches convert to a stable stored token (@[Full Name](user:<id>)) that carries the display name inline — rendering and email-snippet generation never need a database lookup to show a mention, and ambiguous names are deliberately left as plain text rather than guessed. The rate limiter (lib/ratelimit.ts) is D1-backed and keyed by <action>:<ip> using Cloudflare's client-IP header, pruning expired rows from its own bucket on every check so the table stays bounded. The digest engine guards against duplicate sends with a stored lastDigestAt timestamp and a six-day resend window, so a double cron fire or a manual re-trigger the same week is a no-op rather than a duplicate email, and it gives new members a three-day settle period before their first digest.
Creative approach
Craft
The visual identity that shipped is not the one the build brief specified. docs/spec.md called for a rugged, cinematic palette — charcoal, iron gray, ember gold, deep rust — evoking a forge and iron texture. HANDOFF.md records that this was superseded on the live site by a spatial, futuristic PS2/Y2K vapor-grid identity: void black, deep indigo, chrome white, pulse blue for CTAs, glow cyan, violet, with a particle-cross logo mark inside a tilted orbital ring and a chromatic gradient glow. The commit log documents the swap explicitly, and HANDOFF.md is equally explicit that the result is deliberately NOT gothic, rugged, or toxic-masculine — a direct rejection of the tone the original brief specified for a men's platform. Motion is treated as identity rather than decoration: liquid-chrome headline animation, a synthwave grid with a sun-line, full-height embers and fog, scroll parallax, and a named "F.O.R.G.E. scroll-ignite" sequence that only runs on the home page. Every page also carries a prefers-reduced-motion fallback, so the identity's motion-heavy signature degrades to a static poster rather than breaking accessibility.
Reframe
The naming of the community itself changed after launch work was underway: the platform was built and initially shipped as "Faith & Friction Men," and a later commit renamed the community space specifically to "The Forge" and added a founder's note, separating the community brand from the platform's own F.O.R.G.E. Method page, which is a distinct, separately named artifact under the same repo. The bigger reframe is doctrinal: CLAUDE.md's hard rule — never reintroduce Christ, Jesus, "the Lord," scripture, prayer-as-ritual, or church framing in visible copy — sits in direct, acknowledged conflict with docs/spec.md, which still contains scripture reflection segments, prayer moments, and a Brotherhood Code item instructing the platform to "keep Christ central." The repo's own launch-planning document names this conflict outright and states the resolution rule as an operating instruction for future work: CLAUDE.md and HANDOFF.md govern, docs/spec.md's earlier religious framing is dead copy, and drafting from the spec file without checking the newer rule will violate the brand's top constraint on the first pass.
Process and what failed
The standings feature was deliberately built and is framed in HANDOFF.md as "who's-showing-up," not a leaderboard — the repo treats ranking-by-performance as a rejected approach for a brotherhood-accountability product, opting instead for a framing centered on consistency. The founder's-note component is explicitly marked in its own source comment as a scaffold: real copy in the brand voice, but with a placeholder name and a TODO to swap in the real founder's story before the platform is used for heavy promotion, and the comment states plainly that no fabricated specifics were written into it. Two operational corrections are recorded as named incidents rather than smoothed over: the build-script recursion that drove the build host deep into swap, and the local-digest email leak that bounced three messages to fake seed addresses — both are preserved in CLAUDE.md as standing gotchas specifically so a future session does not repeat either mistake.
Outcome
The platform is live in production at faithandfriction.us (apex and www) as an invite-only community — there is no public self-serve signup, and admission runs entirely through the application-and-approval flow. The public marketing site, the full member area (dashboard, Forge feed, pods, standings, library, notifications, settings), the admin approval panel, the weekly digest system, and the security/rate-limiting layer are all built and confirmed working, including a live end-to-end email test of the Resend integration. Several pieces are explicitly not finished or not owner-actioned as of the repo's last update: the companion YouTube/podcast show has zero published episodes and real channel URLs are still placeholders, so it renders its pre-launch state rather than live content; the founder's-note copy is a scaffold awaiting the founder's real story and name; Google OAuth credentials are unconfigured, so only credential-based sign-in works; and analytics has not been enabled.
Related work
- Live2026The Alliance HubA 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…
- Internal2026Evolve TasksA single-tenant task-management and lightweight CRM platform built to give a small real-estate team ClickUp-level functionality on owned infrastructure instead of a per-seat…
- Live2026Monarch MovementA self-hosted community and onboarding platform that turns a real estate team's recruiting SOP into software members can't skip a step of.