Validate OPF files
Every OPF pipeline should validate documents against the canonical JSON Schema before rendering. Here are three ways to do it.
Get the schema
The canonical OPF v1 JSON Schema is served at https://openpresentation.org/schema/opf/v1 — the same URL every deck references in its $schema field. Fetch it once and validate locally:
curl -sL https://openpresentation.org/schema/opf/v1 -o opf.schema.jsonA browsable version with field-by-field documentation is at the OPF schema reference.
Ajv in Node.js
Ajv is the standard JSON Schema validator for JavaScript. Install ajv and ajv-formats, then:
import Ajv from "ajv"
import addFormats from "ajv-formats"
import { readFileSync } from "node:fs"
const schema = JSON.parse(readFileSync("opf.schema.json", "utf8"))
const deck = JSON.parse(readFileSync("deck.opf.json", "utf8"))
const ajv = new Ajv({ allErrors: true })
addFormats(ajv)
const validate = ajv.compile(schema)
if (validate(deck)) {
console.log("Valid OPF document")
} else {
console.error(validate.errors)
process.exit(1)
}ajv-cli
Validate from a terminal or script without writing any code:
npx ajv-cli validate -s opf.schema.json -d deck.opf.json --spec=draft2020 -c ajv-formatsThe OPF package
The @openpresentation/opf package bundles the schema and exposes a validatePresentationhelper, so you don't need to fetch the schema separately:
import { validatePresentation } from "@openpresentation/opf"
import { readFileSync } from "node:fs"
const deck = JSON.parse(readFileSync("deck.opf.json", "utf8"))
const result = validatePresentation(deck)
if (!result.valid) {
console.error(result.errors)
process.exit(1)
}Newer versions of the validator also return a separate warnings array for advisory issues, such as references to unknown catalog ids. Warnings never affect valid — treat them as hints, not failures. Check the developer docs for the package's current publication status.
Validate in CI
If decks live in your repository, validate them on every push so invalid documents never reach a renderer:
# .github/workflows/validate-decks.yml
name: Validate OPF decks
on: [push, pull_request]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: curl -sL https://openpresentation.org/schema/opf/v1 -o opf.schema.json
- run: |
shopt -s nullglob
for deck in decks/*.opf.json; do
npx ajv-cli validate -s opf.schema.json -d "$deck" --spec=draft2020 -c ajv-formats
done