Kaneo Monorepo Structure Explained: Apps, Packages, and Shared Libraries
Kaneo uses a TypeScript-based "apps + packages" monorepo that isolates the API server, React frontend, documentation, and shared libraries into distinct directories for clean separation of concerns.
Kaneo is an open-source project management platform built as a modern JavaScript monorepo. Understanding its directory layout helps developers navigate the codebase, contribute effectively, and extend the platform. This guide breaks down the Kaneo monorepo structure based on the actual source code in usekaneo/kaneo.
The Apps + Packages Pattern
The Kaneo monorepo follows the standard pattern used by tools like Turborepo and Nx. Code is organized into two main categories:
- Apps (
apps/*) — Complete, runnable applications that can be deployed independently - Packages (
packages/*) — Reusable libraries imported by apps and other packages
This structure prevents code duplication while maintaining clear boundaries between deployable units.
Top-Level Directory Overview
| Directory | Purpose |
|---|---|
apps/api |
Hono-based HTTP API with WebSockets and database access |
apps/web |
React/Vite frontend for boards, tasks, and UI state |
apps/docs |
Markdown documentation source files |
apps/site |
Next.js public site for marketing and docs |
packages/libs |
Typed API client shared across consumers |
packages/permissions |
Workspace-scoped authorization definitions |
packages/mcp |
MCP command-line interface package |
tests/api |
Backend unit and integration tests |
i18n/ |
Localization files (e.g., en-US.json) |
deploy/ |
Docker entrypoints and container assets |
charts/kaneo |
Helm chart for Kubernetes deployment |
plans/ |
Architectural design documents |
The API Application (apps/api)
The backend is a Hono server that handles HTTP requests, WebSocket connections, and database operations.
Key locations in apps/api/src/:
openapi.ts— Route registration and OpenAPI metadatadatabase/schema.ts— PostgreSQL schema definitions**/controllers/— Business logic handlersws/— WebSocket adapters for real-time updatesmcp/— MCP tooling integration
Authentication, event handling, and workspace isolation are all implemented here.
The Web Application (apps/web)
The frontend is a React application built with Vite that consumes typed API calls.
Key locations in apps/web/src/:
**/components/— React UI componentshooks/— Custom hooks including permission checks and WebSocket handlersfetchers/— Client utilities for data fetching
The frontend does not call the API directly. Instead, it imports the typed client from packages/libs for full TypeScript safety.
Shared Libraries (packages/*)
packages/libs: The Typed Client
This package exports a type-safe HTTP client that both apps/web and external consumers use.
import { createKaneoClient } from '@kaneo/libs/client';
const client = createKaneoClient({ baseUrl: '/api' });
// Type-safe API call with autocomplete
const projects = await client.project.list({ workspaceId: 'w_123' });
The client ensures frontend and backend types stay synchronized.
packages/permissions: Authorization
Canonical permission definitions enforce workspace-scoped access control.
import { requireWorkspacePermission } from '@kaneo/permissions';
export async function createTask(ctx: Ctx) {
await requireWorkspacePermission(ctx, 'task:create');
// Proceed with controller logic...
}
Both the API and frontend import from this package to maintain consistent permission checks.
packages/mcp: Command-Line Interface
Implements the MCP (standard I/O) protocol for CLI interactions with the Kaneo server.
Data Flow Through the Monorepo
Browser (apps/web)
↓
Typed Client (packages/libs)
↓
Hono API (apps/api)
↓
PostgreSQL
Real-time updates reverse part of this flow: the API's WebSocket layer (apps/api/src/ws) pushes events to React hooks (apps/web/src/hooks/use-*).
Testing and Deployment
Tests are co-located by concern:
tests/apiandtests/api-integrationcover backend logic- Frontend tests live alongside components (
apps/web/src/**/*.test.tsx)
Deployment artifacts at the root enable consistent environments:
compose.yml— Docker Compose for local developmentdeploy/— Production container scriptscharts/kaneo/— Helm chart for Kubernetes
Key Files That Define the Structure
| File | Role |
|---|---|
apps/api/src/openapi.ts |
Hono route registration |
apps/api/src/database/schema.ts |
Database schema source |
apps/web/src/hooks/use-workspace-permission.ts |
Frontend permission checking |
packages/libs/src/client.ts |
Typed client implementation |
packages/permissions/src/middleware.ts |
API permission enforcement |
compose.yml |
Local development orchestration |
These files illustrate how concerns are separated: API logic, UI logic, shared types, and cross-cutting permissions each have dedicated, importable locations.
Real-Time Updates Example
Subscribing to WebSocket events in a React hook:
import { useProjectWebsocket } from '@/hooks/use-project-websocket';
export function useProjectUpdates(projectId: string) {
const ws = useProjectWebsocket(projectId);
useEffect(() => {
const handler = (event: MessageEvent) => {
// Update local state with server event
};
ws.addEventListener('message', handler);
return () => ws.removeEventListener('message', handler);
}, [ws]);
}
Summary
- Apps (
apps/*) contain deployable units: API server, web UI, docs, and marketing site - Packages (
packages/*) provide shared, versioned libraries: typed client, permissions, and MCP tooling - Type safety is enforced across boundaries via
packages/libs - Workspace-scoped permissions are centralized in
packages/permissions - Testing is organized by layer with backend suites in
tests/and frontend tests co-located - Deployment uses Docker and Helm with configuration at the repository root
Frequently Asked Questions
What monorepo tool does Kaneo use?
Kaneo follows the standard "apps + packages" convention common to Turborepo, Nx, and pnpm workspaces. The repository structure uses workspace-level dependencies to link packages/* into apps/* without publishing to npm.
How does the frontend stay type-safe with the API?
The frontend imports createKaneoClient from packages/libs, which exposes methods with TypeScript types derived from the API's OpenAPI specification. This guarantees that request parameters and response shapes match the actual server implementation.
Where are database migrations and schema defined?
Database schema lives in apps/api/src/database/schema.ts. The API application owns all data persistence logic; no other app or package directly accesses the database.
Can I deploy the API and web frontend separately?
Yes. apps/api and apps/web are independent deployable units. The API can run without the frontend, and the frontend can be built as static files or served through apps/site (Next.js) depending on your hosting requirements.
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 →