Skip to content

From your repository to the catalog.

A custom plugin can live in any public or private repository. See the end-to-end author guide for scaffolding, dependencies, tests, builds and publishing. This page covers its public showcase.

Automatic public discovery

The public site reads the core and plugin collection source locations, plus public GitHub repositories with the heinzel-plugin topic. It recognizes a project at the repository root or plugins/<folder>/pyproject.toml by its project.entry-points."heinzel.modules" declaration. It reads metadata at an immutable commit; it never imports, installs or executes the plugin to build the website.

gh repo edit your-account/heinzel-harbor --add-topic heinzel-plugin

A new public project appears after a successful scheduled refresh. GitHub schedules are best effort; the catalog shows its snapshot time. A broken or over-budget optional source is omitted with a generic notice. Per-source project and blob limits, an aggregate project cap and a refresh API budget keep one topic repository from crowding out healthy entries. An incomplete discovery or required-source failure keeps the previously deployed site. Publication uses a freshly checked public visibility for every included source. Removal or visibility changes take effect on the next successful refresh.

Private projects are excluded even when the workflow's GitHub account can read them. They remain discoverable through authenticated CLI catalog access for authorized users. There is no public page or private metadata cache on this website.

Add a good description

The ordinary project name, version, description and Heinzel dependency range already supply a useful entry. Add optional owner-maintained presentation metadata to the same pyproject.toml:

[tool.heinzel.catalog]
title = "Harbor"
category = "utilities"
highlights = [
  "Summarize the work waiting for you",
  "One operation through CLI, MCP and REST",
  "A Today widget and useful notifications",
]
# Paths are relative to this project, including in a collection.
artwork = ["docs/assets/harbor.webp"]
themes = ["src/heinzel_harbor/themes/harbor.toml"]

Use one of utilities, connectors, themes or reference. Keep highlights factual and short. Omit artwork and themes if your plugin does not have them. The site bounds text and file sizes, rejects traversal and links, and accepts owner artwork as PNG, JPEG or WebP only. Supplier HTML, CSS, scripts and SVG do not enter the site.

Theme previews read actual light and dark palette tokens from the declared TOML. For existing projects, theme TOML inside an explicitly declared Hatch wheel package's themes/ directory is also recognized. The site draws its own inert illustration; it labels it a palette preview rather than presenting it as a runtime screenshot.

The "included" badge is derived from the official standard profile and owning metadata. Declaring yourself standard in another repository does not grant that badge. Source versions and compatibility declarations are shown as metadata, not as a certification against the newest SDK.

Publish UI and CLI screenshots

Every plugin detail page has a screenshot gallery with separate User interface and Command line groups. This includes plugins that supply themes. Capture the running plugin and its CLI in an isolated demonstration profile, commit the raster images to its owning public project, and declare them alongside its other metadata:

[[tool.heinzel.catalog.screenshots]]
path = "docs/assets/ui-light.webp"
surface = "ui"
caption = "Harbor in the app, light appearance"

[[tool.heinzel.catalog.screenshots]]
path = "docs/assets/cli.webp"
surface = "cli"
caption = "hz harbor status in the terminal"

Use at most eight PNG, JPEG or WebP screenshots, each no larger than 2 MiB. Paths are relative to the plugin, including collection projects. Images open at full size and captions also serve as alternative text. Include light and dark captures for themes. Screenshots show actual runtime behavior; theme palette illustrations and character artwork remain separately labeled. Missing captures are shown explicitly rather than replaced by illustrations. Keep examples free of personal data and credentials. Update captures when the interface changes.

Showcase YouTube soundscapes

The catalog reads inert *.toml files under a declared Hatch wheel package's soundscapes/ directory. With Hatch's default layout it also recognizes src/<distribution_with_underscores>/soundscapes/. For a custom layout, declare paths explicitly:

[tool.heinzel.catalog]
soundscapes = ["src/heinzel_harbor/soundscapes/tide.toml"]

It displays soundscapes declaring kind = "stream", [stream] provider = "youtube" and an eleven-character video identity. This works for theme and regular plugins. A Listen on YouTube link works without JavaScript; Play loads the privacy-enhanced YouTube player only after a click. No video, thumbnail or player is requested before that click. Availability and embedding permissions are controlled by YouTube and the video owner. The catalog reads these declarations without executing a provider or checking playback during builds.

Build and verify the website

make docs-site          # deterministic build from checked-in public metadata
make docs-site SERVE=1  # local preview with reload
make docs-site-check    # browser behavior, phone layouts, light/dark and accessibility
make docs-catalog       # explicit online refresh; needs gh authentication

docs/_data/catalog.json is the offline snapshot. HZ_SITE_CATALOG=/path/to/catalog.json selects another snapshot for a site build. Unit tests use synthetic unknown projects and hostile metadata; browser checks exercise the built site, including keyboard filtering and a JavaScript-disabled catalog.

The Docs workflow refreshes public metadata on an hourly schedule, relevant changes to main, manual dispatch and release publication. It checks out current main for publication so an older release cannot roll back site code. One production deployment queue serializes publication. Provider media recording is a separate explicit job and is never part of metadata refresh. No cross-repository publishing credential is required.

The installation CTA advances only when a complete standard profile, matching release artifact hashes and the published core PyPI wheel can be verified. See ADR 0098 for the publishing boundary.