Contributing Guidelines
Thank you for your interest in contributing to EchoStats! This guide covers everything you need to know to submit high-quality contributions.
Getting Started
- Fork the repository on GitHub
- Clone your fork locally
- Set up the development environment (see Installation)
- Create a branch for your changes
- Make changes, commit, and push
- Open a Pull Request against
main
Development Environment
Prerequisites
| Tool | Version | Purpose |
|---|---|---|
| Python | 3.12+ | Backend API |
| uv | Latest | Python package manager |
| Node.js | 22+ | Frontend |
| pnpm | 10+ | Node package manager |
| Docker | 24+ | Local services (MongoDB, Redis) |
Local Setup
# Clone and enter the projectgit clone https://github.com/your-username/echostats.gitcd echostats
# Start infrastructure (MongoDB + Redis)docker compose up -d mongo redis
# Backend setupcd apiuv synccp .env.example .env # Configure your Spotify credentialsuv run uvicorn app.main:app --reload --port 8000
# Frontend setup (in a new terminal)cd webpnpm installcp .env.example .env.localpnpm devSeed Data
EchoStats includes seed data for development (15 artists, 25 tracks, ~1,800 history entries). Use the dev-login endpoint to bypass OAuth during development:
curl http://localhost:8000/api/v1/auth/dev-loginCode Style
Python (Backend)
EchoStats uses Ruff for both linting and formatting.
cd api
# Check for lint errorsuv run ruff check .
# Auto-fix lint errorsuv run ruff check --fix .
# Format codeuv run ruff format .
# Type checking with mypyuv run mypy app/Key Ruff settings:
| Setting | Value |
|---|---|
| Target version | Python 3.12 |
| Line length | 100 characters |
| Import sorting | isort-compatible (I rules) |
| First-party packages | app |
The Ruff configuration enables an extensive rule set including E, F, W, I, N, UP, S, B, A, C4, DTZ, PIE, PT, RET, SIM, TID, TCH, ARG, PL, TRY, PERF, and RUF families. See api/pyproject.toml for the full configuration.
Python conventions:
- Use
async/awaitfor all I/O operations (MongoDB, Redis, HTTP calls) - Use Beanie ODM models for MongoDB documents
- Use Pydantic models for request/response schemas
- Use
structlogfor logging, notprint() - Type-annotate all function signatures
TypeScript (Frontend)
EchoStats uses Biome for linting and formatting.
cd web
# Lint and format checkpnpm biome check .
# Auto-fix issuespnpm biome check --write .
# Format onlypnpm biome format --write .Key Biome settings:
| Setting | Value |
|---|---|
| Indent style | Spaces |
| Indent width | 2 |
| Line width | 100 |
| Import sorting | Automatic |
| Unused variables | Warning |
TypeScript conventions:
- Use functional React components with hooks
- Use
"use client"directive only when the component needs client-side interactivity - Prefer named exports over default exports for components
- Use Tailwind CSS classes — avoid inline styles and CSS modules
- Use
fetchwith relative URLs (/api/v1/...) for API calls - Keep components small and composable
Commit Message Format
EchoStats follows Conventional Commits for consistent, parseable commit history.
Format
<type>(<scope>): <short description>
[optional body]
[optional footer]Types
| Type | When to Use |
|---|---|
feat | New feature or capability |
fix | Bug fix |
docs | Documentation changes only |
style | Code formatting (no logic change) |
refactor | Code change that neither fixes a bug nor adds a feature |
perf | Performance improvement |
test | Adding or updating tests |
chore | Build process, CI, dependency updates |
ci | CI/CD pipeline changes |
Scopes
Use a scope to indicate which part of the codebase is affected:
| Scope | Area |
|---|---|
api | Backend Python code |
web | Frontend Next.js code |
worker | ARQ background worker |
helm | Helm chart changes |
docker | Docker/Compose changes |
docs | Documentation site |
deps | Dependency updates |
Examples
# Good commit messagesfeat(api): add genre distribution endpointfix(web): resolve theme flicker on page loaddocs: update authentication guide with curl exampleschore(deps): bump fastapi to 0.115.6refactor(api): extract token refresh into service layerperf(web): lazy-load analytics charts for faster initial renderfix(worker): handle Redis connection timeout during syncci: add Python 3.12 to test matrixBranch Naming
Use descriptive branch names with a type prefix:
<type>/<short-description>Examples
feat/genre-distribution-endpointfix/theme-flicker-on-loaddocs/authentication-guidechore/bump-fastapi-versionrefactor/extract-token-serviceRules
- Use lowercase with hyphens (kebab-case)
- Keep it short but descriptive
- The type prefix should match your commit type
- Branch from
mainfor all changes
Pull Request Process
Before Submitting
-
Ensure your branch is up to date with
main:Terminal window git fetch origingit rebase origin/main -
Run linters and formatters:
Terminal window # Backendcd api && uv run ruff check . && uv run ruff format --check .# Frontendcd web && pnpm biome check . -
Run tests:
Terminal window # Backendcd api && uv run pytest# Frontendcd web && pnpm test -
Test your changes manually — verify the feature works in the browser
PR Description
Your pull request should include:
- What — A clear description of the change
- Why — The motivation or issue being resolved
- How — Brief technical approach (for non-trivial changes)
- Testing — How you verified the change works
- Screenshots — For UI changes, include before/after screenshots
Review Process
- A maintainer will review your PR
- CI checks must pass (linting, tests, build)
- Address any review feedback with new commits (don’t force-push during review)
- Once approved, a maintainer will merge using squash merge
Testing
Backend Tests
cd api
# Run all testsuv run pytest
# Run with coverageuv run pytest --cov=app --cov-report=term-missing
# Run a specific test fileuv run pytest tests/test_auth.py
# Run tests matching a patternuv run pytest -k "test_login"Tests use pytest with pytest-asyncio for async test support. Use httpx.AsyncClient for testing API endpoints.
Frontend Tests
cd web
# Run testspnpm test
# Run tests in watch modepnpm test --watchWriting Tests
- Backend: Place tests in
api/tests/mirroring the source structure - Frontend: Co-locate test files with components (e.g.,
Component.test.tsx) - Aim for meaningful coverage of business logic, not 100% line coverage
- Test edge cases: empty data, error responses, expired tokens
Architecture Guidelines
Adding a New API Endpoint
- Create or update the router in
api/app/routers/ - Define Pydantic request/response models
- Add business logic in
api/app/services/ - Register the router in
api/app/main.py - Add tests in
api/tests/
Adding a New Dashboard Page
- Create the page in
web/src/app/dashboard/<page>/page.tsx - Add the data-fetching hook in
web/src/hooks/ - Create visualization components in
web/src/components/ - Add the page to the sidebar navigation in the layout
- Ensure responsive design works on mobile
Database Changes
- Use Beanie ODM document models in
api/app/models/ - MongoDB collections are created automatically from document classes
- For schema changes, ensure backward compatibility — MongoDB is schema-less but your code should handle old documents gracefully
Reporting Issues
When reporting bugs, include:
- EchoStats version (shown in sidebar or
GET /api/health) - Deployment method (Docker Compose or Helm)
- Browser and OS (for frontend issues)
- Steps to reproduce the issue
- Expected vs actual behavior
- Relevant logs from the API, worker, or browser console
Code of Conduct
Be respectful, inclusive, and constructive. We’re all here to build something great together. Harassment, discrimination, or hostile behavior will not be tolerated.