MosesTab
Church management software replacing a stack of separate tools.
The problem
Churches run on tools that do not talk to each other: a member database in one place, a giving platform in another, a forms tool, a check-in app, a rota spreadsheet. Each is affordable alone and punishing in aggregate.
The cost is not only the subscriptions. It is the administration: the same family entered four times, attendance that cannot be compared against giving, and a volunteer team spending Sunday afternoon reconciling exports.
What I built
A tenant-scoped platform where every church is addressed by slug and every API call is scoped to it. Members, groups and ministries, events, attendance, a forms builder, child check-in, visitor management and giving all sit behind one login.
Users belong to many churches with a per-church role, so staff who serve more than one congregation get one account rather than several. Permissions are supplied per section and per church, and the route guard resolves the active church before any protected view renders.
It is two front ends against a shared Django REST API: a React 19 and Vite dashboard using TanStack Router and Query for the authenticated product, and a Next.js public site for marketing and public giving.
Decisions I'd defend
Giving runs on Stripe Connect with a connected account per church, not a single platform account. Money reaches a church directly and payouts, balances, payout schedules, instant payouts and refunds are all the church’s own. It costs an onboarding flow, and it is the difference between a product churches can trust with donations and one they cannot.
Wallet payments were the fiddly part. Apple Pay and Google Pay go through the Stripe Payment Request API on the connected account, which means checking wallet availability before rendering the buttons at all, then confirming with actions handled manually so the wallet sheet closes correctly. Stripe.js caches its instance globally, which breaks when every church is a different connected account, so instances are loaded and cached per account instead.
Text-to-give is a Twilio number provisioned per church, with keywords mapped to giving baskets and a tokenised card on file so an SMS can complete a donation. It carries its own guardrails: minimum, maximum and daily limits in minor units, because an SMS is a very easy thing to send twice.
Child check-in is the part that has to be right. Pickup authorisation is an explicit per-guardian permission rather than something inferred from the relationship, so "can check in" and "can check out" are separate flags. Allergies and medical notes are surfaced on the roster and on every scan result rather than sitting a click away, classrooms carry volunteer-ratio and capacity constraints, and checkout requires a security code with optional guardian identity and PIN.
Where it is now
Live and in use, with a free plan that needs no card. The dashboard is the only one of the three front ends with a test suite: Vitest with Testing Library and MSW, covering the auth flows and the member import path.