~/work/sankofa-lab
Sankofa Lab website
Website for a STEM education non-profit in Africa
The website for Sankofa Lab, an educational non-profit that makes STEM learning accessible to pre-tertiary students in Africa. It's a fast static site built with Astro and hosted on Cloudflare Pages. A Cloudflare Worker in TypeScript handles the contact form and a question box where students can send questions to the team.
Static
Astro site on Cloudflare Pages for quick load times
CI/CD
GitHub Actions deploys the site and the Worker on every push
2 forms
handled by one Cloudflare Worker in TypeScript
sankofalab.org

01 · the problem
Sankofa Lab needed a public website to explain its programs, publish blog posts, and let students, parents, and partners get in touch. Students also needed a way to send questions to the team. As a non-profit, it needed hosting that costs little to run.
02 · what I built
- Built the site with Astro as static pages with self-hosted fonts and very little client-side JavaScript, hosted on Cloudflare Pages.
- Wrote a Cloudflare Worker in TypeScript that serves two form endpoints, one for the contact form and one for a student question box, and emails each submission to Sankofa Lab's inbox.
- Added spam protection with a honeypot field and length limits on every field. Honeypot hits get a normal success response, so bots can't tell they were caught.
- Set up a Markdown blog with Astro content collections, where each post's category, topics, audience, and hero image alt text are checked at build time.
- Added SEO metadata, a sitemap, a 404 page, and a social share card.
- Wrote a GitHub Actions workflow that builds the site and deploys both the site and the Worker on every push to main.
03 · how it works
- 1
content
Pages are Astro components and blog posts are Markdown files in the repo.
- 2
build
Astro builds static HTML and checks each post's frontmatter against a schema.
- 3
deploy
GitHub Actions deploys to Cloudflare Pages, and deploys the Worker with Wrangler, on every push to main.
- 4
pages
Cloudflare Pages serves the pages, and requests to /api/* go to the Worker.
- 5
forms
The Worker validates each submission and emails it to Sankofa Lab's inbox.
04 · key decisions
Static pages with one small Worker
Most of the site doesn't change often, so there's no reason to build pages on every visit. I built it as static pages, which load fast and cost little to host. The only server code is a small Worker that handles the contact form and the student question box.
Forms that still send without JavaScript
The contact form and the student question box are regular HTML forms, so a message still goes through even if the page's JavaScript doesn't run. When it does run, it sends the form in the background and shows a confirmation without reloading the page.
No email address on the question box
Students using the question box may be minors, so it asks only for the question, with an optional first name and school or grade.
05 · where it stands
- ✓Live at sankofalab.org.
- ✓The contact form and the student question box deliver to Sankofa Lab's inbox.
- ✓Every push to main deploys the site and the Worker.