Embed JDF on the web
jdf.js is a JavaScript library that turns any .jdf URL into a fully styled, scrollable, searchable embed in your web page. Think PDF.js — but the file you point at is plain JSON, so you can also generate it, diff it, and edit it with any tool.
Hello, embed
Drop these three lines into any HTML page and you have a fully working JDF viewer:
<link rel="stylesheet" href="https://unpkg.com/@uurtech/jdf@0.1.8/dist/jdfjs.css">
<script type="module" src="https://unpkg.com/@uurtech/jdf@0.1.8"></script>
<jdf src="/whitepaper.jdf"></jdf>
Result, rendered live below — this is a real <jdf> tag in this page, not a screenshot:
The only embed form: <jdf>
One tag. The library registers <jdf> as a custom element with reactive attributes — change src via JS and the embed re-renders.
<jdf src="/doc.jdf"></jdf>
<!-- configure with attributes -->
<jdf src="/doc.jdf"
width="800"
height="600"
zoom="1.2"
sidebar="true"
dark-mode="auto"></jdf>
<!-- update programmatically -->
<script>
document.querySelector("jdf").setAttribute("src", "/other.jdf");
</script>
Configuration
| Attribute | Type | Default |
|---|---|---|
src | string | required |
width | number (px) or any CSS length | — |
height | number (px) or any CSS length | 600px |
zoom | number | 1 |
fit | "manual" · "fit-width" · "fit-page" | "manual" |
sidebar | boolean | false |
toolbar | boolean | true |
dark-mode | "auto" · "light" · "dark" | "auto" |
page | integer (0-based) | 0 |
manual | boolean | — |
To opt out of auto-init for a specific tag, add manual. For SPA pages where you mount content async, call jdf() manually:
import { jdf } from "@uurtech/jdf";
// after your async content lands
jdf(); // scan the whole document
jdf(myContainer); // scan inside one container
Programmatic API
For full control, install via npm and use the JS API directly:
npm install @uurtech/jdf
import { embed, render, JDFViewer } from "@uurtech/jdf";
import "@uurtech/jdf/style.css";
// 1. Embed by URL
const v1 = await embed("#viewer", "/doc.jdf", {
zoom: 1.2,
sidebar: true,
onPageChange: (i) => console.log("on page", i),
});
v1.goToPage(2);
v1.setZoom(1.5);
// 2. Render an in-memory document
const doc = { $jdf: "1.0.0", meta: { title: "Hi" }, pages: [...] };
const v2 = render("#out", doc);
// 3. Class form for advanced wiring
const el = document.getElementById("v");
const v3 = new JDFViewer(el, doc, { darkMode: "dark" });
v3.setDocument(otherDoc); // hot-swap
See the API reference for every method, option, and event. See live examples for sidebar / dark mode / multi-page setups. See framework integrations for React, Vue, Svelte snippets.
Hosting your .jdf file
Just put it on a URL. JDF files are static JSON — every static host works. The fetch needs to succeed with CORS allowed if cross-origin.
- GitHub Pages / Cloudflare Pages / Netlify / Vercel: drop a
.jdfin yourpublic/folder, link to it. - S3 / R2 / GCS: upload + set public read + CORS allowed.
- CDN: works as expected.
.jdffiles compress well (~80% gzip) so setContent-Encoding: gzip.
Suggested response headers:
Content-Type: application/json
Cache-Control: public, max-age=3600
Access-Control-Allow-Origin: *
Browser support
Chrome 88+, Firefox 87+, Safari 14+, Edge 88+. The library uses ES modules, IntersectionObserver, customElements, and the fetch API — all baseline in browsers shipped after early 2021.