Kanban & Board Variants
12 production-ready boards — pick one, see the live preview, copy the code
Personal Tasks
Simple to-do board with three lanes.
Install with:
npx afnoui add kanban/kanban-personal-tasksPersonal Tasks
JSON Configuration
3 columns · 4 cardsSource Code
Required Dependencies & Files
Install packages and copy 16 files to get this kanban running.
Runtime deps
npm install react react-dom lucide-react clsx tailwind-merge class-variance-authority- Requires shadcn/ui components: button, badge, input, label, textarea, select, dialog, scroll-area, avatar, progress, use-toast.
- Bring `cn` from your `@/lib/utils` (clsx + tailwind-merge).
- DnD library is bundled — no @dnd-kit dependency.
- Import components/dnd/dnd.css once at app entry (e.g. in your global stylesheet).
Variant-specific (regenerated per board) Shared engine (copy once)
Variant-specific
Your generated board component — wires the engine to your config + data + onChange hook.
src/boards/MyTasks/MyTasks.tsx
src/boards/MyTasks/MyTasks.tsx
import { useState } from "react";
import { KanbanBoard } from "@/components/kanban/KanbanBoard";
import { boardConfig } from "./config";
import { initialCards } from "./data";
import { useMyTasksCardChange, useMyTasksLoadMore } from "./useCardChange";
import type { KanbanCardData } from "@/components/kanban/types";
/**
* My Tasks
* Personal productivity board
*
* Drag-and-drop is powered by the project's custom Pointer DnD library
* (no @dnd-kit dependency). Cards persist locally — wire `useCardChange`
* to your backend to make moves stick across reloads.
*/
export default function MyTasks() {
const [cards, setCards] = useState<KanbanCardData[]>(initialCards);
const handleCardChange = useMyTasksCardChange();
const handleLoadMore = useMyTasksLoadMore();
return (
<div className="space-y-4">
<div>
<h2 className="text-xl font-bold">{boardConfig.title}</h2>
{boardConfig.subtitle && (
<p className="text-sm text-muted-foreground">{boardConfig.subtitle}</p>
)}
</div>
<KanbanBoard
config={boardConfig}
cards={cards}
onCardsChange={setCards}
onCardChange={handleCardChange}
onLoadMore={handleLoadMore}
/>
</div>
);
}