Best for
Devs who want a polished animated task list they can drop into a productivity app or portfolio
Stack
A ready-made Tasks with Framer Motion UI you can fork, run, and customize with the prompt pack below.
What's actually inside
The honest engineer's breakdown — what the Tasks with Framer Motiontemplate does, how it's wired, and where it's opinionated.
This template renders a fully animated task list where every interaction — adding a task, completing it, reordering, and deleting — has a distinct motion response. The TaskList component orchestrates entrance and exit sequences using AnimatePresence, while TaskItem wraps each row in a motion.div that plays a layout animation on reorder and an exit variant on delete. Spring physics on the CompletionCheckbox make the check feel tactile rather than instantaneous.
Drag-to-reorder is handled by Framer Motion's built-in Reorder primitives (Reorder.Group and Reorder.Item), with a ReorderHandle using useDragControls to restrict the drag hit area to the grip icon alone. The AddTaskInput has a subtle submit animation and inline validation feedback — the kind of micro-interaction that makes forms feel alive. EmptyState slides in via a named variant preset when the list empties.
The honest caveat: task state lives in React component memory by default — a page refresh wipes everything. The localStorage prompt in the prompt pack addresses this, but it requires a careful useEffect dance to avoid SSR crashes (Next.js App Router runs components on the server first). shadcn/ui components are used as style primitives and restyled heavily via className, so if you pull this into an existing shadcn install you may hit registry mismatches on the Checkbox component specifically.
Key UI components
TaskListOrchestrates AnimatePresence entrance/exit sequences for the full task collection
TaskItemIndividual task row with layout animation, completion toggle, and drag-to-reorder
AddTaskInputInput field with submit animation and inline validation feedback
CompletionCheckboxCustom checkbox with spring-physics check mark animation
ReorderHandleDrag grip using useDragControls and Reorder.Item to restrict drag hit area
EmptyStateAnimated placeholder that slides in via variant preset when the task list is empty
Libraries it leans on
framer-motionProvides variants, AnimatePresence, Reorder group/item, useDragControls, and spring transitions throughout
shadcn/uiButton, Input, and Checkbox used as base style primitives, restyled via className overrides
Fork it and get it running
Forking takes under five minutes in the browser — no local Node setup required. You'll go from community preview to a live .vercel.app URL without leaving V0.
Open the community template and fork it
Navigate to https://v0.dev/chat/community/x1Y8okrbkTn. You'll see a live preview of the animated task list on the right. Click the blue Fork button in the top-right corner of the preview panel. V0 opens a fresh chat with a copy of the template code — this is your own editable workspace and costs no credits.
Tip: The fork is immediate; no loading screen.
You should see: A new V0 chat opens with the task list code loaded and the preview panel active.
Confirm animations render in the Preview tab
Click the Preview tab (center panel) and interact with the task list — add a task, check it off, drag to reorder. All three interactions should have visible motion responses. If the preview shows a blank screen, reload the preview tab using the refresh icon inside the panel; this is a known V0 sandbox warm-up issue.
Tip: Drag only works on the grip handle icon, not the full row.
You should see: Tasks add with a slide-in, complete with a spring check, and reorder with a smooth layout shift.
Use Design Mode for free visual tweaks
Press Option+D (Mac) or Alt+D (Windows) to enter Design Mode. Click any text element to edit copy directly. Switch to the Themes tab on the left to adjust the color palette — no credits consumed for these changes. Save and return to the chat when done.
You should see: Color and copy changes appear live in the preview without spending credits.
Publish to a live URL
Click the Share button in the top-right, then open the Publish tab. Click "Publish to Production". Deployment takes 30–60 seconds and V0 returns a .vercel.app URL you can share immediately. The URL is public by default.
Tip: Copy the URL before leaving — it's easy to lose in the chat.
You should see: A live .vercel.app URL that shows the animated task list to anyone you share it with.
Connect to GitHub for ongoing development
Open the Git panel (left sidebar icon). Click Connect, authorize GitHub, and choose a repository. V0 auto-creates a branch named v0/main-{hash} and commits the template code. Open a PR in GitHub and merge it. From now on, V0 edits sync to this branch automatically.
Tip: Never rename the connected repo — V0 will lose the link.
You should see: A GitHub repository with the template code and an open PR on a v0/main-{hash} branch.
Swap out placeholder tasks with real data
In your GitHub repo, open the component file containing the initial task array (or use the Code tab in V0). Replace the hardcoded task objects with your own data, or follow the localStorage prompt in the prompt pack below to persist user-created tasks across page reloads. For multi-user persistence, see the Supabase advanced prompt.
You should see: The task list shows your data on load instead of the placeholder "Buy groceries" items.
The prompt pack
Copy-paste these straight into v0's chat to customize the Tasks with Framer Motiontemplate. Each one names this template's own components — no generic filler.
Change color scheme to indigo and slate
Recolors the completed-task state and hover highlight to an indigo palette without touching any animation logic.
Add `className` overrides on TaskItem's motion.div so the completed-task background uses Tailwind `bg-indigo-50` and the check mark inside CompletionCheckbox uses `text-indigo-600`. Update the hover ring on TaskItem to `ring-indigo-300`. Keep all existing AnimatePresence exit variants and spring transition values completely unchanged.
Add due date badge to each task
Adds an optional animated due-date label to each task row without modifying the existing drag or completion behavior.
Add a `dueDate?: string` field to the task data type. Inside TaskItem, render a small `<span>` badge showing the due date formatted as `MMM D` using `date-fns/format`. Wrap the badge in a `motion.div` with `initial={{ opacity: 0 }} animate={{ opacity: 1 }}` and only render it when `dueDate` is defined — skip the badge entirely for tasks without a due date.Persist tasks to localStorage across reloads
Gives users persistent tasks that survive a page refresh, using the correct App Router SSR-safe localStorage pattern.
In the parent component that holds the tasks state, initialize the state as an empty array — do NOT read localStorage during useState initialization because that runs on the server in Next.js App Router and throws `ReferenceError: localStorage is not defined`. Instead, add a `useEffect(() => { const saved = localStorage.getItem('tasks'); if (saved) setTasks(JSON.parse(saved)); }, [])` to load on mount. Add a second `useEffect` with `tasks` as the dependency that calls `localStorage.setItem('tasks', JSON.stringify(tasks))` on every change.Add swipe-to-delete on mobile
Adds a native-feeling swipe-to-delete gesture on mobile that integrates with the existing AnimatePresence exit system.
Wrap TaskItem's inner content in a `motion.div` with `drag="x"` and `dragConstraints={{ left: -120, right: 0 }}`. When the `onDragEnd` handler detects `event.offset.x < -100`, trigger a delete: first play the AnimatePresence exit variant `{ x: -200, opacity: 0 }` on the TaskItem, then call the remove handler after a 300ms delay. Behind the draggable layer, reveal a red trash icon div that becomes visible as the user swipes left.Connect tasks to Supabase with real-time sync
Replaces in-memory task state with a Supabase-backed real-time list that syncs across browser tabs and devices.
Add a Supabase project via the Connect panel. Create a `tasks` table with columns `id uuid DEFAULT gen_random_uuid()`, `title text NOT NULL`, `completed bool DEFAULT false`, and `user_id uuid`. Enable Row Level Security and add a policy allowing users to access only their own rows. In a Server Action, wrap all inserts and toggle-complete updates. In the client TaskList component, add a `useEffect` that subscribes to real-time changes: `supabase.channel('tasks').on('postgres_changes', { event: '*', schema: 'public', table: 'tasks' }, payload => { /* update local state */ }).subscribe()`. Set `NEXT_PUBLIC_SUPABASE_URL` and `NEXT_PUBLIC_SUPABASE_ANON_KEY` in V0's Vars panel.Add Clerk auth so each user sees their own tasks
Adds per-user task isolation with Clerk authentication, connecting identity to Supabase rows so tasks are completely private.
Install Clerk via the Connect panel. Wrap the root `layout.tsx` with `<ClerkProvider>`. Add a middleware.ts file using `clerkMiddleware()` to protect the `/` route and redirect unauthenticated users to `/sign-in`. In the Supabase tasks table, store the `userId` returned by `auth()` on each insert. Filter the task query with `.eq('user_id', userId)` so users only see their own data. Add a `<UserButton />` component from `@clerk/nextjs` in the header for sign-out.Gotchas when you extend it
The failures people actually hit when they push this template past its defaults — and the exact fix for each.
ReferenceError: localStorage is not definedWhy: The parent component initializes task state from `localStorage` during the useState call, which executes on the server during SSR in Next.js App Router. The server has no localStorage object.
Fix: Move all localStorage reads into a `useEffect(() => { ... }, [])` hook so they execute client-side only. Initialize the state as an empty array: `const [tasks, setTasks] = useState([])`. See the localStorage persistence prompt above for the complete pattern.
Move the localStorage initialization out of useState's default value — read it inside a useEffect instead, and initialize state as an empty array to avoid SSR errors
AnimatePresence exit animations not playing when tasks are removedWhy: The exiting TaskItem must stay in the React tree until its exit animation finishes. AnimatePresence tracks elements by their `key` prop — if you use array index as the key, the wrong element exits when items shift positions.
Fix: Ensure every `<motion.li key={task.id}>` uses the task's unique ID as the key, not the array index. Without a stable key, AnimatePresence cannot distinguish which item is leaving.
All TaskItem components are keyed by array index — switch to task.id as the key so AnimatePresence can track exits correctly
Drag reorder breaks layout after Tailwind v3/v4 version mismatchWhy: V0 generates code against Tailwind v3.4.17. If you pull to a local project created with `create-next-app` (which now defaults to Tailwind v4), utility classes like `gap-y-2` may render differently or not at all.
Fix: Pin Tailwind to v3 in package.json (`"tailwindcss": "^3.4.17"`) and add a `tailwind.config.js` with content paths. Alternatively, keep the project entirely within V0 and deploy via Share → Publish to avoid the version mismatch entirely.
The project is using Tailwind v4 but V0 generated v3 classes — add tailwind.config.js with content paths and install tailwindcss@3
Framer Motion Reorder.Item conflicts with shadcn/ui's drag-and-drop utilitiesWhy: If you add a dnd-kit or shadcn DnD library alongside Framer's Reorder, two pointer-event systems compete for the same drag target. The result is erratic drag behavior — items snap back, ghost elements appear, or the list freezes.
Fix: Remove shadcn drag helpers and rely solely on Framer Motion's Reorder.Group, Reorder.Item, and useDragControls. The template was designed around Framer's drag system and does not need a second DnD layer.
Remove the dnd-kit import — the template already uses Framer Motion Reorder which handles drag natively
Module not found: Error: Can't resolve '@/components/ui/checkbox'Why: shadcn/ui Checkbox is referenced in CompletionCheckbox but V0 auto-generates the import without always scaffolding the component file, especially when the template is pulled into a new project.
Fix: Run `npx shadcn@latest add checkbox` in your project root to install the missing component. Alternatively, send a follow-up prompt to V0 asking it to generate the Checkbox component file inline.
The Checkbox component is missing — run npx shadcn add checkbox or ask V0 to generate the component file
Template vs. custom — the honest call
A forked template gets you far, fast. Here's where it holds up, and where you'll outgrow it.
The template is enough when
- You need a polished animated task list for a portfolio, side project, or internal tool with standard add/complete/delete operations
- Your data is static or stored in localStorage and you don't need multi-user sync
- You want smooth drag-to-reorder out of the box without writing Framer Motion variants from scratch
- You need a working Framer Motion reference for AnimatePresence and Reorder patterns to adapt into a larger app
Go custom when
- You need server-side task syncing with real-time collaboration across multiple users
- You need recurring tasks, subtasks, priority levels, or calendar integration beyond simple list management
- You're integrating into an existing app with its own state management (Zustand, Redux) and component library
RapidDev can extend this V0 template with Supabase persistence, Clerk auth, and production-ready task management in a few days — without burning credits on error loops.
Frequently asked questions
Is this Framer Motion task list template free to use?
Yes. V0 community templates are free to fork and use. You'll need a V0 account (free tier available) to fork. The generated code is yours to use in any project.
Can I use this template in a commercial product?
Yes. V0 community templates have no commercial use restrictions. You own the generated code. Review Vercel's terms of service for any hosting-specific constraints, but the template code itself is unrestricted.
Why does my fork break in preview — animations don't play?
The most common cause is a blank or frozen preview in V0's sandbox on first load. Click the refresh icon inside the Preview panel, or open the Share menu and open in a new tab. If the issue persists after a prompt edit, the sandbox may need a warm-up — wait 10 seconds and refresh again.
How do I connect a database to save tasks permanently?
The quickest path is the Supabase advanced prompt in the prompt pack above — it gives you a complete Server Action setup with RLS and real-time sync. For a simpler no-database option, the localStorage prompt persists tasks in the browser between reloads (single user only).
Why does my task list disappear on refresh?
By default the template stores tasks in React component state, which resets on every page load. Use the 'Persist tasks to localStorage' prompt from the prompt pack to fix this. For multi-user persistence, use the Supabase prompt.
Can I add subtasks or nested lists to this template?
Yes, but it requires meaningful structural changes. Framer Motion's Reorder.Group is designed for flat lists — nesting Reorder groups introduces complexity around drag event propagation. Plan for 2-4 hours of prompt work or manual coding to implement a reliable nested list.
Can RapidDev customize this template for my app?
Yes. RapidDev extends V0 task templates with Supabase persistence, Clerk auth, real-time sync, and custom animation variants — shipped in production, not just a prototype. Reach out through the RapidDev site for a scoping conversation.
Does drag-to-reorder work on mobile touchscreens?
Framer Motion's Reorder supports touch events, but the drag hit area (the ReorderHandle grip) is small on mobile. Use the 'Add swipe-to-delete on mobile' prompt as an alternative gesture for deletion. For better mobile drag UX, consider increasing the grip icon's touch target size via padding.
Outgrowing the template?
RapidDev turns v0 prototypes into production apps — real auth, database, and payments — at $13K–$25K.
Book a free consultation30-min call. No commitment.