|
| 1 | +# LibreChat |
| 2 | + |
| 3 | +## Project Overview |
| 4 | + |
| 5 | +LibreChat is a monorepo with the following key workspaces: |
| 6 | + |
| 7 | +| Workspace | Language | Side | Dependency | Purpose | |
| 8 | +|---|---|---|---|---| |
| 9 | +| `/api` | JS (legacy) | Backend | `packages/api`, `packages/data-schemas`, `packages/data-provider`, `@librechat/agents` | Express server β minimize changes here | |
| 10 | +| `/packages/api` | **TypeScript** | Backend | `packages/data-schemas`, `packages/data-provider` | New backend code lives here (TS only, consumed by `/api`) | |
| 11 | +| `/packages/data-schemas` | TypeScript | Backend | `packages/data-provider` | Database models/schemas, shareable across backend projects | |
| 12 | +| `/packages/data-provider` | TypeScript | Shared | β | Shared API types, endpoints, data-service β used by both frontend and backend | |
| 13 | +| `/client` | TypeScript/React | Frontend | `packages/data-provider`, `packages/client` | Frontend SPA | |
| 14 | +| `/packages/client` | TypeScript | Frontend | `packages/data-provider` | Shared frontend utilities | |
| 15 | + |
| 16 | +The source code for `@librechat/agents` (major backend dependency, same team) is at `/home/danny/agentus`. |
| 17 | + |
| 18 | +--- |
| 19 | + |
| 20 | +## Workspace Boundaries |
| 21 | + |
| 22 | +- **All new backend code must be TypeScript** in `/packages/api`. |
| 23 | +- Keep `/api` changes to the absolute minimum (thin JS wrappers calling into `/packages/api`). |
| 24 | +- Database-specific shared logic goes in `/packages/data-schemas`. |
| 25 | +- Frontend/backend shared API logic (endpoints, types, data-service) goes in `/packages/data-provider`. |
| 26 | +- Build data-provider from project root: `npm run build:data-provider`. |
| 27 | + |
| 28 | +--- |
| 29 | + |
| 30 | +## Code Style |
| 31 | + |
| 32 | +### Structure and Clarity |
| 33 | + |
| 34 | +- **Never-nesting**: early returns, flat code, minimal indentation. Break complex operations into well-named helpers. |
| 35 | +- **Functional first**: pure functions, immutable data, `map`/`filter`/`reduce` over imperative loops. Only reach for OOP when it clearly improves domain modeling or state encapsulation. |
| 36 | +- **No dynamic imports** unless absolutely necessary. |
| 37 | + |
| 38 | +### DRY |
| 39 | + |
| 40 | +- Extract repeated logic into utility functions. |
| 41 | +- Reusable hooks / higher-order components for UI patterns. |
| 42 | +- Parameterized helpers instead of near-duplicate functions. |
| 43 | +- Constants for repeated values; configuration objects over duplicated init code. |
| 44 | +- Shared validators, centralized error handling, single source of truth for business rules. |
| 45 | +- Shared typing system with interfaces/types extending common base definitions. |
| 46 | +- Abstraction layers for external API interactions. |
| 47 | + |
| 48 | +### Iteration and Performance |
| 49 | + |
| 50 | +- **Minimize looping** β especially over shared data structures like message arrays, which are iterated frequently throughout the codebase. Every additional pass adds up at scale. |
| 51 | +- Consolidate sequential O(n) operations into a single pass whenever possible; never loop over the same collection twice if the work can be combined. |
| 52 | +- Choose data structures that reduce the need to iterate (e.g., `Map`/`Set` for lookups instead of `Array.find`/`Array.includes`). |
| 53 | +- Avoid unnecessary object creation; consider space-time tradeoffs. |
| 54 | +- Prevent memory leaks: careful with closures, dispose resources/event listeners, no circular references. |
| 55 | + |
| 56 | +### Type Safety |
| 57 | + |
| 58 | +- **Never use `any`**. Explicit types for all parameters, return values, and variables. |
| 59 | +- **Limit `unknown`** β avoid `unknown`, `Record<string, unknown>`, and `as unknown as T` assertions. A `Record<string, unknown>` almost always signals a missing explicit type definition. |
| 60 | +- **Don't duplicate types** β before defining a new type, check whether it already exists in the project (especially `packages/data-provider`). Reuse and extend existing types rather than creating redundant definitions. |
| 61 | +- Use union types, generics, and interfaces appropriately. |
| 62 | +- All TypeScript and ESLint warnings/errors must be addressed β do not leave unresolved diagnostics. |
| 63 | + |
| 64 | +### Comments and Documentation |
| 65 | + |
| 66 | +- Write self-documenting code; no inline comments narrating what code does. |
| 67 | +- JSDoc only for complex/non-obvious logic or intellisense on public APIs. |
| 68 | +- Single-line JSDoc for brief docs, multi-line for complex cases. |
| 69 | +- Avoid standalone `//` comments unless absolutely necessary. |
| 70 | + |
| 71 | +### Import Order |
| 72 | + |
| 73 | +Imports are organized into three sections: |
| 74 | + |
| 75 | +1. **Package imports** β sorted shortest to longest line length (`react` always first). |
| 76 | +2. **`import type` imports** β sorted longest to shortest (package types first, then local types; length resets between sub-groups). |
| 77 | +3. **Local/project imports** β sorted longest to shortest. |
| 78 | + |
| 79 | +Multi-line imports count total character length across all lines. Consolidate value imports from the same module. Always use standalone `import type { ... }` β never inline `type` inside value imports. |
| 80 | + |
| 81 | +### JS/TS Loop Preferences |
| 82 | + |
| 83 | +- **Limit looping as much as possible.** Prefer single-pass transformations and avoid re-iterating the same data. |
| 84 | +- `for (let i = 0; ...)` for performance-critical or index-dependent operations. |
| 85 | +- `for...of` for simple array iteration. |
| 86 | +- `for...in` only for object property enumeration. |
| 87 | + |
| 88 | +--- |
| 89 | + |
| 90 | +## Frontend Rules (`client/src/**/*`) |
| 91 | + |
| 92 | +### Localization |
| 93 | + |
| 94 | +- All user-facing text must use `useLocalize()`. |
| 95 | +- Only update English keys in `client/src/locales/en/translation.json` (other languages are automated externally). |
| 96 | +- Semantic key prefixes: `com_ui_`, `com_assistants_`, etc. |
| 97 | + |
| 98 | +### Components |
| 99 | + |
| 100 | +- TypeScript for all React components with proper type imports. |
| 101 | +- Semantic HTML with ARIA labels (`role`, `aria-label`) for accessibility. |
| 102 | +- Group related components in feature directories (e.g., `SidePanel/Memories/`). |
| 103 | +- Use index files for clean exports. |
| 104 | + |
| 105 | +### Data Management |
| 106 | + |
| 107 | +- Feature hooks: `client/src/data-provider/[Feature]/queries.ts` β `[Feature]/index.ts` β `client/src/data-provider/index.ts`. |
| 108 | +- React Query (`@tanstack/react-query`) for all API interactions; proper query invalidation on mutations. |
| 109 | +- QueryKeys and MutationKeys in `packages/data-provider/src/keys.ts`. |
| 110 | + |
| 111 | +### Data-Provider Integration |
| 112 | + |
| 113 | +- Endpoints: `packages/data-provider/src/api-endpoints.ts` |
| 114 | +- Data service: `packages/data-provider/src/data-service.ts` |
| 115 | +- Types: `packages/data-provider/src/types/queries.ts` |
| 116 | +- Use `encodeURIComponent` for dynamic URL parameters. |
| 117 | + |
| 118 | +### Performance |
| 119 | + |
| 120 | +- Prioritize memory and speed efficiency at scale. |
| 121 | +- Cursor pagination for large datasets. |
| 122 | +- Proper dependency arrays to avoid unnecessary re-renders. |
| 123 | +- Leverage React Query caching and background refetching. |
| 124 | + |
| 125 | +--- |
| 126 | + |
| 127 | +## Development Commands |
| 128 | + |
| 129 | +| Command | Purpose | |
| 130 | +|---|---| |
| 131 | +| `npm run smart-reinstall` | Install deps (if lockfile changed) + build via Turborepo | |
| 132 | +| `npm run reinstall` | Clean install β wipe `node_modules` and reinstall from scratch | |
| 133 | +| `npm run backend` | Start the backend server | |
| 134 | +| `npm run backend:dev` | Start backend with file watching (development) | |
| 135 | +| `npm run build` | Build all compiled code via Turborepo (parallel, cached) | |
| 136 | +| `npm run frontend` | Build all compiled code sequentially (legacy fallback) | |
| 137 | +| `npm run frontend:dev` | Start frontend dev server with HMR (port 3090, requires backend running) | |
| 138 | +| `npm run build:data-provider` | Rebuild `packages/data-provider` after changes | |
| 139 | + |
| 140 | +- Node.js: v20.19.0+ or ^22.12.0 or >= 23.0.0 |
| 141 | +- Database: MongoDB |
| 142 | +- Backend runs on `http://localhost:3080/`; frontend dev server on `http://localhost:3090/` |
| 143 | + |
| 144 | +--- |
| 145 | + |
| 146 | +## Testing |
| 147 | + |
| 148 | +- Framework: **Jest**, run per-workspace. |
| 149 | +- Run tests from their workspace directory: `cd api && npx jest <pattern>`, `cd packages/api && npx jest <pattern>`, etc. |
| 150 | +- Frontend tests: `__tests__` directories alongside components; use `test/layout-test-utils` for rendering. |
| 151 | +- Cover loading, success, and error states for UI/data flows. |
| 152 | +- Mock data-provider hooks and external dependencies. |
| 153 | + |
| 154 | +--- |
| 155 | + |
| 156 | +## Formatting |
| 157 | + |
| 158 | +Fix all formatting lint errors (trailing spaces, tabs, newlines, indentation) using auto-fix when available. All TypeScript/ESLint warnings and errors **must** be resolved. |
0 commit comments