The platform-curated catalog for Musher — the one-click deployable items that appear in the storefront.
Each item is a self-contained directory under items/ holding the three
authoring surfaces a catalog entry spans: its components (the building
blocks), its blueprint (the composition graph), and its listing (the
storefront wrapper). All three use the Musher spec-document envelope, defined
normatively in musher-dev/spec.
Third-party marks. The icons under
items/*/media/are the official marks of the upstream projects they identify. They remain the property of their respective owners, are included for nominative identification only, and are not covered by this repository'sLICENSE. SeeNOTICEandICONS.md.
items/
└── <slug>/ # ONE self-contained item per directory
├── listing.yaml # storefront wrapper
├── blueprint.yaml # composition graph
├── components/
│ └── <name>.yaml # ≥1; every file referenced by blueprint.yaml
└── media/ # optional assets
├── icon.png
└── screenshots/*.png
The directory name is the slug, so slug uniqueness is structural.
These are hard requirements. A violation is rejected when the platform syncs this repo:
- the directory name equals both
listing.yaml's andblueprint.yaml'smetadata.slug, and theirmetadata.versionvalues match; - every blueprint node's
componentresolves to acomponents/<name>.yamlfile in the same item directory, and every such file is referenced — no unreferenced components; - media paths are item-relative, live under
media/, contain no.., use a supported extension, and exist on disk; - every node's
sizenames a Compute Profile the platform offers; - image refs are pinned —
:latest,:mainand:edgeare rejected; - component shape follows the workload kind:
SERVICErequires endpoints plus a readiness probe for a public endpoint;WORKER,JOBandCRONforbid endpoints.
Per the spec, a listing deploys exactly one blueprint, and compute is a per-node concern on the blueprint node rather than on the component.
Create items/<slug>/ with a component file per building block.
components/my-app.yaml
specVersion: v1
kind: COMPONENT
metadata:
version: 1 # the version blueprint nodes pin
spec:
workload:
kind: SERVICE # SERVICE | WORKER | JOB | CRON
source:
type: IMAGE
ref: ghcr.io/example/my-app:1.2.3 # pinned — no :latest
endpoints:
primary:
containerPort: 8080
protocol: HTTP
visibility: PUBLIC
health:
readiness:
path: /healthz
initialDelaySeconds: 30
contract: # typed inputs — the install form
inputs:
adminPassword:
schema: { type: STRING, isSensitive: true }
isRequired: true
suppliedBy: USER
ui: { label: Admin password }
target: { envVarKey: ADMIN_PASSWORD }
outputs: {}blueprint.yaml — references the component file by repo-local path and
binds compute per node:
specVersion: v1
kind: BLUEPRINT
metadata: { slug: my-app, version: 1 }
spec:
components:
web: # graph-local node name (map order = graph order)
component: ./components/my-app.yaml # must begin ./ and end .yaml
size: general.standard.small # binding Compute Profile
connections: {} # inbound wires, keyed by consumer input
parameters: {} # empty ⇒ derived from merged USER inputsThe ./ prefix is load-bearing, not decorative: a bare name is not
distinguishable from the UUID a published reference uses, so without it no
validator could tell which resolver the reference wanted.
listing.yaml
specVersion: v1
kind: LISTING
metadata: { slug: my-app, version: 1 }
spec:
listingKind: BLUEPRINT # BLUEPRINT | COMPONENT
displayName: My App
summary: One-line storefront tagline (≤ 280 chars)
description: |
Markdown long-form description.
category: DEVELOPER_TOOLS
lifecycleStage: STABLE # STABLE | BETA | EXPERIMENTAL | SUNSET
tags: [example]
homepageUrl: https://example.com
sourceRepoUrl: https://github.com/example/my-app
license: MIT
icon: media/icon.png # optional; see ICONS.md
screenshots: # optional; {file, caption?} in display order
- file: media/screenshots/01-home.png
caption: The home screenA multi-service item adds more entries under spec.components — unique node
names, one components/<name>.yaml per reference — and wires connections
between declared component outputs and inputs. A wire's two ends must agree on
schema.type, and on schema.semanticType wherever the consuming input names
one. A COMPONENT-kind listing still
authors a trivial single-node blueprint.yaml wrapping its one component.
npm install
npm testEvery item is validated against the schemas at the tip of the public
musher-dev/spec repository, fetched at
run time rather than vendored — so what the corpus is judged against is the
contract as it currently stands, not a copy of it that has quietly fallen
behind. The repository is public, so no credential is involved. The suite
covers the three phases a client can decide offline: the YAML profile, the JSON
Schema bundles, and the semantic rules that bind an item's documents to each
other and to its directory. See tests/README.md.
The Musher platform remains the sole authority. These tests are the same
contracts applied early, not a second one: they run the phases that need no
network, and they cannot see the capability phase at all — whether a Compute
Profile is actually offered, whether a published component exists, whether a
version is monotonic. An item that passes here can still be rejected at sync.
Keep changes to one item per pull request, so a rejection that only the platform can raise is easy to attribute.
This repository holds the platform-curated catalog — the items Musher
maintains directly. It is public so the corpus is a browsable worked example
for anyone authoring against musher-dev/spec.
Community-authored catalog items are not submitted here. They are created and managed directly on the Musher platform. Pull requests adding new third-party listings to this repository will be closed with a pointer to that flow.
Corrections to existing items — a stale image tag, a broken link, an upstream rebrand, a clearer summary — are welcome as pull requests.
The YAML and prose in this repository are covered by LICENSE.
The third-party marks under items/*/media/ are not — see
NOTICE.