A new writer's first copy used to draw a coloured box. template-map-a.vue now draws the points in data/places.geojson on a basemap with one translated title, through the library's own pieces (useMapInstance, resolveMapProvider, labelFont, emissivePaint). It follows the page's engine, locale (right-to-left included) and token, and with no token it runs on keyless MapLibre, so it works with no account. template-map-b.vue stays as the second-screen example, so the README, the tutorial and the plugin-designer skill (rename a, delete b) stay true. The README gains the map's pieces table and the dx-maps paths. Library change: library/i18n/locales/<11>/template.json (key template.title) is eagerly globbed into every bundle, so consumers need rebuilding (rule 5B).
129 lines
7.5 KiB
Markdown
129 lines
7.5 KiB
Markdown
# template-bundle — copy this to start a new plugin
|
|
|
|
**This folder is the STARTER. Copy it to make a new plugin. That's the whole idea.**
|
|
|
|
Your starting point. **Copy this folder, then build your map inside the copy** — don't start from
|
|
blank. It's a tiny working bundle plus a `src/` sandbox laid out for your real code:
|
|
|
|
- **`template-map-a.vue` is a real map.** It draws the points in `data/places.geojson` on a basemap,
|
|
shows one translated title, and follows the page's engine, language (including right-to-left) and
|
|
Mapbox token. **It needs no account**: with no token it runs on the free MapLibre engine. Swap in
|
|
your own points and it is your map.
|
|
- **`template-map-b.vue`** is a second, trivial screen (a coloured box). It only shows that one
|
|
bundle can hold several screens. Delete it if you want one.
|
|
|
|
## In plain English (read this first)
|
|
|
|
If you've never touched this repo, here are the only 4 words you need:
|
|
|
|
| Word | Plain-English meaning |
|
|
|---|---|
|
|
| **plugin / bundle** | One folder = one plugin. It compiles into a **single `.js` file** you can paste onto any web page. "Bundle" and "plugin" mean the same thing here — the folder you copy. |
|
|
| **profile** | One `.vue` file inside the folder = one **screen** (one map). A bundle can hold one profile or many. You pick which screen shows at embed time with a `profile` name. |
|
|
| **root.vue** | Each profile IS a normal Vue component — it's the "root" (the top of the tree) for that one screen. The filename (minus `.vue`) is the profile's name. Everything that screen draws hangs off this one file. |
|
|
| **`src/`** | Your private sandbox — your own colors, components, and helpers. Nothing in here can affect another plugin. Shared building blocks live in `library/` (imported as `@map/…`) and you never edit those. |
|
|
|
|
**Make a new plugin in 2 moves:**
|
|
|
|
```bash
|
|
# 1. copy this starter to a new name
|
|
cp -r plugin-designs/template-bundle plugin-designs/my-plugin
|
|
|
|
# 2. build (the ONE command)
|
|
bun run build # → public/dx-maps/my-plugin/my-plugin.js (your paste-anywhere plugin)
|
|
```
|
|
|
|
Then rename the tag + profile strings (the "exactly four things" list below) so your copy has its
|
|
own name, and rebuild. That's it — the build auto-detects your new folder, compiles it to one `.js`
|
|
custom element, and lists it in the gallery.
|
|
|
|
> Proven: a copy of this folder (`cp -r` + rename the 4 strings) runs `bun run build` and emits a
|
|
> working `<my-plugin>` custom element `.js` bundle that passes every build guard. If it builds for
|
|
> the starter, it builds for your copy.
|
|
|
|
## Two zones — know which one a file is in
|
|
|
|
| Zone | What | Edit it? |
|
|
|---|---|---|
|
|
| **`library/`** (imported as `@map/…`) | shared, reusable building blocks — map, legends, toolbars, composables, color + API registries | **No — reuse only.** A change here can break every other map. |
|
|
| **`plugin-designs/<your-map>/src/`** | your private sandbox — screens, colors, API wiring, components, utils | **Yes — build anything.** Nothing here leaks to another map. |
|
|
|
|
Rule of thumb: **local by default.** Code only moves into `library/` once a *second* map genuinely
|
|
needs it — an expert move, not a first move. To see everything `library/` offers, read
|
|
`../../documentation/reference.md` (that's the menu you pick from).
|
|
|
|
## Build a new map — the steps
|
|
|
|
1. **Copy this folder** → `plugin-designs/<your-map>/`, then change **exactly four things**:
|
|
- the **folder name** (= bundle name = output file `<your-map>.js`),
|
|
- the **tag** in `index.js` (`customElements.define('<your-map>', …)`),
|
|
- the **tag + `profile` strings** in `index.html` (the staging page must mount your tag),
|
|
- the **`.vue` filenames** — rename `template-map-a.vue` to your screen's name and delete
|
|
`template-map-b.vue` if you only want one screen (filename = the `profile` name).
|
|
Nothing else. Check it: `bun run dev` → your map renders at
|
|
`http://localhost:5173/plugin-designs/<your-map>/index.html`.
|
|
2. **List what your map needs** — data, colors, controls (legend, search, share, fullscreen…).
|
|
3. **Pick pieces from `../../documentation/reference.md`** and import them by reference (`@map/…`) — never
|
|
copy library code into your folder.
|
|
4. **Put your own code in `src/`** — screens, components, hooks, helpers.
|
|
5. **Set colors in `src/colors/colors.json`** (plain hex, no code). For color that varies by data,
|
|
use a strategy `.js` in `src/colors/` (copy `example-mode.js`).
|
|
6. **Build** — `bun run build` (or just this one: `BUNDLE=<your-map> bun run build:bundle`).
|
|
|
|
## What's in this folder
|
|
|
|
```
|
|
template-bundle/
|
|
├── index.js ← bundle entry: registers <template-bundle>, globs ./*.vue
|
|
├── index.html ← dev staging page (the build needs it to find the bundle)
|
|
├── template-map-a.vue ← profile "template-map-a": THE MAP ← FLAT at the bundle root
|
|
├── template-map-b.vue ← profile "template-map-b": a box ← FLAT at the bundle root
|
|
├── data/places.geojson ← the map's points (imported by template-map-a.vue, ships inside the .js)
|
|
└── src/ ← YOUR SANDBOX (each subfolder has its own README)
|
|
├── api/ colors/ components/ composables/ utils/
|
|
```
|
|
|
|
**The flat rule:** profile `.vue` files sit **directly in the bundle folder** — there is no
|
|
`profiles/` subfolder, because the entry discovers them with a flat glob
|
|
(`import.meta.glob('./*.vue')`). A `.vue` inside a `profiles/` subfolder would NOT be found. Keep
|
|
your profile screens flat; the small pieces they're built from live in `src/`.
|
|
|
|
Everything builds into **one** file: `public/dx-maps/template-bundle/template-bundle.js`.
|
|
|
|
## The map's pieces (template-map-a.vue)
|
|
|
|
| Piece | Where it comes from | To change it |
|
|
|---|---|---|
|
|
| the points | `data/places.geojson` (a static import, so no extra request on the host) | replace the file with your own GeoJSON points |
|
|
| the pin colour | `src/colors/colors.json` → `pins.selected` | edit the hex |
|
|
| the engine (Mapbox or MapLibre) | the page: `profile-config` `provider`, `?provider=`, or `window.MAP_PROVIDER`; no token → MapLibre | nothing: leave it to the page |
|
|
| the language and right-to-left | the page's locale, given by the library's ProfileLoader | nothing: leave it to the page |
|
|
| the title | `t('template.title')` from `library/i18n/locales/<lc>/template.json` | see below |
|
|
|
|
**Your own text.** Translations live in `library/` (every locale in one place), so a new key there
|
|
is a library change: ask the build owner to land it. Until then, a plain English string in your
|
|
`.vue` is fine.
|
|
|
|
## The two ways you import
|
|
|
|
- **Reuse from the library** → the `@map/…` alias: `import { useMapInstance } from '@map/composables/useMapInstance.js'`
|
|
- **Your own sandbox code** → a relative path: `import colors from './src/colors/colors.json'`
|
|
|
|
There's no alias for your sandbox — your code is always relative. That boundary keeps it private.
|
|
|
|
## Embed it
|
|
|
|
```html
|
|
<script src="/dx-maps/template-bundle/template-bundle.js"></script>
|
|
<template-bundle profile-config='{"profile":"template-map-a"}'></template-bundle>
|
|
<template-bundle profile-config='{"profile":"template-map-b"}'></template-bundle>
|
|
```
|
|
|
|
(`profile` must match a `.vue` filename in this folder, without `.vue`. Add a third profile by
|
|
dropping another flat `.vue` next to these and rebuilding — no config to edit.)
|
|
|
|
## See also
|
|
|
|
- `src/README.md` — sandbox layout · `../README.md` — the plugin-designs authoring guide
|
|
- `../../documentation/tutorial.md` — 3 zones + 3 rules in one page · `../../documentation/reference.md` — the `@map/…` menu
|
|
- `../doxa-simple-map/index.js` — a fuller, real-map reference entry
|