Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.osschat.dev/llms.txt

Use this file to discover all available pages before exploring further.

Contributing to OpenChat

Thanks for your interest in contributing to OpenChat! This guide will help you get started.

Before You Start

1

Install Prerequisites

  • Bun 1.3+ - Package manager and runtime
  • Node.js 20+ - Required for some tooling
  • Git - Version control
  • Docker (optional) - For container-based development
2

Read the Codebase

Familiarize yourself with:
3

Set Up Development Environment

Follow the Quickstart to get OpenChat running locally.

Development Workflow

1. Create a Branch

# Sync with main
git checkout main
git pull --rebase origin main

# Create feature branch
git checkout -b feat/your-feature-name
Branch naming conventions:
  • feat/ - New features
  • fix/ - Bug fixes
  • docs/ - Documentation changes
  • refactor/ - Code refactoring
  • chore/ - Maintenance tasks

2. Make Changes

Follow our coding standards:
ConventionExample
IndentationTabs
File nameskebab-case (sign-in.tsx)
Componentsapps/web/src/components/
Type importsimport type { Foo } from "..."

3. Verify Your Changes

Run these before pushing:
# Lint
bun check

# Type check
bun check-types

# Run tests
bun test

# Build (for build-critical changes)
bun build

4. Commit with Conventional Commits

Use Conventional Commits format:
# Feature
git commit -m "feat(web): add workspace picker"

# Bug fix
git commit -m "fix(server): prevent duplicate chat titles"

# Documentation
git commit -m "docs: update deployment guide"

# Chore
git commit -m "chore: update dependencies"
Scopes: web, server, docs, extension, or omit for cross-cutting changes.

5. Open a Pull Request

Include in your PR:
  • Summary - What changed and why
  • Scope - Which apps affected (web/server/both)
  • Testing notes - How to verify the change
  • Screenshots/GIFs - For UI changes
Link related issues with Fixes #123 or Closes #123 to auto-close them on merge.

Coding Standards

TypeScript

// ✅ Good: Type-only import
import type { User } from "@/lib/types";

// ✅ Good: Named exports
export function useAuth() { ... }
export const AUTH_COOKIE = "ba_session";

// ❌ Avoid: Default exports (except for pages)
export default function Component() { ... }

React Components

// ✅ Good: Clear, focused component
function ChatMessage({ message }: { message: Message }) {
  return (
    <div className="p-4">
      <span>{message.content}</span>
    </div>
  );
}

// ✅ Good: Use cn() for conditional classes
import { cn } from "@/lib/utils";

<div className={cn(
  "base-class",
  isActive && "active-class"
)} />

Convex Functions

// ✅ Good: Use new syntax
export const myQuery = query({
  args: { id: v.id("users") },
  handler: async (ctx, args) => {
    return ctx.db.get(args.id);
  },
});

// ✅ Good: Rate limit mutations
export const myMutation = mutation({
  args: { ... },
  handler: async (ctx, args) => {
    const { ok, retryAfter } = await rateLimiter.limit(ctx, "myMutation", {
      key: args.userId,
    });
    if (!ok) throwRateLimitError("action", retryAfter);
    
    // ... rest of handler
  },
});

Testing

Running Tests

# All tests
bun test

# Specific workspace
bun test:web
bun test:server

# Watch mode
bun test:watch

# With coverage
bun test -- --coverage

Writing Tests

Colocate tests with source files:
src/
  lib/
    utils.ts
    utils.test.ts
  components/
    Button.tsx
    Button.test.tsx
Example test:
// utils.test.ts
import { describe, it, expect } from "vitest";
import { formatDate } from "./utils";

describe("formatDate", () => {
  it("formats date correctly", () => {
    const date = new Date("2024-01-15");
    expect(formatDate(date)).toBe("January 15, 2024");
  });
});

Convex Tests

Use convex-test for Convex function tests:
// chats.test.ts
import { describe, it, expect, beforeEach } from "vitest";
import { convexTest } from "convex-test";
import { api } from "./_generated/api";

describe("chats", () => {
  it("creates a chat", async () => {
    const t = convexTest(schema);
    
    // Insert test user
    const userId = await t.run(async (ctx) => {
      return ctx.db.insert("users", { ... });
    });
    
    // Test the mutation
    const chatId = await t.mutation(api.chats.create, {
      userId,
      title: "Test Chat",
    });
    
    expect(chatId).toBeDefined();
  });
});

Documentation

Update docs when:
  • Adding user-facing features
  • Changing configuration options
  • Modifying API behavior
  • Updating deployment steps

Docs Structure

docs-site/           # Mintlify documentation
├── index.mdx        # Introduction
├── quickstart.mdx   # Getting started
├── guides/          # In-depth guides
│   ├── architecture.mdx
│   ├── authentication.mdx
│   └── ...
└── self-hosting/    # Deployment docs
    ├── docker.mdx
    └── environment.mdx

Local Docs Preview

cd docs-site
bunx @mintlify/cli dev
# Open http://localhost:3000

Pull Request Review

What We Look For

  • Code follows project conventions
  • Tests added/updated for changes
  • Documentation updated if needed
  • No breaking changes (or clearly documented)
  • Commits are clean and well-described
  • CI checks pass

Automated Checks

PRs trigger:
  • Lint - oxlint
  • Type check - TypeScript
  • Tests - Vitest
  • Build - Production build verification
  • CodeQL - Security scanning

Getting Reviews

  1. Self-review first - Check your own PR before requesting review
  2. Respond to feedback - Address comments or explain why you disagree
  3. Keep it small - Smaller PRs get faster, better reviews

Common Tasks

Adding a New Page

  1. Create route file in apps/web/src/routes/
  2. Use auth guard pattern if needed
  3. Add navigation link to sidebar
// apps/web/src/routes/new-page.tsx
import { createFileRoute } from "@tanstack/react-router";
import { useAuth } from "@/lib/auth-client";

export const Route = createFileRoute("/new-page")({
  component: NewPage,
});

function NewPage() {
  const { isAuthenticated, loading } = useAuth();
  
  if (loading) return <Loading />;
  if (!isAuthenticated) return <SignInPrompt />;
  
  return <div>Your content here</div>;
}

Adding a Convex Function

  1. Add to appropriate file in apps/server/convex/
  2. Update schema if adding new table
  3. Run bun x convex codegen to update types
// apps/server/convex/example.ts
import { query, mutation } from "./_generated/server";
import { v } from "convex/values";

export const myQuery = query({
  args: { id: v.id("users") },
  handler: async (ctx, args) => {
    return ctx.db.get(args.id);
  },
});

Adding UI Components

  1. Use shadcn/ui primitives when possible
  2. Add to apps/web/src/components/
  3. Follow existing patterns in the codebase
# Add shadcn component
cd apps/web
bunx shadcn@latest add button

Getting Help

GitHub Discussions

Ask questions and share ideas

GitHub Issues

Report bugs or check existing issues

Code of Conduct

We follow the Contributor Covenant. Be respectful, inclusive, and constructive. For security issues, please email the maintainers directly rather than opening a public issue.
Thank you for contributing to OpenChat! Every contribution helps make the project better.