Maintaining the API
How to make common changes, and what to check afterward. In every case, run the checks before you push:
npm test
npm run lint
npm run check:bundle
Every change to the functions, the data, or the spec also needs a new version. See Release a change.
Quick reference
- Adding a fact or place: edit
data.mjs. IDs must never change or be reused. - Changing data used in an example: the contract test reports which examples no longer match. Update them in the spec.
- Adding a category: update
data.mjs, thecategoryparameter'senum, and the current values listed inCategoryId's description. - Adding an endpoint: add a handler and a route in the function, then the path, examples, and a changelog row in the spec, then test cases.
- Every change needs a new
info.version, a matchingpackage.jsonversion, and a changelog row. CI checks this. - Breaking changes need a
v2. Withinv1, changes must be additive.
Add a fact
Add an entry to the end of facts in netlify/functions/norway-data/data.mjs, with the next unused integer ID:
{ id: 28, category: 'culture', title: 'A short headline', text: 'One or two sentences.', placeIds: [] },
- Never reuse or renumber an ID. The docs promise IDs are stable.
categorymust be an existing category ID.- Every ID in
placeIdsmust be an existing place. Add the place first if it's new.
Adding a fact changes pagination.total, so examples with that total might no longer match. Run npm test. It names each example that's out of date. Update those examples in the spec.
Add a place
Add an entry to places in data.mjs, keeping the array sorted by ID:
{ id: 'lofoten', name: 'Lofoten', type: 'archipelago', description: 'One sentence about the place.' },
- The ID is the name in lowercase ASCII, with spaces turned into hyphens and letters such as
øreplaced (Mjøsabecomesmjosa). - If
typeis a new value, add it to the list of current values in thePlaceschema'stypedescription in the spec.
Add a category
- Add it to
categoriesindata.mjs. - Add its ID to the
categoryparameter'senumincomponents.parameters.Category. The contract test fails if the two lists differ. - Add its ID to the current values listed in
components.schemas.CategoryId's description. - Add a changelog row. A new category is an additive change, so it stays in
v1.
Change the docs
The conceptual docs are in info.description in public/openapi/norway-data.yaml.
- Renaming a
##heading changes its anchor. Search the spec for#description/plus the old heading's anchor, and update each link. - Adding a curl example: put a
bashblock with thecurlcommand directly before ajsonblock with the exact response. The contract test checks the pair. To get the exact response, run the contract test with your best guess and copy the actual output, or call the function withnpm run devrunning. - Adding an endpoint example: if the response has one
example, change it to namedexamples. Give the new example asummary, adescriptionthat starts with the request, anx-example-request, and avaluecopied from the real response. See Examples are real responses. - Don't put an example in the docs that the test can't check, unless the response is random or can't be produced on purpose.
Add an endpoint
- Function: write a handler that starts with
parseQuery()(pass{}if it takes no query parameters), and add its route inroute(). Usepaginate()for a collection andjsonResponse()for a single resource. - Spec: add the path with its parameters, every response it can return (
200,304if it's cacheable,400,404if it has an ID,429,500), and an example withx-example-request. - Index: if it's a new collection, add it to the index handler's
linksand to theApiIndexschema. - Contract test: add requests for each status code. The coverage check lists any you missed.
- Postman collection: add a request with tests to
collections/norway-data-api.postman_collection.json, in the folder for its tag. Runnpm run collectionafter the release is live, since it tests production. - Release: see Release a change. A new endpoint is a minor version.
Release a change
- Bump
info.versionin the spec andversioninpackage.jsonto the same value:- Patch (1.1.0 → 1.1.1) for fixes and data changes.
- Minor (1.1.0 → 1.2.0) for new endpoints, parameters, or fields.
- Add a row at the top of the changelog table in the spec's introduction, with the date and what changed for clients.
- Push. Netlify runs the lint and contract test before deploying, and the smoke test runs against the new deploy.
npm run check:version -- <commit> runs CI's version check locally, comparing against <commit> (for example, origin/main).
Breaking changes
Within v1, only additive changes are allowed: new endpoints, new optional parameters, new fields, and new values for category IDs and place types. Removing or renaming a field, changing a type, or making a parameter required needs a v2 at a new base URL, with v1 left running. The function's ROOT_PATH and VERSION constants and the spec's servers URL are the places to start.
Change the rate limit
Edit rateLimit in the function's config, and update the Rate limits section of the introduction to match. Remember that config values must be literals.
Troubleshooting
The deploy fails during "Functions bundling"
If the deploy log shows Function norway-data has a configuration error, a value in export const config isn't a literal. Netlify reads config without running the code. Replace any constant, template string, or expression with a literal value.
Test Request shows "Failed to fetch"
The browser got a response it couldn't read, which almost always means the request didn't reach the function. Netlify's 404 page has no CORS headers, so a browser reports it as a network error.
- Check that the latest deploy succeeded and that the function shows up in Netlify under Logs > Functions.
- Run
npm run smoke -- https://api.marlasowards.com --redirects. It checks the API, the spec, CORS, and the redirects, and names whatever fails. - If the smoke test passes, the problem is on the reference page's side. See the reference page's troubleshooting docs in the marlasowards.com repo.
The hourly smoke test failed
GitHub emails the repo owner when the scheduled smoke test fails. Open the failed run in the Actions tab: the log lists each failed check. Then check the latest Netlify deploy, and the function logs for errors (search for a requestId from a failed response).
A deploy failed, but the build log only shows a test failure
That's the deploy gate working: Netlify's build command runs the lint and contract test, and the previous deploy stays live. Fix the failure (run npm test locally to see it) and push again.
The API isn't running locally
Use npm run dev, which runs the function with the Netlify CLI at http://localhost:8888.
The contract test says an example isn't the actual response
The data or the API changed, and an example in the spec is out of date. The failure names the request. Run it, and replace the example with the actual response.