API Keys & Security¶
Some services need an API key: a paid geocoder like MapTiler (search.geocoder.apiKey), a basemap style URL with ?key=…, or an Esri layer URL with &token=…. Before you ship one, know what a static web app can and can't protect.
Two separate problems¶
1. Committing a key to git. If you type a key into settings.json and push it, it stays in your repository's history for anyone who can see the repo. This one has a fix: put the key in a .env file in app/, which git already ignores, and point to it from the JSON with $env:.
$env:NAME works in any string in any of the project's JSON files, also inside a longer one, like a style URL: "https://api.maptiler.com/maps/streets/style.json?key=$env:VITE_MAPTILER_KEY". The name must start with VITE_. It's filled in when npm run dev or npm run build reads the files; one that isn't set in .env is reported with the other config problems. Restart the dev server after editing .env.
2. Every visitor can see the key. .env doesn't help here. Conness GIS builds a static site with no server, so Vite writes every VITE_… value into the JavaScript it ships. Anyone using your deployed app can find the key in the browser's network tab or the page source. A static app can't hide a value from its own visitors.
Protecting a key¶
- Restrict it to your domain. Almost every provider (MapTiler, Mapbox, Esri, Google) lets you limit a key to specific websites in its dashboard (an HTTP referrer restriction). A copied key then won't work anywhere else, even though people can see it. For most map keys, this is enough.
- Keep truly secret keys out of the browser. If a key can't be limited to a domain, is tied to billing you can't cap, or allows writing data, it must never reach the browser. The only fix is to send those requests through a small server or edge function that adds the key. Conness GIS doesn't include one.
Sending requests through your own server¶
A proxy is a small piece of code on a server you control, such as a Cloudflare Worker, a Netlify or Vercel function, or an AWS Lambda behind a URL. It holds the key as a secret in the platform's settings (never in your app's files), takes the request from the browser, adds the key, forwards it to the provider and returns the answer. The app then calls the proxy's URL instead of the provider's, with no key in it:
- Geocoding: set
search.geocoder.endpointto the proxy's URL. - Basemaps and tiles: use the proxy's URL as the basemap
styleor the layerurl. A style JSON also lists tile and sprite URLs, so the proxy rewrites those to point back at itself. - Esri services: use the proxy's URL as the layer
url, and let the proxy add thetoken.
The proxy should only forward to the provider you expect (not any URL it's given), and should limit requests, for example by checking the Origin header and adding a rate limit, so it doesn't become a free open door to your key.
The build warning¶
At the end of npm run build, a script scans the built project in app/dist/<project>/ for anything that looks like a key: URL parameters such as ?key=, &token=, &api_key= and &access_token=, and settings like apiKey: "…". If it finds one, it says where and repeats the advice above.
It skips code that only looks like a key, such as template placeholders (${…}) and property paths (options.token). Each warning shows about 40 characters around the key, with the key masked (and any other key in that text), and where it came from: from your config: projects/demo/settings.json:42 when the value is in the project's settings.json, layers.json, basemaps.json or theme.json, or in a .env file in app/ (where a $env: value comes from), otherwise "not in your config files; probably a dependency's code". Keys from your config are listed first.
It only warns; the build still succeeds, because many keys, like a domain-restricted MapTiler key, are meant to be public. Use it as a reminder to check that each listed key is restricted. The script is app/scripts/check-keys.mjs.
Your keys, your responsibility
Conness GIS doesn't manage or secure API keys. Protecting any key you deploy, and paying for any misuse, is up to you and your provider's settings.