Thank you for your interest in contributing to Lumi! This document provides guidelines for contributing to the project.
- Code of Conduct
- Getting Started
- Development Setup
- Branch Naming
- Commit Message Format
- Pull Request Process
- Testing Requirements
- Code Style
- License Agreement
Be respectful, professional, and constructive in all interactions. Harassment, discrimination, or unprofessional behavior will not be tolerated.
- Node.js 22+ (for backend and frontend)
- Docker & Docker Compose (for full stack deployment)
- Git (for version control)
- MongoDB (via Docker or local installation)
# Clone the repository
git clone https://github.com/Poolchaos/Lumi.git
cd Lumi
# Copy environment templates
cp .env.example .env
cp backend/.env.example backend/.env
# Edit .env files with your configuration
# Required: MONGO_ROOT_PASSWORD, JWT_SECRET, JWT_REFRESH_SECRET, ENCRYPTION_SECRET, OPENAI_API_KEY
# Start the stack with Docker
docker-compose up -d
# Access the application
# Frontend: http://localhost:3000
# Backend: http://localhost:5000
# MinIO Console: http://localhost:9003cd backend
# Install dependencies
npm install
# Run in development mode (with hot reload)
npm run dev
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Lint
npm run lint
# Type check
npx tsc --noEmitcd frontend
# Install dependencies
npm install
# Run development server (Vite)
npm run dev
# Run tests
npm test
# Run E2E tests (requires backend running)
npm run test:e2e
# Build for production
npm run build
# Lint
npm run lint
# Type check
npx tsc --noEmitUse descriptive branch names following these conventions:
| Type | Format | Example |
|---|---|---|
| Feature | feature/<area>-<description> |
feature/auth-jwt-refresh |
| Bug Fix | fix/<area>-<issue> |
fix/api-timeout |
| Chore | chore/<area>-<task> |
chore/deps-update |
| Refactor | refactor/<area>-<description> |
refactor/auth-extract-validator |
| Tests | test/<area>-<coverage> |
test/api-integration-suite |
Rules:
- Create a new branch for every feature, fix, or non-trivial change
- Branch from
main - Keep branch scope focused (one feature or fix per branch)
- Delete branches after merging
Follow semantic commit conventions:
type(scope): brief description
- bullet point describing what changed
- bullet point explaining why (if non-obvious)
- maximum 5 lines total (including subject line)
| Type | Description |
|---|---|
feat |
New feature |
fix |
Bug fix |
docs |
Documentation changes |
style |
Code style changes (formatting, missing semicolons, etc.) |
refactor |
Code refactoring (no functional changes) |
test |
Adding or updating tests |
chore |
Maintenance tasks (dependencies, config, etc.) |
perf |
Performance improvements |
ci |
CI/CD pipeline changes |
build |
Build system changes |
Use the component or area affected:
auth,api,frontend,backend,tests,ci,docs,gamification,workouts,profile, etc.
# Good commits
feat(auth): add JWT token refresh endpoint
fix(api): resolve database connection timeout
test(integration): add user isolation test suite
chore(deps): update dependencies to latest stable
docs(readme): add Docker setup instructions
# Bad commits (avoid these)
update stuff
wip
fix bug
changes
added feature- Run all tests - ensure they pass locally
- Check TypeScript compilation - zero errors required
- Run linters - fix all linting issues
- Test manually - verify your changes work as expected
- Review your own code - check for console.log, commented code, TODOs
Use the same format as commit messages:
type(scope): brief description
## Purpose
[1-2 sentences: What does this PR accomplish and why?]
## Changes
- [Bullet list of key changes]
- [Include file paths for major modifications]
- [Mention new dependencies if added]
## Testing
**Unit Tests:**
- [Commands to run unit tests]
- [Expected test count and pass rate]
**Manual Testing:**
- [Steps to reproduce and verify the change]
- [Expected behavior]
**Coverage:**
- [Before/after coverage percentage for affected modules]
## Screenshots (if UI changes)
[Required for any visible UI changes]
- Before: [image or "N/A - new feature"]
- After: [image]
## Checklist
- [ ] All tests passing locally
- [ ] Linting passing
- [ ] No debug artifacts (console.log, debugger, print statements)
- [ ] Documentation updated (if public API changed)
- [ ] No hardcoded secrets or environment-specific values
- [ ] Follows naming conventions and architectural patterns
- [ ] Breaking changes documented (if applicable)
## Dependencies
[List any new dependencies added and justification]
- Dependency: [name]
- Version: [version]
- Why: [reason existing solutions don't suffice]
- License: [license compatibility confirmed]
## Breaking Changes (if applicable)
[If PR introduces breaking changes, include migration guide]
## Linked Issues
Closes #[issue number]
Relates to #[issue number]- Code follows TypeScript and ESLint best practices
- Tests cover new functionality (minimum 85% coverage for critical modules)
- No TypeScript compilation errors
- No hardcoded secrets, API keys, or environment-specific values
- Error handling present for all external API calls
- Accessibility validated for UI changes (WCAG 2.1 AA)
- Security implications reviewed (for auth, secrets, PII changes)
- Maximum 400 lines changed (excluding auto-generated files, test fixtures, lock files)
- Larger changes should be split into logical incremental PRs
MANDATORY: All tests must pass before committing code.
# Backend
cd backend && npm test
# Frontend
cd frontend && npm test
# E2E (requires backend running)
cd frontend && npm run test:e2e- Critical modules (auth, payments, data access): ≥ 85% coverage
- Non-critical modules: ≥ 70% coverage
- All new features: Must include tests
- Backend: Use Jest for unit and integration tests
- Frontend: Use Vitest for unit tests, Playwright for E2E tests
- Test file naming:
*.test.tsor*.spec.ts - Test structure: Arrange-Act-Assert pattern
Example:
describe('User Authentication', () => {
it('should return 401 for invalid credentials', async () => {
// Arrange
const credentials = { email: 'test@example.com', password: 'wrong' };
// Act
const response = await request(app)
.post('/api/auth/login')
.send(credentials);
// Assert
expect(response.status).toBe(401);
expect(response.body.error).toBe('Invalid credentials');
});
});- Zero compilation errors - mandatory for all commits
- No
anytypes in production code (tests may useanyfor mocks) - Explicit return types for all functions
- Strict mode enabled in tsconfig.json
- No unused variables - prefix with
_if required for interface compliance
- ESLint configured for TypeScript
- Prettier for code formatting (runs automatically)
- Run
npm run lintbefore committing - Fix all warnings for new code
backend/
├── src/
│ ├── controllers/ # Route handlers
│ ├── models/ # Mongoose schemas
│ ├── routes/ # Express routes
│ ├── services/ # Business logic
│ ├── middleware/ # Auth, rate limiting, etc.
│ ├── validators/ # Request validation
│ ├── utils/ # Helper functions
│ └── __tests__/ # Test files
frontend/
├── src/
│ ├── pages/ # Route components
│ ├── components/ # Reusable UI components
│ ├── design-system/ # Component library
│ ├── hooks/ # Custom React hooks
│ ├── api/ # API client
│ ├── store/ # Zustand state management
│ ├── utils/ # Helper functions
│ └── types/ # TypeScript type definitions
- No console.log in production code (use proper logging for backend)
- No commented-out code (use git history instead)
- No hardcoded URLs or secrets
- Use environment variables for configuration
- Handle errors gracefully - always include try-catch for external calls
- Write meaningful comments - focus on "why" not "what"
By contributing to Lumi, you agree that:
- Your contributions will be licensed under the PolyForm Noncommercial License 1.0.0
- You have the right to submit the contribution
- You understand the project is NOT free for commercial use
- Commercial use requires a separate paid license
See the LICENSE file for full terms.
- Email: phillipjuanvanderberg@gmail.com
- Issues: GitHub Issues
Thank you for contributing to Lumi!