diff --git a/README.md b/README.md index eea5bfc93..0cae5374d 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,59 @@ capabilities, three outputs, one shared library, one build. | **Shared library, private plugins** — reuse without breaking each other | `bun run check:library-index` | | **One agent per plugin, one shepherd, one working `main`** | [agent swarm](#build-it-with-an-agent-swarm) | +## For vibe coders: build, open the Studio, embed a map + +**1. Open the Plugin Studio** (every map, live, updating as you or your agent edit): + +```bash +bun install --frozen-lockfile +bun run dev # open the address it prints: that page is the Plugin Studio +``` + +**2. Build.** The built maps are already in the repo. After a change, rebuild just that map, or all of them: + +```bash +BUNDLE= bun x vite build # one map (seconds) +BUILD_ALLOW=1 bun run build # every map (~4 min); the output is public/dx-maps/ +``` + +When the DX Life site's repo sits next to this one (`../doxa-life`), the full build also copies the maps into +its `public/`. That is the one path set in `vite.doxa-maps-build-config.json` (`dropin.dest`); nothing else on +your computer is searched. No site there: the step says so and skips. `DOXA_DROPIN=off` turns it off, and +`bun run dropin` copies on demand. + +**3. Embed a map.** Every map has its own embed script: its `embed.script` in `public/dx-maps/manifest.json` (an +`embed.iframe` too). A snippet is two parts, the map's script and its tag: + +```html + + +``` + +On DX Life, the maps are served from its own `public/dx-maps/`, so a page loads `/dx-maps//.js` and +places the map's tag. Copy each snippet from the manifest: its `integrity` hash changes with every build. More: +[the three routes](#where-the-folder-goes-three-routes) and [how a page shows a map](#how-a-page-shows-a-map). + +## For agents: what this repo is for + +This repo builds **mobilization maps**: maps that help disciples, churches and leaders reach their city and the +people groups of the world. When you work here, the goal is one of these: + +| Goal | The production maps that serve it | +|---|---| +| **Reach a city** | Cities with Internet (`cities-internet`); Regions (`regions-dashboard`) and the country map (`country-map`) | +| **Mobilize for people groups** | Big Picture (`dashboard-plus-grid`); Research Map + Grid (`research-map-plus-grid`) | +| **Plan outreach** | Gospel Resources (`gospel-resources`): what exists in each language; Regions, by country | +| **Pray: packets and prayer resources** | UPG-100 (`my-upg-100-list`): prayer packets; Prayer Progress (`doxa-simple-map`) | + +- **Start with the skill:** [`skills/plugin-designer`](./skills/plugin-designer) teaches the patterns, the shared + library and the checks. +- **One plugin per folder** in `plugin-designs/`; shared code goes in `library/` only if it stays reusable for + every other plugin. +- **Land on `development`**, one change at a time through the lock, with `bun run gates:pre` passing. `main` is + production and moves only on a publish. +- These 8 maps are in production. The experimental maps are frozen: leave them as they are. + *Click any ▸ to read more. Everything below is folded so you can scroll the pictures first.* --- diff --git a/internal/sync-dropin.mjs b/internal/sync-dropin.mjs index 424974e9f..a8d5030c1 100644 --- a/internal/sync-dropin.mjs +++ b/internal/sync-dropin.mjs @@ -39,7 +39,7 @@ * Refuses to CREATE : the drop-in folder is the host's decision, not this script's. * Gate: `node internal/public-hygiene-check.mjs --strict` must pass before a public push. * - * Usage: node internal/sync-dropin.mjs [--from public] [--tree doxa-maps] [--keep-staging] + * Usage: node internal/sync-dropin.mjs [--from public] [--tree doxa-maps] [--keep-staging] [--if-present] * [--only a,b | --from-config] [--prune] [--protect a.txt,other] [--dry-run] * e.g. bun run dropin (= --from-config, into dropin.dest: ../doxa-life/public) * Prints: copied · unchanged · deleted (stale inside the allowlist) · pruned (outside it) · @@ -96,6 +96,13 @@ if (PRUNE && basename(dest) === 'public') { console.error(`[sync-dropin] refusing --prune into ${dest}: it is a site's web-root, and --prune would delete every file of the site outside the drop-in. Sync without --prune (bun run dropin); stale files INSIDE the drop-in are still removed.`) process.exit(1) } +// --if-present (the full build's last step): the configured host is OPTIONAL. Its absence is a skip, not an error. +// Only the ONE configured path is checked (dropin.dest, or DOXA_DROPIN_DEST): nothing on the filesystem is searched +// for other repos or sites. DOXA_DROPIN=off skips it even when the host is there. +if (args.includes('--if-present')) { + if (process.env.DOXA_DROPIN === 'off') { console.log('[sync-dropin] skipped: DOXA_DROPIN=off'); process.exit(0) } + if (!existsSync(dest) || !statSync(dest).isDirectory()) { console.log(`[sync-dropin] skipped: no host at the configured path ${dest}`); process.exit(0) } +} if (!existsSync(dest) || !statSync(dest).isDirectory()) { console.error(`[sync-dropin] dest does not exist or is not a directory: ${dest} — create the drop-in folder in the host first`); process.exit(1) } if (!existsSync(FROM)) { console.error(`[sync-dropin] source missing: ${FROM} — run \`bun run build\` first`); process.exit(1) } diff --git a/package.json b/package.json index 529944b65..3878883e6 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "build": "bash internal/build-lock.sh", "build:bundle": "bun x vite build", "build:bundles": "node internal/run-parallel.mjs --bundles", - "build:unlocked": "bun run gates:pre && bun run library-index && bun run check:library-index && bun run clean && bun run token && bun run build:bundles && bun run tree && bun run gates:post", + "build:unlocked": "bun run gates:pre && bun run library-index && bun run check:library-index && bun run clean && bun run token && bun run build:bundles && bun run tree && bun run gates:post && node internal/sync-dropin.mjs --from-config --if-present", "build:watch": "bun x vite build --watch", "cap:sync": "./node_modules/.bin/cap sync android", "cap:verify": "test -f deployment/capacitor/android/app/src/main/assets/public/index.html && echo \"OK webDir copied\" || (echo \"FAIL: empty assets/public -> blank white screen. Check webDir.\" && exit 1)",