How to Contribute to the Lobe Chat Project: A Complete Developer Guide

Fork the repository, clone it locally, run pnpm install to set up the monorepo, create a feature branch, follow the Zustand slice pattern for state management, and submit a PR against the canary branch after running pnpm lint and bunx vitest run.

Contributing to the Lobe Chat project (also known as LobeHub) involves working with a modern AI-agent workspace built on Next.js 16, React 19, and TypeScript. Whether you want to fix bugs, add features, or improve documentation, understanding the monorepo structure and contribution workflow is essential for getting your pull request merged into the lobehub/lobe-chat repository.

Understanding the Lobe Chat Architecture

LobeChat uses a monorepo structure managed by pnpm workspaces. The stack is organized into distinct layers:

Layer Technology Primary Location
Frontend Next.js 16 / React 19 / TypeScript src/app/*, src/routes/*
UI Components Ant Design, @lobehub/ui src/components/*
State Management Zustand, SWR src/store/*
Backend / DB PostgreSQL, PGLite, Drizzle ORM packages/database/*
Desktop Electron src/store/electron/*

Core Architectural Patterns

The repository follows specific patterns for organizing code:

  • App entry & routing: src/app/** and src/routes/** contain Next.js App Router definitions, including page-level routes like the share page at src/routes/share/t/[id]/index.tsx.

  • State slices: src/store/*/slices/* isolates each feature (video generation, evaluation, user memory) into composable Zustand slices.

  • Electron integration: src/store/electron/** bridges the web UI with desktop runtime via IPC, hotkeys, and desktop state management.

  • Server-side utilities: src/utils/server/** provides helpers for parsing model lists and routing variants used by the Next.js API layer.

Setting Up Your Development Environment

Before contributing to the Lobe Chat project, ensure you have the prerequisites installed:

  • Node.js ≥ 18
  • pnpm (package manager)
  • git

Initial Setup Steps

  1. Fork the repository on GitHub to create your personal copy.

  2. Clone your fork locally:

    git clone https://github.com/<YOUR_USERNAME>/lobe-chat.git
    cd lobe-chat
  3. Install dependencies using pnpm workspaces:

    pnpm install

The Contribution Workflow

Follow this canonical process when contributing to Lobe Chat:

1. Create a Feature Branch

git checkout -b feature/your-feature-name

2. Develop and Lint

The codebase follows strict ESLint and Prettier rules. Run the linter to catch style issues early:

pnpm lint

When adding features involving state management, follow the existing Zustand slice pattern. For example, adding a new feature would involve editing src/store/<feature>/slices/* and updating the combined reducer in src/store/<feature>/index.ts.

3. Write Tests

New logic should include unit tests under src/**/*.test.*. Run the test suite:

bunx vitest run

4. Commit Changes

Use clear, conventional commit messages. The project encourages gitmoji for visual clarity:

git add .
git commit -m "✨ feat: add X support"

5. Sync with Upstream

Keep your branch up-to-date with the main canary branch:

git remote add upstream https://github.com/lobehub/lobe-chat.git
git fetch upstream
git merge upstream/canary

6. Submit a Pull Request

Push your branch and open a PR:

git push origin feature/your-feature-name

Navigate to the repository on GitHub and click Compare & pull request. Fill out the PR template located at .github/PULL_REQUEST_TEMPLATE.md and submit for review.

Practical Example: Adding a Zustand Slice

Suppose you want to introduce a bookmark feature that stores user-saved messages. This example demonstrates the architectural pattern used throughout the Lobe Chat project.

Step 1: Create the Slice File

Create src/store/bookmark/slices/items.ts:

// src/store/bookmark/slices/items.ts
import { createSlice } from 'zustand';
import type { BookmarkItem } from '@/types';

export const initialState: BookmarkItem[] = [];

export const bookmarkSlice = createSlice((set, get) => ({
  items: initialState,
  add: (item: BookmarkItem) =>
    set(state => ({ items: [...state.items, item] })),
  remove: (id: string) =>
    set(state => ({ items: state.items.filter(i => i.id !== id) })),
}));

Step 2: Expose the Slice in the Store Index

