Build a Trello-style project management tool with V0 using Next.js, Supabase, and drag-and-drop kanban boards. Features team collaboration with role-based access, real-time card updates via Supabase Realtime, comments, and label management — all in about 1-2 hours from your browser.
What you're building
Every team needs a central place to organize work. Whether you are managing a product launch, coordinating a marketing campaign, or tracking development tasks, a kanban board with team collaboration makes progress visible and keeps everyone aligned.
V0 generates the full project management interface from prompts — the board layout, card components, member management, and comment system. Use the Connect panel for Supabase and queue prompts for each feature while V0 generates them in sequence.
The architecture uses Next.js App Router with Server Components for project and board data fetching, client components for drag-and-drop interactivity, Supabase Realtime for live collaboration, Server Actions for all card and member mutations, and @dnd-kit/core for smooth kanban drag-and-drop.
Final result
A team project management tool with kanban boards, drag-and-drop card management, member invitations with roles, real-time collaboration, card comments, and project settings — similar to Trello or Linear.
Tech stack
Prerequisites
- A V0 account (Premium recommended for prompt queuing)
- A Supabase project (free tier works — connect via V0's Connect panel)
- A team or project to organize (even a personal project works for testing)
- Basic understanding of kanban workflow (columns for stages, cards for tasks)
Build steps
Set up the project and database schema with Supabase
Open V0 and create a new project. Use the Connect panel to add Supabase. Prompt V0 to create the full schema for projects, boards, cards, members, and comments. Enable Realtime on cards and comments tables.
1// Paste this prompt into V0's AI chat:2// Build a project management tool. Create a Supabase schema with:3// 1. projects: id (uuid PK), owner_id (uuid FK), name (text), description (text), created_at (timestamptz)4// 2. boards: id (uuid PK), project_id (uuid FK), name (text), position (integer), created_at (timestamptz)5// 3. cards: id (uuid PK), board_id (uuid FK), title (text), description (text), assignee_id (uuid FK nullable), labels (text[]), due_date (date), position (integer), created_at (timestamptz), updated_at (timestamptz)6// 4. members: id (uuid PK), project_id (uuid FK), user_id (uuid FK), role (text check owner/admin/member/viewer), invited_at (timestamptz) with unique constraint on (project_id, user_id)7// 5. comments: id (uuid PK), card_id (uuid FK), author_id (uuid FK), content (text), created_at (timestamptz)8// Enable Supabase Realtime on cards and comments tables.9// RLS: cards and comments require membership in the project. Members can be read by other project members.10// Generate SQL migration and TypeScript types.Pro tip: Use V0's prompt queuing — queue the schema prompt first, then immediately queue the board view and card detail prompts while the schema generates.
Expected result: Supabase is connected with all five tables created. Realtime is enabled on cards and comments. RLS policies enforce project-level access control.
Build the kanban board view with drag-and-drop
Create the main board page showing columns (boards) with draggable cards. Use @dnd-kit/core for smooth drag-and-drop. When a card is dropped on a different column, update its board_id and position optimistically.
1// Paste this prompt into V0's AI chat:2// Build a kanban board view at app/projects/[id]/page.tsx.3// Requirements:4// - Fetch project boards and cards from Supabase5// - Display boards as columns in a horizontal ScrollArea6// - Each column has: board name header, list of Cards, "Add Card" Button at bottom7// - Each Card shows: title, assignee Avatar, labels as Badges, due date text8// - Use @dnd-kit/core for drag-and-drop:9// - DndContext wrapping all columns10// - SortableContext for each column11// - useSortable on each Card12// - onDragEnd handler that calls moveCard Server Action with new board_id and position13// - Clicking a Card opens a Sheet (right sidebar) with card details14// - "Add Board" Button to create new columns via Dialog15// - Use optimistic updates: useOptimistic to move the card visually before Server Action completes16// - 'use client' for the board component (drag-and-drop requires browser APIs)17// - Server Actions: createCard(), moveCard(), createBoard()Expected result: A horizontal kanban board with draggable cards across columns. Cards move visually on drop with optimistic updates. Clicking a card opens a detail Sheet on the right.
Create the card detail sidebar with comments
Build the Sheet component that opens when clicking a card. It shows the full card details — description, assignee, labels, due date — and a comment thread at the bottom.
1// Paste this prompt into V0's AI chat:2// Build a card detail Sheet component for the project management board.3// Requirements:4// - Opens from right side when clicking a card on the kanban board5// - Header: card title (editable Input on click), DropdownMenu for actions (delete, archive)6// - Body sections:7// - Description: Textarea, auto-saves on blur via Server Action8// - Assignee: Avatar + name, Select dropdown to change assignee from project members9// - Labels: Badge display, Popover with ToggleGroup to add/remove labels (bug/feature/design/urgent/documentation)10// - Due Date: Calendar + Popover (DatePicker pattern)11// - Separator between sections12// - Comments section at bottom:13// - List of existing comments with Avatar, author name, timestamp, content14// - Textarea + Button for adding new comment via Server Action addComment()15// - New comments appear instantly via optimistic update16// - Server Actions: updateCard(), deleteCard(), addComment()17// - 'use client' component for interactivityExpected result: A right-side Sheet showing card details with editable fields for description, assignee, labels, and due date. The comments section shows a threaded conversation with add-comment functionality.
Add real-time collaboration with Supabase Realtime
Subscribe to changes on the cards and comments tables so team members see updates instantly without refreshing. When another user moves a card or adds a comment, the board updates in real time.
1'use client'23import { useEffect } from 'react'4import { createClient } from '@/lib/supabase/client'5import { useRouter } from 'next/navigation'67export function RealtimeProvider({8 projectId,9 children,10}: {11 projectId: string12 children: React.ReactNode13}) {14 const router = useRouter()15 const supabase = createClient()1617 useEffect(() => {18 const channel = supabase19 .channel(`project-${projectId}`)20 .on(21 'postgres_changes',22 {23 event: '*',24 schema: 'public',25 table: 'cards',26 filter: `board_id=in.(select id from boards where project_id='${projectId}')`,27 },28 () => router.refresh()29 )30 .on(31 'postgres_changes',32 {33 event: 'INSERT',34 schema: 'public',35 table: 'comments',36 },37 () => router.refresh()38 )39 .subscribe()4041 return () => {42 supabase.removeChannel(channel)43 }44 }, [projectId, router, supabase])4546 return <>{children}</>47}Pro tip: Wrap the board page with this RealtimeProvider component. When any team member makes a change, router.refresh() fetches fresh data from Supabase and updates the Server Components.
Expected result: When team member A moves a card, team member B sees the card move automatically without refreshing. New comments also appear in real time.
Build the member management and project settings page
Create a settings page where project owners can invite team members, assign roles, and manage project details. Use the Supabase members table with role-based access control.
1// Paste this prompt into V0's AI chat:2// Build project settings at app/projects/[id]/settings/page.tsx.3// Requirements:4// - Only accessible to project owner and admins5// - Two sections via shadcn/ui Tabs: "General" and "Members"6// - General tab: Input for project name, Textarea for description, save Button via Server Action7// - Members tab:8// - Table of current members with columns: Avatar + name, email, role Badge, joined date9// - Role column has a Select dropdown (owner/admin/member/viewer) for role changes (only owner can change roles)10// - DropdownMenu on each row for actions: Change Role, Remove Member11// - "Invite Member" Button opens Dialog with email Input and role Select12// - Server Actions: inviteMember(), updateMemberRole(), removeMember()13// - AlertDialog for confirming member removal14// - Toast notification for successful inviteExpected result: A settings page with General and Members tabs. The Members tab shows a Table of team members with role Badges and a Dialog for inviting new members by email.
Complete code
1'use server'23import { createClient } from '@/lib/supabase/server'4import { auth } from '@clerk/nextjs/server'5import { revalidatePath } from 'next/cache'67export async function createCard(8 boardId: string,9 title: string,10 projectId: string11) {12 const supabase = await createClient()1314 const { data: maxPos } = await supabase15 .from('cards')16 .select('position')17 .eq('board_id', boardId)18 .order('position', { ascending: false })19 .limit(1)20 .single()2122 await supabase.from('cards').insert({23 board_id: boardId,24 title,25 position: (maxPos?.position ?? 0) + 1,26 })2728 revalidatePath(`/projects/${projectId}`)29}3031export async function moveCard(32 cardId: string,33 newBoardId: string,34 newPosition: number,35 projectId: string36) {37 const supabase = await createClient()3839 await supabase40 .from('cards')41 .update({42 board_id: newBoardId,43 position: newPosition,44 updated_at: new Date().toISOString(),45 })46 .eq('id', cardId)4748 revalidatePath(`/projects/${projectId}`)49}5051export async function addComment(52 cardId: string,53 content: string,54 projectId: string55) {56 const { userId } = await auth()57 const supabase = await createClient()5859 await supabase.from('comments').insert({60 card_id: cardId,61 author_id: userId,62 content,63 })6465 revalidatePath(`/projects/${projectId}`)66}Customization ideas
Add card templates
Create reusable card templates with pre-filled descriptions, labels, and checklists that can be applied when creating new cards for recurring task types.
Build a timeline/Gantt view
Add a calendar-based timeline view showing cards with due dates as horizontal bars, giving a Gantt chart perspective of project progress.
Add file attachments to cards
Use Supabase Storage to allow users to upload files (documents, images, designs) directly to cards with drag-and-drop.
Integrate email notifications
Send email notifications via Resend when users are assigned to cards, mentioned in comments, or when due dates approach.
Add activity feed
Track all card changes (moves, edits, comments) in an activity log and display a chronological feed on the project dashboard.
Common pitfalls
Pitfall: Not using optimistic updates for drag-and-drop card movements
How to avoid: Use React's useOptimistic hook to immediately update the card's position in local state, then persist via Server Action in the background.
Pitfall: Implementing drag-and-drop in a Server Component
How to avoid: Mark the kanban board component with 'use client'. Keep the data fetching in a Server Component parent and pass cards as props to the client board.
Pitfall: Not handling position reordering in a database transaction
How to avoid: Use a Supabase RPC function that wraps the position update in a transaction — update the moved card's board_id and position, then shift sibling cards atomically.
Best practices
- Use V0's prompt queuing to generate the board view, card detail Sheet, and member management in rapid succession
- Enable Supabase Realtime on cards and comments tables for instant team collaboration
- Use @dnd-kit/core for accessible, performant drag-and-drop rather than the HTML5 drag-and-drop API
- Implement RLS policies scoped to project membership so cards are only visible to team members
- Use V0's Design Mode (Option+D) to visually adjust card sizes, column widths, and badge colors for free
- Keep the RealtimeProvider as a wrapper component that calls router.refresh() to avoid manually managing subscription state
- Store card labels as a text[] array for simplicity — no need for a separate labels table in the MVP
AI prompts to try
Copy these prompts to build this project faster.
I'm building a project management tool with Next.js App Router and Supabase. I need help with drag-and-drop card reordering. Using @dnd-kit/core, write a client component that renders kanban columns with sortable cards. When a card is dropped in a new column, call a Server Action to update card.board_id and card.position. Use useOptimistic for instant visual feedback. Include the full DndContext, SortableContext, and useSortable setup.
Create a project member invitation system. Build a Dialog with email Input and role Select (admin/member/viewer). On submit, insert into members table. Show pending invitations in a Table with Badge for status. Include a Server Action inviteMember() that checks for existing membership before inserting, and removeMember() with AlertDialog confirmation.
Frequently asked questions
What V0 plan do I need for a project management tool?
V0 Free works for the basic build, but Premium ($20/month) is recommended because the project has multiple complex pages (board view, card details, settings) that benefit from prompt queuing.
How does real-time collaboration work?
Supabase Realtime listens for database changes on the cards and comments tables. When any team member makes a change, the RealtimeProvider component triggers a router.refresh() that fetches fresh data and updates the board for all connected users.
Can I limit what different team members can do?
Yes. The members table has a role field (owner/admin/member/viewer). RLS policies on the database level and role checks in Server Actions enforce what each role can do — viewers can only read, members can create and edit, admins can manage members.
How do I deploy the project management tool?
Click Share then Publish to Production in V0. Alternatively, use the Git panel to connect to GitHub and auto-create a PR for team code review before deploying to Vercel.
Can I import projects from Trello or Asana?
Not out of the box. You would need to build an import API route that accepts the exported JSON from Trello/Asana and maps it to your Supabase schema. Both tools offer public APIs for data export.
Can RapidDev help build a custom project management platform?
Yes. RapidDev has built 600+ apps including team collaboration platforms with kanban boards, Gantt charts, and custom workflow engines. Book a free consultation to discuss your specific requirements.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation