Skip to main content
RapidDev - Software Development Agency
V0 TemplatesAnimation & EffectsIntermediate to customize

Apple Watch Activity Rings V0 Template: Fork It & Build Your Fitness Dashboard

The Apple Watch Activity Rings v0 template renders three concentric animated SVG rings using stroke-dashoffset technique and Framer Motion. Built with Next.js, TypeScript, and Tailwind, it accepts a data-driven props interface so you can swap in any metrics. Ideal for fitness, habit-tracking, or productivity dashboards. The prompt pack covers color swaps, scroll triggers, click interactions, and a full Supabase health_logs integration.

Animation & EffectsIntermediate~5 minutes

Best for

Health, fitness, or productivity dashboards needing a recognizable ring-progress UI with smooth animated SVG fill

Stack

Next.jsTypeScriptTailwind CSSFramer MotionReactSVG

A ready-made Apple Watch Activity Rings UI you can fork, run, and customize with the prompt pack below.

What's actually inside

The honest engineer's breakdown — what the Apple Watch Activity Ringstemplate does, how it's wired, and where it's opinionated.

The template is built around an ActivityRing component — a native SVG circle element that uses the stroke-dasharray / stroke-dashoffset technique to draw an arc fill. Framer Motion animates the stroke-dashoffset from 0% to the target percentage over 1.2–2 seconds with an ease-out curve, giving the rings their satisfying fill-in motion on load. Three of these rings are stacked concentrically (with slightly different radii) inside a single SVG viewport via the RingsStack component, directly mimicking the familiar Apple Watch layout for Move, Exercise, and Stand metrics.

What is genuinely well-done: the DataProps interface accepts an array of { label, value, goal, color } objects, so the template is data-driven from day one — you are not hard-coding ring values. The LegendRow component renders label + current value + daily goal below the rings and updates reactively when props change. The AnimationSequence is cleanly separated from the data layer.

Honest caveat: ring state resets on every parent re-render because the Framer Motion animate is not memoized out of the box. If you add interactive controls or live-fetch data, the rings will replay their fill animation on each re-render — a gotcha you will hit immediately and need to fix before production. The template also has no mobile-responsive ring scaling by default; on very small screens the SVG can clip outside its container.

Key UI components

ActivityRing

SVG circle element animating stroke-dashoffset from 0 to target percentage via Framer Motion

RingsStack

Concentric composition of three ActivityRing elements in a single SVG viewport with distinct radii and colors

AnimationSequence

Framer Motion animate config controlling fill duration, easing, and sequencing of each ring

LegendRow

Three label + value + goal pairs rendered below the rings, driven by the same DataProps interface

DataProps interface

TypeScript props contract accepting { label, value, goal, color }[] so rings are fully data-driven

Libraries it leans on

framer-motion

Animates SVG stroke-dashoffset on motion.circle elements and drives numeric count-up in the center label

react

useState for the interactive demo toggle, TypeScript props, and useMemo for stable ring configs

Fork it and get it running

Forking takes under five minutes and requires only a V0 account. No package installs or local setup needed to get the rings animating in a live preview.

1

Open the template and fork it into your account

Go to https://v0.dev/chat/community/QxXWuZEJjXl in your browser. You will see the live preview with three animated rings. Click the blue Fork button in the top toolbar — V0 copies the entire project into your account and opens it as a new chat. If you are not logged in, V0 will prompt you to sign in first.

Tip: Forking is free and does not consume credits.

You should see: The template opens in your V0 editor with the Preview tab showing all three rings animating on load.

2

Verify the ring animation in the Preview tab

In the V0 editor Preview tab, confirm all three rings fill in sequence from 0 to their target percentage. If the rings appear fully filled with no animation, click the Refresh icon (circular arrow) in the Preview tab header to force a full remount of the Vercel Sandbox. This is a sandbox quirk, not a code issue — the deployed app always animates correctly.

