Skip to main content

Contributing

GospeLib is a polyglot monorepo spanning TypeScript (Next.js), Python (FastAPI), and Go (Chi) services. This guide covers everything you need to go from a fresh clone to a merged pull request.

Getting Started

For initial setup, see Getting Started.

Branch Naming

Create a branch from master using the following prefixes:

PrefixUse when...Example
feat/Adding a new featurefeat/lexicon-search
fix/Fixing a bugfix/gateway-timeout
docs/Documentation-only changesdocs/add-testing-guide
chore/Maintenance, dependency updates, toolingchore/upgrade-vitest
refactor/Restructuring code without behavior changerefactor/content-query-layer

Keep branch names short and descriptive. Use hyphens, not underscores.

Commit Conventions

This project enforces Conventional Commits via commitlint and a Husky commit-msg hook. Every commit must follow this format:

type(scope): description

[optional body]

[optional footer(s)]

Types

TypePurpose
featNew feature
fixBug fix
docsDocumentation only
styleFormatting, missing semicolons, etc.
refactorCode change that neither fixes nor adds
perfPerformance improvement
testAdding or updating tests
buildBuild system or external dependencies
ciCI configuration and scripts
choreOther changes that don't modify src or tests
revertReverts a previous commit

Scopes

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

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

Examples

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

Interactive Commit Workflow

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

pnpm commit
# or
make commit

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

Breaking Changes

To signal a breaking change (triggers a major version bump), add a BREAKING CHANGE footer:

feat(sdk)!: redesign authentication flow

BREAKING CHANGE: The `login()` method now returns a session object instead of a token string.

Pull Request Process

  1. Keep PRs focused on a single concern. One feature, one bug fix, or one refactor per PR.

  2. Title your PR using conventional commit format:

    feat(web): add search page
    fix(gateway): handle missing JWT gracefully
    docs(guides): add testing guide
  3. Link related issues in the PR description so they close automatically on merge.

  4. Ensure CI passes before requesting review. All lint, type-check, and test jobs must be green.

  5. Request review from at least one team member.

CI Flow

Every pull request triggers the following pipeline:

PR opened / updated
--> Lint (all languages)
pnpm nx affected -t lint --parallel=4
pnpm nx affected -t typecheck --parallel=4
--> Test (parallel by language)
test-js: nx affected -t test --parallel=3
test-python: uv run pytest (per service, with containers)
test-go: go test ./... -race (per service)
--> Build check
pnpm nx affected -t build

All jobs must pass before a PR can be merged. Lint and type-check failures block merge.

Pre-Commit Pipeline

Every local commit runs through Husky hooks automatically:

git commit
--> lint-staged
*.{js,jsx,ts,tsx,mjs,cjs,mts,cts} --> eslint --fix, prettier --write
*.{json,md,yml,yaml,css,scss} --> prettier --write
--> commitlint (validates Conventional Commits format)

This catches formatting and lint issues before they reach CI.

Release Process

Component Releases (Automated)

Component releases are fully automated via release-please:

  1. Commits to master are analyzed by release-please.
  2. A release PR is auto-created (or updated) with changelog entries and version bumps.
  3. Merging the release PR triggers the release -- tags are created per component (e.g., gateway/v1.0.0).

No manual versioning or changelog editing is required.

Production Releases

Production deployments are triggered by pushing a release/v*.*.* tag. The production CD pipeline runs the full regression suite, waits for manual approval via GitHub environment protection rules, then builds, pushes, and deploys all service images.

Documentation

GospeLib's engineering documentation lives in a Docusaurus site under apps/docs/. The live site is deployed at docs.gospelib.com.

Adding or Editing a Doc Page

  1. Create or edit a Markdown file in apps/docs/docs/ under the appropriate directory.
  2. Sidebar ordering is autogenerated -- you usually do not need to edit sidebars.ts. Use sidebar_position in frontmatter or _category_.json to control ordering.
  3. Preview locally with pnpm --filter docs dev before pushing.

Adding a Blog Post

Create a new Markdown file in apps/docs/blog/ named YYYY-MM-DD-slug.md with title, authors, and tags frontmatter.

Development Guides

For detailed standards on code quality, testing, and operational practices, see:

  • Code Quality -- Linters, formatters, and type checkers across all languages
  • Testing -- How to run and write tests (Vitest, pytest, Go test)
  • Logging & Observability -- Structured logging, tracing, profiling, and health endpoints
  • Error Handling -- Error catalog, response envelope, and per-language error patterns