FreeLLM API Monorepo Workspace Structure: How Shared, Server, Client, and CLI Are Organized

The FreeLLM API uses a Yarn/npm-style monorepo with four workspaces—shared, server, client, and cli—where the root package.json orchestrates cross-package builds and the shared workspace exports TypeScript definitions consumed via the workspace protocol.

The tashfeenahmed/freellmapi repository implements a clean monorepo workspace structure that separates concerns across a shared library, Express server, React dashboard, and command-line interface. This architecture enables type-safe cross-package imports while maintaining independent deployment artifacts. Understanding how these four workspaces interact is essential for contributing to or deploying the FreeLLM API proxy and admin tools.

Root Package Configuration and Workspace Declaration

The monorepo workspace structure is defined in the root package.json using the standard npm workspaces field. This configuration declares four distinct packages that npm/Yarn treats as linked dependencies.

{
  "private": true,
  "workspaces": [
    "shared",
    "server",
    "client",
    "cli"
  ],
  "scripts": {
    "dev": "concurrently --kill-others-on-fail --names server,client \"npm run dev -w server\" \"npm run dev -w client\"",
    "build": "npm run build -w server && npm run build -w cli && npm run build -w client",
    "test": "npm run test -w server && npm run test -w cli && npm run test -w client --if-present"
  }
}

Each workspace maintains its own package.json and tsconfig.json, enabling independent TypeScript compilation targets while preserving type safety across package boundaries.

The Four Workspace Architecture

Shared Workspace (Common Types)

The shared workspace serves as the foundation for type safety across the monorepo. Located at shared/types.ts, it exports TypeScript interfaces and utilities that both the server and CLI consume.

// server/src/lib/config.ts
import { ProviderConfig } from "shared/types";

Using the workspace protocol, the server and CLI packages import these definitions without publishing to an external registry. This ensures that changes to core data structures propagate immediately to dependent packages during development.

Server Workspace (API Proxy)

The server workspace implements the core FreeLLM API logic as an Express application. The entry point at server/src/app.ts bootstraps the HTTP server and mounts the routing layer.

Key services within this workspace include:

  • Router service (server/src/services/router.ts) – Implements model selection logic based on health checks, rate-limit ledgers, and fallback-chain strategies.
  • Rate-limit ledger (server/src/services/ratelimit.ts) – Tracks RPM (requests per minute), RPD (requests per day), TPM (tokens per minute), and TPD (tokens per day) counters per API key using an in-memory store backed by SQLite.
  • Provider adapters (server/src/providers/) – Each file implements a common Provider interface exposing chatCompletion() and streamChatCompletion() methods for different LLM backends.
  • Health service (server/src/services/health.ts) – Periodically probes provider keys to maintain fresh availability status.

Client Workspace (Admin Dashboard)

The client workspace delivers the administrative interface built with React and Vite. The root component at client/src/App.tsx renders the dashboard that visualizes model routing decisions, key usage analytics, and system health metrics. This package is compiled independently from the server, allowing deployment to static hosting or CDN while communicating with the server API at runtime.

CLI Workspace (Management Tools)

The cli workspace provides operational tooling for system administrators. The entry point at cli/src/index.ts exposes commands that interact directly with the server's SQLite database and HTTP endpoints:

  • freellmapi doctor – Runs health checks against configured providers
  • freellmapi config – Manages local configuration profiles
  • freellmapi key import – Imports API keys into the rate-limiting store

Cross-Workspace Dependencies and Import Patterns

The monorepo workspace structure leverages npm's workspace protocol to link packages internally. When the server package imports shared/types, it resolves to the local filesystem rather than the npm registry. This eliminates version drift between the API implementation and its type definitions.

Each workspace compiles TypeScript independently, allowing the server to target Node.js ESM while the client targets browser-compatible ES modules. The shared package typically emits declaration files only, as it contains no runtime logic requiring bundling.

Development Workflow and Concurrent Execution

The root package.json scripts coordinate development across the server and client workspaces using the concurrently package. Running npm run dev launches both the Express server and Vite dev server simultaneously.


# Install dependencies for all workspaces

npm ci

# Start server and client with hot reloading

npm run dev

# In another terminal, run CLI diagnostics

npx freellmapi doctor

The build pipeline sequences compilation to respect dependencies: the server and CLI build first (as they may run in Node.js environments), followed by the client static assets. Tests execute across all workspaces that define test scripts, using the --if-present flag to skip packages without test suites.

Summary

  • The root package.json declares four workspaces (shared, server, client, cli) and provides orchestration scripts using concurrently and npm workspace flags (-w).
  • The shared workspace at shared/types.ts exports TypeScript definitions imported by both the server and CLI via the workspace protocol.
  • The server workspace implements the Express proxy with routing logic in server/src/services/router.ts, rate limiting in server/src/services/ratelimit.ts, and provider adapters under server/src/providers/.
  • The client workspace is a Vite-powered React application with its entry point at client/src/App.tsx.
  • The CLI workspace at cli/src/index.ts exposes management commands including doctor, config, and key import.

Frequently Asked Questions

How does the shared workspace export types to other packages?

The shared workspace exports TypeScript interfaces from shared/types.ts that other packages import using bare module specifiers like import { ProviderConfig } from "shared/types". Because the root package.json declares "workspaces": ["shared", ...], npm automatically symlinks the shared package into node_modules, resolving these imports to the local filesystem during both development and builds.

What npm scripts are used to run the monorepo in development?

The root package.json defines a dev script that executes concurrently --kill-others-on-fail --names server,client "npm run dev -w server" "npm run dev -w client". This launches the Express server and Vite client dev server simultaneously. The -w (workspace) flag ensures commands execute in the correct package context, while --kill-others-on-fail terminates both processes if either crashes.

Where is the routing logic implemented in the server workspace?

The primary routing logic resides in server/src/services/router.ts, which selects the optimal LLM provider per request based on health status, rate-limit ledger data from server/src/services/ratelimit.ts, and fallback-chain configuration. The Express application mounts this router in server/src/app.ts to handle incoming API requests.

How are provider adapters structured in the codebase?

Provider adapters are located in the server/src/providers/ directory, with one file per LLM service (e.g., OpenAI, Anthropic). Each adapter implements a standardized Provider interface exposing two methods: chatCompletion() for standard requests and streamChatCompletion() for Server-Sent Events streaming. This uniform interface allows the router in server/src/services/router.ts to treat all backends interchangeably while maintaining provider-specific authentication and request formatting.

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 →