You should see: Three concentric rings animate in with an ease-out curve, followed by the LegendRow labels appearing below.

3

Edit ring labels and colors at zero credit cost

Press Option+D (Mac) or Alt+D (Windows) to open Design Mode. Select any text element in the preview — the ring labels in LegendRow, for example — and edit directly in the visual panel. You can also change color swatches for each ring here. Design Mode edits are free and do not consume V0 credits.

Tip: Color changes in Design Mode are reflected live in the Preview; no redeploy needed to see them.

You should see: Ring labels and colors update instantly in the preview without spending any credits.

4

Customize data values or add a fourth ring via chat prompt

In the V0 chat input at the bottom, paste a prompt from the prompt pack below (for example, changing ring colors and labels to match your product). V0 will generate a diff and apply it to the code. After the change, the Preview tab updates automatically — check that all three rings still animate correctly after any code change.

Tip: Start with a quick-difficulty prompt before attempting advanced ones.

You should see: Updated ring colors, labels, or values appear in the preview; animation timing remains intact.

5

Publish to a live Vercel URL

Click the Share icon (top right of the V0 editor) to open the Share panel, then select the Publish tab. Click 'Publish to Production'. V0 builds and deploys the project to a vercel.app subdomain in 30–60 seconds. Once complete, a live URL appears — open it in a new tab to confirm the rings animate identically to the V0 preview.

You should see: A live vercel.app URL is available and all three rings animate correctly on the deployed page.

6

Connect to GitHub for local development or a custom domain

To pull the code locally, open the Git panel in the V0 editor and click Connect. Enter a repository name and V0 auto-creates a branch named v0/main-{hash} in your GitHub account. Merge that PR to main, then clone locally for Cursor or VS Code refinement. For a custom domain, open the Vercel Dashboard → your project → Settings → Domains → Add Domain.

Tip: The Git panel creates the repo for you — no manual git init required.

You should see: A GitHub repo is created with the template code, and the branch is ready to merge or develop locally.

The prompt pack

Copy-paste these straight into v0's chat to customize the Apple Watch Activity Ringstemplate. Each one names this template's own components — no generic filler.

1

Change ring colors and labels to match my product

Swaps the ring palette and metric labels to match your brand without touching animation logic.

Quick win
Paste into v0 chat
Update the three ActivityRing color props to ['#6366f1', '#ec4899', '#14b8a6'] (indigo, pink, teal) and change the LegendRow labels from Move/Exercise/Stand to Daily Steps / Active Minutes / Water Intake. Keep existing AnimationSequence timing and ease-out curve unchanged so the rings still fill in sequence on load.
2

Add a percentage label in the center of the rings

Adds a live count-up number in the center of the SVG rings, synchronized with the fill animation.

Quick win
Paste into v0 chat
Add an SVG text element centered in the RingsStack that displays the outermost ActivityRing's current animated percentage as a whole number (e.g., '78%'). Use Framer Motion's useMotionValue and useTransform to count up the displayed number in sync with the stroke-dashoffset animation so the counter finishes exactly when the ring finishes filling.
3

Make rings interactive — click a ring to reveal a detail card

Turns each ring into a tappable element that reveals detail context without navigating away.

Medium
Paste into v0 chat
Add onClick handlers to each ActivityRing SVG circle (or a transparent hit-area rect over each arc). On click, slide in a Framer Motion AnimatePresence panel below the RingsStack showing the selected metric's label, current value, daily goal, and a short description string. The panel should slide up (y: 20 → 0) and fade in over 0.25 seconds, and dismiss when clicking outside or selecting another ring.
4

Animate rings on scroll into view, not on page load

Defers the ring animation until the user scrolls to the component, making the fill feel earned and purposeful.

Medium
Paste into v0 chat
Wrap the RingsStack in a Framer Motion motion.div with whileInView={{ opacity: 1 }} and viewport={{ once: true, amount: 0.6 }}. Gate the stroke-dashoffset animate call in each ActivityRing behind a useState flag named inView, set to true inside the onViewportEnter callback, so the ring fill animation only plays when the component scrolls into the visible area — not immediately on page load.
5

