Skip to content
~/francis-ohara_
all work

~/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.

AstroAstroTypeScriptTypeScriptCloudflare PagesCloudflare PagesCloudflare WorkersCloudflare WorkersCloudflare EmailCloudflare EmailGitHub ActionsGitHub Actions

Role

Tech Lead

Timeline

Aug 2026 → Present

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

Sankofa Lab website interface

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. 1

    content

    Pages are Astro components and blog posts are Markdown files in the repo.

  2. 2

    build

    Astro builds static HTML and checks each post's frontmatter against a schema.

  3. 3

    deploy

    GitHub Actions deploys to Cloudflare Pages, and deploys the Worker with Wrangler, on every push to main.

  4. 4

    pages

    Cloudflare Pages serves the pages, and requests to /api/* go to the Worker.

  5. 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.

06 · technologies used

AstroFrontend
TypeScriptLanguage
Cloudflare PagesHosting
Cloudflare WorkersBackend
Cloudflare EmailBackend
GitHub ActionsCI/CD