Skip to main content

The tutorial and guides

The Norway Data API's tutorial and how-to guides live in this repo, in the /samples section, not in the API repo. The API reference explains how the API works, and the guides explain how to get things done with it. This page covers how the guides connect to the API, and what to check when the API changes.

Quick reference

  • The guides are in samples/norway-data-api-guides/, under the Norway Data API Guides category in sidebarsSamples.js, and listed on samples/index.mdx.
  • Unlike the other samples, they aren't genericized: their code runs against the live API. Don't add the samples disclaimer to them.
  • The spec links to the tutorial from its Quick start section and from externalDocs. If the tutorial's URL changes, update both in the API repo.
  • The guides link to sections of the reference by anchor, such as #description/errors. If a heading in the spec is renamed, those links break, and the build can't catch it.
  • Every guide ends with a Feedback section: the GuideFeedback component links to the API repo's Docs feedback issue form (.github/ISSUE_TEMPLATE/docs.yml), with the page's URL filled in. Add it to new guides too.
  • The fact of the day guide shows a live demo, the FactOfTheDay component. Its logic is a copy of the page's code. If you change one, change the other.
  • Nothing tests the guides' code automatically. When the API changes, check the guides it affects (see What the guides depend on) and re-run their code (see Test the guides).

The pages​

PageTypeWhat it covers
Show a random fact with its placesTutorialA first program: get a random fact, then each place in its placeIds. Built up step by step, with prerequisites and troubleshooting.
Explore the API in PostmanHow-toImport the Postman collection from the API repo, what's in it, its variables, and running its tests in Postman or with Newman.
Get every item in a collectionHow-toFollow pagination.links.next until it's null.
Handle errors and retriesHow-toWhich errors to retry and how long to wait. Retry decisions use the status code, because some 429s have no body and no type. Everything else uses type.
Cache responses with ETagsHow-tomax-age, If-None-Match, and 304 for server-side code. Browsers do this on their own.
Call the API from a browserHow-toWhat a page can send and read across origins, why requests fail with "Failed to fetch", and Content Security Policy.
Build a fact of the day pageSample appA complete web page that picks a fact from the date, with a live demo on the page.

Conventions​

  • Every program runs as copied. Each page has the complete code, not fragments that only work together.
  • JavaScript and Python in tabs. The tabs use groupId="language", so a reader's choice carries across the page and the other guides.
  • Few requirements. JavaScript needs Node.js 18 or later and uses .mjs files. Python uses only the standard library.
  • Output shown is real output. Any output on a page comes from running that page's code against the live API.
  • Absolute links to the reference. Links to a section of the reference use the full URL, such as https://www.marlasowards.com/api-reference#description/errors. Scalar creates those anchors in the browser, so the build's link checker would report a relative link as a broken anchor.

What the guides depend on​

If this changes in the APICheck
Fields in facts, places, or paginationEvery guide
A heading in the spec's introductionAnchor links in every guide
The Postman collection's requests, folders, variables, or test countsExplore the API in Postman, including the Newman summary
Error types, the problem details format, or Retry-AfterHandle errors and retries
Pagination, or the maximum limit (50)Get every item in a collection, Build a fact of the day page
Cache-Control, ETag, or 304 behaviorCache responses with ETags, Call the API from a browser
CORS headers, or the headers a preflight allowsCall the API from a browser, Build a fact of the day page
The rate limit (60 requests per 60 seconds)The tutorial's troubleshooting, Handle errors and retries, Call the API from a browser
The data, such as the number of facts or fact 14The tutorial's sample output, Get every item in a collection

A known limitation: the browser guide warns against sending If-None-Match from browser code, because 304s from the CDN have no CORS headers (see Design decisions). If that's ever fixed, remove the warning.

Test the guides​

Copy each program from the page into a file and run it. Then compare its output with the page.

  • JavaScript: node <file>.mjs
  • Python: python <file>.py. On Windows, use python -X utf8 <file>.py, or Norwegian letters such as á can print wrong.

Some guides need more than running the code:

  • The tutorial: its output is random. To get the exact output at the top of the page, temporarily change /random-fact to /facts/14.

  • Get every item: at the default page size, every collection fits on one page, so the loop runs only once. Change limit to 4 so it follows several pages, and check that the counts match each collection's pagination.total.

  • Handle errors and retries: the API can't return a 500 on demand. Replace fetch (or Python's urlopen) with a fake that returns a set sequence of responses, and replace the timer (setTimeout or time.sleep) with one that records each wait instead of waiting. Check these cases:

    • a 500 then success
    • a 500 every time (three retries, then an error)
    • a 429 with Retry-After
    • a 429 with an empty body and no header (a 60-second wait)
    • a 400 and a 404 (not retried)
    • a 502 with an HTML body (retried)

    To test against a real 429, send about 70 requests to /random-fact, which is never cached. This uses up your IP address's limit for a minute.

  • Call the API from a browser: only a browser enforces CORS, so curl can't test this guide. Serve the pages from another origin, such as python -m http.server 8000, and load them in headless Chrome with a throwaway profile:

    chrome --headless=new --user-data-dir=<temp-folder> --virtual-time-budget=20000 --dump-dom http://localhost:8000/page.html

    A test page can write each result into the page, and --dump-dom prints it. Also open the guide's page from a file:// URL.

  • Build a fact of the day page: load the page with --dump-dom as above, and check the fact against the rule: the day number (Date.UTC of today divided by 86,400,000) modulo the number of facts, plus one, is the fact's ID while IDs have no gaps. Also check a date whose fact has places, by temporarily changing new Date() to a fixed date, and an error, by temporarily pointing BASE_URL at a path that doesn't exist. Then check the live demo on the built site with npm run build and npm run serve.