Update src/store/bookmark/index.ts:

// src/store/bookmark/index.ts
import { create } from 'zustand';
import { bookmarkSlice } from './slices/items';

export const useBookmarkStore = create(bookmarkSlice);

Step 3: Consume in a Component

Create src/features/bookmark/BookmarkList.tsx:

import { useBookmarkStore } from '@/store/bookmark';

export const BookmarkList = () => {
  const items = useBookmarkStore(state => state.items);
  const remove = useBookmarkStore(state => state.remove);

  return (
    <ul>
      {items.map(item => (
        <li key={item.id}>
          {item.title}
          <button onClick={() => remove(item.id)}>✕</button>
        </li>
      ))}
    </ul>
  );
};

Step 4: Add Unit Tests

Create src/store/bookmark/slices/items.test.ts:

import { bookmarkSlice, initialState } from './items';

test('adds a bookmark', () => {
  const set = jest.fn();
  const get = jest.fn();
  const api = bookmarkSlice(set, get);
  api.add({ id: '1', title: 'Demo' });

  expect(set).toHaveBeenCalledWith({
    items: [{ id: '1', title: 'Demo' }],
  });
});

Step 5: Validate Your Changes

Run the quality checks before committing:

pnpm lint && bunx vitest run

This pattern mirrors existing slice implementations such as src/store/video/slices/*, ensuring architectural consistency across the Lobe Chat project.

Key Files Every Contributor Should Know

Understanding these critical paths will help you navigate the Lobe Chat codebase effectively:

Path Purpose GitHub Link
README.md High-level project description, features, deployment guides README.md
CONTRIBUTING.md Detailed contribution workflow, coding style, PR process CONTRIBUTING.md
pnpm-workspace.yaml Workspace configuration for the monorepo pnpm-workspace.yaml
src/app/** Next.js app router entry points (global layout, CSS, providers) src/app
src/routes/** Page-level route components (e.g., share, chat, settings) src/routes
src/store/** Zustand stores – the single source of truth for UI state src/store
src/utils/server/** Server-side helpers for model parsing and routing src/utils/server
src/styles/** Global styling and Ant Design overrides src/styles
src/store/electron/** Electron desktop integration (IPC, hotkeys) src/store/electron
tests/** Vitest unit-test suites tests

Summary

Contributing to the Lobe Chat project requires understanding its monorepo architecture and established workflows:

  • Architecture: The project uses Next.js 16 with React 19, TypeScript, and Zustand for state management in a pnpm workspace monorepo structure.

  • Setup: Fork the repository, clone locally, and run pnpm install to initialize the workspace dependencies.

  • Development: Create feature branches from canary, follow the slice pattern in src/store/*/slices/* for state management, and adhere to ESLint/Prettier rules via pnpm lint.

  • Testing: Write unit tests in src/**/*.test.* files and validate with bunx vitest run before submitting.

  • Submission: Sync with upstream canary branch, push to your fork, and open a PR using the template in .github/PULL_REQUEST_TEMPLATE.md.

Frequently Asked Questions

What branch should I target when contributing to Lobe Chat?

Always target the canary branch when opening pull requests. The canary branch serves as the main integration branch where features are tested before reaching stable releases. Sync your fork regularly with git fetch upstream and git merge upstream/canary to avoid merge conflicts.

How do I add new state management features to the codebase?

Follow the Zustand slice pattern established in the project. Create your logic in src/store/<feature>/slices/*.ts, then combine it in src/store/<feature>/index.ts using create(). This modular approach keeps the global store composable and matches existing implementations like src/store/video/slices/*.

What testing framework does Lobe Chat use?

The project uses Vitest for unit testing. Write tests in files matching src/**/*.test.* or in the tests/ directory. Run the full suite with bunx vitest run before committing. New logic should include corresponding unit tests to maintain code quality and prevent regressions.

Where can I find the official contribution guidelines?

The comprehensive contribution guide lives in CONTRIBUTING.md at the repository root. This document contains detailed information about coding standards, commit message conventions (gitmoji is encouraged), the PR template location at .github/PULL_REQUEST_TEMPLATE.md, and specific instructions for setting up the development environment.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →