Skip to content

Commit c3da148

Browse files
authored
πŸ“ docs: Add AGENTS.md for Project Structure and Coding Standards (#11866)
* πŸ“ docs: Add AGENTS.md for project structure and coding standards - Introduced AGENTS.md to outline project workspaces, coding standards, and development commands. - Defined workspace boundaries for backend and frontend development, emphasizing TypeScript usage. - Established guidelines for code style, iteration performance, type safety, and import order. - Updated CONTRIBUTING.md to reference AGENTS.md for coding standards and project conventions. - Modified package.json to streamline build commands, consolidating frontend and backend build processes. * chore: Update build commands and improve smart reinstall process - Modified AGENTS.md to clarify the purpose of `npm run smart-reinstall` and other build commands, emphasizing Turborepo's role in dependency management and builds. - Updated package.json to streamline build commands, replacing the legacy frontend build with a Turborepo-based approach for improved performance. - Enhanced the smart reinstall script to fully delegate build processes to Turborepo, including cache management and dependency checks, ensuring a more efficient build workflow.
1 parent 9eeec6b commit c3da148

File tree

4 files changed

+221
-125
lines changed

4 files changed

+221
-125
lines changed

β€Ž.github/CONTRIBUTING.mdβ€Ž

Lines changed: 40 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,14 @@ Project maintainers have the right and responsibility to remove, edit, or reject
2626

2727
## 1. Development Setup
2828

29-
1. Use Node.JS 20.x.
30-
2. Install typescript globally: `npm i -g typescript`.
31-
3. Run `npm ci` to install dependencies.
32-
4. Build the data provider: `npm run build:data-provider`.
33-
5. Build data schemas: `npm run build:data-schemas`.
34-
6. Build API methods: `npm run build:api`.
35-
7. Setup and run unit tests:
29+
1. Use Node.js v20.19.0+ or ^22.12.0 or >= 23.0.0.
30+
2. Run `npm run smart-reinstall` to install dependencies (uses Turborepo). Use `npm run reinstall` for a clean install, or `npm ci` for a fresh lockfile-based install.
31+
3. Build all compiled code: `npm run build`.
32+
4. Setup and run unit tests:
3633
- Copy `.env.test`: `cp api/test/.env.test.example api/test/.env.test`.
3734
- Run backend unit tests: `npm run test:api`.
3835
- Run frontend unit tests: `npm run test:client`.
39-
8. Setup and run integration tests:
40-
- Build client: `cd client && npm run build`.
36+
5. Setup and run integration tests:
4137
- Create `.env`: `cp .env.example .env`.
4238
- Install [MongoDB Community Edition](https://www.mongodb.com/docs/manual/administration/install-community/), ensure that `mongosh` connects to your local instance.
4339
- Run: `npx install playwright`, then `npx playwright install`.
@@ -48,11 +44,11 @@ Project maintainers have the right and responsibility to remove, edit, or reject
4844
## 2. Development Notes
4945

5046
1. Before starting work, make sure your main branch has the latest commits with `npm run update`.
51-
3. Run linting command to find errors: `npm run lint`. Alternatively, ensure husky pre-commit checks are functioning.
47+
2. Run linting command to find errors: `npm run lint`. Alternatively, ensure husky pre-commit checks are functioning.
5248
3. After your changes, reinstall packages in your current branch using `npm run reinstall` and ensure everything still works.
5349
- Restart the ESLint server ("ESLint: Restart ESLint Server" in VS Code command bar) and your IDE after reinstalling or updating.
5450
4. Clear web app localStorage and cookies before and after changes.
55-
5. For frontend changes, compile typescript before and after changes to check for introduced errors: `cd client && npm run build`.
51+
5. To check for introduced errors, build all compiled code: `npm run build`.
5652
6. Run backend unit tests: `npm run test:api`.
5753
7. Run frontend unit tests: `npm run test:client`.
5854
8. Run integration tests: `npm run e2e`.
@@ -118,50 +114,45 @@ Apply the following naming conventions to branches, labels, and other Git-relate
118114
- **JS/TS:** Directories and file names: Descriptive and camelCase. First letter uppercased for React files (e.g., `helperFunction.ts, ReactComponent.tsx`).
119115
- **Docs:** Directories and file names: Descriptive and snake_case (e.g., `config_files.md`).
120116

121-
## 7. TypeScript Conversion
117+
## 7. Coding Standards
118+
119+
For detailed coding conventions, workspace boundaries, and architecture guidance, refer to the [`AGENTS.md`](../AGENTS.md) file at the project root. It covers code style, type safety, import ordering, iteration/performance expectations, frontend rules, testing, and development commands.
120+
121+
## 8. TypeScript Conversion
122122

123123
1. **Original State**: The project was initially developed entirely in JavaScript (JS).
124124

125-
2. **Frontend Transition**:
126-
- We are in the process of transitioning the frontend from JS to TypeScript (TS).
127-
- The transition is nearing completion.
128-
- This conversion is feasible due to React's capability to intermix JS and TS prior to code compilation. It's standard practice to compile/bundle the code in such scenarios.
129-
130-
3. **Backend Considerations**:
131-
- Transitioning the backend to TypeScript would be a more intricate process, especially for an established Express.js server.
132-
133-
- **Options for Transition**:
134-
- **Single Phase Overhaul**: This involves converting the entire backend to TypeScript in one go. It's the most straightforward approach but can be disruptive, especially for larger codebases.
135-
136-
- **Incremental Transition**: Convert parts of the backend progressively. This can be done by:
137-
- Maintaining a separate directory for TypeScript files.
138-
- Gradually migrating and testing individual modules or routes.
139-
- Using a build tool like `tsc` to compile TypeScript files independently until the entire transition is complete.
140-
141-
- **Compilation Considerations**:
142-
- Introducing a compilation step for the server is an option. This would involve using tools like `ts-node` for development and `tsc` for production builds.
143-
- However, this is not a conventional approach for Express.js servers and could introduce added complexity, especially in terms of build and deployment processes.
144-
145-
- **Current Stance**: At present, this backend transition is of lower priority and might not be pursued.
146-
147-
## 8. Module Import Conventions
148-
149-
- `npm` packages first,
150-
- from longest line (top) to shortest (bottom)
151-
152-
- Followed by typescript types (pertains to data-provider and client workspaces)
153-
- longest line (top) to shortest (bottom)
154-
- types from package come first
155-
156-
- Lastly, local imports
157-
- longest line (top) to shortest (bottom)
158-
- imports with alias `~` treated the same as relative import with respect to line length
125+
2. **Frontend**: Fully transitioned to TypeScript.
159126

160-
**Note:** ESLint will automatically enforce these import conventions when you run `npm run lint --fix` or through pre-commit hooks.
127+
3. **Backend**:
128+
- The legacy Express.js server remains in `/api` as JavaScript.
129+
- All new backend code is written in TypeScript under `/packages/api`, which is compiled and consumed by `/api`.
130+
- Shared database logic lives in `/packages/data-schemas` (TypeScript).
131+
- Shared frontend/backend API types and services live in `/packages/data-provider` (TypeScript).
132+
- Minimize direct changes to `/api`; prefer adding TypeScript code to `/packages/api` and importing it.
161133

162-
---
134+
## 9. Module Import Conventions
135+
136+
Imports are organized into three sections (in order):
137+
138+
1. **Package imports** β€” sorted from shortest to longest line length.
139+
- `react` is always the first import.
140+
- Multi-line (stacked) imports count their total character length across all lines for sorting.
141+
142+
2. **`import type` imports** β€” sorted from longest to shortest line length.
143+
- Package type imports come first, then local type imports.
144+
- Line length sorting resets between the package and local sub-groups.
145+
146+
3. **Local/project imports** β€” sorted from longest to shortest line length.
147+
- Multi-line (stacked) imports count their total character length across all lines for sorting.
148+
- Imports with alias `~` are treated the same as relative imports with respect to line length.
149+
150+
- Consolidate value imports from the same module as much as possible.
151+
- Always use standalone `import type { ... }` for type imports; never use inline `type` keyword inside value imports (e.g., `import { Foo, type Bar }` is wrong).
152+
153+
**Note:** ESLint will automatically enforce these import conventions when you run `npm run lint --fix` or through pre-commit hooks.
163154

164-
Please ensure that you adapt this summary to fit the specific context and nuances of your project.
155+
For the full set of coding standards, see [`AGENTS.md`](../AGENTS.md).
165156

166157
---
167158

β€ŽAGENTS.mdβ€Ž

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
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

Comments
Β (0)