From c04a7dc307ce5c0e5dfad3886659e9434417847c Mon Sep 17 00:00:00 2001 From: Jad wauthier Date: Wed, 12 Aug 2026 09:42:56 -0500 Subject: [PATCH] Rework homepage copy for voice and internal linking Shifts the homepage from an argument-driven register to a wonder-driven one, restructures the closing paragraphs to each end on a link instead of a self-explaining sentence, and adds a Projects section with the first project page (GroupsIO Group Manager). Closes #8 Co-Authored-By: Claude Sonnet 5 --- src/layouts/BaseLayout.astro | 1 + src/pages/index.astro | 34 ++++--- .../projects/groupsio-group-manager.astro | 99 +++++++++++++++++++ src/pages/projects/index.astro | 25 +++++ 4 files changed, 143 insertions(+), 16 deletions(-) create mode 100644 src/pages/projects/groupsio-group-manager.astro create mode 100644 src/pages/projects/index.astro diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index 9444818..1dcf3dc 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -19,6 +19,7 @@ const { title } = Astro.props; diff --git a/src/pages/index.astro b/src/pages/index.astro index c9672a2..e75cb00 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -17,31 +17,33 @@ import BaseLayout from '../layouts/BaseLayout.astro'; A few years ago, blind users struggled just to figure out where a control lived on a page - top-left, buried in a sidebar, or three tab-stops past a broken landmark. JAWS 2026’s - Page Explorer (opens in a new tab), + Page Explorer, paired with AI, can now describe an entire page’s layout in detail, in seconds. That’s not incremental improvement. That is the exact kind of threshold Clarke was talking about - things that were once impossible are suddenly ordinary.

- It works because good code makes it possible. Page Explorer can only - describe a page well if it was actually built with real - structure underneath it - not div soup. That is the same reason - a single misplaced comma can break an entire application, and the - same reason a single design choice, like where a control sits on a - page, can make or break a user’s ability to use it. Building - technology is not just about presentation. It is about experience. + When I started writing software in the early 2000s, IDEs had no real + concept of a screen reader. JAWS and NVDA weren’t supported so + much as tolerated — you learned to work around your tools, not + with them. Twenty years later, VSCode ships an accessible view built + specifically for output like mine, no workaround required. That gap + didn’t close on its own. It closed because a few engineers + followed simple rules — real structure, real landmarks, real + semantics — instead of bolting accessibility on after the fact. + You can see that same approach at work in my + projects.

- People often ask me: “How can you code if you can’t see - the computer?” Everyone has limitations. The difference is what - we do with our abilities. I don’t use a monitor and a mouse - - I use a keyboard and a screen reader. That’s not a - limitation on what I can build. It’s just a different - interface. + Page Explorer and VSCode’s accessible view are both, at their + core, AI describing an interface to me. The next step is AI that + doesn’t just describe an interface — it acts on one, and + coordinates with other AI to do it. That’s the question behind + the research I’m doing now: how agents behave, and misbehave, + when several of them have to work together. You can follow that work + on my research page.

- -

Get in touch

diff --git a/src/pages/projects/groupsio-group-manager.astro b/src/pages/projects/groupsio-group-manager.astro new file mode 100644 index 0000000..63be7c2 --- /dev/null +++ b/src/pages/projects/groupsio-group-manager.astro @@ -0,0 +1,99 @@ +--- +export const prerender = true; + +import BaseLayout from '../../layouts/BaseLayout.astro'; +--- + + +
+

GroupsIO Group Manager

+ +

+ A WordPress plugin built for + BITS, a + blindness-focused nonprofit and professional affiliate of the American + Council of the Blind. It keeps BITS’s Groups.io mailing lists in + sync with actual paid membership, automatically, so no one has to + manage list access by hand. +

+ +

The problem

+

+ BITS runs its member communication over Groups.io mailing lists and + manages paid membership through Paid Memberships Pro (PMPro) on + WordPress. Before this plugin existed, keeping the two in sync was a + manual job — someone had to notice when a membership lapsed or a + new member joined, and update Groups.io by hand. Miss it, and either a + lapsed member keeps member-only access, or a new member goes + unreached. +

+ +

What it does

+
    +
  • + When a membership begins or changes, the plugin reads the mailing + list selections already captured on the member’s PMPro + profile and adds them to the corresponding BITS Groups.io lists + — both the lists every member must belong to, and any tied to + their specific membership level. +
  • +
  • + When a membership ends — expiration, cancellation, or account + deletion — the plugin automatically removes the member from + every BITS Groups.io list they were part of. +
  • +
  • + A nightly reconciliation job checks for drift between what PMPro + says a member’s access should be and what Groups.io actually + reflects, and corrects any mismatch. +
  • +
  • + A passwordless “magic link” feature lets a member reach + their WordPress profile by email, without needing to recall a + password. +
  • +
+ +

How it’s built

+

+ Membership-change events are picked up via PMPro’s + pmpro_after_all_membership_level_changes hook and handed + off to a background job queue (Action Scheduler), so a member checking + out or an admin making a change is never blocked waiting on a + Groups.io API round trip. Every add and remove call is logged to a + dedicated audit table, with its own retention policy. The Groups.io + API client handles rate limiting (HTTP 429, honoring + Retry-After with jitter) and retries transient failures + with exponential backoff, and hard-stops all sync activity with an + admin alert if the API credential itself becomes invalid. +

+

+ Because a single member can be registered under different email + addresses for different mailing lists, sync and removal logic + operates on (list, email) pairs rather than assuming one address + covers a member’s entire subscription. The plugin also honors + Groups.io’s own unsubscribe, bounce, and spam signals — + once flagged, a member is permanently excluded from future automatic + adds, in keeping with CAN-SPAM — and handles GDPR/CCPA + right-to-be-forgotten erasure with an immediate, no-grace-period + removal from every list. +

+ +

Admin controls

+

+ Administrators work through a “GroupsIO Management” admin + menu with three pages: feature controls (mandatory lists, grace + period before removal, log retention, and an emergency kill switch), + subgroup management (creating, editing, and inspecting the Groups.io + subgroups themselves), and user assignment (a searchable member list + with per-member details and manual override tools for when + automation needs a human to step in). +

+ +

+ View the source on GitHub (opens in a new tab) +

+ +

Back to projects

+
+
diff --git a/src/pages/projects/index.astro b/src/pages/projects/index.astro new file mode 100644 index 0000000..c515d27 --- /dev/null +++ b/src/pages/projects/index.astro @@ -0,0 +1,25 @@ +--- +export const prerender = true; + +import BaseLayout from '../../layouts/BaseLayout.astro'; +--- + + +
+

Projects

+ +

+ A collection of the software I’ve built — each one an + example of the same practice: real structure, real landmarks, real + semantics, not accessibility bolted on after the fact. +

+ +
    +
  • + GroupsIO Group Manager + — a WordPress plugin that keeps a nonprofit’s Groups.io + mailing lists in sync with paid membership status automatically. +
  • +
+
+