How to Contribute to the Kaneo Project: A Complete Developer Guide

To contribute to Kaneo, fork the repository, install dependencies with pnpm, configure environment variables from .env.sample, create a feature branch using the feat/ or fix/ prefix, and submit a pull request after passing local tests and the Biome linter.

Kaneo is a self-hosted project management platform built as a pnpm monorepo with TurboRepo. Contributing to the kaneo project involves working across a Hono-based backend API and a React 19+ frontend, following strict conventions for code style, testing, and commit messages. This guide walks you through the complete development workflow, from cloning the repository to merging your changes.

Prerequisites and Monorepo Structure

Before you begin contributing to Kaneo, ensure your environment meets the requirements defined in package.json:

  • Node.js ≥ 18
  • pnpm ≥ 10 (enforced via the packageManager field)

The repository is organized as a TurboRepo monorepo with three distinct areas:

  • apps/api/ – Hono backend with PostgreSQL (via Drizzle ORM), Better Auth authentication, and Valibot validation
  • apps/web/ – React 19+ frontend using Vite, TanStack Router, TanStack Query, Zustand, and Tailwind v4
  • packages/ – Shared utilities including packages/libs (Hono wrappers) and packages/mcp (Model-Context-Protocol server implementation)

Setting Up Your Local Development Environment

Follow these steps to configure your local instance of the kaneo project:

  1. Fork and clone the repository:

    git clone https://github.com/<your-username>/kaneo.git
    cd kaneo
  2. Install dependencies using pnpm:

    pnpm install
  3. Configure environment variables by copying .env.sample to .env in both the API and Web application roots. Required variables are documented in the root README.md and the Environment Configuration section of CLAUDE.md.

  4. Start the development servers:

    pnpm dev

    This command launches the API on port 1337 and the Web app on port 5173. The frontend will automatically proxy requests to the backend.

Contribution Workflow Standards

When contributing to the kaneo project, adhere to these Git and workflow conventions:

Branch Naming and Commit Messages

Create feature branches using the prefixes feat/ or fix/:

git checkout -b fix/clear-unused-keys

The project enforces Conventional Commits (e.g., feat:, fix:, docs:) via a pre-commit hook. Write messages that clearly describe the change:

git commit -m "fix: remove stale translation keys"

Finding Work and Getting Help

Browse the GitHub issues filtered by the "good first issue" label for beginner-friendly tasks. For real-time guidance, join the community Discord at https://discord.gg/rU4tSyhXXU.

Backend Development Patterns

The Kaneo API in apps/api/ follows a controller pattern with OpenAPI documentation.

Adding a New API Endpoint

Create routes in apps/api/src/<feature>/index.ts and delegate business logic to controllers:

// apps/api/src/tasks/index.ts
import { Hono } from "hono";
import { describeRoute, validator } from "hono-openapi";
import * as v from "valibot";
import { createTask } from "./controllers/create-task";

const tasks = new Hono()
  .post(
    "/",
    describeRoute({
      operationId: "createTask",
      tags: ["Tasks"],
      description: "Create a new task",
    }),
    validator("json", v.object({
      title: v.string(),
      projectId: v.string(),
    })),
    async (c) => {
      const { title, projectId } = c.req.valid("json");
      const task = await createTask({ title, projectId });
      return c.json(task, 201);
    },
  );

export default tasks;

Controllers live in apps/api/src/<feature>/controllers/ and contain the business logic, keeping routes thin. Database schemas are defined in apps/api/src/database/schema.ts using Drizzle ORM with CUID2 identifiers.

Frontend Development Patterns

The web application in apps/web/ uses TanStack Query for server state management.

Creating Query Hooks

Define typed hooks in apps/web/src/hooks/queries/:

// apps/web/src/hooks/queries/tasks/use-tasks.ts
import { useQuery } from "@tanstack/react-query";
import { getTasks } from "@/fetchers/tasks/get-tasks";

export function useTasks(projectId: string) {
  return useQuery({
    queryKey: ["tasks", projectId],
    queryFn: () => getTasks(projectId),
  });
}

Fetchers reside in apps/web/src/fetchers/ and handle the low-level API communication. UI components are built on Radix primitives with Tailwind v4 styling.

Localization Workflow

Kaneo uses i18next with translation keys stored in i18n/*.json. When adding new keys:

  1. Add the key to i18n/en-US.json first
  2. Run pnpm i18n:check:fix to propagate changes to other locales

Example usage in components:

import { useTranslation } from "react-i18next";

export function CloseButton() {
  const { t } = useTranslation();
  return <button>{t("common:actions.close")}</button>;
}

Testing and Quality Assurance

Validate your changes before submitting:

  • Unit tests: Run pnpm test (Vitest)
  • Integration tests: Run pnpm test:integration (requires PostgreSQL)
  • Linting: Run pnpm run lint to auto-fix Biome formatting issues

The .husky/pre-commit hook automatically executes pnpm run build to verify the monorepo compiles before allowing commits.

Submitting Your Contribution

Push your branch and open a pull request against the main repository:

git push origin fix/clear-unused-keys

Include a concise summary, motivation, and screenshots or test results in the PR description. Address review feedback promptly and squash commits before final merge. The CI pipeline will run the full build (pnpm run build) to ensure compatibility.

Summary

  • Fork and clone the kaneo repository, then run pnpm install to initialize the monorepo
  • Configure .env files for both API and Web apps before starting development with pnpm dev
  • Follow conventions: Use feat/ or fix/ branch prefixes, Conventional Commits, and Biome formatting
  • Write tests for new features using Vitest and validate with pnpm test
  • Submit PRs with clear descriptions and ensure the pre-commit build passes

Frequently Asked Questions

Do I need Docker to contribute to the kaneo project?

No, Docker is not required for basic development. You can run the API and Web app directly using pnpm dev after setting up a local PostgreSQL instance. However, Docker Compose files are available in the repository for convenient database setup if preferred.

What happens if the build fails in CI?

The .husky/pre-commit hook runs pnpm run build locally to catch errors before pushing. If CI fails, check that all packages compile by running pnpm run build manually and resolve any TypeScript errors in apps/api/ or apps/web/ before re-pushing.

How do I add a new translation language to Kaneo?

Add the new locale file to the i18n/ directory following the existing JSON structure. Update the language detection logic in the web app and ensure you run pnpm i18n:check:fix to validate the translation keys match the schema defined in the English source files.

Where should I place shared utility functions?

Place reusable utilities that bridge backend and frontend concerns in packages/libs/. For Model-Context-Protocol implementations or server-side integrations, use packages/mcp/ as demonstrated in packages/mcp/src/server.ts.

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 →