Guide
Creating a plugin
This walks through writing a plugin by hand in the built-in editor, from a blank plugin to one running on a real page. If you'd rather describe what you want and have an AI write the code, see Writing a plugin with AI instead β everything below still applies to reviewing and testing what it gives you.
Step by step
-
Open the plugins page
Click the Map Extender icon in your browser toolbar, then Open Plugins. This opens the extension's options page, where every plugin β built-in and your own β is listed.
-
Click New Plugin
Starts a blank plugin with a working template already in the code editor, so you have something that runs before you change anything.
-
Fill in name, description, and usage
The usage field is a short line shown in the popup when the plugin is enabled β "Click Measure, then click the map" is the kind of thing that goes there. It's optional, but it's the only hint a user gets about how to actually use the plugin.
-
Set match patterns
These decide which sites the plugin runs on β
*://*/*for everywhere, or something narrower likehttps://example.com/maps/*. See the API reference for the exact syntax. -
Add a settings schema, if the plugin needs one
Skip this for a plugin with no configurable options. Otherwise see Settings schema β it's a JSON array, editable either as JSON directly or through the form UI.
-
Write the code
Plain JavaScript against the
pluginobject β the full surface is in the API reference. The minimal example below is a reasonable starting point. -
Save, enable, and test
Saving doesn't turn a plugin on by itself β enabling is a separate, per-site switch in the popup. Open a page with a map that matches your patterns, enable the plugin there, and check the log panel on the plugins page if something doesn't work.
Minimal example
plugin.mapHook.onHook(function () {
var layer = plugin.mapHook.createMarkerLayer();
layer.addMarker({
id: 'example',
lat: 45.0703,
lng: 7.6869,
color: 'red',
popup: 'Hello from Map Extender'
});
plugin.log('Marker added');
});
Things that are easy to get wrong
- Clean up after yourself. Layers and map subscriptions are disposed of automatically. Anything else β an injected
<style>, a timer, a listener on your own control markup β needsplugin.onDispose, or it survives until the page reloads. plugin.fetch, notfetch. A directfetchcall from a plugin is subject to the host page's own rules;plugin.fetchgoes through the extension instead.- Debounce anything driven by map movement, and ignore stale responses once a newer one has started. Panning fires often, and public data APIs are usually donated infrastructure that shouldn't be hammered.
- Tile URLs only substitute
{z},{x}, and{y}. An{s}subdomain placeholder is left literal on Google Maps and every tile 404s β use one fixed hostname. - Guard your control lookup.
document.querySelector('[data-map-control-id="β¦"]')can returnnullif the map container went away β log and stop rather than letting it throw.
Debugging
Every plugin.log, plugin.warn, and plugin.error
call appears in the log panel on the plugins page, scoped to that one plugin β that's the
first place to look when something silently doesn't work. Errors also show up in the
browser's own DevTools console (right-click the page β Inspect β Console).
Check that the plugin is actually enabled for the site you're on β saving a plugin never enables it, that's a separate per-site toggle in the popup β and that your match patterns actually cover the page's URL.