focus412×ChurchOps.AI
Handoff response
Response to the engineering handoff

We read all nineteen.

Here is what we found, what we think is genuinely good and worth keeping, our leading hypothesis for the empty dashboard, and an honest map of what happens in what order, with the free part clearly marked.

First, the part that matters

This is a good build.

It is worth saying plainly, because handoff documents tend to read like confessions and this one should not. What is sitting on that laptop is a working three-role assessment platform with a sound relational model, version-controlled migrations, security policies written at the database layer rather than bolted on, anonymous survey links decoupled from authentication, and pipeline state derived from data instead of stored and drifting.

Several of those are decisions that experienced teams get wrong. The data model in particular is normalised enough to carry year-over-year history and denormalised enough to read quickly. We would not change its shape. The handoff document itself is unusually good: nineteen numbered constraints, each with the specific fix, is more clarity than most production systems can produce about themselves.

You built the platform. We are not proposing to replace it. We are proposing to finish it.The short version of everything below
The empty dashboard

Our leading hypothesis for the 0.00 scores, and how to kill it in one query

Stating this carefully, because it is a hypothesis rather than a finding. The zeros are a symptom we saw in the screenshots you shared in June; your handoff document does not mention them, so what follows is inference from the architecture rather than something either of us has confirmed.

Why constraint one is the first place we would look

Averages are recomputed in the browser after each staff member submits. The browser reads the current responses, works out the new averages, and writes them back onto the cycle. That single design choice puts the only write of every derived number on the least reliable machine in the system.

The race you describe, two people submitting within the same few seconds, both browsers reading the same starting state and the second write winning, explains wrong averages cleanly. On its own it does not explain zero averages, because whichever browser writes last still writes the mean of at least one response.

For zeros you need the write to be failing outright rather than merely racing. That could be a permissions rejection on the update, an error swallowed with no handler, or the recompute keyed to a different cycle than the one the responses landed on. All three are failure modes of the same architecture, which is why the constraint is still where we would start.

The query that settles it

Rather than argue about it, this can be answered in about a minute with read access:

Step one
Count rows in responses for a church whose cycle reads 0.00. Responses present, parent cycle empty means the aggregate write is failing, and the hypothesis is confirmed.
Step two
If the responses are not there, the problem is upstream in submission or in the security policy on insert, and the aggregation is innocent. Different fix, and worth knowing before anyone writes a migration.
Either way
Moving the recompute into a database trigger is correct on its own merits. It makes the arithmetic atomic no matter how many people submit at once, and it removes the whole class of failure from the browser.

Worth naming either way: if aggregates have ever been computed client-side under load, historical cycles may hold quietly incorrect averages rather than obviously empty ones, which are harder to notice and worse to present. Recomputing every existing cycle from its raw responses is part of phase zero regardless of which hypothesis turns out to be right.

All nineteen, triaged

What happens in what order

Every constraint from your document, sorted by what it actually blocks rather than by how hard it is. Tap a phase to filter.

1

Client-side aggregation

Phase 0 · free

Scores are recomputed in the browser after every submission, so two responses landing at the same moment can overwrite each other. Last write wins, and a response silently vanishes from the mean.

The fix: Move the recompute into a Postgres trigger on responses INSERT. The database becomes the only thing that does arithmetic.
3

The Anthropic proxy is development-only

Phase 0 · free

The proxy that carries AI calls exists only in the Vite dev config. The moment the app is deployed, every AI request returns a 404, so insights and themes go blank in production, not in development.

The fix: Recreate the same contract as a serverless function. The request shape does not change; only where it runs.
8

Inline styles, no design system

Phase 0 · free

Every component re-declares its own spacing, colour and borders. You named the consequences as no dark mode and inconsistent focus styles; the one that matters commercially is that the app cannot be put into focus412 brand without touching every file.

The fix: Extract the brand tokens to CSS variables and move the client-facing surfaces onto a component library. The survey and the report get done first, because those are the two screens a church actually sees.
15

No deployment

Phase 0 · free

It runs on localhost and nowhere else, so nothing can be shown to a church without your laptop in the room.

The fix: A production URL with the environment configured. You estimated about thirty minutes; we would allow half a day for the environment variables and the first real login. Either way it unblocks everything downstream.
19

Mobile

Phase 0 · free

Several tables overflow on a phone and the heatmap is desktop-only by design. Staff take surveys on their phones.

The fix: A responsive pass on the surfaces staff touch, plus a card view standing in for the heatmap on small screens.
2

No application server

Phase 1

Any rule the database cannot express by itself has nowhere to live. “When a cycle closes, email everyone who responded” being the obvious one.

The fix: Route handlers co-located with the UI, or Supabase Edge Functions. This is the piece that unlocks 11 and 12.
4

Homegrown routing

Phase 1

Two lines of regex reading the URL. Fine at two routes; it stops being fine at the third.

The fix: A real router. An afternoon.
5

State management

Phase 1

One component owns everything and passes a bundle of actions down three or four levels. Every new screen makes that worse.

The fix: Server state moves to a query library, bringing caching, background refresh and optimistic updates arrive for free. UI state gets a small store.
6

Role resolution takes two round trips

Phase 1

After login the app queries two tables just to establish which role it is dealing with, before it can render anything role-specific.

The fix: Put the role in the auth token as a custom claim. The client knows immediately.
11

No email

Phase 1

Invitations do not send and “your report is ready” never arrives. The UI for it exists but the wiring does not, and the built-in mail is rate-limited to roughly two messages an hour per recipient.

The fix: A transactional email provider with templates, triggered off cycle state changes. This is the piece that makes the whole thing run without you chasing people.
12

No PDF or PowerPoint export

Phase 1

The current deliverable is, in your own words, a screenshot of the browser. Meanwhile the archive holds twenty-five hand-built decks. This is the single largest hour-sink in the whole operation.

The fix: Generate the deck server-side in your existing report shape, so what comes out the other end is the deck you already present, in your brand, without anyone assembling it.
14

No test suite

Phase 1

Every regression is caught by a person clicking through the app. As the surface grows that stops being viable.

The fix: Unit tests on the parts where being wrong is expensive (scoring, tiering, aggregation, slug derivation), and a handful of end-to-end tests on the open-cycle-to-report path.
16

No observability

Phase 1

When something breaks for a church, nobody finds out until they mention it.

The fix: Error reporting and product analytics. Quick to install, and it changes what you know about how churches actually use it.
7

Row-level security is all-or-nothing

Phase 2

Policies are written per role, so they cannot express “this coach sees only the churches assigned to them.” That constraint binds the moment a second coach uses the system.

The fix: An engagements join table referenced from the policies.
9

Files are stored inside database columns

Phase 2

Uploads are held as base64 text on the row, so a 5 MB PDF becomes a 7 MB database row. Comfortable at pilot volume, expensive at a hundred churches.

The fix: Object storage with signed URLs; the database keeps only the metadata.
10

No real-time sync

Phase 2

Two people editing in two tabs cannot see each other until someone reloads.

The fix: Realtime subscriptions on the cycle and response tables.
13

The survey instrument is hard-coded

Phase 2

The twenty questions live in a source file, so no engagement can be given a variant and no version of the instrument can be retired cleanly.

The fix: A versioned templates table. This is also where the twenty-first question and the six wording drifts get resolved once and for all.
17

Time zones

Phase 2

The close date is stored in UTC and displayed in whatever zone the viewer is in, so “closes at 5pm Central” cannot currently be expressed.

The fix: Store the zone alongside the timestamp.
18

Accessibility

Phase 2

Custom controls carry no ARIA, keyboard traps are untested, and focus rings are missing in places. Fine for a small pilot; it fails an audit the first time a larger church runs one.

