Scaffolding a new library
This guide covers the workflow for adding a brand-new package under
@crudx/*. If you're specifically building a transport adapter, read
adapters.md instead — the contract + builder pattern
for adapters has its own conventions.
When to add a new library
- The code is reusable across more than one consumer.
- It has a coherent public surface (one or two responsibilities).
- It's stable enough to version independently.
If any of those is "no" yet, keep the code inside an existing lib until it stabilises. Splitting later is cheap; merging two underbaked libs is not.
1. Pick a name
Naming follows the same scheme as adapters: explicit and self-describing.
| Kind | Convention | Examples |
|---|---|---|
| Foundation | @crudx/<topic> | @crudx/core, @crudx/common |
| Transport adapter | @crudx/<transport>-<client>-adapter | @crudx/rest-tanstack-adapter |
| UI implementation | @crudx/<ui-lib> | @crudx/mui, @crudx/shadcn |
| Other | @crudx/<topic> | (anything new) |
The lib's directory name must match the package suffix
(everything after @crudx/). That name is also the conventional-commit
scope: feat(rest-tanstack-adapter): ….
2. Generate the lib via Nx
yarn nx g @nx/react:library <name> \
--directory=libs/<name> \
--bundler=rollup \
--publishable \
--importPath=@crudx/<name> \
--no-interactive
Nx scaffolds:
libs/<name>/src/index.ts— public entrylibs/<name>/package.json— package manifest (peer deps go here)libs/<name>/project.json— Nx targets (build/lint/test)libs/<name>/tsconfig*.json,jest.config.ts,README.md
It also adds a paths entry to tsconfig.base.json so workspace
imports (@crudx/<name>) resolve to libs/<name>/src/index.ts.
If you don't want to use the generator, copy a sibling lib (e.g.
libs/rest-tanstack-adapter/) and search-replace the name. Make sure to
update both tsconfig.base.json and package.json scripts (see
sections below).
3. Fill in the package manifest
Edit libs/<name>/package.json:
{
"name": "@crudx/<name>",
"version": "0.0.0",
"license": "MIT",
"author": "Louis Loo <louiskhenghao@gmail.com> (https://github.com/louiskhenghao)",
"homepage": "https://github.com/louiskhenghao/crudx/blob/main/libs/<name>#readme",
"keywords": ["react", "crud", "<topic>", "..."],
"peerDependencies": {
"@crudx/core": "^0.0.27",
"react": ">=17"
}
}
Always declare runtime deps as peerDependencies, not
dependencies. The lib must reuse the consumer's React, MUI, Apollo,
TanStack Query, etc. — never bundle its own copy.
4. Wire the Nx project config
libs/<name>/project.json should mirror the template used by other
libs:
namematches the directory.sourceRoot: "libs/<name>/src".buildtarget uses@nx/rollup:rollup, withoutputPath: dist/libs/<name>and the lib's runtime peers listed underexternalso they're not bundled.linttarget pointslintFilePatternsatlibs/<name>/**/*.versiontarget uses@jscutlery/semver:versionwithtagPrefix: "${projectName}@"andpostTargets: ["<name>:build"].
Cross-check against libs/rest-tanstack-adapter/project.json if
unsure.
5. Register release scripts
Add to root package.json scripts:
"build:lib:<name>": "yarn build <name>",
"release:<name>": "yarn nx run <name>:version",
And include <name> in release:all and build:libs if you want it
swept up in the all-targets paths.
Add <name> to the per-package input list of
.github/workflows/release.yml if you want CI-driven releases.
6. Add docs
Every lib must ship a README.md with:
- One-line description and what layer it sits at (foundation / transport adapter / UI / other).
- Install snippet, including peer deps.
- Minimum-viable usage example.
- Link back to the root README for the full picture.
Cross-reference siblings if relevant — e.g. an adapter README links
back to @crudx/core and to ADAPTERS.md.
7. Smoke-test it
Drop a demo into apps/example/src/pages/ exercising the lib's public
API end-to-end. The four test-crud-public-* demos are the template.
Spin up yarn example:dev and click through.
8. Release
Follow the release guide in CONTRIBUTING.md.
First releases typically go out as a 0.0.1 or 0.1.0 (force the
level via --releaseAs=patch / --releaseAs=minor since there's no
prior version for @jscutlery/semver to diff against).
Checklist
- Lib created under
libs/<name>/with name matching the package suffix. -
package.jsondeclares runtime deps aspeerDependencies. -
project.jsonhasbuild,lint,test,versiontargets configured. -
tsconfig.base.jsonhas apathsentry for@crudx/<name>. - Root
package.jsonhasrelease:<name>andbuild:lib:<name>scripts. -
.github/workflows/release.ymlhas the lib in its inputs list. -
README.mdcovers install + usage + link-back to the root README. - At least one
apps/exampledemo exercises the lib. - First release shipped (typically
0.0.1viayarn release:<name> --releaseAs=patch).