feat(publish): make package installable from Gitea npm registry (WHYNOT-WP-0003 T02)
Some checks failed
ci / check (push) Has been cancelled
ci / release (push) Has been cancelled

- package.json: private:false; real repository.url; publishConfig.registry →
  coulomb Gitea npm; lit dependency → peerDependency (^3) + devDependency;
  ship the ir/ consumer contract (files + ./ir/* export); add PUBLISHING.md to files.
- .npmrc: real @whynot scope registry + ${NPM_AUTH_TOKEN} ref (no secret committed).
- PUBLISHING.md: publish flow, token routing (operator/OpenBao — warden route is not
  in this CLI), and consumer install.
- README: registry-install path + lit peer note. CHANGELOG: Added/Changed entries.

Config + packaging validated via `npm pack --dry-run` (ir/, tokens, CSS, PUBLISHING.md
included; .npmrc excluded). Actual `npm publish` + install-verify is gated on a Gitea
NPM_AUTH_TOKEN (operator-owned) and an explicit outward-publish go-ahead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-27 15:15:47 +02:00
parent c538d05434
commit e02011905a
6 changed files with 99 additions and 12 deletions

11
.npmrc
View File

@@ -1,5 +1,6 @@
# When ready to publish to Gitea Packages, uncomment and set NPM_AUTH_TOKEN
# in your shell or CI secrets.
#
# @whynot:registry=https://gitea.example.com/api/packages/whynot/npm/
# //gitea.example.com/api/packages/whynot/npm/:_authToken=${NPM_AUTH_TOKEN}
# @whynot/* is published to and installed from the coulomb Gitea npm registry.
# The auth token is NOT stored here — set NPM_AUTH_TOKEN in your shell/CI.
# It is operator/OpenBao-owned (credential-routing.md: tokens route, never vend);
# obtain a Gitea package token from the operator. Publish flow: see PUBLISHING.md.
@whynot:registry=https://gitea.coulomb.social/api/packages/coulomb/npm/
//gitea.coulomb.social/api/packages/coulomb/npm/:_authToken=${NPM_AUTH_TOKEN}

View File

@@ -6,6 +6,20 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Version
## [Unreleased]
### Added
- **Publishable to the coulomb Gitea npm registry** (WHYNOT-WP-0003 T02) — `private:false`,
`publishConfig.registry`, real `repository.url`, an `.npmrc` scope + `${NPM_AUTH_TOKEN}`
reference (no secret committed), and `PUBLISHING.md` (publish flow + consumer install +
token routing). The package now ships the `ir/` consumer contract (added to `files` and
the `./ir/*` export) so consumers can pin a version and track it.
### Changed
- **`lit` is now a `peerDependency`** (`^3`), not a direct dependency. Consumers must
install `lit` alongside `@whynot/design` (`npm i @whynot/design lit`) so their bundler
dedupes to a single `lit` instance.
## [0.3.0] — 2026-06-27
### Added

55
PUBLISHING.md Normal file
View File

@@ -0,0 +1,55 @@
# Publishing `@whynot/design`
`@whynot/design` is published to the **coulomb Gitea npm registry** so consuming
repos can pin a version (`npm i @whynot/design@x.y.z`) and track it at their own pace
(WHYNOT-WP-0003). The git tag cut by `make release` (see `DesignSystemIntroduction.md`
§6) is the version; publishing makes that version installable.
- Registry: `https://gitea.coulomb.social/api/packages/coulomb/npm/`
- `package.json` `publishConfig.registry` already points `npm publish` here.
- `lit` is a **peerDependency** — consumers install it themselves so their bundler
dedupes to a single `lit` instance.
## The token (never commit it)
Publishing and installing `@whynot/*` need a Gitea package token. It is **not stored in
this repo** — per `.claude/rules/credential-routing.md`, tokens are routed, not vended:
a Gitea package token is operator/OpenBao-owned (`railiance-platform`). Obtain one from
the operator and export it:
```sh
export NPM_AUTH_TOKEN=# Gitea package token; never paste into git/chat/logs
```
`.npmrc` (committed) references it via `${NPM_AUTH_TOKEN}` — no secret lives in the file.
## Publish (maintainer)
```sh
git checkout main && git pull --ff-only
make release VERSION=x.y.z # bumps, cuts CHANGELOG, commits, tags (§6)
git push --follow-tags origin main
npm publish # uses publishConfig.registry + NPM_AUTH_TOKEN
```
`npm publish` is **outward and immutable** — a published version cannot be silently
replaced. Confirm the tag and `npm pack --dry-run` contents first.
## Install (consumer)
Add an `.npmrc` to the consuming repo so the `@whynot` scope resolves to the registry,
then install the package plus the `lit` peer:
```ini
# .npmrc
@whynot:registry=https://gitea.coulomb.social/api/packages/coulomb/npm/
//gitea.coulomb.social/api/packages/coulomb/npm/:_authToken=${NPM_AUTH_TOKEN}
```
```sh
npm i @whynot/design@x.y.z lit
```
The installed package carries the consumer-facing contract under `ir/` (component
contracts, `tokens.json`, exemplars) reachable via the `./ir/*` export — that is what
the `drift` check (WHYNOT-WP-0003 T05) reads to report changes between versions.

View File

@@ -38,8 +38,18 @@ Framework-agnostic by design. Consumers do **not** re-implement components per f
### Node-tooled consumer (React, Vite, Next, Vue, …)
Install from the coulomb Gitea npm registry (add the scope to your `.npmrc` first — see
[`PUBLISHING.md`](./PUBLISHING.md) for the token). `lit` is a peer dependency:
```ini
# .npmrc
@whynot:registry=https://gitea.coulomb.social/api/packages/coulomb/npm/
//gitea.coulomb.social/api/packages/coulomb/npm/:_authToken=${NPM_AUTH_TOKEN}
```
```sh
pnpm add git+ssh://git@gitea.coulomb.social/coulomb/whynot-design.git#v0.3.0
npm i @whynot/design@v0.3.0 lit
# or pin straight from git: pnpm add git+ssh://git@gitea.coulomb.social/coulomb/whynot-design.git#v0.3.0
```
```js

View File

@@ -2,7 +2,7 @@
"name": "@whynot/design",
"version": "0.3.0",
"description": "The neutral, mostly-black-and-white visual language for whynot — prototype cards, signal records, beta plans, decision documents, and any other deliberately-unfinished artefact. Ships tokens, CSS, and Lit-based web components consumable from React, Django, Vue, plain HTML, or anywhere a custom element runs.",
"private": true,
"private": false,
"type": "module",
"main": "./src/index.js",
"module": "./src/index.js",
@@ -21,17 +21,20 @@
"./tokens/type": "./tokens/type.json",
"./tokens/spacing": "./tokens/spacing.json",
"./adapters/django": "./adapters/django/README.md",
"./ir/*": "./ir/*",
"./assets/*": "./assets/*",
"./skill": "./SKILL.md"
},
"files": [
"src",
"tokens",
"ir",
"assets",
"adapters",
"SKILL.md",
"DesignSystemIntroduction.md",
"MultiFrameworkSupport.md",
"PUBLISHING.md",
"README.md",
"CHANGELOG.md"
],
@@ -47,16 +50,20 @@
"showcase": "npx --yes serve -l 4321 .",
"example": "npx --yes serve -l 4322 examples/whynot-control"
},
"dependencies": {
"lit": "^3.2.1"
"peerDependencies": {
"lit": "^3"
},
"devDependencies": {
"@playwright/test": "^1.45.0"
"@playwright/test": "^1.45.0",
"lit": "^3.2.1"
},
"keywords": ["whynot", "design-system", "wireframe", "prototype", "lit", "web-components", "django", "react"],
"repository": {
"type": "git",
"url": "git+ssh://git@gitea.example.com/whynot/whynot-design.git"
"url": "git+ssh://git@gitea.coulomb.social/coulomb/whynot-design.git"
},
"publishConfig": {
"registry": "https://gitea.coulomb.social/api/packages/coulomb/npm/"
},
"license": "UNLICENSED"
}

View File

@@ -100,7 +100,7 @@ tagged. Tag the current state as the first real anchor.
```task
id: WHYNOT-WP-0003-T02
status: todo
status: wait
priority: high
state_hub_task_id: "dbd3a2e6-0623-4efd-8293-399002e85ea2"
```