11 KiB
Contributing to Compass
Thank you for your interest in contributing to Compass! This document provides comprehensive guidelines for contributing to this open-source project.
Table of Contents
- Code of Conduct
- Getting Started
- Development Environment
- Project Structure
- Coding Standards
- Making Changes
- Testing
- Pull Request Guidelines
- Commit Message Guidelines
- Documentation
- Questions and Support
Code of Conduct
Please read and follow our Code of Conduct. We are committed to providing a welcoming and inclusive environment for all contributors.
Getting Started
Prerequisites
Before contributing, ensure you have the following installed:
- Node.js 20.x or later
- Yarn 1.x (classic)
- Git
- Docker (optional, for isolated development)
Fork and Clone
- Fork the repository on GitHub
- Clone your fork:
git clone https://github.com/<your-username>/Compass.git cd Compass - Add the upstream remote:
git remote add upstream https://github.com/CompassConnections/Compass.git
Install Dependencies
yarn install --frozen-lockfile
Development Environment
Running the Development Server
yarn dev
Visit http://localhost:3000 to see the application.
Isolated Development (Recommended)
For full isolation with local Supabase and Firebase emulators:
yarn dev:isolated
Benefits:
- No conflicts with other contributors
- Works offline
- Faster database queries
- Free to reset and reseed data
Requirements:
- Docker (~500MB)
- Supabase CLI
- Java 21+ (for Firebase emulators)
- Firebase CLI
See the README for detailed setup instructions.
Running Tests
# Run all tests
yarn test
# Run tests with coverage
yarn test:coverage
# Run tests in watch mode
yarn test:watch
# Run E2E tests
yarn test:e2e
Linting and Type Checking
# Lint all packages
yarn lint
# Fix linting issues
yarn lint-fix
# Type check all packages
yarn typecheck
Project Structure
This is a Yarn workspaces monorepo with the following packages:
Compass/
├── web/ # Next.js web application
│ ├── components/ # React components
│ ├── hooks/ # Custom React hooks
│ ├── lib/ # Utilities and services
│ ├── pages/ # Next.js pages
│ └── messages/ # Internationalization files
├── backend/
│ ├── api/ # Express API server
│ ├── shared/ # Shared backend utilities
│ ├── email/ # React email templates
│ └── scripts/ # Database migration scripts
├── common/ # Shared TypeScript types and utilities
├── supabase/ # Database migrations and config
├── android/ # Capacitor Android app
└── docs/ # Project documentation
Key Technologies
| Layer | Technology |
|---|---|
| Frontend | Next.js 16, React 19, TypeScript |
| Styling | Tailwind CSS |
| Backend | Express.js, Node.js |
| Database | PostgreSQL (Supabase) |
| Auth | Firebase Auth |
| Storage | Firebase Storage |
| Mobile | Capacitor (Android) |
| Testing | Jest, Playwright |
Coding Standards
TypeScript
- Use strict TypeScript typing
- Avoid
anytype; useunknownwhen necessary - Prefer interfaces over types for object shapes
- Use
constassertions where appropriate
React Components
- Use functional components with hooks
- Name components after their file name
- Export primary component at the top of the file
- Use composition over inheritance
- Keep components small and focused
Example component structure:
import clsx from 'clsx'
import {useState} from 'react'
interface ProfileCardProps {
name: string
age: number
onSelect?: (id: string) => void
className?: string
}
export function ProfileCard({name, age, onSelect, className}: ProfileCardProps) {
const [selected, setSelected] = useState(false)
const handleClick = () => {
setSelected(!selected)
onSelect?.(name)
}
return (
<div className={clsx('card', selected && 'selected', className)}>
<h3>
{name}, {age}
</h3>
<button onClick={handleClick}>Select</button>
</div>
)
}
Naming Conventions
- Files: kebab-case (
profile-card.tsx) - Components: PascalCase (
ProfileCard) - Hooks: camelCase with
useprefix (useUserProfile) - Constants: SCREAMING_SNAKE_CASE
- Types/Interfaces: PascalCase
Import Order
Run yarn lint-fix to automatically sort imports:
- External libraries (React, Next.js, etc.)
- Internal packages (
common/,shared/) - Relative imports (
../,./) - Type imports
Error Handling
- Use try-catch for async operations
- Create custom error types for API errors
- Implement error boundaries for React components
- Log errors with appropriate context
Example:
import {APIError} from './errors'
try {
const result = await api('endpoint', params)
return result
} catch (err) {
if (err instanceof APIError) {
logger.error('API error', {status: err.status, message: err.message})
} else {
logger.error('Unexpected error', err)
}
throw err
}
Accessibility
- Use semantic HTML elements
- Include ARIA labels where appropriate
- Ensure keyboard navigation works
- Use the
SkipLinkcomponent for main content - Announce dynamic content changes with
useLiveRegion
import {useLiveRegion} from 'web/components/live-region'
function MyComponent() {
const {announce} = useLiveRegion()
const handleAction = () => {
// Action completed
announce('Action successful', 'polite')
}
}
Making Changes
Creating a Branch
Never work directly on main. Create a new branch:
git checkout -b type/short-description
Branch types:
feat/- New featuresfix/- Bug fixesdocs/- Documentationrefactor/- Code refactoringtest/- Adding/updating testschore/- Maintenance tasks
Making Commits
Keep commits atomic and descriptive:
git add .
git commit -m "feat(profiles): add compatibility score display
- Added compatibility score calculation
- Display score on profile cards
- Added tests for scoring algorithm"
See Commit Message Guidelines for details.
Keeping Your Fork Updated
# Fetch latest from upstream
git fetch upstream
# Update main branch
git checkout main
git merge upstream/main
# Rebase your feature branch
git checkout feat/your-feature
git rebase main
Testing
Writing Tests
Unit Tests
Place tests in tests/unit/ within each package:
// web/tests/unit/my-function.test.ts
import {myFunction} from '../my-function'
describe('myFunction', () => {
it('should return correct output', () => {
expect(myFunction('input')).toBe('expected')
})
})
Integration Tests
Place in tests/integration/:
// web/tests/integration/api.test.ts
import {render, screen} from '@testing-library/react'
import {MyComponent} from '../MyComponent'
describe('MyComponent', () => {
it('renders correctly', () => {
render(<MyComponent / >)
expect(screen.getByText('Hello')).toBeInTheDocument()
})
})
E2E Tests
Place in tests/e2e/ at the root:
// tests/e2e/web/specs/onboarding.spec.ts
import {test, expect} from '@playwright/test'
test('onboarding flow', async ({page}) => {
await page.goto('/signup')
await page.fill('[name="email"]', 'test@example.com')
await page.click('button[type="submit"]')
await expect(page).toHaveURL('/onboarding')
})
Running Specific Tests
# Run unit tests for web
yarn workspace web test
# Run tests matching pattern
yarn test --testPathPattern="profile"
# Run E2E tests
yarn test:e2e
Test Coverage
Aim for meaningful test coverage. Focus on:
- Business logic
- User interactions
- Error handling
- Edge cases
Pull Request Guidelines
Before Submitting
- Run all tests:
yarn test - Run linter:
yarn lint - Run type check:
yarn typecheck - Update documentation if needed
- Rebase on main if necessary
Pull Request Format
Title: Clear, descriptive title
Description:
## Summary
Brief description of changes
## Changes
- Added compatibility score to profile cards
- Updated search algorithm for better results
## Testing
- Added unit tests for scoring algorithm
- Tested manually with synthetic data
## Screenshots (if UI changes)
PR Checklist
- Code follows style guidelines
- Tests added/updated and passing
- Documentation updated
- No console.log statements (except debugging)
- No debug code left behind
Review Process
- Maintainers review within 48 hours
- Address feedback promptly
- Do not open new PRs for changes - update existing one
- Squash commits before merging
Commit Message Guidelines
Follow Conventional Commits:
<type>(<scope>): <description>
[optional body]
[optional footer]
Types
feat: New featurefix: Bug fixdocs: Documentationstyle: Formattingrefactor: Code restructuringtest: Testschore: Maintenance
Examples
feat(profiles): add compatibility scoring algorithm
fix(api): handle rate limiting gracefully
docs(readme): update installation instructions
refactor(auth): simplify token refresh logic
test(profiles): add unit tests for scoring
Documentation
Updating Documentation
- Update relevant README files
- Add JSDoc comments to complex functions
- Update the
/docsfolder for architectural changes
API Documentation
API docs are auto-generated and available at:
- Production: https://api.compassmeet.com
- Local: http://localhost:8088 (when running locally)
Questions and Support
- Discord: https://discord.gg/8Vd7jzqjun
- Email: hello@compassmeet.com
- GitHub Issues: For bug reports and feature requests
Thank you for contributing to Compass! Together we're building a platform for meaningful connections.