feat: interactive ROI calculator at /tools/roi + resources hub#50
feat: interactive ROI calculator at /tools/roi + resources hub#50sidneyswift wants to merge 2 commits into
Conversation
- New /tools/roi page with 4-slider calculator (roster, hours, cost, content) - Animated result cards: time saved, cost saved, content boost, ROI multiple - Comparison bar showing weekly hours with vs without Recoup - Copy file lib/copy/roi.ts (single source of truth) - Custom slider CSS in globals.css - Resources page now links to ROI calc, blog, playbook, demos (was 'Coming soon') - TypeScript clean (no new errors)
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 59 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
4 issues found across 5 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="components/roi/ROICalculator.tsx">
<violation number="1" location="components/roi/ROICalculator.tsx:46">
P3: Users requesting reduced motion still get number animations on every slider update. Skip the RAF animation when `prefers-reduced-motion: reduce` matches.</violation>
<violation number="2" location="components/roi/ROICalculator.tsx:87">
P2: The slider inputs lack a programmatic label association. Each `<label>` in `SliderInput` has no `htmlFor` and the corresponding `<input>` has no `id`, so assistive technology cannot associate the visible label with the range control. This means a screen reader user hears an unnamed slider instead of something like "Artists in your roster, slider 10". Add `useId()` from React (available in React 19) to generate a unique ID and wire it via `htmlFor` on the label and `id` on the input.</violation>
<violation number="3" location="components/roi/ROICalculator.tsx:223">
P2: Changing “Posts per artist per week” never changes a displayed result: `contentBoost` remains 150% because both terms scale equally. Show the resulting content volume or remove this input so every slider has an observable calculation effect.</violation>
</file>
<file name="app/resources/page.tsx">
<violation number="1" location="app/resources/page.tsx:7">
P2: Title will render with a duplicated `| Recoup` suffix. The root layout already applies `title: { template: "%s | Recoup" }`, so the page-level string `Resources — Tools, Blog & More | Recoup` gets wrapped again producing `Resources — Tools, Blog & More | Recoup | Recoup` in the browser tab and OG tags.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| const annualTimeSaved = Math.round(weeklyHours * automationRate * 52); | ||
| const annualCostSaved = Math.round(annualManualCost * automationRate); | ||
|
|
||
| const contentWithout = postsPerWeek * roster * 52; |
There was a problem hiding this comment.
P2: Changing “Posts per artist per week” never changes a displayed result: contentBoost remains 150% because both terms scale equally. Show the resulting content volume or remove this input so every slider has an observable calculation effect.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At components/roi/ROICalculator.tsx, line 223:
<comment>Changing “Posts per artist per week” never changes a displayed result: `contentBoost` remains 150% because both terms scale equally. Show the resulting content volume or remove this input so every slider has an observable calculation effect.</comment>
<file context>
@@ -0,0 +1,341 @@
+ const annualTimeSaved = Math.round(weeklyHours * automationRate * 52);
+ const annualCostSaved = Math.round(annualManualCost * automationRate);
+
+ const contentWithout = postsPerWeek * roster * 52;
+ const contentWith = Math.round(contentWithout * 2.5);
+ const contentBoost = contentWithout > 0
</file context>
|
|
||
| export const metadata: Metadata = buildPageMetadata({ | ||
| title: `Resources — Blog & Demos | ${siteConfig.name}`, | ||
| title: `Resources — Tools, Blog & More | ${siteConfig.name}`, |
There was a problem hiding this comment.
P2: Title will render with a duplicated | Recoup suffix. The root layout already applies title: { template: "%s | Recoup" }, so the page-level string Resources — Tools, Blog & More | Recoup gets wrapped again producing Resources — Tools, Blog & More | Recoup | Recoup in the browser tab and OG tags.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At app/resources/page.tsx, line 7:
<comment>Title will render with a duplicated `| Recoup` suffix. The root layout already applies `title: { template: "%s | Recoup" }`, so the page-level string `Resources — Tools, Blog & More | Recoup` gets wrapped again producing `Resources — Tools, Blog & More | Recoup | Recoup` in the browser tab and OG tags.</comment>
<file context>
@@ -1,23 +1,88 @@
export const metadata: Metadata = buildPageMetadata({
- title: `Resources — Blog & Demos | ${siteConfig.name}`,
+ title: `Resources — Tools, Blog & More | ${siteConfig.name}`,
description:
- "Blog posts and demos. Everything you need to run your music business with AI agents — strategy, content, fans, and operations.",
</file context>
| return ( | ||
| <div className="space-y-3"> | ||
| <div className="flex items-center justify-between"> | ||
| <label className="text-[13px] text-[var(--muted-foreground)] tracking-wide"> |
There was a problem hiding this comment.
P2: The slider inputs lack a programmatic label association. Each <label> in SliderInput has no htmlFor and the corresponding <input> has no id, so assistive technology cannot associate the visible label with the range control. This means a screen reader user hears an unnamed slider instead of something like "Artists in your roster, slider 10". Add useId() from React (available in React 19) to generate a unique ID and wire it via htmlFor on the label and id on the input.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At components/roi/ROICalculator.tsx, line 87:
<comment>The slider inputs lack a programmatic label association. Each `<label>` in `SliderInput` has no `htmlFor` and the corresponding `<input>` has no `id`, so assistive technology cannot associate the visible label with the range control. This means a screen reader user hears an unnamed slider instead of something like "Artists in your roster, slider 10". Add `useId()` from React (available in React 19) to generate a unique ID and wire it via `htmlFor` on the label and `id` on the input.</comment>
<file context>
@@ -0,0 +1,341 @@
+ return (
+ <div className="space-y-3">
+ <div className="flex items-center justify-between">
+ <label className="text-[13px] text-[var(--muted-foreground)] tracking-wide">
+ {label}
+ </label>
</file context>
| if (t < 1) raf = requestAnimationFrame(tick); | ||
| } | ||
|
|
||
| raf = requestAnimationFrame(tick); |
There was a problem hiding this comment.
P3: Users requesting reduced motion still get number animations on every slider update. Skip the RAF animation when prefers-reduced-motion: reduce matches.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At components/roi/ROICalculator.tsx, line 46:
<comment>Users requesting reduced motion still get number animations on every slider update. Skip the RAF animation when `prefers-reduced-motion: reduce` matches.</comment>
<file context>
@@ -0,0 +1,341 @@
+ if (t < 1) raf = requestAnimationFrame(tick);
+ }
+
+ raf = requestAnimationFrame(tick);
+ return () => cancelAnimationFrame(raf);
+ }, [value, prefix, suffix, duration]);
</file context>
Interactive ROI calculator with 4 sliders (roster size, hours/artist/week, team cost, posts/artist/week). Animated result cards showing time saved, cost saved, content boost, ROI multiple. Also overhauls /resources from 'Coming soon' to real links hub.
New files: app/tools/roi/page.tsx, components/roi/ROICalculator.tsx, lib/copy/roi.ts, custom slider CSS.
Summary by cubic
Adds an interactive ROI calculator at /tools/roi and replaces the /resources placeholder with a simple links hub. Helps teams quickly estimate time and cost savings, content boost, and ROI.
/tools/roicalculator with 4 sliders: roster size, hours/artist/week, team hourly cost, posts/artist/week.lib/copy/roi.ts; custom slider styling added inapp/globals.css./resourcespage now links to the ROI calculator, blog, playbook, and demos.Written for commit 0a24caa. Summary will update on new commits.