Indiana Field Archery Association · 2026

Rebuilding a 60-year-old association's website

A volunteer-run state sports body was running WordPress on a PHP version that had been end-of-life for three years, with half its pages unreachable and every competition result buried in a PDF. I rebuilt it as a static site with a real content model, cut running costs from $283 a year to about $12, and handed the board a CMS they can actually use.

Role
Sole engineer — audit, architecture, migration, build, hosting, handover
Stack
  • Astro
  • Sanity CMS
  • Cloudflare Pages
  • Pagefind
  • GitHub Actions
  • Running costs cut from $282.69/yr to ~$12/yr
  • 395 legacy documents kept at their original URLs, so no existing link broke
  • 19 previously unreachable pages brought back into the site
  • Board members publish shoots and results themselves, with no developer involved

The state of things

The Indiana Field Archery Association has been running since 1964. Its website had been maintained by volunteers for years, which had the failure mode volunteer-maintained sites usually have: the information was all there, and none of it could be found.

The audit turned up more than expected.

  • PHP 7.4, end-of-life since November 2022 and unpatched ever since.
  • 19 of 38 pages were unreachable from the menu or any link — including the three pages holding the association’s best historical records.
  • 395 of 477 media items were PDFs. Nearly every competition result was a link to one. Nothing was searchable, filterable or readable on a phone.
  • Every image on the site had empty alt text. Not most of them — all 79.
  • Pinch-zoom was disabled site-wide, which matters a great deal for a membership that skews older.
  • Three overlapping calendar plugins were installed simultaneously.

What I built

A static site on Astro, with content in Sanity so board members edit through a web UI rather than a page builder. Cloudflare Pages serves it.

The decision that shaped the rest: legacy URLs had to keep working. Results PDFs are linked from emails, Facebook posts and printed handouts going back years. So the migrated documents ship at their original WordPress paths instead of being re-uploaded into the CMS — existing links resolve, and the CMS stays small.

The migration ran against the old site’s REST API. That turned up a trap worth recording: Divi only expands its shortcodes in the query-loop context, so fetching a page by slug — or with a _fields filter — returns raw [et_pb_...] markup with every link stripped, at status 200. The same page ID returns completely different bytes depending on how you ask for it. Verified on one page: 34 links via pagination, zero via slug lookup.

What changed for members

  • One searchable results archive instead of a menu of PDF links, filterable by year, type and district, with site-wide search on a build-time index.
  • A page for every one of the 34 member clubs, with directions and the shoots they’ve hosted.
  • Calendar subscriptions — members subscribe once and new dates appear on their phone. Indiana spans two time zones, so events carry their own zone rather than assuming one.
  • Sixty years of Lifetime Achievement history, back to 1966, out of a page-builder table and into structured content.
  • Every page passes automated accessibility testing, and pinch-zoom works again.

What it costs now

Before After
Hosting $107 $0
SSL certificate $80 $0
DNS $55.69 $0
Domain $40 ~$12
Total $282.69 ~$12

The site is plain files rather than software on a server, so there is no login, no database and no plugins — nothing to patch and very little to attack.

Keeping it honest

The site ships with a health monitor that runs every six hours and checks the things that have actually gone wrong: soft 404s, the 125 document links, iCal feeds validated as real RFC 5545 rather than merely returning 200, certificate and domain expiry, and whether the calendar has run out of upcoming events — the failure with no symptom, where the site looks perfect and is simply out of date.