OPF registry guide
Publish reusable OPF design choices over plain HTTPS and validate them through the same API that validates decks.
What is a registry?
A registry is a pair of JSON shapes: an index that lists items and their registry_urls, and a per-item descriptor that carries the full details for one item. Both use the same schema.
Each item declares a type from the registered OPF type namespace. As of OPF v1.0, the supported types are:
- registry:background
- registry:chart
- registry:color-scheme
- registry:font-scheme
- registry:layout
- registry:narrative
- registry:theme
Index shape
The index identifies the registry and lists its items. Each entry points at a per-item descriptor via registry_url.
{
"$schema": "https://pptx.dev/schema/registry.schema.json",
"name": "string",
"registry_url": "https://your-host/registry.json",
"opf_version": "1.0",
"items": [
{
"name": "string",
"type": "registry:layout",
"registry_url": "https://your-host/registry/layouts/your-layout.json",
"dependencies": [],
"opf_version": "1.0"
}
]
}Required at the index level: name, registry_url, opf_version, and items. Each entry in items requires name, type, registry_url, and opf_version; dependencies is optional.
Per-item descriptor shape
Fetching an item's registry_url returns a descriptor that carries the OPF payload, copy targets, and metadata needed to render or embed the item.
{
"$schema": "https://pptx.dev/schema/registry.schema.json",
"name": "string",
"type": "registry:layout",
"registry_url": "https://your-host/registry/layouts/your-layout.json",
"dependencies": [],
"opf_version": "1.0",
"slug": "your-layout",
"category": "layouts",
"description": "string",
"web_url": "https://your-host/layouts/your-layout",
"opf": [
{ "name": "default", "label": "Default OPF snippet", "language": "json", "source": "...", "value": { } }
],
"copy_targets": [
{ "name": "registry_url", "label": "Registry URL", "content_type": "text/plain", "value": "https://your-host/registry/layouts/your-layout.json" }
],
"metadata": { }
}Required on a descriptor: name, type, registry_url, and opf_version. Common additional fields are slug, category, description, web_url, dependencies, opf[] (snippet records), copy_targets[], and metadata.
Field reference
- $schema
- Must equal
https://pptx.dev/schema/registry.schema.json. Optional but recommended; enables tooling to locate the schema automatically. - name
- Display name of the registry or item.
- registry_url
- Canonical HTTPS URL of this JSON file. Must be fetchable without authentication.
- opf_version
- OPF contract version the payload targets. Currently
"1.0". - type
- Registry item type. One of the 7
registry:*values listed above. Required on per-item descriptors and on each entry initems. - dependencies
- Array of
registry_urlstrings this item depends on, for example a theme that references color and font schemes. - items
- Index-only. Array of entries that point at per-item descriptors.
- slug / category / description / web_url
- Per-item display metadata.
slugis the URL-safe id;categorygroups items (for examplelayouts,themes);web_urlpoints at a human-viewable page. - opf[]
- Array of snippet records — each has
name,label,language,source(string form), andvalue(parsed form). - copy_targets[]
- Array of copyable strings surfaced to users — each has
name,label,content_type, andvalue. - metadata
- Informational object. Extensible by publishers; validators ignore unknown keys.
Example: index
Example descriptor for https://www.pptx.gallery/registry.json:
{
"$schema": "https://pptx.dev/schema/registry.schema.json",
"name": "PPTX.gallery OPF Registry",
"registry_url": "https://www.pptx.gallery/registry.json",
"opf_version": "1.0",
"items": [
{
"name": "Cover",
"type": "registry:layout",
"registry_url": "https://www.pptx.gallery/registry/layouts/cover.json",
"dependencies": [],
"opf_version": "1.0"
},
{
"name": "Cool Horizon",
"type": "registry:color-scheme",
"registry_url": "https://www.pptx.gallery/registry/color-schemes/cool-horizon.json",
"dependencies": [],
"opf_version": "1.0"
},
{
"name": "Minimal",
"type": "registry:theme",
"registry_url": "https://www.pptx.gallery/registry/themes/minimal.json",
"dependencies": [
"https://www.pptx.gallery/registry/color-schemes/cool-horizon.json",
"https://www.pptx.gallery/registry/font-schemes/aptos.json"
],
"opf_version": "1.0"
}
]
}Example: per-item descriptor
Example descriptor for https://www.pptx.gallery/registry/layouts/cover.json:
{
"$schema": "https://pptx.dev/schema/registry.schema.json",
"name": "Cover",
"type": "registry:layout",
"registry_url": "https://www.pptx.gallery/registry/layouts/cover.json",
"dependencies": [],
"opf_version": "1.0",
"slug": "cover",
"category": "layouts",
"description": "A presentation cover with a title, optional subtitle, and logo.",
"web_url": "https://www.pptx.gallery/layouts/cover",
"opf": [
{
"name": "default",
"label": "Default OPF snippet",
"language": "json",
"source": "{\n \"name\": \"Cover example\",\n \"slides\": [\n {\n \"layout\": \"cover\",\n \"title\": \"Presentation title\"\n }\n ],\n \"catalogs\": {\n \"default\": {\n \"source\": \"https://www.pptx.gallery\",\n \"layouts\": {\n \"cover\": {\n \"name\": \"Cover\",\n \"summary\": \"The opening slide: title, subtitle and an optional picture.\",\n \"tags\": [\n \"Openers and closers\"\n ],\n \"design\": {\n \"titleAlignment\": \"center\",\n \"contentAlignment\": \"center\"\n },\n \"direction\": \"row\",\n \"regions\": [\n {\n \"name\": \"title\"\n },\n {\n \"name\": \"media\",\n \"accepts\": [\n \"image\",\n \"video\"\n ],\n \"role\": \"media\",\n \"flow\": \"none\",\n \"bleed\": true\n }\n ],\n \"description\": \"Open a presentation with its subject and a short introduction. Add a picture when it helps establish the context.\",\n \"preview\": {\n \"vectorSrc\": \"https://www.pptx.gallery/layout-previews/cover.svg\"\n }\n }\n }\n }\n }\n}",
"value": {
"name": "Cover example",
"slides": [
{
"layout": "cover",
"title": "Presentation title"
}
],
"catalogs": {
"default": {
"source": "https://www.pptx.gallery",
"layouts": {
"cover": {
"name": "Cover",
"summary": "The opening slide: title, subtitle and an optional picture.",
"tags": [
"Openers and closers"
],
"design": {
"titleAlignment": "center",
"contentAlignment": "center"
},
"direction": "row",
"regions": [
{
"name": "title"
},
{
"name": "media",
"accepts": [
"image",
"video"
],
"role": "media",
"flow": "none",
"bleed": true
}
],
"description": "Open a presentation with its subject and a short introduction. Add a picture when it helps establish the context.",
"preview": {
"vectorSrc": "https://www.pptx.gallery/layout-previews/cover.svg"
}
}
}
}
}
}
}
],
"copy_targets": [
{
"name": "registry_url",
"label": "Registry URL",
"content_type": "text/plain",
"value": "https://www.pptx.gallery/registry/layouts/cover.json"
},
{
"name": "web_url",
"label": "Gallery URL",
"content_type": "text/plain",
"value": "https://www.pptx.gallery/layouts/cover"
},
{
"name": "opf:default",
"label": "Default OPF snippet",
"content_type": "application/json",
"value": "{\n \"name\": \"Cover example\",\n \"slides\": [\n {\n \"layout\": \"cover\",\n \"title\": \"Presentation title\"\n }\n ],\n \"catalogs\": {\n \"default\": {\n \"source\": \"https://www.pptx.gallery\",\n \"layouts\": {\n \"cover\": {\n \"name\": \"Cover\",\n \"summary\": \"The opening slide: title, subtitle and an optional picture.\",\n \"tags\": [\n \"Openers and closers\"\n ],\n \"design\": {\n \"titleAlignment\": \"center\",\n \"contentAlignment\": \"center\"\n },\n \"direction\": \"row\",\n \"regions\": [\n {\n \"name\": \"title\"\n },\n {\n \"name\": \"media\",\n \"accepts\": [\n \"image\",\n \"video\"\n ],\n \"role\": \"media\",\n \"flow\": \"none\",\n \"bleed\": true\n }\n ],\n \"description\": \"Open a presentation with its subject and a short introduction. Add a picture when it helps establish the context.\",\n \"preview\": {\n \"vectorSrc\": \"https://www.pptx.gallery/layout-previews/cover.svg\"\n }\n }\n }\n }\n }\n}"
}
],
"metadata": {
"category": "layouts",
"slug": "cover",
"page_url": "https://www.pptx.gallery/layouts/cover",
"inspector_url": "https://pptx.dev/inspector?config=layouts:cover"
}
}Pointing at an external registry
Tools consume a registry by fetching its registry_url, reading the items array, and fetching each item's registry_url on demand. That is the entire discovery protocol — no index file, manifest, or authentication is required beyond serving the JSON publicly.
Validating your registry
Send the public registry URL to /api/v1/validate:
curl -X POST https://pptx.dev/api/v1/validate \
-H "Authorization: Bearer $PPTX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"registryUrl":"https://www.pptx.gallery/registry.json"}'The response includes top-level valid, errors, and warnings, plus one result per registry item. A top-level valid: false means the registry file could not be used as a valid registry; a per-item valid: false means that item failed its own OPF validation.
If you validate locally with AJV, enable Draft 2020-12 and ajv-formats. The registry schema uses format: "uri" for HTTPS fields.
pnpm --package=ajv-cli@5.0.0 --package=ajv-formats@3.0.1 dlx ajv validate \ --spec=draft2020 \ -c ajv-formats \ -s schema.json \ -d registry.json
Publishing
Host the JSON anywhere HTTPS is available, such as GitHub Pages, Vercel, S3, or Cloudflare R2. Each file must be publicly fetchable, no larger than 1 MiB, and should be served with an application/json Content-Type.
Stability guarantees
Registries built against OPF v1.0 validate for the life of v1.0. See the OPF v1.0 stability contract for the versioning rules that keep third-party registries compatible.