Files

139 lines
7.1 KiB
Markdown
Raw Permalink Normal View History

# LobeHub Development Guidelines
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
Guidelines for using AI coding agents in this LobeHub repository.
2025-12-02 19:05:08 +08:00
2025-08-29 15:52:02 +08:00
## Tech Stack
2026-04-26 00:25:00 +08:00
- Next.js 16 + React 19 + TypeScript
- SPA inside Next.js with `react-router-dom`
- `@lobehub/ui`, antd for components; antd-style for CSS-in-JS — **prefer `createStaticStyles` with `cssVar.*`** (zero-runtime); only fall back to `createStyles` + `token` when styles genuinely need runtime computation. See `.cursor/docs/createStaticStyles_migration_guide.md`.
- **Component priority**: `@lobehub/ui/base-ui` (headless primitives) **first**, then `@lobehub/ui` root, then antd as last resort. When the component exists in base-ui, use it — never reach for the root or antd counterpart. Base-ui covers `Select`, `Modal` / `createModal` / `confirmModal`, `DropdownMenu`, `ContextMenu`, `Popover`, `ScrollArea`, `Switch`, `Toast`, `FloatingSheet`. Prefer `@lobehub/ui/base-ui` for new code and migrate root-package call sites opportunistically.
2026-04-26 00:25:00 +08:00
- react-i18next for i18n; zustand for state management
- SWR for data fetching; TRPC for type-safe backend
- Drizzle ORM with PostgreSQL; Vitest for testing
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
## Project Structure
2025-08-29 15:52:02 +08:00
```plaintext
2026-03-14 22:06:09 +08:00
lobehub/
2026-04-26 00:25:00 +08:00
├── apps/
│ ├── desktop/ # Electron desktop app
│ ├── cli/ # LobeHub CLI
│ └── server/ # Server service
├── packages/ # Shared packages (@lobechat/*)
│ ├── database/ # Database schemas, models, repositories
│ ├── agent-runtime/ # Agent runtime
│ └── ...
├── src/
2026-04-26 00:25:00 +08:00
│ ├── app/ # Next.js App Router (backend API + auth)
│ │ ├── (backend)/ # API routes (trpc, webapi, etc.)
│ │ ├── spa/ # SPA HTML template service
│ │ └── [variants]/(auth)/ # Auth pages (SSR required)
│ ├── routes/ # SPA page components (Vite)
│ │ ├── (main)/ # Desktop pages
│ │ ├── (mobile)/ # Mobile pages
│ │ ├── (desktop)/ # Desktop-specific pages
│ │ ├── (popup)/ # Popup window pages
│ │ ├── onboarding/ # Onboarding pages
│ │ └── share/ # Share pages
│ ├── spa/ # SPA entry points and router config
│ │ ├── entry.web.tsx # Web entry
│ │ ├── entry.mobile.tsx
│ │ ├── entry.desktop.tsx
│ │ ├── entry.popup.tsx
│ │ └── router/ # React Router configuration
│ ├── store/ # Zustand stores
│ ├── services/ # Client services
│ ├── server/ # Server services and routers
│ └── ...
└── e2e/ # E2E tests (Cucumber + Playwright)
```
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
## SPA Routes and Features
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
SPA-related code is grouped under `src/spa/` (entries + router) and `src/routes/` (page segments). We use a **roots vs features** split: route trees only hold page segments; business logic and UI live in features.
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
- **`src/spa/`** SPA entry points (`entry.web.tsx`, `entry.mobile.tsx`, `entry.desktop.tsx`, `entry.popup.tsx`) and React Router config (`router/`, with `desktopRouter.config.*`, `mobileRouter.config.tsx`, `popupRouter.config.tsx`). Keeps router config next to entries to avoid confusion with `src/routes/`.
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
- **`src/routes/` (roots)**\
Only page-segment files: `_layout/index.tsx`, `index.tsx` (or `page.tsx`), and dynamic segments like `[id]/index.tsx`. Keep these **thin**: they should only import from `@/features/*` and compose layout/page, with no business logic or heavy UI.
- **`src/features/`**\
Business components by **domain** (e.g. `Pages`, `PageEditor`, `Home`). Put layout chunks (sidebar, header, body), hooks, and domain-specific UI here. Each feature exposes an `index.ts` (or `index.tsx`) with clear exports.
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
When adding or changing SPA routes:
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
1. In `src/routes/`, add only the route segment files (layout + page) that delegate to features.
2. Implement layout and page content under `src/features/<Domain>/` and export from there.
3. In route files, use `import { X } from '@/features/<Domain>'` (or `import Y from '@/features/<Domain>/...'`). Do not add new `features/` folders inside `src/routes/`.
4. **Register the desktop route tree in both configs:** `src/spa/router/desktopRouter.config.tsx` and `src/spa/router/desktopRouter.config.desktop.tsx` must stay in sync (same paths and nesting). Updating only one can cause **blank screens** if the other build path expects the route. `desktopRouter.sync.test.tsx` guards this invariant — keep it passing.
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
See the **spa-routes** skill (`.agents/skills/spa-routes/SKILL.md`) for the full convention and file-division rules.
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
## Development
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
### Starting the Dev Environment
2025-08-29 15:52:02 +08:00
```bash
2026-04-26 00:25:00 +08:00
# SPA dev mode (frontend only, proxies API to localhost:3010)
bun run dev:spa
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
# Full-stack dev (Next.js + Vite SPA concurrently)
bun run dev
```
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
After `dev:spa` starts, the terminal prints a **Debug Proxy** URL:
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
```plaintext
Debug Proxy: https://app.lobehub.com/_dangerous_local_dev_proxy?debug-host=http%3A%2F%2Flocalhost%3A9876
```
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
Open this URL to develop locally against the production backend (app.lobehub.com). The proxy page loads your local Vite dev server's SPA into the online environment, enabling HMR with real server config.
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
### Git Workflow
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
- **Branch strategy**: `canary` is the development branch (cloud production); `main` is the release branch (periodically cherry-picks from canary)
- New branches should be created from `canary`; PRs should target `canary`
- Use rebase for `git pull`
- Commit messages: prefix with gitmoji
- Branch format: `<type>/<feature-name>`
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
### Package Management
2025-08-29 15:52:02 +08:00
2026-04-26 00:25:00 +08:00
- `pnpm` for dependency management
- `bun` to run npm scripts
- `bunx` for executable npm packages
2026-04-26 00:25:00 +08:00
### Testing
2026-04-26 00:25:00 +08:00
```bash
# Run specific test (NEVER run `bun run test` - takes ~10 minutes)
bunx vitest run --silent='passed-only' '[file-path]'
# Database package
cd packages/database && bunx vitest run --silent='passed-only' '[file]'
```
2026-04-26 00:25:00 +08:00
- Prefer `vi.spyOn` over `vi.mock`
### Type Checking
```bash
bun run type-check
```
2026-04-26 00:25:00 +08:00
### i18n
2026-04-26 00:25:00 +08:00
- Add keys to a namespace file under `src/locales/default/` (e.g. `agent.ts`, `auth.ts`)
- Ship en-US and zh-CN by hand in the same PR: write the English source in `src/locales/default/*.ts` and mirror it to `locales/en-US/`; hand-translate `locales/zh-CN/`. Leave all other locales to CI.
- Don't run `pnpm i18n` manually by default — a daily CI workflow (`auto-i18n.yml`) runs it and opens an automated translation PR for any missing keys.
- Run `pnpm i18n` manually only when your branch needs the translated locales immediately, instead of waiting for the daily job (slow; requires `OPENAI_API_KEY`). Note it only fills keys missing from other locales — value-only edits never need it.
2026-06-03 18:45:40 +08:00
### Code Style
- When a single file grows beyond \~800 lines, consider splitting it into multiple files (extract sub-components, hooks, helpers, or types). Smaller, focused files are friendly to humans and agents.
### Code Review
Before reviewing a PR / diff / branch change, read the **review-checklist** skill (`.agents/skills/review-checklist/SKILL.md`) — it lists the recurring mistakes specific to this codebase.