An interactive world map of femtech and women's health innovation — the startups, apps, clinics, NGOs, funds and communities building better care for women, everywhere.
It began as a response to women's-health maps that leave most of the world blank. This one aims for the opposite: 339 cited initiatives across 154 countries, with deep, deliberate coverage of Africa and the Global South that most maps overlook, and every continent represented.
Founders featured on the Blush & Bloom podcast carry a 🎙 badge linking their episode.
Built by Gigi Kenneth — founder of Asele and host of Blush & Bloom.
- 339 initiatives · 154 countries · 6 continents
- Six categories: menstrual & cycle, maternal & fertility, sexual & reproductive health, diagnostics & devices, telehealth, and funding & community
- Real startups where they exist; where a country has no verifiable femtech company, its national UNFPA women's-health programme stands in, so no country with active work sits empty
- Every single pin cites a source URL
- Explore by country — click any country to focus the map to it and list every initiative mapped there; the stat cards recalculate to that country
- Click a pin for a detail panel: description, category, location, link, source, and (for podcast guests) the episode
- Filter by category, search initiatives/countries, or isolate the 🎙 Blush & Bloom founders
- Zoom spreads out dense city clusters so individual dots stay legible
- Editorial landing hero, accessible colour/typography, responsive down to mobile (detail panel becomes a bottom sheet)
Plain Vanilla JS + Vite + d3-geo. No backend, no database — an art-directed SVG world map with data in editable JSON files.
npm install
npm run dev # local dev server
npm run build # production build → dist/ (also prerenders reports + SEO files)
npm run preview # preview the production buildBeyond the map, the site publishes researched, cited country ecosystem reports at /reports/ — scrollytelling deep-dives on femtech and women's-health innovation per country (funding, policy, founders, hubs), each claim linking to a public source. No scoring or tiers; reports are qualitative.
- Data: one JSON per country in
src/data/reports/<slug>.json, plus_index.json(the grid + coming-soon list). - Render:
src/report-render.jsis a pure module (no browser/Vite deps) shared by the client hydrator (src/report.js,src/reports-index.js) and the Node prerender. - Prerender:
scripts/prerender.mjsruns insidenpm run build. For every report it bakes full HTML + head meta (title, description, canonical, OG, Article JSON-LD) into static pages at pretty URLs/reports/<slug>/, plus a "related countries" strip. It also bakes the/reports/index grid (withItemListJSON-LD), fills the home page's crawlable report links, and writessitemap.xml+llms.txt. - Validate:
node test-reports.mjschecks every report's schema and that all claims are sourced. Run before deploy.
To add a country, see the recipe in docs/NEXT-STEPS.md.
Everything crawlers and AI engines need is generated at build time, no server:
sitemap.xml— all pages, pretty URLs.robots.txt— allows general crawlers plus named AI crawlers (GPTBot, ClaudeBot, PerplexityBot, OAI-SearchBot, Google-Extended) so the reports can be cited in AI answers.llms.txt— a markdown summary + report index for AI crawlers (GEO), auto-generated from_index.json.- Structured data —
Articleper report,ItemListon the reports index. - Internal linking — home links to every report; each report links to related countries.
Live at femtech.asele.tech (Vercel; canonical points here). Verified in Google Search Console with the sitemap submitted — setup + gotchas in docs/search-console.md.
- Vercel Web Analytics — aggregate pageviews, referrers, countries, top pages. Privacy-friendly, no cookie banner. Wired via
@vercel/analyticsinject()in every page entry; view it in the Vercel dashboard. - Live visitor feed (owner-only) — a real-time
/live?key=<key>page streaming arrivals, page views, and report-link clicks with coarse location, cookieless. Each page pingsapi/ping.js, which forwards Vercel's geo headers to a secret ntfy topic;api/live.jsrenders the key-gated feed and the ntfy app gives phone push. No database. Setup indocs/live-feed-setup.md.
This map is community-sourced and open to contributions. Spotted a missing initiative, a wrong location, a broken link, or an error in a country report? There are two ways in:
- Suggest an edit (no GitHub needed) — the "Suggest an edit or addition" button on the map, and "Suggest an edit" on every report, open an in-site form. Submissions land in a review Google Sheet; corrections are applied by hand (nothing publishes automatically). Maintainer setup:
docs/contributions-setup.md. (The older approved-to-map-live initiative form still works too:docs/submissions-setup.md.) - Open a pull request — edit the JSON directly (below). The map is only as inclusive as the people who build it.
All data lives in JSON files under src/data/. To add an initiative, add one object to the appropriate file (see Data model below). Fields:
{
"name": "Organization name",
"org_type": "company | app | clinic | ngo | fund | community",
"country": "Country",
"city": "City",
"lat": 6.5244,
"lng": 3.3792,
"category": "menstrual | maternal | srh | diagnostics | telehealth | funding",
"description": "One factual sentence, 140 characters or fewer.",
"url": "https://official-website.example",
"source": "https://where-you-verified-this.example",
"confidence": "high | medium",
"podcast": {
"guest_name": "Founder name",
"episode_title": "Episode title",
"episode_number": 17,
"episode_url": "https://…"
}
}sourceis required — every pin must cite where it came from. No unsourced entries.- Drop the
podcastblock for anything that isn't a Blush & Bloom guest. lat/lngare the decimal coordinates of the org's city (any maps service gives these).- Categories map to pin colours; pick the closest fit.
- Real, verifiable organizations only. If you can't cite a source, don't add it.
- One object per initiative. Keep descriptions factual and short.
- Names are de-duplicated case- and punctuation-insensitively, so you won't create an accidental double.
- Run
npm run buildbefore opening the PR to confirm the JSON parses.
Data is split into layers, all merged and de-duplicated by name at runtime in src/main.js:
| File | What it holds |
|---|---|
src/data/initiatives.json |
Core/seed set of well-known global femtech companies |
src/data/more.json |
Regional deep-scrape results and gap fills |
src/data/podcast.json |
Blush & Bloom guest-founder organizations (🎙) |
src/data/communities.json |
Femtech ecosystem networks, associations and accelerators |
src/data/programs.json |
National UNFPA / UN women's-health programmes that fill otherwise-empty countries |
src/data/continents.js |
Country → continent lookup (drives the click-to-explore behaviour) |
src/data/meta.js |
Small UI copy/config |
Add a real startup to more.json; add a podcast guest to podcast.json; the rest are mostly maintained by the project.
The dataset was compiled from public sources and is cited but not exhaustive or infallible. Some entries are medium confidence, and a few placeholders (national UNFPA programmes) stand in for countries where no femtech company could be verified. Corrections and additions are always welcome — that's the point.
Menstrual & cycle · Maternal & fertility · Sexual & reproductive health · Diagnostics & devices · Telehealth · Funding & community
Operational setup and handoff notes live in docs/:
| Doc | Covers |
|---|---|
NEXT-STEPS.md |
Full handoff: current state, how the reports system works, the add-a-country recipe, open next steps, gotchas |
contributions-setup.md |
The "Suggest an edit" modal → Google Sheet pipeline (Apps Script, deploy, VITE_CONTRIBUTE_URL) |
submissions-setup.md |
The older approved-to-map-live initiative form (Google Form → Sheet → map JSON) |
search-console.md |
Google Search Console verification + sitemap, the verification gotchas, and why Bing is skipped |
live-feed-setup.md |
The owner-only /live real-time visitor feed (ntfy topic + env vars) |
Code is available for reuse. The dataset is community-contributed and provided as-is for reference; please keep source attributions intact if you build on it.