Context Cards

Shows a small definition card when a reader hovers a technical term in your writing. The definitions come from structured data already on your page, so nothing extra has to be written. This page covers how the script is delivered and how to add it.

The Problem This Solves

Technical writing has a reader problem. Use a term like canonical or crawl budget and you lose anyone who does not know it. Stop and define it and you bore everyone who does.

ctx-cards solves that by putting the definition one hover away. Readers who need it get it; readers who do not are never interrupted.

Where the definitions come from. Many sites already publish a glossary as structured data, using a schema.org type called DefinedTermSet. Structured data is a block of information in your page written for machines rather than people, normally so search engines can understand your content. Here that same block is read a second time, by the script, to show your readers something useful. One source, two audiences, nothing extra to write.

None of your page text is sent anywhere. The script reads what is already in the browser and does the matching there.

What This Page Covers

ctx-cards is the script. This page is about how it gets to your website, which matters more than it sounds.

When you add someone else's script to your site, you are trusting whatever that address serves, today and every day after. If it changes without warning, your pages change too. The delivery here is built so that cannot happen: every address contains a version number, and the contents of a version never change.

The Addresses

Three kinds of file, all pinned to a version number such as v0.10.0.

https://cdn.jakelabate.com/context-cards/<tag>/dist/ctx.min.js
https://cdn.jakelabate.com/context-cards/<tag>/packs/<pack>.json
https://cdn.jakelabate.com/context-cards/<tag>/sites/<site>.json

The script derives its pack URLs from its own src by swapping /dist/<file> for /packs, so a pinned script tag pins its packs to the same release automatically. Nothing extra to configure, and no way for a script and its data to end up on different versions.

Set It Up

One line, pasted just before the closing </body> tag in your page. Most CMSs have a footer scripts field for exactly this.

<script src="https://cdn.jakelabate.com/context-cards/v0.10.0/dist/ctx.min.js"
        integrity="sha384-..."
        crossorigin="anonymous"
        data-packs="seo-core"
        data-style="paper"
        defer></script>

The integrity line is a safety catch worth understanding. It is a fingerprint of the exact file you expect. If what arrives does not match it, the browser refuses to run it rather than running something you did not approve. Since the contents of a version never change, the fingerprint never changes either. Copy the current value from dist/ctx.min.js.sri in the repository.

What Is Deliberately Restricted

Technical detail. Included because an open file host is a liability, and it is fair to show how this one is closed.

Two limits matter more than the delivery itself.

  • Only dist/, packs/ and sites/ are reachable. Without a directory allowlist this would serve any file in the repository from my domain under a permissive CORS header.
  • A ref must be a vN.N.N tag or main. Without it, any commit in history would be addressable, which is an open proxy with extra steps.

Addresses containing unusual characters are rejected outright, which stops anyone walking out of the allowed folders. A numbered version is stored for a year, because its contents can never change. The unnumbered main address is allowed for testing only and is deliberately not stored, because what it points at does change.

Upgrading

New versions do not arrive on their own. Your page stays on whatever version number is in your script tag until you change it, so nothing on your site can shift because I released something.

To upgrade, change the version number in the address and update the integrity fingerprint to match. Old versions keep working indefinitely, so there is no deadline and no forced migration.

Card Kinds

Every card shares one shell, one tail, one entrance and one dismiss behaviour. Only the body changes, set by ctx.kind on the term. Cards below are captured from the rendered component, not redrawn.

The term card kind, showing a definition, an optional expansion, and a link out.
term A definition, an optional expansion, and a link out.
The verdict card kind, showing an adjudicated claim. The badge carries the ruling; the rows carry the evidence behind it.
verdict An adjudicated claim. The badge carries the ruling; the rows carry the evidence behind it.
The verdict card kind, showing the same shell, opposite ruling. A tool that can only render agreement is not adjudicating.
verdict The same shell, opposite ruling. A tool that can only render agreement is not adjudicating.
The entity card kind, showing a product, person or organization, with an avatar and meta rows.
entity A product, person or organization, with an avatar and meta rows.
The steps card kind, showing a numbered procedure.
steps A numbered procedure.
The compare card kind, showing two columns, for the distinction a definition alone would blur.
compare Two columns, for the distinction a definition alone would blur.
The code card kind, showing a snippet with a caption. This one shows the markup the card itself was built from.
code A snippet with a caption. This one shows the markup the card itself was built from.
The quote card kind, showing a cited passage with attribution.
quote A cited passage with attribution.

Charts

Any kind can carry ctx.chart. These are sparklines rather than charts: no axes, no tooltips, nothing to interrogate. A card that disappears on mouse-out is the wrong container for a number that needs studying, so when one does, the card's job is to link out to it.

A line sparkline inside a stat card, showing a trend over continuous time.
line A trend over continuous time.
A bars sparkline inside a stat card, showing discrete periods.
bars Discrete periods.
A ring sparkline inside a stat card, showing one percentage of a whole.
ring One percentage of a whole.
A progress sparkline inside a stat card, showing completion against a target.
progress Completion against a target.
A share sparkline inside a stat card, showing composition, stacked to 100%.
share Composition, stacked to 100%.
A hbars sparkline inside a stat card, showing a ranked comparison.
hbars A ranked comparison.
A range sparkline inside a stat card, showing a position between two bounds.
range A position between two bounds.
A winloss sparkline inside a stat card, showing pass and fail runs.
winloss Pass and fail runs.

Live On This Page

This page runs the script it describes, so you can try it here. The five terms below are deliberately technical ones, marked wherever they appear in the text above. Hover one on a computer, or tap it on a phone, and its definition appears.

  • DefinedTermSet, the schema.org type the script reads.
  • subresource integrity, the hash that pins the bytes.
  • immutable, the caching guarantee a tagged path makes.
  • edge cache, where a tagged response lives after the first request.
  • CORS, the header that decides who may read the response.

Nothing is sent anywhere to make that work. The script reads the markup already in the document, scans the prose in the browser, and no page text leaves the page. The only network requests it makes are for the script itself and any term packs, both from this CDN.

Source

The script and the delivery Worker live in the same repository, which is what keeps a release and the thing serving it from drifting apart.

Context Where Your Readers Need It

Contextual definition cards driven by the structured data already on your page. Open source, no page text leaves the browser.