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/**andsrc/routes/**contain Next.js App Router definitions, including page-level routes like the share page atsrc/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
-
Fork the repository on GitHub to create your personal copy.
-
Clone your fork locally:
git clone https://github.com/<YOUR_USERNAME>/lobe-chat.git cd lobe-chat -
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 installto initialize the workspace dependencies. -
Development: Create feature branches from
canary, follow the slice pattern insrc/store/*/slices/*for state management, and adhere to ESLint/Prettier rules viapnpm lint. -
Testing: Write unit tests in
src/**/*.test.*files and validate withbunx vitest runbefore submitting. -
Submission: Sync with upstream
canarybranch, 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →