Last week PewHQ crossed the line into pilot-ready. This week it met an actual church, and that meeting rearranged the entire roadmap in about ninety minutes. Most of what follows is the result. Chervil also shipped 0.28.0, SlingAgent got a real scheduling calendar, and ReelRifter stopped pretending free streaming services do not exist. Let me walk you through it.
PewHQ took the overwhelming majority of the week’s work. I am going to group it by theme, because commit order would not tell the story.
The meeting that changed the plan. On Monday I sat down with a church that had left Realm for One Church and then come back, because finance and people had to live together. Four facts came out of that conversation, and every one of them is now load-bearing:
1. Any plan shaped like One Church ends the way One Church ended.
2. The unmet need is a forum, not a broadcast tool. They want threads where a reply can go to one person, which neither Realm nor One Church allows.
3. Sixty percent of their people failed to log into Realm. So the feature has to work by email for someone who never signs in.
4. Their youth are on Discord and GroupMe, which is a safeguarding problem before it is a tidiness one.
I also asked a church running Planning Center, eSPACE and Teams what they use for outreach. The answer was “none for outreach.” They are not shopping for a church management system, they already have one. They named a hole. So the strategy is now explicit: coexist with what a church already runs, do not try to replace it, and build the things nobody is filling for them. That killed a general ledger (months of work in a domain where approximately right is worthless) and promoted group email to the top of the list.
Group email threads, the wedge. This is the biggest thing that shipped this week. A church group now gets its own email address, something like mensstudy@yourchurch.pewhq.com. Anyone in the group emails it, and it fans out to every member. Reply goes privately to the person who wrote it, Reply-all reaches the group. That behavior falls out of header placement rather than a setting anyone has to find, which is the whole point: it works for the sixty percent who will never log in.
Getting there was a week of small, careful decisions:
• A one-day spike before committing to a vendor. I sent real replies from Gmail and Outlook and checked whether threading headers survived. They did: twenty-nine headers came through from Gmail and forty-two from Outlook, the client’s full set. That meant no second email vendor and no MIME parser to own.
• Loop defence in both directions. One holiday auto-reply fanned out to four hundred people, whose auto-responders answer it, is how real mailing lists melt down. Inbound mail carrying auto-reply markers is dropped before routing, and every outbound copy is stamped so well-behaved responders stay quiet.
• Sender authorization is not decoration. An address that fans out to hundreds with no membership check is an open relay. Non-members are refused silently, because replying “you are not a member of Men’s Study” tells a stranger the address is live and who is on it.
• Provisioning is automatic. Turning threads on for the first group provisions the church’s receiving subdomain at Resend, writes the MX record into Vercel DNS, and every group after that reuses it. Status stays honest as “pending” until DNS actually propagates, because handing out an address that quietly drops mail is worse than making someone wait.
• A daily digest, built before the traffic rather than after. Three states per group: every message, one email a day, or nothing by email. Per group matters, because someone drowning in one chatty group otherwise unsubscribes from the church entirely and loses everything else with it.
• Web posting, moderation, @-mentions and bounce suppression. Members with no address on file can post from the browser and it still joins the same conversation. Leaders can remove a post or mute a member in their own group only (no global queue, because that becomes the office bottleneck this feature exists to remove). Removal is always soft, and always will be.
Youth supervision, which is the safeguarding answer. A group is supervised because a minor is in it, never because someone remembered to tick a box. A safeguarding control that can be forgotten is not one. Guardians are derived from adults sharing the child’s household. They receive every message and can read the archive, and they cannot post, because an adult appearing inside a youth group discussion is exactly the thing this prevents. The group page reports how many children have no adult on file rather than implying cover that is not there.
Then the piece that actually beats Discord: a parent can download a full transcript of everything said in every group their child is in, as plain text they can hand to a safeguarding officer or a lawyer. It includes removed posts, marked as removed, because a transcript that quietly omits what a leader took down would answer the question wrongly while looking complete. And supervised groups are never purged by a retention policy, whatever the church sets, because “what was said to my child” is the question the whole layer exists to answer.
The treasurer’s week. Finance got the vocabulary an audit and a Form 990 already use, without building a general ledger:
• Donor restriction on funds. US nonprofit reporting splits net assets into with-restriction and without. PewHQ could total money per fund but could not answer “how much of this is spoken for,” which is the question an auditor, a board and a 990 all ask in the same words.
• Closing the books. Once January is closed and reported, January must still say the same thing in March. Without a lock, a backdated gift silently changes a published number, and that is the complaint that sends a church back to its old system.
• Bank reconciliation. The question a treasurer actually asks is “the bank shows $4,182.19, what was that?” Stripe batches several days of charges and takes its fees before depositing, so that number matches no gift and no daily total. PewHQ now walks payout to charge to gift and shows both the gross giving and the fee, so a treasurer can prove the number rather than trust it.
• Two correctness bugs found while wiring that up. Paid event registrations settle through the same Stripe account, so a payout carrying 3,400 of retreat tickets and no giving would have reported a3,400 negative fee. And recurring gifts were recorded with an invoice id but no payment intent, and reconciliation matches on intents, so every payout carrying regular giving under-reported income and over-reported Stripe’s fee. Recurring is usually a church’s steadiest money, so that one would have been wrong for most churches most months.
• A board statement. One printable page, with balances shown as of a date and activity within a period, never mixed. A year’s giving printed beside an all-time balance is the classic church-finance report error, and no two people read it the same way.
The newsletter got a real composer. The church I looked at builds its “this week” section as a graphic in Canva, which means it cannot reflow on a phone, cannot be read aloud, is invisible when a mail client blocks images, and has to be remade weekly. All of that already exists in PewHQ as calendar data. So there is now a block editor (words, this week’s events, photos), automatic two-column layout chosen rather than configured, a length budget so the bottom of a long letter is not wasted, and a preview that runs the real send-time renderer instead of an approximation. It is all built with tables and inline styles, because Outlook still lays out mail with Word’s engine.
Text messaging got compliant. Before a church can text anyone in the US, carriers want consent provenance and a HELP reply. Both landed, along with A2P 10DLC registration in the ISV model, where each church registers under its own EIN, because trust score and throughput are per-brand and a shared brand would let one church’s bad list throttle everyone. Broadcasts moved from inline sending to a real queue with delivery-status callbacks, and usage is metered per segment, not per message, because one emoji flips a text from 160 characters to 70 and more than doubles what I pay Twilio. Number release now has a thirty-day grace period, since congregants have that number saved in their phones.
The church website builder became a real website. I benchmarked two live church sites. The gap that mattered was not polish: both had seven or eight real navigation items and PewHQ had one page with three anchor links. So: real multi-page sites with configurable nav, ministries as their own thing (a church publishes three ministries while running forty groups), a contact page whose form feeds the guest funnel, a mobile menu, the church’s own logo, service times laid out as an actual schedule, an optional map, and the PewHQ attribution removed from every church-facing surface. It is the church’s site, not mine.
And you can now draft the whole thing from a short interview. Answer a few questions about your town, tradition, tone and ministries, and Grok drafts the headline, the about page, what-to-expect, and two or three pages. The model writes copy and nothing else. It never touches the database, the admin gets the whole draft as ordinary editable fields, and a normal save commits it. Most of that prompt is a list of the ways church-website copy usually goes wrong: stock phrases, exclamation marks, insider vocabulary a first-time visitor will not know, and inventing facts nobody supplied.
Demos, so a church can actually look. Three things shipped here. A public click-through tour at /tour, built from captured stills rather than the live app (prospects have no login, and a real congregation’s records must not sit on a public page). A /try page for anyone who finds us without an invite. And demo minting: I can hand any prospect their own private sandbox church, seeded with a fictional congregation, that resets itself every night. Each invite gets its own org, because a shared sandbox means two churches overwriting each other’s groups halfway through an evaluation.
A demo org is an ordinary church isolated by the same row-level security as every other one. What makes it a sandbox is what it may not do: no email that actually lands in an inbox, no text that actually costs a segment, no Stripe account connected to the platform. Those are incidents, not embarrassments. Everything else stays live, because a demo where half the buttons are dead teaches a church nothing.
Then I added a nightly check that the demo churches still demo well, after a full recapture exposed seven screens that were honest but bad adverts: child check-in showing a “create your first room” form on the step titled “Sunday morning”, reports reading zero attendance for nine of twelve months on the screen that promises twelve-month trends, serving teams all reading “upcoming: 0”. All seeding gaps rather than product faults, and all now caught automatically before a prospect sees them.
And the honest one: row-level security had never actually been enforced. I ran a diagnostic against production and got this back:
current_user is_superuser bypasses_rls
neondb_owner f t
That is the whole explanation. Every tenant policy in the schema was correct. FORCE ROW LEVEL SECURITY was set on seventy-four tables. And none of it had ever been evaluated, because a role with rolbypassrls ignores RLS everywhere, and FORCE does not close that (it removes the table owner’s ordinary exemption and has no effect on BYPASSRLS). So the tenancy model had been running on one leg, and the symptom I had been chasing, two demo churches showing the same fifty people, was not a quirk. It was that.
The fix is a new pewhq_app role with NOBYPASSRLS, with a two-count transaction that proves policies bite before the connection string is switched, and instructions to do it on a Neon branch first. I also audited every untenanted read and scoped the ones that needed it. The security page tells churches the database “refuses to return anything else.” That was not true on Sunday. It is true now. Finding this before a pilot rather than during one is the single best outcome of the week.
Last theme, and it is a lesson: findability. Five separate times in this project, a feature turned out to exist under a name nobody would search for. Outreach was spread across three menus. Paid registrations were filed as Forms, and I nearly built a duplicate registrations table before realizing the whole thing already worked. Per-tenant sending domains were assumed missing. Each time the fix was local. The cause was not.
That failure is unrecoverable in the field. Nobody files a bug saying “I assumed you didn’t have this.” They just conclude the software cannot do it. So there is now a search index keyed on the church’s words: tithe, offering, first-time guest, bulletin, rota, nursery, mailing list, tax receipt, 990, camp registration. Ctrl/Cmd+K from anywhere. Things I deliberately do not build answer honestly rather than returning nothing, so searching “work order” points at eSPACE and “general ledger” points back at your own accounting package. “We don’t, and here’s who does” is a better answer than silence. A CI check compares the nav against the index so a screen cannot go missing, and it found three real gaps the first time it ran.
The admin navigation got grouped the same week (thirteen flat items is not a menu, it is a list you have to read), Money finally got its own menu so a treasurer can find the treasurer’s screens, and three labels got renamed from what the code called them to what a church secretary would call them: “Finder” became Sign-up requests, “Workflows” became Follow-up plans, “Engagement” became Who needs attention. Contextual help went from six of seventy-eight admin pages to all of them, resolved from one mapping instead of edited page by page.
The pattern across all of it is worth saying plainly: the gaps in this product are mostly joins between things that already exist, not missing capabilities. A connect card now starts a follow-up automatically instead of waiting for someone to notice it on a Monday. The engagement screen can enroll someone, not just log that a call happened. An event can name the form people register on, so a paid retreat stops offering a free RSVP beside an $85 ticket, which is how a church ends up with a coach booked for forty and thirteen people who paid.
Chervil shipped 0.28.0, and it closes two gaps I hit myself while using it.
Saved replies. Composed pages already filed themselves into the Library, but a chat answer lived only in its tab and went with it. Now a star on any of Sprig’s replies files it in a new Library, Replies section, where it can be re-read, searched by its own text, copied, reused as composer context, or opened as a real Chervil page (which gets it Export, Print and Remix for free). It syncs like bookmarks.
A print preview worth the name. Windows was reporting “This app doesn’t support print preview,” because Electron ships Chromium’s printing stack without Chrome’s preview UI. So Chervil now draws its own: a paginated sheet with destination, range, copies, layout, paper, margins, scale, colour and background graphics beside it. Save as PDF is a destination, and the system dialog stays one click away.
That work also turned up a genuine landmine. A page range Chromium rejects, a typo or pages past the end, wedged PDF generation for the whole app, Export PDF included, until restart. Ranges are now parsed and clamped against the document’s real length before they ever reach it.
Sprig got two new portraits for the release posts as well: reclining on an Android phone for 0.27.0, and standing on a wharf with save icons and a printer floating past for 0.28.0.
SlingAgent spent the week turning its calendar from a display into a tool.
There is now a week view alongside the month grid: a Fedica-style hour-by-hour layout with a live “now” line, overlapping posts split into side-by-side lanes, and drag-to-reschedule snapped to fifteen minutes. A generated batch is a dozen posts a few minutes apart, which shaved the old layout into unreadable slivers, so posts sharing a time window now draw as a single stacked chip that opens a list, and dragging that chip moves the whole batch while keeping its internal spacing. Already-published posts never move.
Clicking an empty slot now creates something. It asks which link to promote and deep-links into that link’s generator with the slot attached, so the batch lands at the exact minute you put it rather than the usual preferred-hours scheduling. That works from the mobile agenda too.
The rest of the week was chasing one bug family to the ground. “Optimized” scheduling was resolving to your earliest preferred posting hour on the chosen day, so scheduling anything after 9am produced a time in the past and got refused with “Pick a date and time in the future.” It now walks your preferred hours and takes the first one that has not passed, previews the resolved time, opens on tomorrow if today has no hours left, and disables the button instead of round-tripping to a rejection. Related: request-level failures were being rendered as a fabricated X result row, which is why every one of these errors read as an X (Twitter) failure.
Also landed: a light and dark theme switch (the site was dark-only even though the light palette already existed in the stylesheet), account chips in the share-once picker that lead with the actual platform mark instead of a profile photo that might not load, and a mobile menu that no longer runs off the top of the screen.
ReelRifter had a blind spot. TMDB’s display priority tracks paid service prominence, so it buries the free ad-supported services well past the picker’s forty-service cap (Tubi ranks 346 in the US, Pluto TV 72). They had no entry in the price catalog either, and an unpriced provider gets dropped from the optimizer’s cost math and stripped off every title. Net effect: a show streaming free on Tubi looked like it needed a paid subscription.
Tubi, Pluto TV, Plex, Xumo Play, PBS and Freevee are now rescued into the picker and priced at zero, so their coverage counts against what you actually need to pay for. Freevee in particular was hiding as “Amazon Prime Video Free with Ads,” which sorts next to Amazon Prime Video and reads as a tier of it rather than the free standalone catalog it is. The duplicate Plex listing (TMDB carries the same catalog under two ids) now collapses into one chip.
The other significant fix: auto-finish now understands shows you watched out of order. It used to promote a show to Finished only when your linear progress pointer sat on the final aired episode. That pointer moves forward-only and follows TMDB’s season numbering, so it missed a whole class of genuinely finished shows: anything watched out of order, or imported from Trakt or Plex whose season splits disagree with TMDB. Long anime is the worst case, where TMDB folds 180 episodes into one season and the import used four. Now it also finishes a show when you have as many watched episodes recorded as the show has aired. A dry run over production found twenty titles across the user base that qualify today, zero of which the old rule would have caught, with no false positives. The nightly sweep also got faster: a full pass over all 2,002 candidate rows now takes about 17 seconds where the cron was burning 54.
Also: the sticky title bar stopped hiding behind the sidebar rail on desktop, the Episodes tab moved ahead of Cast & Crew on TV pages (because “what do I watch next” is why people open the page), and the Watchmode batch crons now honor Retry-After on a 429 instead of treating every rate limit as permanent quota death.
One meeting with a real church turned PewHQ from a feature list into a strategy, group email and youth safeguarding became the wedge, the tenancy model got a hole closed that had been open the whole time, and three other products got quietly sharper.
That was a heavy one, and honestly the most useful thing that happened all week was sitting in a room and being told what a church actually needs. If you run a church, or know someone who does, and you would like a private sandbox to poke at, reply to this post and I will mint you one. Same for Chervil, SlingAgent or ReelRifter: reply here or find me on Discord. I read everything.
See you next Friday.

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.