- Home
- Introduction to Colibri
- Contributing to Colibri
Contributing Guidelines
How to contribute to Colibri - code standards, PR process, and community guidelines
Thank you for considering contributing to Colibri! This document outlines our standards, processes, and best practices to help you contribute effectively.
Code of Conduct
We are committed to providing a welcoming and inclusive environment. By participating, you agree to:
- Be respectful and considerate in all interactions
- Provide constructive feedback
- Accept constructive criticism gracefully
- Focus on what’s best for the community and project
- Show empathy towards other community members
Report unacceptable behavior to the project maintainers.
Getting Started
Prerequisites
Before contributing, ensure you have:
- Read the Development Setup guide
- Set up your local development environment
- Familiarized yourself with the Architecture
- Read through this guide completely
Finding Work
Good First Issues
Look for issues labeled good first issue - these are beginner-friendly and well-defined.
Help Wanted
Issues labeled help wanted are priorities where we’d appreciate community help.
Feature Requests
Check feature request issues for ideas. Always discuss in the issue before starting work to ensure alignment.
Bug Reports
bug issues are always welcome! If you can reproduce and fix a bug, please do.
Contribution Workflow
1. Fork and Clone
# Fork the repository on GitHub, then:
git clone https://github.com/YOUR_USERNAME/colibri.git
cd colibri
# Add upstream remote
git remote add upstream https://github.com/colibri-hq/colibri.git2. Create a Branch
Use descriptive branch names:
# For features
git checkout -b feature/add-book-ratings
# For bug fixes
git checkout -b fix/upload-modal-crash
# For documentation
git checkout -b docs/improve-setup-guide
# For refactoring
git checkout -b refactor/simplify-metadata-aggregatorBranch naming conventions:
feature/- New featuresfix/- Bug fixesdocs/- Documentation changesrefactor/- Code refactoringtest/- Adding or updating testschore/- Maintenance tasks
3. Make Your Changes
Follow these principles:
Write Clean Code
- Keep functions small and focused
- Use descriptive variable and function names
- Add comments for complex logic
- Follow existing patterns in the codebase
Maintain Type Safety
- Add types for all function parameters and returns
- Avoid
anytypes - useunknownand type guards - Keep TypeScript strict mode enabled
Test Your Changes
- Write unit tests for new utilities
- Add integration tests for SDK resources
- Write E2E tests for user-facing features
- Ensure all tests pass before committing
Keep Commits Atomic
- One logical change per commit
- Commit often with clear messages
- Don’t mix unrelated changes
4. Follow Code Standards
TypeScript Style
// ✓ Good: Explicit types, clear naming
async function fetchWorkById(id: string): Promise<Work | null> {
const result = await db.selectFrom("works").selectAll().where("id", "=", id).executeTakeFirst();
return result ? new Work(result) : null;
}
// ✗ Avoid: Implicit types, unclear naming
async function get(x: string) {
const r = await db.selectFrom("works").selectAll().where("id", "=", x).executeTakeFirst();
return r ? new Work(r) : null;
}Svelte Component Style
<script lang="ts">
// ✓ Good: Props interface, clear state management
import type { Work } from '@colibri-hq/sdk';
interface Props {
work: Work;
onSave?: (work: Work) => void;
}
let { work, onSave }: Props = $props();
let isEditing = $state(false);
let isDirty = $derived(/* ... */);
async function handleSave() {
if (!isDirty) return;
await work.update(/* ... */);
onSave?.(work);
}
</script>
<!-- Clear, semantic HTML with Tailwind -->
<article class="rounded-lg border border-gray-200 p-4">
<h2 class="text-xl font-semibold">{work.title}</h2>
<button onclick={handleSave} disabled={!isDirty}>
Save Changes
</button>
</article>Database Queries
// ✓ Good: Explicit column selection, typed result
interface WorkSummary {
id: string;
title: string;
author_count: number;
}
const works = await db
.selectFrom("works")
.select(["id", "title"])
.select((eb) => [eb.fn.count("contributions.creator_id").as("author_count")])
.leftJoin("contributions", "works.id", "contributions.work_id")
.groupBy("works.id")
.execute();
// ✗ Avoid: Select all, no types
const works = await db.selectFrom("works").selectAll().execute();5. Write Good Commit Messages
Follow the Conventional Commits specification:
<type>(<scope>): <subject>
<body>
<footer>Types:
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changes (formatting, etc.)refactor: Code refactoringperf: Performance improvementstest: Adding or updating testschore: Maintenance tasksci: CI/CD changes
Examples:
# Simple feature
feat(upload): add drag-and-drop support for multiple files
# Bug fix with scope
fix(metadata): handle missing ISBN in Open Library responses
# Breaking change
feat(auth)!: migrate to WebAuthn Level 3 API
BREAKING CHANGE: Passkeys created with older versions will need to be re-registered.
# Documentation
docs(contributing): add section on commit message format
# Multiple changes (avoid if possible)
feat(works): add series support
- Add series table and relationships
- Update work creation to accept series
- Add series UI componentsCommit message guidelines:
- Use imperative mood (“add feature” not “added feature”)
- Keep subject line under 72 characters
- Capitalize subject line
- No period at the end of subject
- Separate subject from body with blank line
- Explain what and why in body, not how
6. Test Your Changes
Before pushing, run all checks locally:
# Type checking
pnpm check
# Linting
pnpm lint
# Formatting
pnpm fmt
# All tests
pnpm test
# Or run checks for specific package
cd packages/sdk
pnpm test
pnpm lint
pnpm checkPre-commit hooks will run automatically via lefthook, but it’s better to run these manually during development.
7. Push and Create Pull Request
# Push to your fork
git push origin feature/your-feature-name
# Create PR on GitHubPull Request Guidelines:
Title: Follow same format as commit messages:
feat: add book rating systemfix: prevent crash when uploading large PDFsdocs: improve metadata provider documentation
Description: Use this template:
## Description
Brief summary of what this PR does and why.
## Changes
- Bullet list of specific changes
- Be concise but clear
## Testing
How did you test this? What scenarios did you cover?
## Screenshots (if applicable)
Before/after screenshots for UI changes
## Checklist
- [ ] Tests added/updated
- [ ] Documentation updated
- [ ] No breaking changes (or documented)
- [ ] All checks pass locallyDraft PRs: Use draft PRs for work-in-progress to get early feedback.
8. Code Review Process
What to expect:
- Automated checks run - CI will run tests, linting, type checking
- Maintainer review - A maintainer will review your code within a few days
- Feedback - You may receive comments asking for changes
- Iteration - Make requested changes and push new commits
- Approval - Once approved, your PR will be merged
During review:
- Be responsive to feedback
- Don’t take criticism personally - it’s about the code, not you
- Ask questions if you don’t understand feedback
- Update PR description if scope changes
Addressing feedback:
# Make changes
git add .
git commit -m "refactor: simplify error handling per review"
# Push to same branch
git push origin feature/your-feature-name
# PR updates automaticallySquashing commits: We’ll typically squash commits when merging, so don’t worry about keeping a clean history during iteration.
Code Standards
TypeScript Configuration
All packages use strict TypeScript:
strict: truenoImplicitAny: truestrictNullChecks: truenoUnusedLocals: truenoUnusedParameters: true
ESLint Rules
Shared config from @colibri-hq/shared:
- Import ordering
- Svelte accessibility rules
- TypeScript best practices
- Unused variable detection
Prettier Formatting
- Indentation: 2 spaces (not tabs)
- Line width: 120 characters
- Single quotes for strings
- Trailing commas: ES5
- Semicolons: yes
Prettier runs automatically on commit via lefthook.
File Organization
component-name/
├── ComponentName.svelte
├── ComponentName.test.ts
├── ComponentName.stories.svelte (if UI component)
├── helper-utilities.ts
├── types.ts
└── index.ts (exports)Testing Standards
Test Coverage
We aim for:
- SDK: 80%+ coverage on core resources
- Utilities: 90%+ coverage
- Metadata providers: 70%+ coverage
- UI components: Test critical interactions
Writing Good Tests
Unit Tests (Vitest):
import { describe, it, expect } from "vitest";
describe("normalizeISBN", () => {
it("removes hyphens from ISBN-13", () => {
const result = normalizeISBN("978-0-14-028329-7");
expect(result).toBe("9780140283297");
});
it("returns null for invalid ISBNs", () => {
const result = normalizeISBN("invalid");
expect(result).toBeNull();
});
it("handles ISBN-10 format", () => {
const result = normalizeISBN("0-14-028329-4");
expect(result).toBe("0140283294");
});
});Integration Tests:
import { describe, it, expect, beforeEach } from "vitest";
import { db } from "../database";
import { Work } from "./work";
describe("Work resource", () => {
beforeEach(async () => {
await db.deleteFrom("works").execute();
});
it("creates a work with metadata", async () => {
const work = await Work.create({
title: "The Great Gatsby",
subtitle: "A Novel",
language: "en",
});
expect(work.id).toBeDefined();
expect(work.title).toBe("The Great Gatsby");
});
});E2E Tests (Playwright):
import { test, expect } from "@playwright/test";
test.describe("Book Upload", () => {
test("user can upload and edit book metadata", async ({ page }) => {
await page.goto("/");
// Upload
await page.click("text=Upload");
await page.setInputFiles("input[type=file]", "test-fixtures/book.epub");
// Wait for processing
await expect(page.locator("text=Upload complete")).toBeVisible();
// Edit metadata
await page.click("text=Edit");
await page.fill("input[name=title]", "Updated Title");
await page.click('button:has-text("Save")');
// Verify
await expect(page.locator('h1:has-text("Updated Title")')).toBeVisible();
});
});Test Best Practices
- One assertion per test when possible
- Descriptive test names that explain the scenario
- Arrange-Act-Assert pattern
- Test edge cases and error conditions
- Mock external services (APIs, storage, etc.)
- Use test fixtures for consistent data
Documentation Standards
Code Comments
/**
* Normalizes an ISBN by removing hyphens and validating format.
*
* @param isbn - ISBN string in ISBN-10 or ISBN-13 format
* @returns Normalized ISBN without hyphens, or null if invalid
*
* @example
* ```typescript
* normalizeISBN('978-0-14-028329-7') // '9780140283297'
* normalizeISBN('invalid') // null
* ```
*/
export function normalizeISBN(isbn: string): string | null {
// Implementation
}README Files
Every package should have a README with:
- Brief description
- Installation instructions
- Usage examples
- API reference (or link to docs)
User-Facing Documentation
When adding features, update relevant docs in apps/docs/content/:
- User guide for new features
- API reference for new endpoints
- Architecture docs for significant changes
Specialized Contributions
Adding a Metadata Provider
- Create file:
packages/sdk/src/metadata/providers/your-provider.ts - Implement
MetadataProviderinterface - Add tests:
your-provider.test.ts - Register provider in
index.ts - Document in
apps/docs/content/packages/sdk/metadata.md
See the metadata-expert agent in .claude/agents/ for guidance.
Adding a CLI Command
- Create file:
apps/cli/src/commands/topic/command.ts - Extend
Commandbase class - Add tests:
apps/cli/test/commands/topic/command.test.ts - Document in
apps/docs/content/cli/
See the cli-expert agent in .claude/agents/ for guidance.
Adding a UI Component
- Create component:
packages/ui/src/lib/ui/ComponentName/ - Write component:
ComponentName.svelte - Add stories:
ComponentName.stories.svelte - Export in
index.ts - Test in Storybook
See the ui-components-expert agent in .claude/agents/ for guidance.
Database Schema Changes
- Create migration:
pnpx supabase migration new feature_name - Write SQL in
supabase/migrations/ - Test locally:
pnpx supabase db reset - Generate types:
cd packages/sdk && pnpm types - Update resource classes if needed
- Document in
supabase/schemas/if adding new table
See the database-expert agent in .claude/agents/ for guidance.
Reporting Bugs
Before Submitting
- Search existing issues - Your bug may already be reported
- Update to latest version - Bug may already be fixed
- Check documentation - Ensure it’s not expected behavior
- Reproduce consistently - Can you trigger it reliably?
Bug Report Template
## Description
Clear description of what the bug is.
## Steps to Reproduce
1. Go to '...'
2. Click on '...'
3. Scroll down to '...'
4. See error
## Expected Behavior
What should happen?
## Actual Behavior
What actually happened?
## Environment
- OS: [e.g. macOS 13.0]
- Browser: [e.g. Chrome 120]
- Colibri version: [e.g. 0.3.0]
- Node.js version: [e.g. 18.17.0]
## Additional Context
- Screenshots
- Error logs
- Related issuesRequesting Features
Before Requesting
- Search existing requests - May already be requested
- Check roadmap - May already be planned
- Consider scope - Does it fit Colibri’s goals?
Feature Request Template
## Problem
What problem does this solve?
## Proposed Solution
How would you solve it?
## Alternatives Considered
What other approaches did you consider?
## Use Case
Who would use this? When? Why?
## Implementation Notes
Any technical considerations?Community
Communication Channels
- GitHub Issues: Bug reports, feature requests
- GitHub Discussions: Questions, ideas, general discussion
- Pull Requests: Code review, implementation discussion
Getting Help
For contributors:
- Read Development Setup
- Check Architecture Guide
- Reference specialized agents in
.claude/agents/ - Ask in GitHub Discussions
For users:
- Check User Guide
- See Troubleshooting
- Search GitHub Issues
- Ask in GitHub Discussions
Recognition
Contributors are recognized in:
- GitHub contributors graph
- Release notes
- Project README
Significant contributions may lead to:
- Maintainer status
- Decision-making involvement
- Early access to new features
License
By contributing, you agree that your contributions will be licensed under the same license as the project (GNU AGPL v3).
All contributions must be your original work or properly attributed. Do not submit code you don’t have the right to license.
Questions?
Don’t hesitate to ask questions:
- Comment on relevant issues
- Start a GitHub Discussion
- Ask in your PR
We’re here to help you contribute successfully!
Thank You!
Every contribution, no matter how small, makes Colibri better. We appreciate your time and effort in improving the project.
Happy contributing!