# Publishing WrNexus to npm All 39 `@wrnexus/*` packages are built and published to the **public npm registry** (`registry.npmjs.org`), then installed on any machine with **Bun**. ## Prerequisites The `@wrnexus/*` packages are **scoped**, so the `wrnexus` npm **organization** must exist and you must be a member with publish rights (a username scope like `@clintchiz` would work without an org, but the packages are named `@wrnexus/*`). 1. Create the org once at (name: `wrnexus`). - A **free** org can publish unlimited **public** packages. - To publish **private** (`restricted`) packages first and flip them public later, the org needs a paid **Teams** plan (private scoped packages require it). 2. `npm login` (registry `https://registry.npmjs.org/`). The repo `.npmrc` points the scope at public npm: ``` @wrnexus:registry=https://registry.npmjs.org/ ``` ## Mandatory release workflow Do not publish packages with ad-hoc `npm publish` commands during a normal release. The repository release commands enforce the complete framework + migration + documentation workflow. Every release must have an entry in `packages/cli/src/update.ts`'s `MIGRATIONS` list. The entry must be idempotent and conservative. If a release requires no project file change, add a documented no-op migration entry so that the decision is explicit and reviewable. ### 1. Prepare Align every `packages/*/package.json` version, add the update migration and tests, then run: ```bash bun run release:prepare ``` This command refuses to prepare a release when versions differ or migration coverage is missing. It runs the complete framework check, builds all publish artifacts, and verifies that every staged manifest uses the aligned version and `restricted` access. Review the generated `.publish` changes, then commit and push the framework repository. The publish step will refuse to run from an uncommitted or unpushed framework checkout. ### 2. Publish privately and update documentation ```bash bun run release:private ``` The command performs the remaining release as one guarded workflow: 1. Rebuild and validate all private package artifacts from the pushed commit. 2. Publish every missing `@wrnexus/*` package in dependency order. Already-published packages are verified and skipped, so an interrupted release can be resumed safely. 3. Confirm every package is private and run the newly published CLI updater, including its migrations, against `D:\Company\wrnexusjs`. The updater's immediate project check is deferred because its generated docs inputs are rebuilt in the next step. 4. Align every docs-site dependency, regenerate package pages twice, update `public/llms.txt`, `public/llms-full.txt`, the sitemap, and the documentation index. 5. Run the authoritative docs-site check and production build, verify that `public/llms.txt` contains the current version and every framework package, then commit and push the docs repository. If the documentation checkout lives elsewhere, set `WRNEXUS_DOCS_ROOT` before running the publish command. Both repositories must start clean and synchronized with their active remote branches. Only use the individual commands printed by `scripts/publish-packages.ts` for diagnosed recovery. Finish recovery by rerunning `bun run release:private`; it is the authoritative completion check. ## Publishing implementation The packages ship raw TypeScript in the repo (`main`/`exports` → `src/*.ts`), so they are **built** for publishing. `scripts/publish-packages.ts` builds each package with [tsup](https://tsup.egoist.dev) (bundled JS + a single `.d.ts`) and **stages** a publishable copy under `.publish//` with a rewritten manifest: - `main`/`module`/`types`/`exports`/`bin` point at `./dist/*` - `workspace:*` deps → `^` - `private` removed; `license` → `MIT`; `publishConfig` → `{ registry, access }` - runtime assets copied (`@wrnexus/ui` → `components/`, `ui.css`) The dev `package.json` (pointing at `src/`) is **never modified**, so in-repo dev and tests keep working. ### Private staging details By default the lower-level staging script creates **`restricted`** (private) manifests. It is called by the mandatory release commands and requires the `wrnexus` org on a paid Teams plan. ```bash # Lower-level recovery/debug command only bun run scripts/publish-packages.ts # Publish (deps first). The script prints the exact order + --access flag; e.g. npm publish .publish/core --access restricted npm publish .publish/compiler --access restricted # … through … npm publish .publish/cli --access restricted ``` When an approved release is ready to become public, **flip every package to public** (no republish needed): ```bash npm access public @wrnexus/core npm access public @wrnexus/compiler # … the script prints the full list … ``` ### Public staging for an explicitly approved public release To stage public manifests from the start (free org is enough): ```bash WRNEXUS_NPM_ACCESS=public bun run scripts/publish-packages.ts npm publish .publish/core --access public # … ``` Bump `version` in each `packages/*/package.json` before republishing (npm rejects a duplicate version). ## Consume on another machine (needs Bun) ```bash mkdir my-wrn-app && cd my-wrn-app # Scaffold via the CLI npm i @wrnexus/cli bunx wrnexus create app cd app # scaffolds with @wrnexus/* deps declared bun install # pulls @wrnexus/core, styles, validation, db, cli bun run dev # or: bun run build && bun dist/server.js ``` While the packages are still **private**, the consuming machine must be logged in to npm (`npm login`) as a user with read access to the `wrnexus` org. Once public, no auth is needed. `wrnexus create` scaffolds an app that already declares its `@wrnexus/*` runtime dependencies and a dev-dependency on `@wrnexus/cli`, so `bun install` + `bun run dev` works standalone. > Everything runs under **Bun** (the framework uses `Bun.serve`, `bun:sqlite`, > `Bun.password`, `Bun.build`, …). Node is not a supported runtime.