The fix: The component-library work in phase zero brings accessible primitives with it and does much of this automatically; the rest is a focused pass.
Numbering follows your handoff document exactly, so the two can be read side by side.
Keep, rewrite, delete

Where we agree with you, and the two places we would push back

Agreed, without reservation

  • Keep the migrations. They are the schema's history and they are idempotent. They port as-is.
  • Keep the instrument file. You called it the methodology in code and you are right. It is the product. It moves into a versioned table, unchanged in content.
  • Keep the scoring and tier logic. We recomputed it against 528 responses and it reproduces your published figures exactly.
  • Keep derived pipeline state. Computing the stage instead of storing it is the right call and it is why the pipeline has not drifted.
  • Delete the auth bypass and the migration that opens up anonymous access, before anything is exposed to a real church.

Two places we would go slower than the document suggests

“Rewrite all React components.” True eventually, but not first. A full rewrite of every screen puts three to four weeks between today and the first thing a church can see. We would rather brand the two surfaces a church actually touches, the survey and the report, then deploy those, and let the internal admin screens stay plain a while longer. They are working, and nobody outside your team looks at them.

“Move to a new framework.” Also probably right, and also not urgent. None of the five phase-zero fixes require it, and re-platforming before the data layer is trustworthy means debugging two things at once. Better to make the current build correct and visible, then move it on a known-good foundation.

Neither of these is a disagreement about the destination. It is a disagreement about what to do in week one.

The plan

Four phases, and the first one is free

Phase 0 · Polish & ship the demoFree
Constraints 1, 3, 8, 15, 19 · one pilot church, end to end

This is the build we committed to in June, and it has not changed. One church goes all the way through: survey out, staff respond on their phones, scores compute correctly, report renders in focus412 brand, live on a real URL you can send to someone. Nothing about it is a trial or a teaser; when it is done you own it.

Definition of done. All of these, or it is not finished
  • Aggregates computed in the database; two simultaneous submissions both survive
  • Every existing cycle recomputed from raw responses, so the archive is correct
  • AI insight and theme extraction working in production, not just locally
  • Survey and report rendered in your brand: correct palette, correct type, correct logo usage, per your brand guide
  • Live on a production URL with real authentication and the development bypass removed
  • Both surfaces usable on a phone, because that is where staff will take it
  • One real church taken through a full cycle, start to finish, with you watching

What we would ask of you: read access to the repository and the Supabase project, one pilot church willing to go first, and one decision on which version of the instrument is the version of record.

Phase 1 · The production platform$6,500
Constraints 2, 4, 5, 6, 11, 12, 14, 16 · partner rate, one-time, you own it

This is the phase that gets you out of the loop. A server layer so rules can live somewhere; email so invitations and “your report is ready” send themselves; tests on the maths where being wrong is expensive; and error reporting so you find out about problems before a church tells you.

The centre of it is the export. Twenty-five hand-built decks sit in the archive you sent us. Phase one is where a finished deck (your shape, your brand, your language) comes out the other end of a completed cycle without anyone assembling it. If only one thing on this page gets built after the free work, it should be this.

Phase 2 · Scale & multiple coaches$5,500
Constraints 7, 9, 10, 13, 17, 18 · partner rate, one-time, you own it

Everything that binds the second time a second person uses the system: per-coach visibility, files out of the database and into proper storage, live sync between tabs, a versioned instrument that can be varied per engagement without a deploy, real time zones, and an accessibility pass that survives an audit at a larger church.

This is also where the twenty-first question and the six drifted question wordings get settled permanently, because it is where the instrument stops being a source file.

Phase 3 · The benchmark engine$4,500
Not in the handoff document · partner rate, one-time, you own it

Nothing in this phase is a bug fix, because none of it exists yet. It is the thing you described in June: a church finishes its cycle and sees immediately how it compares to churches its size, its age, its region and its stage, drawn from every church that has ever taken it.

