Drawing 02.3, nonprofit platform
No More Fatherless
Grant intake and administration for a 501(c)(3) that funds adoptions and walks with foster youth. Families apply in minutes with no account, the team reviews and awards from one place, and approved families send their receipts through a private link.
| No. | Part | What it does here |
|---|---|---|
| 1 | Browser | Families apply with no account and send receipts by emailed link; admins sign in by magic link. |
| 2 | EventBridge | A daily call that clears abandoned receipts, prunes guard rows, and sends deadline reminders. |
| 3 | CloudFront | TLS, the www redirect, and the secret origin header; it has no route to the receipts bucket. |
| 4 | Next.js on Lambda | The application, the receipts page, and the admin in one container, with secrets read from SSM at start. |
| 5 | Receipts bucket | Private S3: presigned uploads in, an admin-gated stream out, and every read logged. |
| 6 | Neon Postgres | Grants and their questions, applications, hashed access tokens, the audit trail, and the rate limits. |
| 7 | SendGrid | Admin sign-in links, receipt links, and deadline reminders. |
Why it exists
They were running real grant applications through scattered forms and inboxes. They needed one accountable system: simple for a family in a hard season to apply, and organized enough for a small team to keep up.
The interesting part
Each grant is the admin's to define: its availability window, its largest award, and its own questions, and one schema built from those questions validates both the form and the server. Questions are archived, never deleted, and every answer keeps its own copy of the question it answered, so rewording a question can never change what an applicant was asked. That matters two years later, when a board member asks what a 2026 applicant agreed to.
Receipts come after approval. The family gets a link with a hashed, expiring token, and each receipt goes from the browser straight to a private S3 bucket through a five-minute upload URL with its size signed in. The bucket is not behind the CDN at all; the only way out is a route that checks for an admin. A daily scheduled call clears abandoned uploads and sends one deadline reminder per family, and the rate limits live in Postgres, so they fail closed.
What it does
- Grants with their own questions, windows, and award limits
- Applications with no account, for a whole family
- Receipts by private link after approval
- Review, awards, and CSV export in one admin
- Sign-in by emailed link for an allow-listed team
Plates
