Publish a component
How a package enters the registry: build a declarative package from source, publish it to a registry, and read it back from the catalog. The package format is the same one every catalog entry uses.
The package contract
A package is a directory with a manifest (component-package.json), a payload and a JSON Schema for its props. kind: block packages are declarative document-IR content; nothing in a package executes on the host.
| kind | what it ships | status |
|---|---|---|
block | declarative document-IR specs, prop schemas, tokens, READMEs | 57 entries in the current catalog |
theme | tokens and stylesheets | accepted by the format; no catalog entry yet |
adapter | format projections, such as framework importers | accepted by the format; no catalog entry yet |
plugin | third-party executable code | refused until a host sandbox with explicit capability grants exists |
Build and publish
docsloth component build --dir ./package [--out ./dist]
docsloth component publish --dir ./package --registry https://registry.docsloth.dev --token "$DOCSLOTH_TOKEN"
A directory registry works the same way without a token: docsloth component publish --dir ./package --registry ./registry writes index.json and packages/<name>/<version>/{manifest.json,files/…}.
HTTP publishing contract
| Field | Value |
|---|---|
| Method and path | POST /v1/packages |
| Authorization | Bearer <token> (from --token or DOCSLOTH_TOKEN); the token is never stored in the manifest, the registry or stdout |
| Body | { "manifest": { … }, "files": { "<path>": "<base64>" } } |
| Success | 2xx { "ok": true, "digest": "sha256:…", "unchanged": true|false } |
| Refusal | 409 (or any non-2xx) when a name+version is republished with different bytes (DSL1705); an identical republish is a no-op |
The machine-readable contract is /api/v1/publish.json. Publishing auth and the hosted write path are cloud-side (owner / registry team); this static site documents the contract and does not accept publishes.
What this registry serves
| Surface | Path | What it carries |
|---|---|---|
| Search index | /api/v1/search.json | every catalog entry with its description, trust class, status, tools, URLs and install ref |
| Catalog | /api/v1/catalog.json | the same JSON as /catalog.json (one derivation, two routes) |
| Component metadata | /api/v1/components/<name>.json | one entry plus its version resolution |
| Version resolution | /api/v1/versions.json | 57 entries; 57 carry a built package version and digest, 0 keep the catalog placeholder |
| Publishing contract | /api/v1/publish.json | the POST /v1/packages contract, immutability rules and package kinds |
| Agent index | /llms.txt | the human/agent table of contents for every page |
Honest limits
The registry site is static: the API endpoints are pre-rendered files generated from packages/contracts/component-catalog.json, there is no request-time database and no query-time search service — clients filter the search index themselves. Version resolution reports the versions present in this generated catalog; a hosted registry resolves latest across all published versions.
Index signatures, yank/revoke and publisher identity are registry-operator concerns and are out of scope here; see docs/MARKET_FLOW.md for the full chain and the failure codes.