How to Contribute to the Usekaneo/Kaneo Project: A Complete Guide
The Kaneo contribution process requires understanding its pnpm monorepo architecture, following established patterns for backend controllers and frontend hooks, and adhering to Biome formatting and Conventional Commits standards.
Kaneo is a self-hosted project management platform built as a modern TypeScript monorepo. Whether you want to fix a bug, add a feature, or improve documentation, this guide walks you through exactly how to contribute to Kaneo based on the actual source code structure.
Understanding Kaneo's Architecture
Before writing code, you need to understand how Kaneo is organized. The repository uses pnpm workspaces with three distinct layers:
| Layer | Technology Stack | Location |
|---|---|---|
| API (backend) | Hono, Drizzle ORM, Better Auth, Valibot, PostgreSQL | apps/api/ |
| Web (frontend) | React 19+, TanStack Router, TanStack Query, Zustand, Radix UI, Tailwind CSS v4 | apps/web/ |
| Shared packages | Reusable utilities and types | packages/ |
The build system uses TurboRepo (turbo.json) to orchestrate tasks across all packages. Everything is containerized with Docker and deployable via Helm charts in charts/kaneo/.
Setting Up Your Development Environment
Follow these steps to get Kaneo running locally:
-
Fork and clone the repository from
github.com/usekaneo/kaneo. -
Install dependencies with pnpm:
pnpm install
-
Configure environment variables by copying
.env.sampleto.env, then followENVIRONMENT_SETUP.mdfor database setup, CORS configuration, and other requirements. -
Start development servers:
pnpm dev
- Verify your setup by running the test suite:
pnpm test
pnpm test:integration
The CI pipeline defined in .github/workflows/ci.yml will run these same checks on your pull request, so pass them locally first.
Contributing to the Backend (API)
Backend code lives in apps/api/ and follows a controller pattern with OpenAPI documentation.
Adding a New API Endpoint
Create a controller in apps/api/src/<feature>/controllers/, then expose it through a feature module:
// apps/api/src/status/controllers/get-status.ts
export async function getStatus() {
return { status: "🟢 Kaneo is running!" };
}
// apps/api/src/status/index.ts
import { Hono } from "hono";
import { describeRoute } from "hono-openapi";
import { getStatus } from "./controllers/get-status";
export const status = new Hono()
.get(
"/",
describeRoute({
operationId: "getStatus",
tags: ["Status"],
description: "Health check endpoint",
}),
async (c) => c.json(await getStatus())
);
Key Backend Files to Know
apps/api/src/database/schema.ts— Central Drizzle ORM schema definitionapps/api/src/database/relations.ts— Foreign key and cascade rule mappingsapps/api/vitest.config.ts— Test configuration
All request validation uses Valibot schemas. Authentication is handled by Better Auth middleware.
Contributing to the Frontend (Web)
Frontend code lives in apps/web/ and follows a strict data-fetching pattern: fetchers → hooks → components.
Creating a Data Fetcher
First, create a fetcher function:
// apps/web/src/fetchers/status/get-status.ts
export async function getStatus() {
const res = await fetch(`${import.meta.env.VITE_API_URL}/status`);
return res.json();
}
Exposing via TanStack Query
Wrap the fetcher in a query hook:
// apps/web/src/hooks/queries/status/use-status.ts
import { useQuery } from "@tanstack/react-query";
import { getStatus } from "@/fetchers/status/get-status";
export function useStatus() {
return useQuery(["status"], getStatus);
}
For mutations, place hooks in apps/web/src/hooks/mutations/ instead.
Building UI Components
Consume hooks in React components:
// apps/web/src/components/StatusBadge.tsx
export function StatusBadge() {
const { data, isLoading } = useStatus();
if (isLoading) return <span>Loading…</span>;
return <span>{data?.status}</span>;
}
Key Frontend Directories
apps/web/src/fetchers/— API interaction functionsapps/web/src/hooks/queries/— TanStack Query read hooksapps/web/src/hooks/mutations/— TanStack Query write hooksapps/web/src/components/— Reusable UI components
State management uses Zustand for global state and TanStack Query for server state. UI components build on Radix UI primitives with Tailwind CSS v4 styling.
Contributing to Shared Packages
Reusable code belongs in packages/ and is imported via the @/ alias throughout the codebase. For example, email utilities live in packages/email/. When adding shared code:
- Create or use an appropriate package under
packages/ - Export from the package's
index.ts - Import elsewhere using
@/package-name
Code Standards and Quality
Kaneo enforces strict consistency through automated tooling:
| Tool | Purpose | Configuration |
|---|---|---|
| Biome | Formatting and linting | Double quotes, semicolons, import ordering |
| Conventional Commits | Git history structure | feat:, fix:, docs:, refactor: prefixes |
| TurboRepo | Build pipeline | Defined in turbo.json |
Before committing, run:
pnpm lint
pnpm format
The CI pipeline will reject PRs that fail these checks.
Testing Your Contributions
Kaneo has two test suites:
- Unit tests:
tests/api/— fast, isolated tests for business logic - Integration tests:
tests/api-integration/— full request/response cycles
Add tests alongside your code changes. The existing patterns in these directories show how to structure them.
Submitting Your Contribution
-
Branch from
mainwith a descriptive name:feat/status-endpointorfix/auth-redirect. -
Commit using Conventional Commits:
feat: add health check endpointfix: correct redirect after logindocs: update API authentication section
-
Push to your fork and open a Pull Request against
usekaneo/kaneo/main. -
Verify CI passes — the pipeline in
.github/workflows/ci.ymlruns lint, build, and all tests.
Review CONTRIBUTING.md in the repository for any additional requirements.
Summary
- Kaneo is a pnpm monorepo with separate
apps/api/,apps/web/, andpackages/directories - Backend contributions use Hono controllers with Valibot validation and OpenAPI documentation
- Frontend contributions follow a fetcher → hook → component pattern using TanStack Query
- All code must pass Biome formatting and use Conventional Commits
- The TurboRepo build system and CI pipeline validate every change automatically
Frequently Asked Questions
What programming languages does Kaneo use?
Kaneo is built entirely in TypeScript. The backend uses Hono (a lightweight web framework), and the frontend uses React 19+ with modern tooling including TanStack Router, TanStack Query, and Tailwind CSS v4.
Do I need to know the entire codebase to contribute?
No. Kaneo's architecture is deliberately layered, so you can contribute to just the API, web frontend, or shared packages independently. Start with one layer and follow the established patterns in that area.
How do I test my changes before submitting a PR?
Run pnpm test for unit tests and pnpm test:integration for integration tests. The CI pipeline defined in .github/workflows/ci.yml runs these same commands, so passing locally ensures your PR will pass automated checks.
Where can I find the official contribution guidelines?
The CONTRIBUTING.md file in the repository root contains authoritative guidelines for coding standards, PR workflow, and community expectations. For environment setup details, see ENVIRONMENT_SETUP.md.
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 →