Skip to main content

Your First PR

This guide walks you through the workflow for making a change and getting it merged — from branch creation to CI passing.

1. Create a Branch

Branch from main using this naming convention:

<type>/<scope>-<short-description>

Examples:

git checkout main
git pull origin main
git checkout -b feat/web-add-search-page
git checkout -b fix/gateway-timeout-handling
git checkout -b docs/content-update-api-docs

The type and scope match the Conventional Commits convention below.

2. Write Conventional Commits

Every commit must follow Conventional Commits. This is enforced by a commit-msg hook — commits that don't match will be rejected.

Format

type(scope): description

[optional body]

[optional footer(s)]

Types

TypeWhen to Use
featNew feature
fixBug fix
docsDocumentation only
styleFormatting, semicolons, etc. (no logic change)
refactorCode change that neither fixes nor adds a feature
perfPerformance improvement
testAdding or updating tests
buildBuild system or external dependencies
ciCI configuration and scripts
choreOther changes that don't modify src or tests

Scopes

Use one of these scopes to indicate the area of change:

web · mobile · admin · gateway · content · auth · billing · ai · notifications · ingest · ui · sdk · types · config · infra · ci · deps

Examples

git commit -m "feat(web): add dark mode toggle"
git commit -m "fix(gateway): handle timeout on health check"
git commit -m "docs(content): update API schema docs"

Instead of writing the commit message manually, use the Commitizen wizard:

pnpm commit

This walks you through type, scope, description, body, and breaking changes interactively.

3. Run Checks Locally

Before pushing, run the same checks that CI will run:

# Lint TypeScript/JavaScript
pnpm lint

# Type-check TypeScript
pnpm typecheck

# Run tests
pnpm test

For changes in a specific service:

# Python service (e.g., content)
cd services/content
uv run ruff check . # Lint
uv run mypy . # Type check
uv run pytest # Test

# Go service (e.g., gateway)
cd services/gateway
go vet ./... # Vet
go test ./... -race # Test
Run only affected projects

For faster checks, use Nx to run only what's affected by your changes:

pnpm nx affected -t lint --parallel=4
pnpm nx affected -t test --parallel=3

4. Push and Open a PR

git push origin feat/web-add-search-page

Then open a pull request on GitHub. Use the same Conventional Commit format for the PR title:

feat(web): add search page

PR Guidelines

  • Keep PRs focused on a single concern. One feature, one fix, or one refactor per PR.
  • Link related issues in the PR description (e.g., Closes #42).
  • Ensure CI passes before requesting review.

5. What CI Checks

When you open a PR, the CI pipeline runs:

JobWhat It Does
Lintnx affected -t lint --parallel=4 — ESLint for TS/JS
TypecheckTypeScript strict type checking
Test JSVitest for affected TypeScript/JavaScript projects
Test Pythonpytest for affected Python services (with FalkorDB + PostgreSQL containers)
Test Gogo test ./... -race for affected Go services
BuildDocker image builds for all affected services

All jobs must pass before a PR can be merged.

6. After Merge — Releases

Releases are fully automated via release-please:

  1. Commits to main are analyzed by release-please.
  2. A release PR is auto-created with changelog entries and version bumps.
  3. Merging the release PR creates tags per component (e.g., gateway/v1.0.0).
  4. CD pipelines trigger on component tags.

No manual versioning or changelog editing required.

Verify It Worked

After your PR is merged:

  1. Check that CI passed on main.
  2. If release-please opened or updated a release PR, your change is included in the changelog.
  3. Your commit appears in the main branch history with the correct conventional commit format.

Next Step

See the Port Map & Services Overview for a quick reference of all services, ports, and data stores.

For coding standards, review guidelines, and more on the development workflow, see the Contributing section.