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
packageManagerfield)
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 validationapps/web/– React 19+ frontend using Vite, TanStack Router, TanStack Query, Zustand, and Tailwind v4packages/– Shared utilities includingpackages/libs(Hono wrappers) andpackages/mcp(Model-Context-Protocol server implementation)
Setting Up Your Local Development Environment
Follow these steps to configure your local instance of the kaneo project:
-
Fork and clone the repository:
git clone https://github.com/<your-username>/kaneo.git cd kaneo -
Install dependencies using pnpm:
pnpm install -
Configure environment variables by copying
.env.sampleto.envin both the API and Web application roots. Required variables are documented in the rootREADME.mdand the Environment Configuration section ofCLAUDE.md. -
Start the development servers:
pnpm devThis 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:
- Add the key to
i18n/en-US.jsonfirst - Run
pnpm i18n:check:fixto 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 lintto 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 installto initialize the monorepo - Configure
.envfiles for both API and Web apps before starting development withpnpm dev - Follow conventions: Use
feat/orfix/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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →