Jonathan Mellette Contact

Solutions architecture · Live demo at goodsoilumc.org · The church is fictional

Good Soil UMC

A website engine for small congregations. The site is a book you turn, with tabs down its edge; every page is also a real address; and its help desk answers from a list the church writes, with no language model. The same engine runs two real congregations’ sites. They aren’t named here, so it’s shown on a church that doesn’t exist, built in a day.

Status
Live since 12 Oct 2026, kept out of every search index on purpose. The engine, begun 22 Sep 2026, also runs two live congregations’ sites.
Licence
None stated: a private repository. The vendored page-curl library, page-flip, is MIT.
Stack
HTML · CSS · JavaScript with no build step · one small Python CGI script · Apache rewrite rules · rsync deploy
Links
goodsoilumc.org · source is private

Measured · how

The constraint

A small church’s website is kept by whoever has time, read by people who aren’t sure they’d be welcome, and asked the same twenty questions all week. It has to be easy to change, easy to read, and able to answer without a person at the desk.

At a glance

pages in the book, under 8 tabs, each with its own address (51 in all)
80
answers the help desk knows, each a line the church can read and edit
124
language models, and 0 package dependencies
0
from the demo’s first commit to the site live on its own domain
32min
How these were measured
  • 80 pages, 8 tabs, 51 addresses: the site’s own structural checker, run on 12 Oct 2026 (scripts/check_demo.py: “80 leaves · 8 tabs · 19 events · 51 addresses · all structural checks pass”).
  • 124 answers: the lines with a keyword list in data/answers.js, counted the same day.
  • 0: the help desk is a keyword matcher in js/chat.js with no network call except logging a miss; no package.json, lockfile or node_modules exists anywhere in the served site.
  • 32 min: the commit adding the demo church is timed 19:06 on 12 Oct 2026, and the commit that deploys it to its domain 19:38.
The book opened to its first spread: on the left, Good Soil United Methodist Church, Harrow Creek, Texas, with Sunday times of 9:30 and 10:45, a Wednesday supper at 6, the address and the phone number; on the right, Find your way, with three drawn pictures labelled To Know, To Grow and To Sow. Tabs run down the right edge: Home, Know, Grow, Sow, Events, Articles, Help, Contact.
Fig. 1 The first spread, opened from the cover, at 1600×1000 on the live site. The church, the town and the history are invented; the pictures are drawn stand-ins.

The short version

  1. Made a demo that can’t mislead anyone: fictional by construction, out of every search index by a header that fails loudly rather than quietly, and checked by a script before every deploy.
  2. Built a help desk with no AI in it: it answers from a list the church writes, says plainly that it is not an AI, and writes down what it couldn’t answer so the list can grow.
  3. Used the demo to improve the real sites: the accessibility audit run on the demo went back into both live congregations’ copies before the demo itself went live.

Case 1 of 3

A demo that can’t mislead anyone

A convincing church website for a church that doesn’t exist is a hazard: someone could look for a service and drive to it. So the fiction is enforced, not just stated.

Everything about Good Soil is invented, down to a town called Harrow Creek with a creek that only runs after rain. The phone number uses the 555 exchange that films use, and the mailing address is an obvious placeholder, so nothing on the site can reach a real person. The footer says it is a demonstration on every page, and the help desk says so if you ask whether the church is real.

It must also never be found by someone searching for a real church on a Sunday morning. Every response from the server, pages, pictures and scripts alike, carries an X-Robots-Tag: noindex header, and the page repeats it as a meta tag. The header rule sits outside any module guard on purpose: if the server ever lost the module that sends it, the site would fail with an error instead of quietly becoming indexable.

The live site and the checker · 12 Oct 2026
$ curl -sI https://www.goodsoilumc.org/ | grep -i x-robots
x-robots-tag: noindex, nofollow

$ python3 scripts/check_demo.py
80 leaves · tabs ['welcome', 'know', 'grow', 'sow', 'events', 'articles', 'help', 'contact'] · 19 events · 51 addresses
✓ all structural checks pass
Fig. 2 Re-run on 12 Oct 2026. The same header is on the site’s pictures. The checker also confirms an even page count with every tab opening on a left page, every internal link and picture resolving, and alt text on every image.
How we know

The curl run in Fig. 2, plus the same header on /images/share.jpg. The unguarded header rule and the noindex meta tag, read in the site’s .htaccess and index.html; the checks named above, read in scripts/check_demo.py, and its call in the deploy script ahead of the upload, all on 12 Oct 2026.

Case 2 of 3

A help desk with no AI in it

Visitors ask when worship is, whether their kids are welcome, and where to park. The help desk answers from a plain list the church writes, and says so.

Each answer is one line: a few keywords, then the reply. The first line that matches wins, so specific questions (“Ash Wednesday”) sit above general ones (“Wednesday”), and a short keyword can be marked to match whole words only, so “hi” doesn’t fire on “this.” The list is ordinary text a church secretary can edit; nothing is trained, and nothing about a visitor’s question leaves the browser unless the list has no answer for it.

When it has no answer, two things happen. The question is written down by a small server script whose log lives outside the web root, so the church can see what people actually ask and add a line for it. And the visitor is offered an email with their question already in it, because the honest fallback is a person. The list opens with the answers that matter most, a crisis line and a plain welcome, ahead of service times.

The Help spread. The left page says: I’m not an AI. I’m a short list of answers the church wrote, matched to the words in your question. The right page shows a question, Can I bring my kids to Wednesday supper?, answered with times for Sunday School, the nursery, the Wednesday supper where kids eat free, and the Cherub Choir.
Fig. 3 The help desk on the live site, asked two questions in headless Chromium on 12 Oct 2026. The left page says what it is before anyone asks.
How we know

Read on 12 Oct 2026: the matcher in js/chat.js (first match wins, the whole-word flag, the miss handling and the prefilled email), the list format at the top of data/answers.js, and cgi/miss.py, which keeps the date, a trimmed address and the words. The deploy script creates the log’s folder outside the web root. Fig. 3 was captured by typing the questions into the live page.

Case 3 of 3

A book with real addresses, and a demo that paid its way

The book is the navigation, but every page is also a link someone can paste into a message, and the whole site still reads as a plain page without script.

The page engine came from Whisper’s Shout, the songbook built the night before. Here the words live in the HTML itself, as sections that each declare their tab and their address, so a screen reader or a browser with script turned off gets the text as served, and a “plain view” link drops the book for a simple page. A rewrite rule hands any address that isn’t a real file back to the one document, and the script opens the book at that page. A missing picture still returns a real 404.

Events carry the dates they are announced from and the day they end, and a small script removes finished ones before the book is built, so the Events tab always shows what’s next. An event is always a two-page spread, so removing one never knocks a tab off its left-hand page. The checker enforces that too.

The demo was built from the engine in a day, and an accessibility audit of it turned up fixes: keyboard focus that stays put, focus rings that show, page numbers and arrows with enough contrast, one main landmark and one heading per page. Those went back into both live congregations’ copies three minutes before the demo itself went live.

How we know

Read on 12 Oct 2026: the rewrite rule in .htaccess (it skips anything with a file extension), js/events.js, and the page declarations in index.html. On the live site, /know/our-pastor returned 200 and a missing .jpg returned 404. The fixes are one commit at 19:35 that changes only the two live congregations’ copies (10 files); the deploy commit follows at 19:38.