The companion benchmark brief shows what that already looks like against your existing archive. The work here is turning that from something we built by hand into something that updates itself, plus the region derivation and the de-identification step that should run before any church's data joins the pool.

The comparison

What this costs the conventional way

The timeline below is not ours. It is the one in section seven of your own handoff document: “estimated calendar time for a competent full-stack engineer to reach production-parity: three to four weeks.” We have taken your estimate and applied what that work actually bills at. The only figure we supplied is the hourly rate.

Phases one and two, which together are your “production parity”

Senior contractor, solo
$15,000 – $25,000
3 to 4 weeks
Your own estimate at $110 to $180 an hour. Assumes you find a good one, manage them yourself, and accept that when they finish they take everything they learned with them.
Development agency
$40,000 – $75,000
8 to 12 weeks
The same scope with discovery, project management, QA and contingency added. The calendar roughly triples because process and onboarding are billable too.
Partner rate
$12,000
Roughly 4 to 6 weeks
One-time, and you own it. Built by someone who has already read your archive, your instrument and your twenty-five reports, so none of the first week goes on discovery.

Phase three, the benchmark engine

This one is not in your handoff, so there is no estimate of yours to anchor to. The figures below are ours, and we would rather label them clearly than let them look more solid than they are.

Custom analytics build
$25,000 – $50,000
6 to 10 weeks
A data pipeline plus a language-model layer, commissioned from a firm that has to learn church-health assessment from scratch first. Our estimate, not yours
Off-the-shelf platform
$10,000 – $30,000
Every year, forever
Fast to start and never finished paying for. You cannot put the four D’s inside it, your per-question coaching insight has nowhere to live, and the benchmark that would be your differentiator belongs to the vendor. Recurring
Partner rate
$4,500
Roughly 2 to 3 weeks
One-time. The methodology is already understood, and the benchmark you saw in the companion brief already exists as a worked example against your real data.
Our calendar figures are indicative rather than committed. Real dates get fixed when we scope each phase, before anything starts. We would rather under-promise here and hold to it.

The partner rate, and what makes it one

These are not list prices. They are what we are charging focus412, and it is worth saying why rather than leaving you to wonder.

Phase 0 · Polish & ship the demoFree
Phase 1 · The production platform$6,500
Phase 2 · Scale & multiple coaches$5,500
Phase 3 · The benchmark engine$4,500
All three together$13,500 Against $6,500 + $5,500 + $4,500 taken separately, a saving of $3,000. One-time either way, no retainer, and you own every line of it.

The honest reason for the rate is that we want to build this with you rather than for you. You are the first church-consulting group we have done this with, and what you already have is unusual: a real methodology, twenty-five engagements of evidence behind it, and a working platform that most people in your position would not have got as far as building.

If it goes the way we think it will, the thing we would most value is not a bigger invoice. It is being able to point at this work, and, when it feels natural and only where you think it fits, being introduced to a church or two in your world who might want something similar. No obligation attached to any of the numbers above, and nothing here is contingent on it. It just seems like the kind of relationship where both of us end up better off, and we would rather name that openly than hope for it quietly.

Phase zero stays free regardless, and it is not contingent on any of the rest. If we finish the demo and you decide to take the code to someone else, that is a completely reasonable outcome and the work is still yours.

One thing to be straight about: these prices cover building and handing over. If at some point you would rather we also operated and monitored it for you, that is a separate and explicit conversation, never something that quietly becomes assumed.

Next

Three things, and the first one takes a minute

  1. Send read access

    The repository and the Supabase project. We can confirm the aggregation diagnosis in a single query and tell you within the hour whether it is what we think it is.

  2. Name the pilot church

    One church, ideally mid-sized and already familiar with you, willing to be first through the finished flow.

  3. Thirty minutes together

    Enough to settle the instrument of record, the twenty-first question, and which of the four phases, if any, you actually want after the free one.