Model or dataset
Kanba-co/kanba avatar
Kanba-co/kanba

Kanba: a self-hostable Trello alternative on Next.js and Supabase

Kanba is an open-source project management tool for modern teams.

663 stars114 forksTypeScriptMIT

At a glance

What is it?
Kanba is an open source kanban board for small teams, built on Next.js with shadcn/ui, Supabase or PostgreSQL through Prisma, and Stripe for billing. It suits solo developers and small teams who want to own their data, and it arrives with a deployment guide that favours self-hosting over the hosted app.
Who is it for?
Kanba fits a solo developer or small team that wants a Trello-shaped board running on its own infrastructure, with Supabase or PostgreSQL behind it and Stripe only if it charges for seats. It is the wrong choice for a team that needs multiple workspaces with fine-grained permissions, for anyone unwilling to run Supabase or PostgreSQL, and for a project that assumes an active release cadence, since the newest published release is 1.0.8 from 2025-08-11.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 76 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A kanban board for makers, with a hosted app and a self-hosting path

Kanba is described as an open-source, lightweight Trello alternative designed for makers and indie hackers, with a focus on simplicity, speed and scalability. The README names the stack directly: Tailwind CSS, shadcn/ui, Supabase and Stripe integration. The features it lists are unlimited projects, team collaboration, and dark and light mode.

The stated audience is solo developers and small teams who want full control without unnecessary complexity.

What makes it interesting as a project rather than a product is that both consumption modes exist. There is a hosted site at kanba.co, and the deployment guide in the README covers running it yourself. The repository root holds a Dockerfile, a docker-compose.yml, a separate docker-compose.postgres.yml, a prisma directory, a supabase directory, a vercel.json and a scripts directory, alongside README-DEPLOYMENT.md, README_POSTGRES.md and POSTGRES_SETUP.md. That is a repository built around the assumption that people will run their own instance.

The licence is MIT with a LICENSE file at the root, and the last push to the repository was on 2026-08-08 with the repository not archived. The release history shows 1.06 with PostgreSQL and Prisma support on 2025-07-27, 1.0.7 with a done tick on kanban tasks on 2025-08-01, and 1.0.8 with bookmarks and tasks on 2025-08-11. The gap between that newest release and the last commit is the fact to weigh before depending on the project.

The package metadata names the project kanban-project-manager at version 0.1.0 and marks it private, which is consistent with an application rather than a published library.

Local API routes replaced Supabase Edge Functions for the Stripe path

The deployment guide opens with a change that explains most of the current configuration. The application now uses local Next.js API routes instead of Supabase Edge Functions for Stripe integration, and the README gives two reasons: it makes deployment simpler and it lets you use standard .env files for configuration.

The API surface is two routes. POST /api/stripe/checkout creates Stripe checkout sessions, and POST /api/stripe/webhook handles Stripe webhook events. The README then lists the benefits of local API routes: no need to deploy separate edge functions, standard .env file support, easier debugging locally, better integration with Next.js, and no vendor lock-in since it can be deployed to any platform that supports Next.js.

That last point is the substantive one. Edge Functions are a Supabase concept that only run inside a Supabase project, so a deployment of that shape ties the application to Supabase even if the database is elsewhere. Moving the two Stripe endpoints into the Next.js application removes that coupling, and it is also why the Stripe keys are marked as server-side only in the environment variable list, since the route handlers are the only place that should see them.

The billing integration is optional. The environment variable list separates the Supabase configuration, which is required, from the Stripe configuration, which is labelled optional. A self-hosted instance with no payments is a supported configuration, not a degraded one.

The security notes at the end of the deployment guide are worth reading as a checklist for your own setup: never expose the Stripe secret key or the Supabase service role key to the client, use the NEXT_PUBLIC_ prefix only for client-side variables, regularly rotate the webhook secrets, and monitor webhook delivery in the Stripe dashboard.

Environment variables decide whether you are on Supabase or PostgreSQL

The .env.example file shows a configuration with two paths, and the first line picks between them. The database provider is chosen with a variable whose default is supabase, with postgresql as the alternative.

The Supabase block is three variables: the project URL and the anonymous key, both prefixed for the client, and the service role key, which is server-side only. The PostgreSQL block uses DATABASE_URL and DIRECT_URL connection strings, and the example values show the standard form of a Postgres URL with a password, host and port.

The same file also carries commented-out local PostgreSQL connection strings for development, and a set of example connection strings for other providers, including Railway and Supabase-hosted Postgres. The local examples are commented out because, as the file says, they are only needed when the database provider is postgresql.

That is the first trap for a self-hoster. The default path assumes Supabase, and the PostgreSQL path is opt-in, so a configuration that has a DATABASE_URL set but still has DATABASE_PROVIDER=supabase will not use it. The two paths are separate configurations rather than interchangeable settings, and the README's local development steps assume you have already made that choice.

The site configuration block is separate again, with the site URL given twice under different names, once as NEXT_PUBLIC_SITE_URL for production and once as NEXTAUTH_URL, plus a NEXTAUTH_SECRET for the authentication library.

Running it locally: four steps and a webhook tunnel

The local development section is four steps, and the third one is the one that trips people up on the payments path.

Install the dependencies:

bash
npm install

Create the environment file by copying the example:

bash
cp .env.example .env.local

Then run the development server:

bash
npm run dev

And for testing the Stripe webhooks locally, the README points at the Stripe CLI:

