Repository rules
The heart of iiiftools is a small registry: one database row per digital library, holding the rule that turns its viewer URLs into IIIF manifest URLs. The registry is the shared source of truth that otherwise lives in scattered scripts and folklore.
Anatomy of a rule
Section titled “Anatomy of a rule”| Field | Meaning |
|---|---|
host_patterns | regexes matched against host/path?query (scheme stripped) — decides whether the rule applies |
strategy | how to find the manifest: regex_template, page_scrape, or generic |
params | JSON config the strategy interprets |
image_api_quirks | per-repository download behaviour (see below) |
priority | lower = tried first; the generic fallback sits at 1000 |
Rules are edited in the dashboard’s Repositories page. Every rule has a Test box: paste a real viewer URL and see whether it matches, what candidate manifest URLs the strategy produced, and which validated as IIIF — before saving anything.
Strategies
Section titled “Strategies”regex_template
Section titled “regex_template”Pure declarative extraction: a regex captures ids from the URL, a template builds the manifest URL. Supports derived substrings for repositories that shard paths by id prefix:
{ "rules": [{ "extract": "/(\\d{8,10})(?:[/?#]|$)", "derived": { "p1": ["g1", 0, 4], "p2": ["g1", 4, 8] }, "template": "https://view.nls.uk/manifest/{p1}/{p2}/{g1}/manifest.json" }]}page_scrape
Section titled “page_scrape”Fetches the viewer page and hunts for the manifest in its HTML: rel="manifest" links,
Mirador/UV embed attributes (data-manifest, manifestUri), inline viewer config, plus
configurable extra patterns and suffix probes.
generic
Section titled “generic”The priority-1000 fallback that matches any URL: first tries the URL itself as a manifest, then scrapes with the default patterns. This is why many unlisted IIIF sites work with no rule at all.
Image API quirks
Section titled “Image API quirks”Some libraries need special handling at download time:
honor_info_sizes— only request sizes advertised in the image’sinfo.json(some servers 503 on/full/max/and unlisted sizes — and serve the error HTML with HTTP 200, which iiiftools detects by sniffing the image magic bytes).rate_limit_ms— pause between downloads.user_agent— a repository-specific UA string.
Built-in repositories
Section titled “Built-in repositories”| Slug | Covers | Strategy |
|---|---|---|
nlw | viewer.library.wales/<id>, hdl.handle.net/10107/<id> | regex_template → iiif.llyfrgell.cymru |
nls | digital.nls.uk, view.nls.uk | regex_template → view.nls.uk/manifest/… (with honor_info_sizes) |
lambeth | Lambeth Palace Library (LUNA) | page_scrape |
generic | anything else | generic fallback |
Seeds only create rows that don’t exist yet — once a repository is in the database, the database wins, and your edits survive every deploy.