
Shipping a Next.js NGO Site on a 3G Budget (Under 100KB JS)
A production Next.js site for a youth-led NGO — total per-page JS under 100KB, a single-screen Stripe donation flow that roughly doubled completion, and markdown-in-git content so the volunteer team can update the site without learning a CMS. This is the build journal for ushaqlarimizaoyredek.com and what I learned shipping something where the users aren't other developers.
TL;DR
- Stack: Next.js + markdown content files (no CMS).
- Performance: Under 100KB per-page JS, zero third-party scripts, under-1s load on throttled 3G.
- Donation flow: Single-screen Stripe Checkout, no account, preset amounts — completion roughly doubled.
- Hardest part: Writing the content clearly, not writing the code.
Context
Quick break from the usual AI stuff. Ushaqlarimiza Oyredek is a youth-led NGO focused on providing education to underprivileged children in Azerbaijan. I led the site build. It was my first time shipping something where the users aren't other developers, and it completely changed how I think about the word "ship."
The team behind Oyredek is all students and early-career volunteers. They needed a site that (a) explains what they do, (b) makes it easy for people to donate, and (c) makes it easy for other young people to get involved. Nothing flashy. Nothing that needs a DevOps engineer to maintain.
Stack decision: no CMS
My instinct was Next.js with Sanity or Contentful. Great for us developers — awful for the content team, who would need to learn a new admin UI, an access-control model, and a preview workflow just to edit a paragraph.
I switched to a plain Next.js build with markdown content files and a really simple admin flow:
| Concern | Choice | |---|---| | Content storage | Markdown in git | | Editor | Any text editor, or GitHub's web UI | | Admin flow | PR → auto-deploy on merge | | Preview | Vercel preview URLs per PR |
The volunteers who update the site don't learn a CMS; they edit markdown. It's been working well for over a year.
Performance on a 3G budget
A lot of our target audience is on lower-end phones and spotty connections. According to GSMA, 40% of connections in Sub-Saharan Africa are 2G–3G, and even in Azerbaijan real-world mobile speeds in the mountains can drop to a megabit or below. Every asset on the page has to justify itself.
What I ended up doing:
next/imageaggressively, with propersizeshints so browsers request the right resolution. This alone knocks hundreds of KB off mobile.- Inlining the logo as raw SVG — skips an HTTP request and parses instantly.
- Cutting third-party JS to zero. No analytics loader, no Google Fonts CDN — nothing that touches a third-party domain on first load. (Analytics moved to a privacy-respecting server-side log of page paths instead.)
- Total per-page JS under 100KB.
- Aggressive
Cache-Control: max-age=..., immutableon static assets so repeat visits are essentially free.
End result: the site loads in under a second on a throttled 3G connection, which is the bar I wanted.
The donation flow — where conversion doubled
NGO donation flows get abandoned constantly. People click "donate", then they're asked to make an account, then the form is eight fields long, and they bounce. The Stripe nonprofits research documents this pattern across thousands of nonprofits.
I pushed to keep it to:
- Single-screen Stripe Checkout.
- Preset amounts with a clear total.
- No account creation, no marketing popup.
| Metric | Before | After | |---|---|---| | Completion rate | baseline | ~2× baseline |
Measured before-and-after after launch. Roughly doubled.
The content step that took longer than the code
The part that surprised me most was how much time I spent on content structure, not code.
- What programs do we run?
- Who do we work with?
- Where does my money go?
Those are hard questions for a small org to write out clearly, and the website forced us to answer them. That felt like the most impactful part of the project, honestly — not the code, the clarity. If you're ever working with a small NGO, schedule more calendar time for writing than you think you need.
If you're looking for a first real-world web project
Find a small organization that needs a site. You'll learn more about performance, accessibility, and content strategy than any tutorial can teach you — and the org gets something real out of it.
Key takeaways
- CMS choice is a user-empathy decision. For a small volunteer team, markdown + PRs wins over any CMS.
- 100KB of JS is a feature, not a limitation. Every dependency has to justify itself on a 3G budget.
- Single-screen Stripe Checkout ≈ 2× donation completion. The NGO playbook of "account + long form + upsell" destroys conversion.
References
- ushaqlarimizaoyredek.com — the site in production
- Stripe — Online Giving guide
- Stripe — Nonprofit payment processing
- Background reading — Building for Low-Bandwidth Environments
- More projects
Frequently Asked Questions
Why keep total JS under 100KB?
The target audience for Ushaqlarimiza Oyredek is often on lower-end phones and spotty connections. On a throttled 3G network, 200KB of JavaScript takes 5–15 seconds to arrive and parse. Keeping total per-page JS under 100KB means the site is interactive in under a second for the people who most need it to work.
Which Next.js features gave the biggest wins on low bandwidth?
next/image with proper sizes hints for responsive images, inlining the logo as raw SVG to skip an HTTP request, removing every third-party script (no analytics loader, no Google Fonts CDN), and aggressive static generation so first-byte time doesn't include a server render.
Why markdown files instead of a CMS?
The content team is students and volunteers. Learning a CMS (Sanity, Contentful) is a heavier lift than editing a markdown file in a pull request. Markdown keeps the site fast (zero CMS fetch on build) and keeps maintenance friction low for non-engineers.
What made the donation form convert twice as well?
Three decisions: single-screen Stripe Checkout instead of a multi-page flow, preset donation amounts with a clear total, and no account creation. The NGO playbook of 'make an account → long form → marketing popup' kills donations. Completion roughly doubled after the switch.
What surprised you about building a site for a real organization?
How much time I spent on content structure, not code. 'What programs do we run? Who do we work with? Where does my money go?' are hard questions for a small NGO to answer clearly, and the website forced us to answer them. That clarity was the most impactful part of the project.