Aimone Advisory Book a call
← All work
Nonprofit · built and run as a volunteer board member

Save the Queen City: a volunteer board that no longer depends on one inbox

Everything a volunteer preservation group runs on: public site, members hub and a daily routine that files documents and briefs the board.

"I'm blown away with what Tom has done with it."

Vice President, Plainfield preservation nonprofit (I serve on its board)
The Save the Queen City website

What changed

The situation

The group runs on volunteers, with no budget for staff or software. Its work depends on showing up at the right city hearing with the right history in hand.

What I built

A public site

Member sign-ups, an email list the group owns, and always-current links to city agendas.

A private members hub

Real board and member logins, not a shared password.

A daily routine at 5 a.m

It files inbox attachments into a tagged archive, syncs meeting invites, and pulls new city meeting documents.

An AI board briefing

The members home page opens with a summary of what's new and what needs action, with a link to every source it used, beside the calendar.

A searchable archive

Ask questions across years of minutes and case files.

A practice copy

The whole site, duplicated, where the board reviews changes before they go live.

A nightly check

Both sites are checked, and an alert goes out only when something is wrong.

What it costs

Beyond the domain, effectively nothing. Everything runs inside AWS and Google free tiers, on accounts that belong to the nonprofit, so the group isn't locked into any volunteer's personal subscription.

How it fits together

The group's Google Workspace holds mail, files and calendar and runs the daily routine. AWS serves the site, guards the members hub and checks itself nightly.

Save the Queen City architectureSTQC AWS ACCOUNTSANDBOX · FULL REPLICASTQC GOOGLE WORKSPACEOUTSIDE123456789Publicresidents, pressBoard + membersown loginsCloudflare DNSdomain onlyCloudFrontTLS, cachingEdge functionclean URLs +members gateS3 sitepublic pages +members hubLogin functionsession cookieCognitoboard + memberaccountsSNSalert only ifsomething is wrongNightly validatorread-only checks,both sitesUpdate functionsecret-signed;writes + refreshesSandbox siteown CDN, bucket,loginsTerraformone modulebuilds bothShared inboxboard mailDrive archivefiled, tagged,sensitivity-markedApps Scriptdaily 5 am runCalendarinvites syncedGeminiboard briefingNotebookLMQ&A over yearsof recordsCity agenda portalmeetings + PDFs

Colors follow AWS service categories; grey is outside the account; dashed lines are background paths. Swipe the diagram sideways.

Step by step
  1. The public reaches the site through CloudFront. An edge function cleans up addresses on every request.
  2. Members sign in through a login function backed by Cognito. The edge function turns anyone without a valid session away from the members area.
  3. Every day at 5 a.m., an Apps Script routine reads the shared board inbox.
  4. Attachments are filed into the Drive archive by topic and date, tagged, and marked if sensitive. Thread context is saved beside them.
  5. The routine watches the city’s agenda portal and pulls new meeting documents as they are posted.
  6. Gemini writes the board briefing under strict rules: business items only, and a link for every source.
  7. The routine publishes the briefing and recent documents through a secret-signed update function.
  8. The update function edits the right sections of the site and refreshes the cache, on both the live site and the sandbox.
  9. Every night, a read-only validator checks both sites against the site plan and sends an alert through SNS only if something is off.

Technical details

For your IT person: components, trade-offs and security. Open any section.

Components
LayerServiceWhat it does here
EdgeCloudFront + CloudFront FunctionTLS, caching, and clean-URL rewrites. The function also checks for a session cookie before serving anything under the members area.
SiteS3 (private)Static public pages and the members hub, readable only by CloudFront.
Sign-inLambda (login) + CognitoThe login function is a second CloudFront origin for sign-in paths. It checks credentials against Cognito and sets the session cookie on the parent domain, so the apex, www and production addresses all work.
PublishingLambda (update)Accepts signed requests from the daily routine, updates named sections of pages, stores hosted files, and refreshes CloudFront.
CheckingLambda (validator, Python) + SNSEvery night it reads both buckets and checks them against a schema of pages, entities, categories and redirects. It flags any hand-written brief older than three weeks. It never writes.
Daily routineGoogle Apps ScriptRuns once a day around 5 a.m. Its steps are filing, library organizing, sensitivity tagging, thread export, calendar sync, agenda watch, the briefing and the publish.
AIGemini API, NotebookLMGemini writes the briefing. The routine picks the current model automatically and keeps a cached fallback, so a model retirement doesn’t break the morning run. NotebookLM answers questions over the archive.
WorkspaceGmail, Drive, CalendarA shared board inbox, the document archive and the group calendar, all owned by the nonprofit.
EnvironmentsTerraform (shared module)The same module builds production and a complete sandbox, each with its own bucket, CDN, sign-in pool and functions.
Design decisions and trade-offs
Use the Workspace the board already lives inThe mail, files and calendar were already in Google. Running the routine there means no copying data out and no new logins for volunteers.
Serve the site from AWSPrivate buckets, edge-gated members pages and real sign-ins cost nothing at this scale. The site no longer depends on a paid website plan.
Sign every writeThe only way to change the site from outside is a request carrying a shared secret, into a function that can edit only named sections.
Sandbox with its own loginsThe board reviews changes on a full copy. Its sign-in pool is separate, so a sandbox login can’t open the real members area.
Checks that stay quietThe nightly validator emails only when something breaks, so an alert always means something.
Written restore stepsEvery change is snapshotted before it ships. The routine has a tested backup copy and step-by-step restore notes, so a new volunteer could recover it.
Security and privacy
  • The members area is enforced at the edge and at sign-in, not by hiding links.
  • Sensitive case files are tagged so they stay out of anything public.
  • Secrets live in script properties and function settings, never in page code.
  • The nonprofit owns both the AWS and the Google accounts.

Run a nonprofit or a small office?

The same pattern works for any group whose knowledge lives in a shared inbox. Book a free 30-minute fit call and I’ll tell you what it would take.

More write-ups