npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@openpresentation/opf

v0.11.0

Published

Canonical Open Presentation Format schemas, catalogs, TypeScript types, and local validation.

Readme

@openpresentation/opf

Canonical Open Presentation Format package for JavaScript and TypeScript.

Publishes the OPF schemas, catalog presets, raw spec files, generated TypeScript types, examples, docs, and local validation helpers. The schema is pre-stable (0.x — expect breaking changes between minor versions until 1.0). This package does not render PowerPoint files, parse .pptx, fetch remote catalogs, call hosted APIs, provide telemetry, or use AI.

The canonical npm package remains @openpresentation/opf; a separate @openpresentation/opf-spec package is not used for v0.2.0 so existing downstream imports stay stable. The packed npm artifact includes package-addressable OPF schemas, catalogs, reference files, and an optional downstream-service reference openapi.yaml under spec/.

Repository: https://github.com/OpenPresentation/opf

File naming

Use *.opf.json for complete Open Presentation Format documents, such as deck.opf.json.

OPF documents are plain JSON, and the .opf.json suffix keeps that visible to editors, validators, agents, and repository tooling. Avoid bare *.opf for OPF JSON because that extension is already used by other document and project formats.

Install

pnpm add @openpresentation/opf
# or: npm install @openpresentation/opf
# or: yarn add @openpresentation/opf

Requires Node 24 starting with version 0.10.0. Earlier published versions retain their recorded runtime requirements.

Usage

Use the common root API for most application code:

import {
  presentation,
  audiences,
  tones,
  catalogs,
  validate,
  validatePresentation,
} from "@openpresentation/opf";

import type { Presentation } from "@openpresentation/opf";

const deck: Presentation = {
  name: "Quarterly Review",
  slides: [{ title: "Quarterly Review", items: ["Revenue", "Product", "Hiring"] }],
};

console.log(presentation.$id);
console.log(validatePresentation(deck).valid);
console.log(validate(tones[0], "tones").valid);
console.log(audiences.map((audience) => audience.id));
console.log(Object.keys(catalogs));

Use focused imports when you only need one surface:

import { presentation, audience } from "@openpresentation/opf/schemas";
import { audiences, tones } from "@openpresentation/opf/catalogs";
import { specFileEntries } from "@openpresentation/opf/spec-files";
import { validate, assertValid } from "@openpresentation/opf/validator";
import {
  layoutPreviews,
  getLayoutPreview,
  hasLayoutPreview,
} from "@openpresentation/opf/previews";
import type { Presentation, Audience, Tone } from "@openpresentation/opf/types";

The root entry exports every schema, catalog, and validation helper for convenience. Prefer the focused subpaths above when a package consumer only needs one surface, so the root bundle's full catalog/schema payload is not loaded unnecessarily.

Contextual lint (0.10.0)

Version 0.10.0 adds lintSource(source, options) and lintPresentation(document, options) from @openpresentation/opf/lint and the root API. They report strict JSON syntax, duplicate keys, schema constraints, local catalog alternatives, asset registry errors, and explicit host contracts. Source diagnostics retain original UTF-16 ranges without rewriting the document. Options accept already loaded catalogs and contracts; no remote resources are fetched.

Earlier versions do not include these APIs. See the lint guide for configuration and the source CLI. Passing lint does not certify layout, fonts, or native export fidelity.

Layout previews

@openpresentation/opf/previews ships pre-rendered HTML thumbnails for the slide layouts catalogued at pptx.gallery. Each preview is a Tailwind-styled fragment sized to fill a 16:9 container and only depends on the standard --background, --foreground, --card, --muted, --muted-foreground, --accent, and --border CSS variables.

import { getLayoutPreview } from "@openpresentation/opf/previews";

export function LayoutThumbnail({ slug }: { slug: string }) {
  const html = getLayoutPreview(slug);
  if (!html) return null;
  return (
    <div
      className="aspect-[16/9] overflow-hidden rounded-lg border border-border bg-card"
      dangerouslySetInnerHTML={{ __html: html }}
    />
  );
}

Raw HTML source-of-truth lives under spec/previews/layouts/<slug>.html and is also addressable via @openpresentation/opf/spec/previews/layouts/<slug>.html.

Example decks

@openpresentation/opf/examples ships every .opf.json file from examples/ in the upstream repo, already parsed and validated against the presentation schema at build time.

import {
  examples,
  galleries,
  getExample,
  getExamplesByGallery,
} from "@openpresentation/opf/examples";

const compliance = getExample("compliance-readiness-review");
const businessDecks = getExamplesByGallery("business-functions");

console.log(`${examples.length} example decks across ${galleries.length} galleries`);

Each ExampleRecord includes the parsed Presentation object plus its repo-relative path, top-level category (gallery, technical, …), and gallery slug when applicable.

Documentation pages

@openpresentation/opf/docs ships the top-level docs/*.md reference pages (schema-reference, catalog-schema-reference, content-payloads, content-item-design-overrides, examples). Subdirectories like docs/migrations and docs/plans are intentionally excluded — those move too quickly to ship inside a pinned npm release.

import { docs, getDoc } from "@openpresentation/opf/docs";

for (const doc of docs) {
  console.log(`${doc.title} — ${doc.file}`);
}

const schemaRef = getDoc("schema-reference");
console.log(schemaRef?.markdown.slice(0, 200));

Upstream README

@openpresentation/opf/repo-readme exposes the raw markdown of the upstream OpenPresentation/opf README.md at the version pinned by this release. Use it when you want to mirror the canonical README inside another site or app without doing a network fetch.

import { repoReadme } from "@openpresentation/opf/repo-readme";

console.log(repoReadme.split("\n").slice(0, 3).join("\n"));

Validation results carry errors (structural problems that make valid false) and warnings (advisory issues such as unknown catalog ids in narrative, design, or chart type references — these never affect valid). Documents that declare matching inline catalogs.<kind>.records[] or a custom catalogs.<kind>.source are exempt from unknown-id warnings for that kind.

const result = validatePresentation(deck);
if (!result.valid) console.error(result.errors);
for (const warning of result.warnings) console.warn(warning.path, warning.message);

Validate catalog records locally:

import { audiences, validateCatalogRecord } from "@openpresentation/opf";

for (const record of audiences) {
  const result = validateCatalogRecord("audiences", record);
  if (!result.valid) {
    console.error(result.errors);
  }
}

Raw canonical JSON is published under spec/:

import presentationSchema from "@openpresentation/opf/spec/schemas/opf.schema.json" with {
  type: "json",
};

The raw spec manifest exposes typed package paths for files that should be resolved from npm instead of GitHub. openapi.yaml is a reference contract for downstream services that choose to expose OPF over HTTP; OpenPresentation does not host that API.

import { specFileEntries } from "@openpresentation/opf/spec-files";

const openApi = specFileEntries.find((entry) => entry.path === "openapi.yaml");
console.log(openApi?.packagePath);

Package-addressable catalog paths can be used by OPF catalog resolvers:

{
  "catalogs": {
    "narratives": {
      "source": "pkg:@openpresentation/opf/spec/catalogs/narratives"
    }
  }
}

Development

pnpm --filter @openpresentation/opf typecheck
pnpm --filter @openpresentation/opf test
pnpm --filter @openpresentation/opf pack:dry-run

src/generated/ and dist/ are generated from the root spec/ directory and are intentionally ignored by git.