Contribution Guide
This guide covers our code standards, PR process, and how we work together.
Code Style & Conventionsโ
TypeScriptโ
We use TypeScript throughout the codebase. Key conventions:
// โ
Good: Explicit types for function parameters and returns
function processForm(form: FormDefinition): ProcessedForm {
// ...
}
// โ Avoid: Using `any`
function processForm(form: any): any {
// ...
}
// โ
Good: Use interfaces for object shapes
interface FormField {
id: string;
type: FieldType;
label: string;
required?: boolean;
}
// โ
Good: Use enums or union types for known values
type FieldType = 'text' | 'number' | 'select' | 'date';
React Componentsโ
// โ
Good: Functional components with TypeScript
interface ButtonProps {
label: string;
onClick: () => void;
variant?: 'primary' | 'secondary';
}
export function Button({ label, onClick, variant = 'primary' }: ButtonProps) {
return (
<button className={variant} onClick={onClick}>
{label}
</button>
);
}
// โ
Good: Use 'use client' directive for client components
'use client';
export function InteractiveComponent() {
const [state, setState] = useState(false);
// ...
}
File Organizationโ
// โ
Good: One component per file, named after the component
src/components/FormBuilder/FieldPalette.tsx
// โ
Good: Index files for clean imports
src/components/FormBuilder/index.ts
export { FormBuilder } from './FormBuilder';
export { FieldPalette } from './FieldPalette';
// โ
Good: Colocate related files
src/components/FormBuilder/
โโโ FormBuilder.tsx
โโโ FormBuilder.test.tsx
โโโ FormBuilder.styles.ts
โโโ index.ts
Stylingโ
We use Material-UI (MUI) for components. Avoid Tailwind.
// โ
Good: MUI components and sx prop
import { Box, Button, Typography } from '@mui/material';
<Box sx={{ p: 2, display: 'flex', gap: 2 }}>
<Typography variant="h6">Title</Typography>
<Button variant="contained">Action</Button>
</Box>
// โ Avoid: Tailwind classes
<div className="p-2 flex gap-2">
PR Expectationsโ
PR Sizeโ
Keep PRs focused and reviewable:
| Size | Lines Changed | Review Time |
|---|---|---|
| Small | < 100 | Same day |
| Medium | 100-300 | 1-2 days |
| Large | 300-500 | 2-3 days |
| Too Large | 500+ | Please split |
Rule of thumb: If a PR does multiple things, split it.
PR Descriptionโ
Every PR should include:
## Summary
Brief description of what this PR does.
## Changes
- Added X
- Fixed Y
- Updated Z
## Testing
How you tested these changes:
- [ ] Unit tests pass
- [ ] Manual testing done
- [ ] Tested on Chrome/Firefox/Safari
## Screenshots
(If UI changes, include before/after screenshots)
## Related Issues
Fixes #123
Commit Messagesโ
Follow Conventional Commits:
# Format
<type>(<scope>): <description>
# Examples
feat(forms): add date range field type
fix(workflows): resolve execution timeout issue
docs(api): update authentication examples
refactor(lib): simplify form validation logic
test(forms): add unit tests for conditional logic
chore(deps): update dependencies
Types:
feat- New featurefix- Bug fixdocs- Documentationrefactor- Code refactoring (no behavior change)test- Adding or updating testschore- Maintenance, dependencies
Review Processโ
What We Look Forโ
- Correctness - Does it work as intended?
- Code Quality - Is it readable and maintainable?
- TypeScript - Are types correct and helpful?
- Tests - Are changes tested appropriately?
- Performance - Any obvious performance issues?
- Security - No security vulnerabilities introduced?
Turnaroundโ
- Small PRs: Same day or next day
- Medium PRs: 1-2 days
- Large PRs: 2-3 days
If you haven't heard back in 3 days, ping in the PR comments.
Review Feedbackโ
We use conventional comments:
// nitpick: Consider renaming for clarity
// suggestion: Could use a helper function here
// question: Why is this needed?
// issue: This will cause a bug when...
// praise: Nice refactor!
Testingโ
What Needs Testsโ
| Change Type | Testing Required |
|---|---|
| New feature | Unit tests + integration tests |
| Bug fix | Test that reproduces the bug |
| Refactoring | Existing tests should pass |
| UI component | Component tests (optional for now) |
Running Testsโ
# Run all tests
npm run test
# Run specific test file
npm run test -- path/to/file.test.ts
# Run tests in watch mode
npm run test:watch
# Run with coverage
npm run test:coverage
Test Structureโ
describe('FormValidator', () => {
describe('validateField', () => {
it('should return error for required empty field', () => {
const field = { required: true, value: '' };
const result = validateField(field);
expect(result.valid).toBe(false);
expect(result.error).toBe('This field is required');
});
it('should pass for valid email', () => {
const field = { type: 'email', value: 'test@example.com' };
const result = validateField(field);
expect(result.valid).toBe(true);
});
});
});
How Decisions Get Madeโ
Small Decisionsโ
Make them yourself. If it's easily reversible and doesn't affect architecture, just do it.
Medium Decisionsโ
Discuss in PR comments or GitHub Discussions. Get one other person's input before proceeding.
Large Decisionsโ
For architectural changes or new features:
- Open a GitHub Discussion with a proposal
- Get feedback from multiple people
- Document the decision
- Implement
Communication Normsโ
Async-Firstโ
We work async. Expectations:
- Response time: Within 24-48 hours on weekdays
- No real-time requirement: No Slack or instant messaging
- Written communication: Discussions happen in GitHub
Where Discussions Happenโ
| Topic | Location |
|---|---|
| Code questions | PR comments |
| Feature ideas | GitHub Discussions |
| Bug reports | GitHub Issues |
| Architecture decisions | GitHub Discussions |
| General questions | GitHub Discussions |
When to Ask vs. When to Decideโ
Ask when:
- It affects other people's work
- It's not easily reversible
- You're genuinely unsure
Decide when:
- It's within your PR scope
- It's easily reversible
- You've done the research
Getting Unstuckโ
If you're blocked:
- Check existing code - Similar patterns probably exist
- Search GitHub Issues - Someone may have faced this
- Read the docs - Architecture overview might help
- Ask in your PR - Create a draft PR and ask questions there
- Open a Discussion - For broader questions
No question is too small. We'd rather you ask than spin.
Next Stepsโ
- Getting Started - Set up your environment
- Current Priorities - See where help is needed
- Architecture Overview - Understand the codebase