How to Contribute to the Kaneo Project: Complete Contributor Guide
To contribute to the Kaneo project, fork the repository on GitHub, clone your fork locally, install dependencies with pnpm install, configure environment variables from .env.sample, and run pnpm dev to start the development servers before submitting a pull request that follows Conventional Commits and passes Biome linting and Vitest testing.
Kaneo is a self-hosted project management platform built as a pnpm monorepo with TurboRepo. Contributing to this open-source project requires understanding its three-tier architecture—Backend API, Frontend Web App, and Shared Packages—while adhering to strict code quality standards enforced through automated tooling. This guide walks you through the complete contribution workflow, from initial environment setup to merging your first pull request.
Prerequisites and System Requirements
Before contributing to Kaneo, ensure your development environment meets the following specifications defined in the root package.json:
- pnpm ≥10 (specified in the
packageManagerfield) - Node.js ≥18
- PostgreSQL (required for running integration tests locally)
The project strictly uses Biome for code formatting with specific rules: spaces for indentation, double quotes for strings, and mandatory semicolons.
Setting Up the Local Development Environment
Follow these steps to configure your local Kaneo development environment:
-
Fork and clone the repository:
git clone https://github.com/<your-username>/kaneo.git cd kaneo -
Install monorepo dependencies:
pnpm install -
Configure environment variables by creating
.envfiles in both the API and Web app directories, copying from.env.sample. Required variables are documented in the rootREADME.mdand the Environment Configuration section ofCLAUDE.md. -
Start the development servers:
pnpm devThis command launches the API server on port 1337 and the Web app dev server on port 5173, accessible at
http://localhost:5173.
Understanding the Kaneo Architecture
Contributing effectively requires familiarity with how the codebase is organized in pnpm-workspace.yaml.
Backend API Structure
The API resides in apps/api/ and is built with Hono (Node.js) using a controller-based pattern:
- Database: PostgreSQL accessed via Drizzle ORM, with schema definitions centralized in
apps/api/src/database/schema.ts - Authentication: Better Auth
- Validation: Valibot for input sanitization
- Documentation: OpenAPI via
hono-openapi
Controllers contain business logic and are organized under apps/api/src/workspace/controllers/, keeping route definitions thin.
Frontend Web App Structure
The React 19+ application lives in apps/web/ and uses Vite for tooling:
- Routing: TanStack Router
- State Management: TanStack Query for server state, Zustand for client state
- Styling: Tailwind v4 with Radix UI primitives
- Data Fetching: Typed fetchers in
apps/web/src/fetchers/consumed by query hooks inapps/web/src/hooks/queries/
Shared Packages
Reusable code lives in packages/:
packages/libs/: Thin wrappers around Hono and other utilitiespackages/mcp/: Model Context Protocol server implementation (seepackages/mcp/src/server.ts)
Contribution Workflow and Standards
Finding Work
Browse the "good first issue" label on GitHub Issues or join the community Discord at https://discord.gg/rU4tSyhXXU for guidance.
Branch Naming and Commits
Create feature branches following the fix/ or feat/ naming convention:
git checkout -b fix/clear-unused-keys
All commits must follow Conventional Commits format (feat:, fix:, docs:), enforced by the pre-commit hook in .husky/pre-commit.
Code Quality Enforcement
Before submitting, run the linter and fix issues automatically:
pnpm run lint
The pre-commit hook automatically executes pnpm run build to verify the entire monorepo compiles correctly.
Testing Requirements
Validate your changes against the test suite:
- Unit tests:
pnpm test(Vitest) - Integration tests:
pnpm test:integration(requires PostgreSQL connection)
Adding New Features: Code Examples
Creating a New API Endpoint
When adding endpoints to apps/api/src/tasks/index.ts, use the OpenAPI decorator pattern and Valibot validation:
// 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;
Business logic belongs in dedicated controllers within apps/api/src/tasks/controllers/ to maintain separation of concerns.
Adding a Frontend Query Hook
Data fetching follows a strict pattern: fetchers wrap API calls, and hooks consume them via TanStack Query:
// 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),
});
}
The fetcher getTasks resides in apps/web/src/fetchers/tasks/get-tasks.ts and returns typed task arrays.
Implementing Localization
Kaneo uses i18next with JSON translation files stored in the i18n/ directory:
import { useTranslation } from "react-i18next";
export function CloseButton() {
const { t } = useTranslation();
return <button>{t("common:actions.close")}</button>;
}
Add new keys to i18n/en-US.json first, then run pnpm i18n:check:fix to propagate changes to other locale files.
Summary
- Kaneo is a pnpm monorepo with TurboRepo requiring Node.js ≥18 and pnpm ≥10
- Architecture splits into
apps/api/(Hono/Drizzle),apps/web/(React/Vite), andpackages/(shared utilities) - Development starts with
pnpm install, environment configuration, andpnpm devfor concurrent server startup - Code standards enforce Biome formatting, Conventional Commits, and Vitest testing via
.husky/pre-commithooks - Feature development follows strict patterns: controllers for API logic, fetcher/hook pairs for frontend data, and i18next keys for localization
Frequently Asked Questions
What package manager does the Kaneo project use?
The Kaneo project strictly uses pnpm version 10 or higher as specified in the packageManager field of package.json. Using npm or Yarn will result in lockfile conflicts and is not supported by the monorepo configuration.
How do I run tests before submitting a pull request?
Execute pnpm test to run unit tests with Vitest, or pnpm test:integration to run API integration tests that require a PostgreSQL database connection. These commands ensure your changes don't break existing functionality before submission.
Where are database schema changes defined?
All Drizzle ORM schema definitions live in apps/api/src/database/schema.ts, which uses CUID2 for IDs and includes timestamp utilities. When adding new tables or columns, modify this central schema file and generate migrations according to the conventions outlined in CLAUDE.md.
What happens if my code doesn't follow the formatting rules?
The Biome linter automatically enforces code style (spaces, double quotes, semicolons) through the pnpm run lint command and the .husky/pre-commit hook. If your code fails linting, the commit will be blocked until you fix the issues, either manually or by running the lint command with the --write flag.
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 →