A pnpm monorepo of the shared UI packages that make up the OpenNSW Framework — reusable React components and renderers styled with Radix UI Themes, published under the @opennsw npm scope.
| Package | Description |
|---|---|
@opennsw/jsonforms-renderers |
JSON Forms controls and layout renderers for React, styled to match the OpenNSW portal applications. |
@opennsw/auth |
Shared OIDC setup for the portals: UserManager defaults, IdP config parsing, role mapping and bearer headers. |
.
├── packages/ # publishable @opennsw/* packages (one dir each)
│ ├── auth/
│ └── jsonforms-renderers/
├── eslint.config.js # shared, repo-wide ESLint flat config
├── .prettierrc # shared Prettier config
├── pnpm-workspace.yaml # workspace globs (packages/*)
├── .github/workflows/ # CI, PR checks and release automation
├── .claude/skills/ # Claude Code skills (release-package)
└── CONTRIBUTING.md # PR titles, labels and the release procedure
Tooling is centralized at the root so every package shares one lint, format, and TypeScript setup.
- Node.js
>=22.18.0 - pnpm
>=11(the repo pins it viadevEngines;corepackorpnpm's own self-install will fetch the right version)
pnpm installRun from the repo root — each one fans out across the workspace:
| Command | What it does |
|---|---|
pnpm build |
Build every package (pnpm --recursive run build). |
pnpm type-check |
Type-check every package. |
pnpm test |
Run every package's unit tests. |
pnpm lint |
Lint the whole repo with the shared ESLint config (eslint .). |
pnpm format:check |
Verify Prettier formatting. |
pnpm format:fix |
Apply Prettier formatting. |
To work on a single package, use a filter, e.g.:
pnpm --filter @opennsw/jsonforms-renderers run dev- Create
packages/<name>/— it's picked up automatically by thepackages/*workspace glob. - Scope the package name as
@opennsw/<name>and set"version". - Define
buildandtype-checkscripts in itspackage.json. CI runs these withpnpm --recursive, which silently skips packages that lack them — so without these scripts the package builds green but goes unverified. - No ESLint or Prettier setup is needed: the root
eslint.config.js(withprojectService) and.prettierrccover allpackages/**automatically. - To publish it, follow Adding a package: register the npm Trusted Publisher and tag the first release. The shared
release.ymlstages every package.
packages-ci.yml runs on pull requests that touch packages/** or the shared root config. It performs type-check → lint → format check → build, then a security stage (dependency review + pnpm audit). Lint and the security checks are currently non-blocking (continue-on-error); type-check, formatting, and build must pass.
Every PR also gets a Conventional Commit Title check (pr-title.yml) and a Release notes label check (pr-labels.yml), which labels the PR with its package and change type. See CONTRIBUTING.md.
Each package is versioned, tagged (<package-dir>-v<version>) and released to npm on its own, with Trusted Publishing (OIDC, no token secret) and staged publishing: CI stages the version and a maintainer approves it on npm with 2FA. In short:
- Run Release - Bump package version in the Actions tab and merge the PR it opens.
- Run the
release-packageskill in Claude Code: it drafts the package's release notes from only the PRs that belong to it and creates a draft GitHub Release. - Publish the draft on GitHub. That creates the tag, and
release.ymlstages the package on npm. - A maintainer approves the staged package on npm (2FA). Only then is it live.
The full procedure, the PR labels it relies on, and how to add a package are in CONTRIBUTING.md.