Contributing Code - joinruach/JoinRuach GitHub Wiki
Thank you for contributing to Ruach Studios. This guide will help you submit high-quality code that aligns with our standards and workflow.
Key Principles:
- Quality over speed — Take time to do it right
- Test before you ship — No untested code in production
- Document as you go — Future you will thank present you
- Ask questions early — Clarify before you code
Browse open issues and find one that matches your skill level:
- Good First Issue — Perfect for newcomers
- Help Wanted — Ready for contribution
- Bug — Something broken that needs fixing
- Enhancement — New feature or improvement
Comment on the issue to let others know you're working on it.
Read the issue carefully and ask questions if anything is unclear. Better to clarify now than to rework later.
Follow the Development Setup guide if you haven't already.
Always create a new branch for your work:
# For new features
git checkout -b feat/feature-name
# For bug fixes
git checkout -b fix/bug-description
# For documentation
git checkout -b docs/update-readmeBranch Naming Convention:
-
feat/— New feature -
fix/— Bug fix -
docs/— Documentation -
refactor/— Code refactoring -
test/— Adding tests -
chore/— Maintenance tasks
We use ESLint and Prettier to enforce consistent code style.
# Check for linting errors
pnpm lint
# Auto-fix linting errors
pnpm lint:fix
# Format code
pnpm format-
Always use types — Avoid
anyunless absolutely necessary - Export types — Make types reusable
- Use Zod for validation — Runtime type safety
Example:
import { z } from 'zod';
// Define schema
const UserSchema = z.object({
email: z.string().email(),
name: z.string().min(1),
age: z.number().min(18).optional(),
});
// Infer type
type User = z.infer<typeof UserSchema>;
// Validate data
const user = UserSchema.parse(data);- Use functional components — No class components
- Prefer server components — Use client components only when necessary
- Keep components small — Single Responsibility Principle
- Use TypeScript — Always type props
Example:
// Server Component (default)
export default function ServerComponent() {
return <div>Server-rendered content</div>;
}
// Client Component (when interactivity is needed)
'use client';
import { useState } from 'react';
export default function ClientComponent() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}Every feature or bug fix should include tests.
import { describe, it, expect } from 'vitest';
import { validateEmail } from './utils';
describe('validateEmail', () => {
it('should return true for valid email', () => {
expect(validateEmail('[email protected]')).toBe(true);
});
it('should return false for invalid email', () => {
expect(validateEmail('not-an-email')).toBe(false);
});
});import { render, screen } from '@testing-library/react';
import { expect, it } from 'vitest';
import Button from './Button';
it('renders button with text', () => {
render(<Button>Click me</Button>);
expect(screen.getByRole('button')).toHaveTextContent('Click me');
});# Run all tests
pnpm test
# Run tests in watch mode
pnpm test:watch
# Run tests with coverage
pnpm test:coverage// Good: Explains WHY, not WHAT
// Using debounce to prevent excessive API calls during rapid input
const debouncedSearch = debounce(search, 300);
// Avoid: States the obvious
// Set count to 0
const count = 0;/**
* Fetches user data from the API
* @param userId - The unique identifier for the user
* @returns Promise containing user data
* @throws {Error} If user is not found
*/
async function fetchUser(userId: string): Promise<User> {
// ...
}If your changes affect setup, usage, or configuration, update the README.
Follow Conventional Commits:
<type>(<scope>): <short description>
<optional body>
<optional footer>
Types:
-
feat:— New feature -
fix:— Bug fix -
docs:— Documentation changes -
style:— Code style changes (formatting, etc.) -
refactor:— Code refactoring -
test:— Adding or updating tests -
chore:— Maintenance tasks
Examples:
git commit -m "feat(auth): add Google OAuth integration"
git commit -m "fix(api): resolve null pointer exception in user endpoint"
git commit -m "docs(readme): update installation instructions"Make small, atomic commits. Each commit should represent a single logical change.
# Stage specific files
git add src/components/Button.tsx
# Commit
git commit -m "feat(ui): add Button component"# Push to GitHub
git push origin feat/your-feature-name- Go to GitHub
- Click "New Pull Request"
- Select your branch
- Fill out the PR template:
## Description
Brief description of what this PR does.
## Related Issue
Closes #123
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Documentation update
- [ ] Code refactoring
## Checklist
- [ ] I have tested my changes locally
- [ ] I have added tests for my changes
- [ ] I have updated documentation (if needed)
- [ ] My code follows the project's style guidelines
- [ ] All tests pass- Request a review from a maintainer
- Code quality — Clean, readable, maintainable
- Tests — Adequate test coverage
- Documentation — Clear comments and updated docs
- Performance — No unnecessary rerenders or inefficiencies
- Security — No vulnerabilities introduced
- Alignment — Matches project vision and standards
- Be open — Feedback is a gift
- Ask questions — Clarify if something is unclear
- Make changes — Address all comments
- Push updates — Your PR will automatically update
# Make requested changes
git add .
git commit -m "refactor: address PR feedback"
git pushOnce approved, a maintainer will merge your PR. Your code is now in production! 🎉
- Review your own PR first — Catch obvious issues before submitting
- Keep PRs small — Easier to review (under 400 lines of code)
- Provide context — Explain your decisions in the description
- Be patient — Reviews take time
- Be kind — Everyone is learning
- Be specific — Point to exact lines and explain why
- Approve quickly — Don't block good work
- Suggest, don't demand — Unless it's a critical issue
Always run tests before pushing:
pnpm test
pnpm lint
pnpm type-checkNever commit .env.local or sensitive data. Add to .gitignore if needed.
Break large changes into smaller, logical PRs. Easier to review and safer to merge.
Fix linting errors before pushing. Use:
pnpm lint:fixKeep your branch up to date with main:
git fetch origin
git rebase origin/mainIf your branch is behind main, rebase instead of merging:
git fetch origin
git rebase origin/mainIf conflicts arise, resolve them and continue:
git add .
git rebase --continueBefore merging, you may be asked to squash commits:
# Squash last 3 commits into 1
git rebase -i HEAD~3Mark all but the first commit as squash, save, and edit the commit message.
To apply a specific commit from another branch:
git cherry-pick <commit-hash>- GitHub Discussions: Ask Questions
- Discord: Join our developer channel
- Email: [email protected]
Open an issue on GitHub.
Every merged PR earns you:
- Credit in the Contributors section
- GitHub history showing your impact
- Community appreciation — we celebrate wins together
"Whatever you do, work heartily, as for the Lord and not for men." — Colossians 3:23