Nonprofit
Donor management for a small nonprofit
A small nonprofit records donors, one-off and recurring donations, and which campaign each came from. It flags recurring donations that have stopped, and produces the annual tax receipt for each donor without anyone assembling it by hand.
Automatically generated draft
Written by machine against our own engineering playbook. The company is invented; the decisions are the ones we would make on a real build. A reviewed blueprint goes further — nine sections, agreed line by line, and it is what the build is tested against.
Section 01 · What has to work
The product must automatically generate an accurate annual tax receipt for each donor, consolidating all their one-off and recurring donations.
Section 03 · Screens
Every screen, and what it is for.
- ›Dashboard — Team sees recent donations and flagged lapsed recurring donations, donation totals must be instant.
- ›Donors — Team searches and views all donors, search results must be instant.
- ›Donor Profile — Team views one donor's complete giving history, all donations must load instantly.
- ›Campaigns — Team creates or edits fundraising campaigns, campaign list must be instant.
- ›Tax Receipt Generation — Team selects a year and generates all receipts, the preview must be instant.
Anything not on this list is not in version one. That is what keeps a fixed price fixed.
Section 04 · The data model
What it stores, and who can read a row.
Donor
id uuid, name text, email text, address jsonb, created_at timestamptz
Access · A team member can read any donor record.
Campaign
id uuid, name text, start_date date, end_date date, created_at timestamptz
Access · A team member can read any campaign record.
Donation
id uuid, donor_id uuid, campaign_id uuid, amount numeric(10,2), payment_processor_charge_id text, donated_at timestamptz, status enum(pending, succeeded, failed)
Access · A team member can read any donation record.
RecurringProfile
id uuid, donor_id uuid, campaign_id uuid, amount numeric(10,2), interval enum(weekly, monthly, quarterly, yearly), status enum(active, lapsed, cancelled), payment_processor_subscription_id text
Access · A team member can read any recurring profile record.
TaxReceipt
id uuid, donor_id uuid, tax_year int, total_amount numeric(10,2), issued_at timestamptz, pdf_storage_key text
Access · A team member can read any receipt; a donor reads their own.
Those access rules belong in the database, not in the screens. Someone who edits the address bar still cannot read a row that is not theirs — and the test that proves it blocks delivery if it fails.
Section 05 · States
RecurringProfile: active → lapsed → cancelled
Most scope arguments three weeks into a build are really arguments about a state nobody named at the start.
Section 06 · Where this breaks
What bites products like this one.
Payment processor webhooks fail, causing donation records to become out of sync with actual payments.
Build a nightly reconciliation job that compares our records against the processor's data via their API.
A donation made late on Dec 31 in the donor's timezone is recorded as Jan 1 server-time.
All transaction times are stored as timestamptz (UTC); the tax year cutoff is explicitly defined as midnight UTC.
Team members create duplicate donor records, splitting a single donor's giving history across two profiles.
On donor creation, perform a lookup by email and flag potential duplicates for manual review and merge.
Section 08 · Deliberately left out
What version one does not do.
- ×Real-time dashboard alerts for lapsed recurring donations — we would provide a daily report instead to defer building background job infrastructure.
- ×Historical data import from spreadsheets — we would require manual entry for v1 to focus on capturing new data correctly first.
This is the section that protects the date, and the only place in the document where somebody says no. It is also why clients trust the rest of it.
Still open
What we would ask before quoting.
- Which payment processor (e.g., Stripe, GoCardless) holds the master record of donations, and will we have API access?
- What are the specific formatting and legal text requirements for an official tax receipt in your jurisdiction?
- How is existing donor and donation history stored now, and in what format will we receive it for a future import?
Half of this already exists
Doc Intake
The paperwork half of this is a solved problem: documents read on arrival, validated against your rules, and a person asked only about what does not add up.
It is one of our pre-built products: the code is handed over to you, adapted to your own wording and rules, and the rest of the specification above is built on top of it rather than from scratch.
Your product, not this one
Get this written for what you are actually building.
Describe it in a sentence and the generator returns the same sections for your own product. Free, no email, nothing saved to a list.
Next step
Find out if your idea fits in 10 working days.
Tell us what you want to build. We reply the same day with a straight yes, no, or here is what we would cut.