Community
Contributing
How to contribute to NextRush — from setup to pull request.
This guide covers setup, workflow, and conventions for contributing to NextRush.
Prerequisites
| Requirement | Version |
|---|---|
| Node.js | >=22.0.0 |
| pnpm | 10.29.3 (managed via corepack) |
| Git | Any recent version |
The project uses corepack to manage pnpm. Node.js >=22 ships with corepack built-in.
Quick Start
Fork and Clone
# Fork on GitHub, then:
git clone https://github.com/YOUR_USERNAME/nextrush.git
cd nextrushInstall Dependencies
# Enable corepack (ships with Node.js >=22)
corepack enable
# Install project dependencies (uses pnpm@10.29.3 from packageManager field)
pnpm installBuild Packages
pnpm buildRun Tests
pnpm testCreate Branch
git checkout -b feat/your-featureBranch prefix should match the commit type: feat/, fix/, docs/, refactor/, test/, perf/, chore/.
Repository Structure
NextRush is a monorepo using Turborepo and pnpm workspaces:
nextrush/
├── packages/
│ ├── core/ # @nextrush/core
│ ├── router/ # @nextrush/router
│ ├── di/ # @nextrush/di
│ ├── decorators/ # @nextrush/decorators
│ ├── errors/ # @nextrush/errors
│ ├── types/ # @nextrush/types
│ ├── runtime/ # @nextrush/runtime
│ ├── dev/ # @nextrush/dev
│ ├── nextrush/ # nextrush (meta package)
│ ├── adapters/ # Platform adapters
│ │ ├── node/ # @nextrush/adapter-node
│ │ ├── bun/ # @nextrush/adapter-bun
│ │ ├── deno/ # @nextrush/adapter-deno
│ │ └── edge/ # @nextrush/adapter-edge
│ ├── middleware/ # Middleware packages
│ │ ├── cors/
│ │ ├── body-parser/
│ │ └── ...
│ └── plugins/ # Plugin packages
│ ├── controllers/
│ ├── logger/
│ └── ...
├── apps/
│ ├── docs/ # Documentation site
│ └── playground/ # Testing playground
├── draft/ # Architecture documents
└── turbo.json # Turborepo configDevelopment Workflow
Running Commands
View all available commands
# Build all packages
pnpm build
# Run all tests
pnpm test
# Run tests for specific package
pnpm --filter @nextrush/core test
# Type check
pnpm typecheck
# Lint
pnpm lint
# Lint and auto-fix
pnpm lint:fix
# Format
pnpm format
# Check formatting (CI)
pnpm format:check
# Run tests with coverage
pnpm test:coverage
# Clean build artifacts
pnpm cleanPackage Development
When working on a specific package:
cd packages/core
# Run tests in watch mode
pnpm test:watch
# Build package
pnpm build
# Type check
pnpm typecheckDocumentation
cd apps/docs
# Start dev server
pnpm dev
# Build docs
pnpm buildCode Style
TypeScript
- Strict mode: Always use strict TypeScript
- No any: Avoid
anytype; useunknownif needed - Explicit types: Export interfaces and types explicitly
- ESM: Use ES modules (
import/export)
File Structure
// 1. Type imports
import type { Context, Middleware } from '@nextrush/types';
// 2. Value imports
import { compose } from './middleware';
// 3. Types/interfaces (export first)
export interface MyOptions {
enabled: boolean;
}
// 4. Implementation
export function myFunction(options: MyOptions): void {
// ...
}Naming Conventions
| Type | Convention | Example |
|---|---|---|
| Files | kebab-case | body-parser.ts |
| Types/Interfaces | PascalCase | RouterOptions |
| Functions | camelCase | createRouter |
| Constants | UPPER_SNAKE | DEFAULT_TIMEOUT |
| Private fields | underscore prefix | _internal |
Comments
// Good: Explain WHY, not WHAT
// Rate limit is per-IP to prevent abuse from single sources
const rateLimit = createRateLimiter({ keyGenerator: (ctx) => ctx.ip });
// Bad: Obvious comment
// Create router
const router = createRouter();Testing
Test Structure
import { describe, it, expect, beforeEach } from 'vitest';
describe('MyFeature', () => {
describe('basic functionality', () => {
it('should do something', () => {
expect(result).toBe(expected);
});
});
describe('edge cases', () => {
it('should handle empty input', () => {
// ...
});
});
describe('error cases', () => {
it('should throw on invalid input', () => {
expect(() => fn(null)).toThrow();
});
});
});Test Guidelines
- One assertion per test when possible
- Descriptive names:
should return 404 when user not found - Test behavior, not implementation
- No mocking unless necessary
Coverage Requirements
| Metric | Threshold |
|---|---|
| Lines | 90% |
| Functions | 90% |
| Statements | 90% |
| Branches | 85% |
- All exports: Every public function tested
- Error paths: All error scenarios covered
Run pnpm test:coverage to verify thresholds before submitting.
Pull Request Process
Before Submitting
- Tests pass:
pnpm test - Coverage meets thresholds:
pnpm test:coverage - Types check:
pnpm typecheck - Lint passes:
pnpm lint - Formatting correct:
pnpm format:check - Documentation updated (if needed)
- Changeset added (if needed)
PR Title Format
type(scope): description
Examples:
feat(router): add wildcard route support
fix(core): handle async middleware errors
docs(guides): add authentication guide
chore(deps): update typescript to 5.xTypes
feat: New featurefix: Bug fixdocs: Documentationchore: Maintenancerefactor: Code change without feature/fixtest: Adding testsperf: Performance improvement
Review Process
- Automated checks — CI must pass
- Code review — At least one approval
- Documentation — Updated if needed
- Merge — Squash and merge
Adding a New Package
Create Package Structure
mkdir -p packages/middleware/my-middleware/src
cd packages/middleware/my-middlewareCreate package.json
{
"name": "@nextrush/my-middleware",
"version": "3.0.4",
"description": "Description here",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
},
"scripts": {
"build": "tsup",
"test": "vitest run",
"test:watch": "vitest",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@nextrush/types": "workspace:*"
},
"devDependencies": {
"typescript": "^5.9.3",
"vitest": "^4.0.18"
}
}Create tsconfig.json
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src"
},
"include": ["src"]
}Create tsup.config.ts
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
dts: true,
clean: true,
sourcemap: true,
});Implement and Test
// src/index.ts
import type { Middleware } from '@nextrush/types';
export interface MyMiddlewareOptions {
// ...
}
export function myMiddleware(options?: MyMiddlewareOptions): Middleware {
return async (ctx, next) => {
// Implementation
await next();
};
}Documentation Contributions
Writing Guidelines
- Human-first: Explain concepts before code
- Show examples: Include runnable code
- Be accurate: Test all code examples
- Keep current: Update when APIs change
Structure
Every doc page should have:
- Title and description
- Problem explanation
- Solution overview
- Code examples
- Common issues
- Next steps
See the Documentation Instructions for detailed guidelines.
Getting Help
- Questions: Open a Discussion
- Bugs: Open an Issue
- Code review: Request review on your PR
First-time contributors: Look for issues labeled
good first issue.Questions?
If anything in this guide is unclear, open a Discussion. Contributions of all sizes are welcome.