How to Integrate Kaneo with Other Tools: A Complete Technical Guide
Kaneo integrates with external tools through a modular architecture that uses REST API endpoints, shared database schemas, WebSocket broadcasts, and reusable React hooks to connect services like Slack, GitHub, Gitea, Discord, and custom webhooks.
Kaneo is designed as an extensible, open-source project management platform. This guide breaks down exactly how its integration system works under the hood, drawing directly from the usekaneo/kaneo source code.
Kaneo Integration Architecture Overview
All Kaneo integrations follow a consistent six-layer architecture. Understanding these layers shows how to integrate Kaneo with other tools using established patterns.
1. Backend API Endpoints
Each integration lives under a dedicated /api/{integration}-integration namespace. These routes are built with Hono and validated by Valibot.
In apps/api/src/slack-integration/index.ts, the route definition looks like this:
import { Hono } from 'hono';
import { createSlackIntegration, deleteSlackIntegration, getSlackIntegration } from './controllers';
export const slackIntegration = new Hono()
.get('/', getSlackIntegration)
.post('/', createSlackIntegration)
.delete('/', deleteSlackIntegration);
This pattern repeats across GitHub (/api/github-integration), Gitea (/api/gitea-integration), Discord (/api/discord-integration), and webhook integrations.
2. Database Schema for Integrations
Integration data is stored in a shared integration table defined in apps/api/src/database/schema.ts. The schema includes:
type— discriminator for the integration service (slack, github, gitea, etc.)projectId— association to the Kaneo projectconfig— provider-specific JSON configuration- OAuth tokens and refresh credentials
This unified approach lets Kaneo query all integrations for a project with a single database call.
3. Real-Time WebSocket Broadcasts
When integrations change, connected clients receive updates immediately. The broadcast system in apps/api/src/ws/broadcast-adapter.ts supports both single-instance and multi-instance deployments:
// apps/api/src/ws/broadcast-adapter.ts
export async function broadcastIntegrationChange(projectId: string, payload: any) {
await broadcastAdapter.publish(`project:${projectId}:integration`, JSON.stringify(payload));
}
- Development: In-memory adapter
- Production: Redis-backed adapter for horizontal scaling
4. Frontend Fetchers and React Query Hooks
Each integration exposes typed fetcher functions and corresponding hooks. For example, Slack integration uses:
- Fetcher:
apps/web/src/fetchers/slack-integration/create-slack-integration.ts - Hook:
apps/web/src/hooks/mutations/slack-integration/use-slack-integration.ts
These hooks automatically:
- Cache server state with React Query
- Invalidate related queries on mutation
- Surface errors via toast notifications
5. OAuth and Device Flow Authentication
For providers requiring OAuth (GitHub, Gitea, Discord) or device authorization, Kaneo uses a reusable auth-service.ts located at packages/mcp/src/auth/auth-service.ts. This service handles:
- Token exchange and storage
- Automatic token refresh
- Secure credential encryption
The device flow implementation at packages/mcp/src/auth/device-flow.ts follows RFC 8628 for headless authentication scenarios.
6. RBAC Permission Enforcement
All integration routes enforce the same role-based access control as core Kaneo features. The middleware in apps/api/src/auth.ts validates that the requesting user has appropriate permissions (viewer, member, or admin) before allowing integration operations.
Practical Integration Examples
Connecting Slack to a Kaneo Project
Here's a complete React component that demonstrates how to integrate Kaneo with Slack using the provided hooks:
import { useCreateSlackIntegration } from '@/hooks/mutations/slack-integration/use-slack-integration';
import { useGetSlackIntegration } from '@/hooks/queries/slack-integration/use-get-slack-integration';
function SlackConnect({ projectId }: { projectId: string }) {
const { data: slack, isLoading } = useGetSlackIntegration(projectId);
const createMutation = useCreateSlackIntegration(projectId);
if (isLoading) return <p>Loading integration status...</p>;
if (slack?.connected) return <p>✓ Slack is connected to this project.</p>;
return (
<button
onClick={() => createMutation.mutate({ webhookUrl: 'https://hooks.slack.com/services/...' })}
disabled={createMutation.isLoading}
>
{createMutation.isLoading ? 'Connecting...' : 'Connect Slack'}
</button>
);
}
The useCreateSlackIntegration hook handles POSTing to /api/slack-integration with proper error handling and cache invalidation.
Implementing GitHub OAuth Server-Side
For GitHub integration, the OAuth callback controller in apps/api/src/github-integration/controllers/oauth-callback.ts exchanges temporary codes for access tokens:
import { Hono } from 'hono';
import { getGithubToken } from '@/mcp/auth/token-store';
import { upsertGithubIntegration } from '@/github-integration/service';
export const githubOAuthCallback = new Hono()
.get('/', async (c) => {
const code = c.req.query('code');
const state = c.req.query('state'); // Contains projectId for association
const token = await getGithubToken(code);
await upsertGithubIntegration({
userId: c.get('userId'),
projectId: state,
token
});
return c.redirect('/dashboard/settings/integrations');
});
Adding a Custom Integration to Kaneo
To integrate a new external tool with Kaneo, follow this implementation roadmap:
-
Extend the database schema — Add provider-specific fields to
apps/api/src/database/schema.ts -
Create API routes — Implement Hono routes in
apps/api/src/{service}-integration/index.tswith Valibot validation -
Build controller logic — Handle authentication, webhook verification, and business logic in
apps/api/src/{service}-integration/controllers/ -
Expose frontend fetchers — Add typed HTTP wrappers in
apps/web/src/fetchers/{service}-integration/ -
Create React Query hooks — Implement data fetching hooks in
apps/web/src/hooks/queries/{service}-integration/ -
Build UI components — Add settings panels and connection buttons in
apps/web/src/components/integrations/ -
Update permissions — Register any new required scopes in
apps/api/src/auth.ts -
Write comprehensive tests — Cover API endpoints in
tests/api/**and full flows intests/api-integration/**
Key Source Files for Kaneo Integrations
| Component | Path | Purpose |
|---|---|---|
| API route definitions | apps/api/src/slack-integration/index.ts |
REST endpoint registration |
| Integration schema | apps/api/src/database/schema.ts |
Unified database structure |
| WebSocket broadcasting | apps/api/src/ws/broadcast-adapter.ts |
Real-time client updates |
| OAuth service | packages/mcp/src/auth/auth-service.ts |
Token management and refresh |
| Device flow | packages/mcp/src/auth/device-flow.ts |
RFC 8628 implementation |
| Frontend fetchers | apps/web/src/fetchers/*-integration/* |
HTTP client abstractions |
| React Query hooks | apps/web/src/hooks/queries/*-integration/ |
Data synchronization |
| Integration UI | apps/web/src/components/integrations/ |
Settings and connection UI |
| Permission middleware | apps/api/src/auth.ts |
RBAC enforcement |
| Test suites | tests/api/**, tests/api-integration/** |
Verification coverage |
Summary
- Kaneo uses a standardized pattern for all integrations: Hono API routes → controllers → database → WebSocket broadcast → React Query hooks
- Existing integrations (Slack, GitHub, Gitea, Discord, webhooks) demonstrate production-ready implementations you can reference
- The
integrationtable inapps/api/src/database/schema.tsserves as the central store for all connected services - Real-time synchronization happens through
apps/api/src/ws/broadcast-adapter.ts, supporting both single and multi-instance deployments - Adding new tools requires consistent changes across eight layers: database, API, controllers, fetchers, hooks, UI, permissions, and tests
Frequently Asked Questions
What authentication methods does Kaneo support for integrations?
Kaneo supports three primary authentication patterns according to the source code: standard OAuth 2.0 for GitHub, Gitea, and Discord; OAuth Device Flow (RFC 8628) for headless or CLI scenarios via packages/mcp/src/auth/device-flow.ts; and simple webhook URL validation for services like Slack. The reusable auth-service.ts handles token storage, encryption, and automatic refresh across all OAuth providers.
How does Kaneo keep integration data synchronized across clients?
Kaneo broadcasts integration changes through WebSocket messages using the adapter pattern in apps/api/src/ws/broadcast-adapter.ts. When any integration is created, updated, or deleted, the server publishes to a project-scoped channel (project:${projectId}:integration), and connected clients receive the payload instantly. The production configuration uses Redis as the broadcast backend to support multiple API instances.
Can I integrate Kaneo with tools that aren't officially supported?
Yes. The modular architecture in usekaneo/kaneo is designed for extension. You need to implement the eight-step pattern: database schema extension, Hono API routes, controller logic, frontend fetchers, React Query hooks, UI components, permission updates, and tests. Reference the existing slack-integration or github-integration directories as working templates.
Where are integration credentials stored securely?
OAuth tokens and sensitive configuration are stored in the integration table's encrypted config column, defined in apps/api/src/database/schema.ts. The packages/mcp/src/auth/auth-service.ts module handles encryption at rest and provides methods for secure token retrieval. Environment-specific encryption keys should be configured via the application's secure configuration system.
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 →