7.8 KiB
Contributing Guide
How to contribute to MetaBuilder development.
📋 Table of Contents
- Project Workflow (0-kickstart)
- Getting Started
- Code Style
- Testing
- Documentation
- Pull Request Process
Project Workflow (0-kickstart)
This repo follows ../.github/prompts/0-kickstart.md as the current workflow source of truth. If anything here conflicts, prefer 0-kickstart.md.
Key rules:
- Start with
../.github/prompts/0-kickstart.mdand other prompts as needed. - Commit as you go with descriptive messages; default to trunk-based work on
mainunless a PR flow is required. - Use
actto diagnose GitHub workflows (npm run act,npm run act:diagnose). - Keep unit tests parameterized; create new test files where possible; keep 1:1 source-to-test naming.
- Leave TODO comments for missing functionality.
- Check
./todo/before starting. - One lambda per file; classes are containers for related lambdas (see
../.github/prompts/LAMBDA_PROMPT.md). - Route data access through DBAL; treat it as the trusted layer.
- Design for flexibility, modularity, and containerization.
- UI work follows
./RADIX_TO_MUI_MIGRATION.mdand../UI_STANDARDS.md.
Getting Started
Prerequisites
- Node.js 18+
- Git
- npm or yarn
Setting Up Development Environment
-
Clone Repository
git clone <repo> cd metabuilder -
Install Dependencies
npm install -
Set Up Database
npm run db:generate npm run db:push -
Start Development Server
npm run dev -
Run Tests
npm run test:e2e npm run lint
Code Style
TypeScript/React Conventions
- One Lambda per File - Split logic so each file contains a single lambda; classes are containers only
- Naming - Use PascalCase for components, camelCase for functions
- Imports - Use absolute imports with
@/prefix - Props - Define prop interfaces, use destructuring
Example:
// ✅ Good
interface ButtonProps {
label: string;
onClick: () => void;
disabled?: boolean;
}
export function Button({ label, onClick, disabled }: ButtonProps) {
return <button onClick={onClick} disabled={disabled}>{label}</button>;
}
// ❌ Bad - No props interface, too many lines
export function Button(props: any) {
// ... 200 lines of code
}
Styling
- Use Material-UI (
@mui/material) components and thesxprop - Avoid Tailwind utility classes and Radix UI imports
- Use
.module.scssfor custom component styles when needed - Follow
../UI_STANDARDS.mdand./UI_MIGRATION.md
// ✅ Good
import { Button, Box } from '@mui/material'
<Box sx={{ display: 'flex', gap: 2 }}>
<Button variant="contained">Click me</Button>
</Box>
Hooks & State Management
- Use React hooks (useState, useEffect, useContext)
- Keep hooks in separate hook files in
src/hooks/ - Export from
src/hooks/index.tsfor easy importing
Testing
Running Tests
# Unit tests
npm run test:unit:watch
# E2E tests
npm run test:e2e
# All tests
npm run test:all
Writing Tests
-
Unit Tests - Test individual functions in isolation with parameterized cases
it.each([ { input: [1, 2, 3], expected: 6 }, { input: [], expected: 0 }, ])('calculates total correctly', ({ input, expected }) => { expect(calculateTotal(input)).toBe(expected) }) -
E2E Tests - Test complete user flows
test('user can create and edit item', async ({ page }) => { await page.goto('/'); await page.fill('[name="title"]', 'Test'); await page.click('button[type="submit"]'); await expect(page.locator('text=Test')).toBeVisible(); }); -
Coverage - Aim for 80%+ coverage on critical paths
-
File Mapping - Keep tests next to sources with matching names (
foo.ts+foo.test.ts)
Documentation
Adding Documentation
-
JSDoc Comments - Document all exported functions and interfaces
/** * Calculates the sum of numbers * @param numbers - Array of numbers to sum * @returns The sum of all numbers * @example * const total = sum([1, 2, 3]); // 6 */ export function sum(numbers: number[]): number { return numbers.reduce((a, b) => a + b, 0); } -
README Files - Keep README.md in key directories:
/src/- Source code overview/src/lib/- Library utilities/src/components/- Component library/packages/- Modular packages
-
Architecture Docs - Document complex systems in
docs/architecture/ -
Examples - Create
.example.tsxfiles showing how to use components -
TODOs - Leave TODO comments for missing functionality
Running Quality Checker
# Check documentation quality
./scripts/doc-quality-checker.sh /workspaces/metabuilder
# With verbose output
./scripts/doc-quality-checker.sh /workspaces/metabuilder true
Target: 80%+ quality score
Pull Request Process
Trunk-based work on main is the default. Use the PR process below only when a PR/feature branch flow is explicitly required (external contributions, review gates, or automation).
Before Creating PR
-
Run Linter
npm run lint -
Fix Issues
npm run lint:fix -
Run Tests
npm run test:e2e -
Update Documentation
- Add/update JSDoc comments
- Update README if needed
- Update architecture docs if design changes
PR Template
## Description
Briefly describe what this PR does.
## Changes
- Change 1
- Change 2
- Change 3
## Testing
How to test these changes:
1. Step 1
2. Step 2
## Checklist
- [ ] Tests pass
- [ ] Linter passes
- [ ] Documentation updated
- [ ] No breaking changes
PR Review
- Address all review comments
- Keep commits clean and logical
- Update PR description if scope changes
- Ensure CI passes before merge
🚫 Common Mistakes
❌ Don't:
- Create components larger than 150 LOC
- Use CSS-in-JS or inline styles
- Hardcode values that should be configurable
- Skip tests for "simple" changes
- Forget to update documentation
- Commit without linting
✅ Do:
- Keep components focused and testable
- Use Tailwind CSS exclusively
- Make code reusable and configurable
- Test all code paths
- Document as you code
- Run linter before committing
🆘 Getting Help
TODO: Links below use ../docs/... from docs/CONTRIBUTING.md and resolve to docs/docs; update to correct relative paths (including security and copilot).
- Architecture Questions: See docs/architecture/
- API Questions: See API Development Guide TODO: E2E tests guide lives under frontends/nextjs/e2e; update this link.
- Testing Questions: See E2E Tests Guide
- Security Questions: See Security Guidelines