bash
stripe listen --forward-to localhost:3000/api/stripe/webhook

That last command matters more than it looks. The webhook endpoint is the only way the application learns that a payment succeeded, and Stripe will not deliver to localhost on its own. The forward is what closes the loop in development.

The package scripts show how much of the database tooling is first-class. There are separate scripts for generating the Prisma client, pushing the schema, running migrations, and opening Prisma studio, plus a setup script and start, stop and reset scripts for the Postgres container. The build script is prisma generate followed by next build, so the client is regenerated on every build rather than being committed.

The troubleshooting section in the deployment guide covers three areas: webhook issues, where the secret has to match the endpoint, the logs live in the Stripe dashboard and the URL has to be right; environment variables, where all the required ones have to be set and the service role key has to have the right permissions; and CORS, where the API routes include the headers and the domain may need to be whitelisted.

Docker, Vercel, and the same app two ways

Two deployment paths are documented, and the repository supports both properly.

For Vercel, the steps are short. Run npx vercel to deploy, add all the environment variables through the dashboard or the CLI, and point the Stripe webhook at the deployed domain, in the form of a Vercel URL ending in /api/stripe/webhook. The presence of a vercel.json at the repository root and a vercel-build script that runs prisma generate and next build with debug output shows this path is the one the project tunes for.

For Docker, the Dockerfile is a three-stage build on node:20-alpine. The dependencies stage copies the package files and runs npm ci with prefer-offline and no-audit. The builder stage copies the node_modules, the source, sets NEXT_TELEMETRY_DISABLED and runs npm run build. The runner stage copies the public directory, the .next output, node_modules and the package file, sets NODE_ENV to production, exposes port 3000 and starts with npm start.

The compose file matches that image. The web service builds from the repository, is named kanban-app, publishes port 3000, passes through the two public Supabase variables, and lists the service role key commented out with a note in Turkish that it should be added if needed. It also reads env_file from .env.local and restarts unless stopped.

That commented-out service role key is the interesting detail. It is excluded from the container environment on purpose, which means the containerised app cannot do the privileged operations that need it. If you deploy this way and need those operations, you have to add the variable and understand that you are now putting a service role key into a container environment, and it must never reach the browser, as the security notes say.

Where Kanba is the wrong tool

The first wrong-tool case is a team that needs more than a board. This is a single-application kanban board with projects, lists, tasks and collaboration. There is no sign in the README of the features a larger workspace product needs, such as multiple workspaces with separate permissions, custom fields, workload views, granular sharing, or an audit trail. If your team is choosing between this and a commercial product, that gap is the deciding factor rather than the licensing.

The second is a team that does not want to run Supabase. The default database path is a Supabase project, and the alternative is a PostgreSQL database that you host and point Prisma at. Either way you are operating a database and an authentication layer. If you expected a hosted SaaS where someone else runs the infrastructure, the self-hosting path is the whole job.

The third is a project that assumes an active release train. The newest published release is 1.0.8 from 2025-08-11, while the last commit is from 2026-08-08, and the README also asks for stars to help discovery, which is what a project does when it needs visibility rather than when it is shipping steadily. The commits are still arriving, so the code is not dead, but the packaged releases are a year behind the working tree, and the changelog in git is the only record of what changed.

The fourth is a team with a compliance requirement around payments. The Stripe integration is deliberately simple, with two endpoints and a set of documented keys, and the security notes are a checklist rather than a threat model. A team that needs audit logging on payment events or a formal key management process will build that themselves.

The alternative to weigh is the hosted Trello itself, or another hosted board. The difference in approach is that Kanba gives you a codebase you can read, modify and deploy, where the hosted options give you a service with support and a defined feature set. For a solo developer who wants the data in their own database that trade usually favours Kanba, and for a team that needs permissions and reporting it usually does not.

Editorial conclusion

Kanba fits a solo developer or small team that wants a Trello-shaped board running on its own infrastructure, with Supabase or PostgreSQL behind it and Stripe only if it charges for seats. It is the wrong choice for a team that needs multiple workspaces with fine-grained permissions, for anyone unwilling to run Supabase or PostgreSQL, and for a project that assumes an active release cadence, since the newest published release is 1.0.8 from 2025-08-11. Before adopting it, read the deployment guide, decide whether you want the hosted app or your own deployment, and treat the Supabase and PostgreSQL paths as different configurations rather than interchangeable ones.

Frequently asked questions

What is Kanba and who is it for?

It is an open source, lightweight Trello alternative for makers, indie hackers and small teams, built with Next.js, Tailwind CSS, shadcn/ui, Supabase and Stripe integration, supporting unlimited projects and team collaboration.

How do I run Kanba locally?

Run npm install, copy .env.example to .env.local with cp .env.example .env.local, fill in the values, then start the dev server with npm run dev.

Does Kanba need Supabase, or can it use PostgreSQL?

Both are supported. The .env.example file sets DATABASE_PROVIDER to supabase by default, and setting it to postgresql switches the connection strings to the DATABASE_URL and DIRECT_URL values.

How do I test the Kanba Stripe webhooks locally?

The README says to use the Stripe CLI with stripe listen --forward-to localhost:3000/api/stripe/webhook, which forwards Stripe's webhook events to the local API route.

Official sources

  1. Kanba-co/kanba on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/kanba-co-kanba.svg)](https://hysenlabs.com/projects/kanba-co-kanba)

Was this useful?