Fetch real activity data from a Supabase health_logs table

Replaces the static demo values with real per-user activity data from Supabase, making the rings live.

Advanced
Paste into v0 chat
Create a Next.js Server Component wrapper around RingsStack that fetches today's row from a Supabase health_logs table (columns: steps, active_minutes, water_ml, user_id) filtered by the current Clerk user's ID. Map the fetched values to percentage-of-goal props for each ActivityRing using the goals stored in a separate goals column. Add error.tsx for fetch failure states. Store SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY in the V0 Vars panel — no NEXT_PUBLIC_ prefix, these are server-only.
6

Build a weekly trend view with staggered mini ring history

Adds a 7-day weekly history strip below the main rings, giving users trend context at a glance.

Advanced
Paste into v0 chat
Add a horizontal scrollable row of 7 miniature RingsStack instances (one per day of the week) below the main rings. Each mini-stack should be 40px diameter and show that day's completion percentage. Fetch all 7 rows from the Supabase health_logs table in a single query ordered by date. Animate each mini-stack into view using Framer Motion staggerChildren with a 0.08s stagger delay so they cascade in left to right when the section mounts.

Gotchas when you extend it

The failures people actually hit when they push this template past its defaults — and the exact fix for each.

SVG stroke-dashoffset animation stutters or snaps to final value without animating

Why: Framer Motion's motion.circle requires both stroke-dasharray and the initial stroke-dashoffset to be set as explicit numeric values before the animation starts. If stroke-dasharray is missing from the initial render, the animation has no baseline to interpolate from and snaps to the end state.

Fix: Set both stroke-dasharray and stroke-dashoffset as explicit numeric values calculated from the circle radius (circumference = 2 * Math.PI * radius) in the SVG element's style attribute before Framer Motion animates them.

Fix prompt — paste into v0
Ensure ActivityRing sets explicit numeric stroke-dasharray and initial stroke-dashoffset values calculated from the circle radius (circumference = 2 * Math.PI * radius) before the Framer Motion animation starts
Ring animation replays every time the parent component re-renders

Why: The Framer Motion animate value is tied to state that changes on re-render (e.g., a hover state or live data fetch); the ring resets to 0 and re-fills on every render cycle, which looks broken in any interactive context.

Fix: Wrap ActivityRing with React.memo and use a stable key prop based on the metric label so the animation only fires when the underlying data changes, not on every parent re-render. Alternatively, use a Framer Motion useAnimation hook and call play() only once on mount.

Fix prompt — paste into v0
Memoize the ActivityRing component with React.memo and use a stable key prop based on the metric label so the animation doesn't replay on parent re-renders
Rings look visibly different sizes between V0 preview and deployed Vercel URL

Why: V0's preview sandbox applies different default CSS resets than the deployed Next.js app. SVG viewport units may scale unexpectedly when the surrounding layout differs between environments.

Fix: Set an explicit viewBox and pixel width/height on the RingsStack SVG element. Use pixel values for circle radius and stroke-width rather than percentages or em units.

Fix prompt — paste into v0
Add an explicit viewBox='0 0 200 200' and width={200} height={200} to the RingsStack SVG element so it renders consistently in both V0 preview and production
Module not found: Error: Can't resolve '@/components/ui/chart' after asking V0 to add charts

Why: The shadcn/ui chart component references recharts, which may not be in the shadcn registry at the exact version V0 expects, causing a build failure when adding the weekly history bar chart.

Fix: Ask V0 to install recharts directly and build the weekly history panel using recharts primitives (BarChart, Bar, XAxis, YAxis) instead of the shadcn chart wrapper.

