Thanks for your interest in contributing to Yavio! This guide covers everything you need to get started.
By participating, you agree to uphold our Code of Conduct.
- Node.js 20+ LTS
- Docker v24+ and docker-compose v2.20+
- pnpm (package manager)
# Clone the repo
git clone https://github.com/teamyavio/yavio.git
cd yavio
# Install dependencies
pnpm install
# Copy environment config
cp .env.example .env
# Fill in the required secrets (see comments in .env.example)
# Start infrastructure (PostgreSQL + ClickHouse)
docker compose up postgres clickhouse -d
# Run database migrations
pnpm db:migrate
# Start the development servers
pnpm devpackages/
dashboard/ # Next.js 16 dashboard
ingest/ # Fastify ingestion API
sdk/ # @yavio/sdk (server + widget)
cli/ # @yavio/cli
shared/ # Shared types and validation
migrations/
clickhouse/ # ClickHouse schema migrations
postgres/ # PostgreSQL schema migrations
config/ # Docker service configs
specs/ # Technical specifications
By contributing to Yavio, you agree that your contributions will be licensed under the MIT License.
Open a bug report issue. Include:
- Steps to reproduce
- Expected vs. actual behavior
- Environment details (OS, Node version, Docker version)
- Logs or screenshots if applicable
Open a feature request issue. Describe:
- The problem you're trying to solve
- Your proposed solution
- Alternatives you've considered
- Check existing issues — look for an open issue or create one before starting work
- Fork the repo and create a branch from
main - Follow the branch naming convention (see below)
- Write tests for any new functionality
- Run the checks before pushing (see below)
- Open a pull request using the PR template
| Prefix | Use |
|---|---|
feat/ |
New features (feat/user-identification) |
fix/ |
Bug fixes (fix/clickhouse-timeout) |
docs/ |
Documentation changes (docs/sdk-quickstart) |
refactor/ |
Code refactoring (refactor/event-pipeline) |
test/ |
Adding or updating tests (test/ingestion-api) |
chore/ |
Maintenance tasks (chore/update-deps) |
The project uses Biome for linting and formatting. Configuration is shared across all packages.
# Check formatting and lint
pnpm lint
# Auto-fix issues
pnpm lint:fix
# Format code
pnpm format- TypeScript — strict mode, no
anyunless absolutely necessary - Imports — use path aliases (
@/lib/...) within packages - Naming —
camelCasefor variables/functions,PascalCasefor types/components,SCREAMING_SNAKE_CASEfor constants - Tests — colocate test files next to source (
*.test.ts)
# Run all tests
pnpm test
# Run tests for a specific package
pnpm --filter @yavio/sdk test
pnpm --filter dashboard test
pnpm --filter ingest test
# Run tests in watch mode
pnpm test:watch
# Run with coverage
pnpm test:coverageAll new code must maintain a minimum of 80% test coverage. PRs that drop coverage below this threshold will not be merged. Run pnpm test:coverage to verify before submitting.
- Fill out the PR template completely
- Ensure all CI checks pass (lint, type check, tests)
- Keep PRs focused — one feature or fix per PR
- Update documentation if your change affects public APIs
- A maintainer will review your PR and may request changes
- Once approved, a maintainer will merge your PR
Use Conventional Commits:
feat(sdk): add .identify() method for user tracking
fix(ingest): handle malformed event payloads gracefully
docs: update self-hosting guide with TLS instructions
test(dashboard): add integration tests for funnel view
chore: update dependencies
Format: type(scope): description
- type:
feat,fix,docs,test,refactor,chore,ci - scope (optional): package name (
sdk,ingest,dashboard,cli,docs) - description: imperative mood, lowercase, no period
All errors use the YavioError class from @yavio/shared/errors. Never throw a bare Error in service code.
import { YavioError, ErrorCode } from "@yavio/shared/errors";
// Throw with a stable code, message, HTTP status, and optional metadata
throw new YavioError(
ErrorCode.DASHBOARD.WORKSPACE_NOT_FOUND,
"Workspace not found",
404,
{ slug: "my-workspace" },
);Each service owns a range of codes (defined in packages/shared/src/error-codes.ts):
| Range | Service | Object |
|---|---|---|
YAVIO-1000 – 1999 |
SDK | ErrorCode.SDK |
YAVIO-2000 – 2999 |
Ingestion API | ErrorCode.INGEST |
YAVIO-3000 – 3999 |
Dashboard | ErrorCode.DASHBOARD |
YAVIO-4000 – 4999 |
Intelligence | ErrorCode.INTELLIGENCE |
YAVIO-5000 – 5999 |
Database | ErrorCode.DB |
YAVIO-6000 – 6999 |
CLI | ErrorCode.CLI |
YAVIO-7000 – 7999 |
Infrastructure | ErrorCode.INFRA |
- Always use
YavioErrorwith a code from the catalog — no bareErrorin service code - Wrap unknown errors — if you catch an unknown error, re-throw it as a
YavioError(preserve if already one) - Include metadata — pass context like variable names, slugs, or filenames in the
metadatafield - Codes are permanent — never reuse or reassign an existing code
- Adding a new code: pick the next unused number in the service range, add it to
packages/shared/src/error-codes.ts, and document it in.specs/07_error-catalog.md
See .specs/07_error-catalog.md for the full error specification.
# Connect to ClickHouse CLI
docker exec -it yavio-analytics-clickhouse-1 clickhouse-client
# Query events
SELECT * FROM yavio.events LIMIT 10;# Connect to PostgreSQL
docker exec -it yavio-analytics-postgres-1 psql -U yavio_service -d yavio# Start everything
docker compose up -d
# Check service health
docker compose ps
# View logs
docker compose logs -f ingest
docker compose logs -f dashboard- Join our Discord
Thank you for contributing!