Thank you for your interest in contributing to Reactive! This guide will help you get up and running.
-
Fork and clone
git clone https://github.com/growae/reactive.git cd reactive -
Install dependencies
pnpm install
-
Build all packages
pnpm build
-
Run tests
pnpm test -
Run linting and type checks
pnpm check # Biome linter + formatter pnpm check:types # TypeScript type checking
reactive/
├── packages/
│ ├── core/ @growae/reactive — vanilla TypeScript, no framework deps
│ ├── react/ @growae/reactive-react — React hooks wrapping core
│ ├── vue/ @growae/reactive-vue — Vue composables wrapping core
│ ├── solid/ @growae/reactive-solid — Solid primitives wrapping core
│ ├── connectors/ @growae/reactive-connectors — wallet connectors
│ ├── cli/ @growae/reactive-cli — code generation CLI
│ └── create-reactive/ create-reactive — project scaffolder
├── site/ VitePress documentation site
├── playgrounds/ Example applications
│ ├── vite-react/
│ ├── vite-vue/
│ ├── vite-solid/
│ └── next/
├── test/ Integration test infrastructure
└── .github/ CI/CD workflows and templates
- Strict mode —
strict: trueis enforced across all packages - No
any— useunknownand type guards instead - ESM only — all packages emit ESM; use
.jsextensions in relative imports even for.tsfiles import type— useimport typefor type-only imports (required byverbatimModuleSyntax)- Module resolution —
NodeNext; see 07-project-rules.md for full details
- Vitest is the test runner
- Co-located tests — place
*.test.tsfiles next to the source they test - Type tests — use
*.test-d.tsfor compile-time type assertions withexpectTypeOf - Every feature requires tests — PRs without tests for new functionality will be asked to add them
- DEFAULT_TTL = 300 — all transaction-building actions default to 300 blocks (~15 hours). Users can override with
ttl: 0or any custom value. - Amounts in aettos — internal representation uses aettos (smallest unit); use
toAe()/toAettos()for conversion. - Network, not Chain — Aeternity uses string network IDs (
ae_mainnet,ae_uat), not numeric chain IDs.
We follow Conventional Commits:
| Prefix | Use for |
|---|---|
feat: |
New feature |
fix: |
Bug fix |
chore: |
Maintenance, deps, config |
refactor: |
Code restructuring without behavior change |
docs: |
Documentation only |
test: |
Adding/updating tests |
ci: |
CI/CD changes |
Use package scopes when applicable: feat(core):, fix(react):, test(vue):.
Keep the subject line under 72 characters.
-
Create a branch from
main:git checkout -b feat/my-new-feature
-
Write code and tests — ensure every new file has a matching
.test.ts -
Verify everything passes:
pnpm check && pnpm check:types && pnpm test
-
Add a changeset for user-facing changes:
pnpm changeset
Follow the prompts to select affected packages and write a summary.
-
Push and open a PR targeting
main -
Fill out the PR template — describe your changes, test plan, and link related issues
We use changesets for versioning and changelogs.
- User-facing changes (new features, bug fixes, breaking changes) need a changeset
- Internal changes (refactors, CI, docs, tests) generally do not
- Choose the correct semver bump:
patch— bug fixes, small improvementsminor— new features, non-breaking additionsmajor— breaking changes
pnpm changesetBefore pushing changes to @growae/reactive-cli or @growae/create-reactive, test them locally to catch issues before they hit npm.
-
Build the package
pnpm --filter @growae/reactive-cli build
-
Test commands directly
# Version node packages/cli/dist/cli.js --version # Help node packages/cli/dist/cli.js --help # Init (creates reactive.config.ts in cwd) cd /tmp && mkdir test-cli && cd test-cli node /path/to/reactive/packages/cli/dist/cli.js init # Generate (requires a reactive.config.ts) node /path/to/reactive/packages/cli/dist/cli.js generate
-
Test as if installed from npm (using pnpm link)
# From the reactive root cd packages/cli pnpm link --global # Now use it anywhere reactive --version reactive init reactive generate # Unlink when done pnpm unlink --global
-
Verify library exports work
node -e "import('@growae/reactive-cli').then(m => console.log(Object.keys(m)))"
-
Build the package
pnpm --filter @growae/create-reactive build
-
Test the scaffolder directly
cd /tmp && mkdir test-scaffold && cd test-scaffold node /path/to/reactive/packages/create-reactive/dist/cli.js
This starts the interactive prompt. Walk through the framework selection and verify the scaffolded project structure.
-
Test as if installed from npm (using pnpm link)
cd packages/create-reactive pnpm link --global # Now use it anywhere create-reactive # Unlink when done pnpm unlink --global
Run all checks before pushing CLI changes:
# Build both CLI packages
pnpm --filter @growae/reactive-cli build
pnpm --filter @growae/create-reactive build
# Run all tests
pnpm test
# Type check
pnpm check:types
# Lint + format
pnpm checkIntegration tests run against a local Aeternity node via Docker:
docker compose up -d
pnpm test:integration
docker compose downThese are gated behind the INTEGRATION=true environment variable and skipped in normal pnpm test runs.
The documentation site lives in site/ and uses VitePress.
cd site
pnpm dev # Start dev server
pnpm build # Build for productionWhen adding a new action, hook, or composable, add a corresponding documentation page and update the sidebar in site/.vitepress/config.ts.
- Open a GitHub Discussion for questions
- Check existing issues before filing a new one
- Join the Aeternity community channels for ecosystem-wide discussions
By contributing to Reactive, you agree that your contributions will be licensed under the MIT License.