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 metadata
  • database/schema.ts — PostgreSQL schema definitions
  • **/controllers/ — Business logic handlers
  • ws/ — WebSocket adapters for real-time updates
  • mcp/ — 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 components
  • hooks/ — Custom hooks including permission checks and WebSocket handlers
  • fetchers/ — 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/api and tests/api-integration cover 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 development
  • deploy/ — Production container scripts
  • charts/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:

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 →