- SPA sidebar: suppress the leading section divider on the FIRST nav group. Every section emitted a `.sep` rule before its header, so Prayer Mobilization (the first section) drew a 1px line directly under the header with nothing above it to divide. drawSide() now tracks a firstGroup flag and skips it. - Research dashboard: when the table under the map collapses, resize the map to fill the freed space. The ResizeObserver alone missed the grid reflow at the instant the table cell flips to display:none (v-show), leaving the map canvas at its old size (gray gap). DashboardMapPanel now also resizes on the 'toggleTable' bus event (rAF + a 280ms settle pass), with clean teardown. |
||
|---|---|---|
| .github/workflows | ||
| app-profiles | ||
| capacitor/android | ||
| contributing | ||
| docs | ||
| internal | ||
| layouts | ||
| library | ||
| public | ||
| .env.example | ||
| .gitattributes | ||
| .gitignore | ||
| bun.lock | ||
| capacitor.config.json | ||
| CONTRIBUTING.md | ||
| index.html | ||
| LICENSE | ||
| package.json | ||
| README.md | ||
| vite.config.js | ||
| vite.doxa-maps-build-config.json | ||
doxa-maps
A JAMstack bundler for composable, embeddable-first maps — one build outputs every map as a framework-agnostic web component, and composes them into a single-page application.
app-profiles/<map>/ bun run build where they run
┌──────────────────┐ ┌──────────────────┐ ┌─────────────────────────┐
│ your map screens │ │ one .js per map │ │ ▸ any partner website │
│ (.vue) + colors + │──────► │ Vue + CSS inlined │────► │ ▸ a SPA (several maps │
│ data wiring │ │ tree-shaken IIFE │ │ in one layout) │
└──────────────────┘ │ + an index.html │ │ ▸ Android/iOS app │
shared library/ ──────► │ per map page │ │ (Capacitor) │
(@map: legend, map, └──────────────────┘ └─────────────────────────┘
controls — reused) public/doxa-maps/… one build → three products
| The idea | In one line |
|---|---|
| Bundle | one self-contained .js = a custom HTML tag (<my-map>) — drop it on any page, no framework, no build step for the host |
| Embeddable by default | every map also gets a generated standalone page — link it or iframe it (Start.me, Notion, any CMS) |
| Many maps, one bundle | a bundle holds as many map screens as you want; add a .vue, rebuild |
| Lean & fast | tree-shaken, Vue + CSS inlined → one request, faster than loading Vue from a CDN, nothing to 404 |
| JAMstack hot-swap | data API, token, even the map engine (Mapbox ↔ MapLibre) are runtime settings — change them with no rebuild |
| SPA | compose several maps into one lazy-loaded layout → a full map site from the same build |
✨ Don't write code? Describe your map to an AI coding agent — start at docs/tutorial.md.
Quickstart
Bun required (bun.sh; bun.lock is committed).
bun install
bun run build # every app-profiles/<bundle>/ → public/doxa-maps/<bundle>/<bundle>.js
bun run dev # live playground at http://localhost:5173/ — every map, clickable,
# with a copy-paste embed snippet for each
Embed a map
<link href="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css" rel="stylesheet" />
<script src="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js"></script>
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
<script src="/doxa-maps/my-map/my-map.js"></script>
<my-map profile-config='{"profile":"my-map","tk":"pk.eyJ..."}'></my-map>
Or skip the script tag entirely — iframe the map's generated page:
/doxa-maps/<bundle>/<profile>/index.html. Both snippets are pre-generated per map in
public/doxa-maps/manifest.json.
Docs
| Read this | When |
|---|---|
| why.md | 2 min — the problem, the "map islands" idea, one diagram |
| tutorial.md | build your first map, step by step |
| how-to.md | task recipes — embed, iframe, SPA, colors, mobile, tokens |
| reference.md | lookup — config fields, build scripts, contracts |
| architecture/ | the deep end — full contracts and catalogs, when you want them |
Contributors: CONTRIBUTING.md.
The output — real maps from this bundler
Every map below is a single self-contained bundle built by one bun run build, embeddable on any
site with one <script> + tag. Colors are data-driven color strategies (@map/colors/).
Research Map — the full example
doxa-research-map · <doxa-research-map> — 7 tabs (prayer, adoption, engagement, regions,
languages, religions) with clustering, filters, legends and poster export. This is the reference
map that shows everything the library can do.
Prayer Map — the flagship embed
doxa-simple-map · <doxa-map> · prayer instance · color: prayer-progress · Semantic Tree
Legend — the prayer map built for embedding on partner sites at scale.
Each also builds its own standalone page (
/doxa-maps/<bundle>/<profile>/index.html) — link it or iframe it on a partner site. See docs/why.md for the idea and docs/how-to.md to build your own.
License
The doxa-maps template (library/ + build tooling) is Apache-2.0 — a permissive base
everyone shares. Your maps under app-profiles/<bundle>/ are yours: your colors, API
connections, and i18n. Full text: LICENSE.

