A VitePress-based static site generator that renders one or more OCX-style package indices into a browsable catalog: a grid of packages, per-package detail pages (README, platforms, versions, install commands), search, and an optional docs mount — all served as plain static files.
Documentation: https://ocx-sh.github.io/catalog/ — source in
docs/.
An index is a sparse, content-addressed HTTP tree of JSON files —
/config.json, /p/<namespace>/<package>.json package roots, and
content-addressed /p/<namespace>/<package>/o/sha256/<hex>.json OCI image
indices. It is the wire format an OCX client
resolves packages through. Producing and serving that tree is out of scope for
this package entirely.
@ocx-sh/catalog is a renderer: point it at one or more indices (a local
directory, an HTTPS endpoint, or a git repository) and it builds a static site
around them. It never writes to an index and never invents index data — it only
reads and displays what is already there. Full framing:
Index vs. catalog.
The reference consumer is ocx-sh/index,
the public OCX package index served at index.ocx.sh, which runs this renderer
against its own p/** tree as a root: true self-mirror.
Pre-1.0, published. The full pipeline is implemented and covered by its own
tests: the CLI, the config loader, the VitePress theme, the CI workflow
renderer, and the source-resolution layer (path/url/git readers feeding
the mirror, catalog.json and _headers emitters).
npm install --save-dev @ocx-sh/catalog vitepress vueRequires Node.js >=20.19. vitepress and vue are peer dependencies — this
package plugs a custom theme into your own VitePress install rather than
shipping a fork of it.
A minimal catalog.config.json for a repository that colocates its own index (a
p/** tree) alongside the config file:
{
"$schema": "https://cdn.jsdelivr.net/npm/@ocx-sh/catalog/src/config/schema/catalog.config.schema.json",
"sources": [
{ "path": ".", "root": true }
],
"brand": { "title": "My OCX Index" }
}npx ocx-catalog build --config ./catalog.config.json --out ./distroot: true marks this source as the catalog's own self-mirror: its wire tree
is served from the site root, and the catalog decorates it with a browsable UI.
Longer walkthrough, including multi-source aggregation and local preview: Quickstart.
Two constraints decide which hosts work:
- A generated catalog site must be served from a domain root — it emits no
base path, so a project-Pages subpath such as
org.github.io/repo/breaks every asset and wire fetch. - The
_headersfile it emits (Content-Security-Policy: sandboxandX-Content-Type-Options: nosniffover the mirrored, untrusted/p/*tree) is read by Cloudflare Pages and Netlify only. Everywhere else it ships inert and the rules are yours to translate.
Details and the per-host decision table: Known limitations, Hosting and headers.
| Section | Contents |
|---|---|
| How-To | Quickstart, sources, GitHub/GitLab deploys, local preview, branding |
| Reference | CLI, config schema, CI rendering, output layout |
| Explanation | Index vs. catalog, multi-source model, security model |
| Ops | Known limitations, hosting and headers, troubleshooting |