Contributing to Refract
First off, thank you for considering contributing to Refract! It's people like you that make Refract such a great framework. We welcome contributions from everyone, regardless of experience level.
Table of Contents
- Code of Conduct
- How Can I Contribute?
- Development Setup
- Project Structure
- Development Workflow
- Testing
- Submitting Changes
- Style Guidelines
- Documentation
- Community
Code of Conduct
By participating in this project, you agree to abide by our Code of Conduct. Please read it before contributing.
Our Pledge
We pledge to make participation in our project a harassment-free experience for everyone, regardless of:
- Age, body size, disability, ethnicity, gender identity and expression
- Level of experience, education, socio-economic status
- Nationality, personal appearance, race, religion
- Sexual identity and orientation
How Can I Contribute?
Reporting Bugs
Before creating bug reports, please check existing issues to avoid duplicates. When creating a bug report, include:
- Clear title and description
- Steps to reproduce
- Expected behavior
- Actual behavior
- Code samples (if applicable)
- Environment details:
- Refract version
- Node.js version
- Browser and version
- Operating system
Bug Report Template:
## Description
Brief description of the bug
## Steps to Reproduce
1. Step one
2. Step two
3. Step three
## Expected Behavior
What should happen
## Actual Behavior
What actually happens
## Code Sample
```javascript
// Minimal reproduction code
```
Environment
- Refract version:
- Node.js version:
- Browser:
- OS:
### Suggesting Enhancements
Enhancement suggestions are tracked as GitHub issues. When creating an enhancement suggestion, include:
1. **Use case** - Why is this enhancement needed?
2. **Proposed solution** - How should it work?
3. **Alternatives considered** - What other solutions did you consider?
4. **Additional context** - Any mockups, diagrams, or examples
### Pull Requests
1. **Small, focused PRs** are easier to review and merge
2. **One feature/fix per PR**
3. **Include tests** for new features
4. **Update documentation** as needed
5. **Follow our coding standards**
6. **Write clear commit messages**
### Improving Documentation
Documentation improvements are always welcome! This includes:
- Fixing typos or clarifying language
- Adding examples
- Improving API documentation
- Translating documentation
- Writing tutorials or blog posts
### Contributing Examples
Share your Refract projects and examples:
1. Add to the `/examples` directory
2. Include a README with setup instructions
3. Keep dependencies minimal
4. Follow our code style
## Development Setup
### Prerequisites
- Node.js 16+ and npm 7+
- Git
- A code editor (VS Code recommended)
- Basic knowledge of JavaScript/TypeScript
### Initial Setup
1. **Fork the repository**
```bash
# Click "Fork" on GitHub, then clone your fork
git clone https://github.com/YOUR-USERNAME/refract.git
cd refract
-
Add upstream remote
git remote add upstream https://github.com/refract-js/refract.git -
Install dependencies
npm install -
Build the project
npm run build -
Run tests
npm test -
Start development mode
npm run dev
Development Tools
VS Code Extensions
We recommend these extensions for the best development experience:
- ESLint
- Prettier
- TypeScript and JavaScript Language Features
- Jest Runner
- GitLens
Editor Configuration
.vscode/settings.json:
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
}
Project Structure
refract/
├── packages/
│ ├── core/ # Core framework
│ │ ├── src/
│ │ ├── tests/
│ │ └── package.json
│ ├── compiler/ # Compiler and build tools
│ ├── devtools/ # Browser DevTools
│ ├── router/ # Official router
│ └── testing/ # Testing utilities
├── examples/ # Example applications
├── docs/ # Documentation
├── scripts/ # Build and release scripts
├── benchmarks/ # Performance benchmarks
└── playground/ # Development playground
Key Directories
packages/core/src- Core framework source codepackages/core/src/refraction- Reactivity systempackages/core/src/lens- Lens implementationpackages/core/src/components- Component systempackages/compiler- Build-time optimizations
Development Workflow
Creating a New Feature
-
Create a feature branch
git checkout -b feature/your-feature-name -
Make your changes
- Write code
- Add tests
- Update documentation
-
Test your changes
npm test
npm run lint
npm run type-check -
Commit your changes
git add .
git commit -m "feat: add new feature"
Working on Core
When modifying core functionality:
-
Run core tests
npm run test:core -
Test in playground
npm run playground -
Check bundle size
npm run size -
Run benchmarks
npm run bench
Debugging
-
Enable debug mode
window.__REFRACT_DEBUG__ = true; -
Use DevTools
- Install Refract DevTools extension
- Open browser DevTools
- Navigate to "Refract" tab
-
Add debug statements
import { debug } from "@refract/core/debug";
debug("component", "Component rendered", props);
Testing
Running Tests
# Run all tests
npm test
# Run specific package tests
npm run test:core
npm run test:compiler
npm run test:router
# Run tests in watch mode
npm run test:watch
# Run with coverage
npm run test:coverage
Writing Tests
-
Unit Tests - Test individual functions
describe("useRefraction", () => {
it("should initialize with default value", () => {
const { result } = renderHook(() => useRefraction(0));
expect(result.current.value).toBe(0);
});
}); -
Integration Tests - Test component interactions
it("should update child when parent state changes", async () => {
const { getByText } = render(<ParentComponent />);
fireEvent.click(getByText("Update"));
await waitFor(() => {
expect(getByText("Updated")).toBeInTheDocument();
});
}); -
E2E Tests - Test full user flows
test("user can complete checkout", async ({ page }) => {
await page.goto("/shop");
await page.click('[data-testid="add-to-cart"]');
await page.click('[data-testid="checkout"]');
// ... more steps
});
Test Guidelines
- Write tests before fixing bugs
- Aim for >80% code coverage
- Test edge cases and error conditions
- Use descriptive test names
- Keep tests focused and isolated
Submitting Changes
Commit Message Guidelines
We follow Conventional Commits:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changes (formatting, etc.)refactor: Code refactoringperf: Performance improvementstest: Test additions or changesbuild: Build system changesci: CI configuration changeschore: Other changes
Examples:
feat(core): add support for async refractions
fix(compiler): resolve JSX transformation issue
docs(api): update useRefraction documentation
perf(core): optimize virtual DOM diffing
Pull Request Process
-
Update your fork
git fetch upstream
git rebase upstream/main -
Push to your fork
git push origin feature/your-feature -
Create Pull Request
- Go to GitHub
- Click "New Pull Request"
- Select your branch
- Fill out the PR template
-
PR Template:
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
- [ ] Tests pass locally
- [ ] Added new tests
- [ ] Updated documentation
## Screenshots (if applicable)
## Related Issues
Closes #123 -
Address Review Feedback
- Make requested changes
- Push updates
- Reply to comments
- Request re-review
Style Guidelines
JavaScript/TypeScript
- Use TypeScript for new code
- Follow ESLint configuration
- Use Prettier for formatting
- Prefer functional programming patterns
- Avoid mutations when possible
// ✅ Good
const newArray = [...oldArray, newItem];
const newObject = { ...oldObject, key: value };
// ❌ Bad
oldArray.push(newItem);
oldObject.key = value;
Naming Conventions
- Files:
kebab-case.ts - Components:
PascalCase - Functions:
camelCase - Constants:
SCREAMING_SNAKE_CASE - Types/Interfaces:
PascalCase
Code Organization
// 1. Imports
import { external } from "package";
import { internal } from "@/internal";
import { relative } from "./relative";
// 2. Types/Interfaces
interface Props {
// ...
}
// 3. Constants
const DEFAULT_VALUE = 10;
// 4. Component/Function
export function Component() {
// ...
}
// 5. Exports
export { Component };
Documentation
Writing Documentation
-
API Documentation
- Use JSDoc comments
- Include examples
- Document parameters and return values
/**
* Creates a new refraction with the given initial value
* @param {T} initialValue - The initial value
* @returns {Refraction<T>} The refraction object
* @example
* const count = useRefraction(0);
* count.set(1);
*/ -
Guide Documentation
- Use clear, simple language
- Include code examples
- Add diagrams where helpful
- Test all code samples
-
README Files
- Every package needs a README
- Include installation instructions
- Provide usage examples
- List API methods
Documentation Standards
- Use American English spelling
- Write in present tense
- Use active voice
- Keep sentences concise
- Include links to related topics
Community
Getting Help
- Discord: Join our server
- Discussions: GitHub Discussions
- Twitter: @refractjs
- Email: dev@refract-js.org
Core Team
Our core maintainers are:
- @maintainer1 - Core architecture
- @maintainer2 - Compiler & optimization
- @maintainer3 - DevTools & DX
- @maintainer4 - Documentation & community
Recognition
Contributors are recognized in:
- Our Contributors page
- Release notes
- Annual contributor spotlight
- Special Discord role
License
By contributing to Refract, you agree that your contributions will be licensed under the MIT License.
Quick Links
Thank you for contributing to Refract! Together, we're building the future of reactive UI development.