Fix prompt — paste into v0
Replace the shadcn/ui chart component with a direct recharts BarChart import for the weekly history panel to avoid shadcn registry resolution errors

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

  • Fitness or habit-tracker MVP where the ring metaphor is already familiar to your users and you need it working today
  • Dashboard widget where the activity rings are one panel among several, not the core product architecture
  • Client pitch or prototype where visual polish and recognizable UI patterns are the priority over real-time data
  • Internal tool or personal project where Supabase integration can be added with a single advanced prompt

Go custom when

  • Rings must animate to real-time WebSocket data (live heart rate, live step count) requiring persistent connection management
  • Design calls for elliptical or non-circular ring shapes that require custom SVG path math beyond circular arcs
  • You need full accessibility compliance with ARIA progressbar roles and screen reader value announcements on data change
  • Your backend is not Supabase or Neon and requires a custom API adapter with rate limiting or caching logic

RapidDev can build a complete health or productivity dashboard around these activity rings — with real Supabase data integration, Clerk authentication, and daily goal tracking, shipped to production on a predictable timeline.

Frequently asked questions

Is the Apple Watch Activity Rings v0 template free to use?

Yes. All templates on v0.dev's community gallery are free to fork. Forking does not consume V0 credits. You only spend credits when you send chat prompts to customize the template after forking.

Can I use this template in a commercial product?

Yes. V0 community templates are generally MIT-licensed and can be used in commercial projects. Check the specific license shown on the template's community page before shipping. The Apple Watch ring design language itself is conceptual — the template uses generic SVG arcs, not Apple's trademarked assets.

Why does my fork break in the V0 preview — the rings are fully filled with no animation?

This is a Vercel Sandbox preview quirk, not a code bug. The sandbox sometimes does not remount components between chat iterations, so the Framer Motion animation has already played and stays at the final filled state. Click the Refresh icon (circular arrow) in the Preview tab header to force a full remount. The deployed Vercel URL always animates correctly on first load.

Why does the ring animation replay every time I interact with the page?

By default, the ActivityRing's Framer Motion animate is not memoized — any state change in a parent component (hover, click, data fetch) causes a re-render and the animation replays from 0. Fix this by wrapping ActivityRing with React.memo and giving it a stable key prop based on the metric label. The fix prompt in the gotchas section above handles this in one step.

How do I connect the rings to real health or fitness data?

The cleanest approach for a Next.js app is a Server Component wrapper that fetches today's values from a Supabase health_logs table and passes them as DataProps to RingsStack. The advanced prompt in the prompt pack above gives you the exact query pattern, env var names (SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY stored in V0 Vars panel), and error.tsx coverage in one paste-able prompt.

Can I add a fourth or fifth ring beyond the default three?

Yes. The RingsStack component accepts a DataProps array, so adding a fourth ring is a matter of passing a fourth object and adjusting the SVG radii to create space. Ask V0: 'Add a fourth ActivityRing to RingsStack with a radius of 50px and a color of #f59e0b, representing a Calories metric' — that is all it takes for the Intermediate-level customization.

Does the template work on mobile?

The rings render on mobile but the SVG does not scale responsively by default. On small screens the viewBox may clip or the rings can appear too large relative to the text. Add max-w-[200px] mx-auto to the SVG wrapper and set the LegendRow to use smaller text-sm Tailwind classes for mobile to get a clean result.

Can RapidDev customize this template for my fitness app?

Yes. RapidDev specializes in extending V0 prototypes into production-grade Next.js applications. For the activity rings template specifically, that means wiring Supabase health_logs, adding Clerk authentication, building a weekly trend view, and handling mobile responsiveness — all shipped on a defined timeline.

Outgrowing the template?

RapidDev turns v0 prototypes into production apps — real auth, database, and payments — at $13K–$25K.

Book a free consultation

30-min call. No commitment.

Want this built for you?

We ship production apps at a fixed price — $13K–$25K, 6–10 weeks, source code yours. You've seen what it takes; we do it every week.

Get a fixed-price quote

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.