Thanks for your interest in contributing! This guide will help you get started.
- Node.js 20 or later (22 recommended — see
.nvmrc) - npm (ships with Node)
# Clone the repo
git clone https://github.com/cleverbrush/framework.git
cd framework
# Install dependencies
npm ci
# Build all packages
npm run build
# Run tests & typechecks
npm run testThis project uses npm workspaces with Turborepo for orchestration. All packages live under libs/:
| Package | Description |
|---|---|
@cleverbrush/schema |
Type-safe schema validation with immutable builders |
@cleverbrush/deep |
Deep equality & deep extend utilities |
@cleverbrush/async |
Async utilities (Collector, debounce, throttle, retry) |
@cleverbrush/mapper |
Schema-driven object mapping |
@cleverbrush/react-form |
React form library powered by schema PropertyDescriptors |
@cleverbrush/scheduler |
Cron-like job scheduler with schema-validated config |
@cleverbrush/knex-clickhouse |
Knex dialect for ClickHouse |
Biome handles both formatting and linting:
# Check for lint/format issues
npm run lint
# Auto-fix issues
npm run lint:fixTests use Vitest and are co-located with source files (*.test.ts):
# Run all tests with typechecking
npm run test
# Run tests for a specific package
npx vitest --run libs/schema# Build all packages (respects dependency order via Turbo)
npm run build
# Clean all build artifacts
npm run cleanThe extension system is the primary way to add new validators. See libs/schema/src/extensions/ for examples.
- Create your extension file (e.g.
libs/schema/src/extensions/myExtension.ts) - Export extension functions that call the builder's
.extend()method - Add tests in a co-located
*.test.tsfile - Re-export from
libs/schema/src/extensions/index.ts
Look at libs/schema/src/extensions/string.ts for a complete example of how extensions add validators like email(), url(), uuid(), etc.
Builders live in libs/schema/src/builders/. Each builder extends the base SchemaBuilder class.
- Create your builder file in
libs/schema/src/builders/ - Extend
SchemaBuilderwith appropriate type parameters - Add a factory function (e.g.
myType()) and export it - Add comprehensive tests in a co-located
*.test.tsfile - Export from
libs/schema/src/index.ts
- Fork the repo and create a feature branch from
master - Make your changes with tests
- Add a changeset — every PR that changes package behavior needs one:
Follow the prompts to select affected packages and describe the change.
npx changeset
- Ensure all checks pass:
npm run lint npm run build npm run test - Open a PR against
master
- patch — bug fixes, internal refactors with no API change
- minor — new features, new extensions, new builders
- major — breaking API changes
All packages are versioned together (fixed release group), so a single changeset covers all packages.
Open a GitHub issue — we're happy to help.