feat: add case study pages and update footer links: - #250
Conversation
- Introduced a new case study page for Dodo Payments, detailing the migration process and its benefits. - Created a main case study overview page to showcase various case studies. - Updated the footer component to include a link to the case studies section. - Added new images for case study representation.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
WalkthroughThe PR adds a case-study index at ChangesDodo Payments Case Studies
Estimated code review effort: 3 (Moderate) | ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration. 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.
Actionable comments posted: 4
🧹 Nitpick comments (6)
apps/web/app/(pages)/case-study/page.tsx (3)
18-19: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd page metadata for
/case-study.The sibling detail page exports
metadatawith title, description, and Open Graph data. This index page has noexport const metadata, so it loses title/description control and social preview data for the case-study listing route.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/app/`(pages)/case-study/page.tsx around lines 18 - 19, Add an exported metadata constant alongside CaseStudyPage for the /case-study route, including the listing page’s title, description, and Open Graph data consistent with the sibling detail page’s metadata pattern.
1-3: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winFix import order to match the web app convention.
next/linkis imported after the@/components/...aliases. Place Next.js imports before internal alias imports.As per coding guidelines, "Follow import order in the web app: React/Next → external libs → internal aliases → relative imports, with blank lines between groups."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/app/`(pages)/case-study/page.tsx around lines 1 - 3, Reorder the imports at the top of the case-study page so the Next.js Link import appears before the internal `@/components` imports, preserving the convention of grouping imports by React/Next, external libraries, internal aliases, and relative paths with blank lines between groups.Source: Coding guidelines
20-25: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winLGTM structurally, but see the consolidated comment on shell duplication.
The fixed border markers,
darkclass,Navbar, andFooterwrapper here duplicate the identical structure inapps/web/app/(pages)/case-study/dodo-payments/page.tsx. See the consolidated comment for the proposed shared-component fix.Also applies to: 81-83
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/app/`(pages)/case-study/page.tsx around lines 20 - 25, Extract the duplicated case-study shell containing the dark main container, fixed border markers, Navbar, and Footer into a shared component, then update both case-study pages to use it. Remove the repeated wrapper structure from the page components while preserving their existing page-specific content.apps/web/app/(pages)/case-study/dodo-payments/page.tsx (3)
1-4: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winFix import order to match the web app convention.
next/linkand theMetadatatype import fromnextcome after the@/components/...aliases. Place Next.js imports first.As per coding guidelines, "Follow import order in the web app: React/Next → external libs → internal aliases → relative imports, with blank lines between groups."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/app/`(pages)/case-study/dodo-payments/page.tsx around lines 1 - 4, Reorder the imports at the top of the page module to follow the web app convention: place the Next.js imports for Link and Metadata first, then the internal "`@/components/`..." imports, with a blank line separating the groups.Source: Coding guidelines
74-79: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winConsider
next/imagefor the banner image.This raw
<img>bypasses Next.js image optimization (responsive sizing, lazy loading, LCP hints). See the consolidated comment shared withapps/web/app/(pages)/case-study/page.tsx.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/app/`(pages)/case-study/dodo-payments/page.tsx around lines 74 - 79, Replace the raw img element in the case-study banner with Next.js’s Image component, preserving the existing source, alt text, and styling while providing the required image dimensions or responsive sizing configuration.
45-50: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winShell wrapper duplicated with the case-study index page.
The fixed border markers,
darkclass,Navbar, andFooterwrapper here are identical toapps/web/app/(pages)/case-study/page.tsx. See the consolidated comment for the proposed shared-component fix.Also applies to: 484-486
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/app/`(pages)/case-study/dodo-payments/page.tsx around lines 45 - 50, Extract the duplicated case-study shell from the page component into a shared wrapper component, including the fixed border markers, dark styling, Navbar, and Footer, then reuse it in both the dodo-payments page and the case-study index page. Preserve each page’s existing content within the shared shell.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/app/`(pages)/case-study/dodo-payments/page.tsx:
- Around line 8-9: Align the customer count in the dodo-payments case study with
the authoritative count used by the case-study index page. Update both the
metadata description and the corresponding body copy in the page component,
preserving the surrounding wording.
- Around line 440-452: Update the two share buttons in the Share control block
to include type="button", accessible aria-labels identifying their respective
social platforms, and onClick handlers that perform the intended sharing
actions. Keep the existing icon markup and styling unchanged.
In `@apps/web/app/`(pages)/case-study/page.tsx:
- Around line 10-11: Update the case-study metadata description in the page
configuration to use the customer count verified against the Dodo Payments
detail page, keeping the description consistent with the “100+ paying customers”
wording used by the detail page.
- Around line 5-16: Update the caseStudies entries with image and imageAlt
fields, then use those fields in the mapped card render instead of hardcoded
Dodo Payments values for the image source and alt text. Also either apply each
study’s color field in the render or remove the unused color property,
preserving generic rendering for all case studies.
---
Nitpick comments:
In `@apps/web/app/`(pages)/case-study/dodo-payments/page.tsx:
- Around line 1-4: Reorder the imports at the top of the page module to follow
the web app convention: place the Next.js imports for Link and Metadata first,
then the internal "`@/components/`..." imports, with a blank line separating the
groups.
- Around line 74-79: Replace the raw img element in the case-study banner with
Next.js’s Image component, preserving the existing source, alt text, and styling
while providing the required image dimensions or responsive sizing
configuration.
- Around line 45-50: Extract the duplicated case-study shell from the page
component into a shared wrapper component, including the fixed border markers,
dark styling, Navbar, and Footer, then reuse it in both the dodo-payments page
and the case-study index page. Preserve each page’s existing content within the
shared shell.
In `@apps/web/app/`(pages)/case-study/page.tsx:
- Around line 18-19: Add an exported metadata constant alongside CaseStudyPage
for the /case-study route, including the listing page’s title, description, and
Open Graph data consistent with the sibling detail page’s metadata pattern.
- Around line 1-3: Reorder the imports at the top of the case-study page so the
Next.js Link import appears before the internal `@/components` imports, preserving
the convention of grouping imports by React/Next, external libraries, internal
aliases, and relative paths with blank lines between groups.
- Around line 20-25: Extract the duplicated case-study shell containing the dark
main container, fixed border markers, Navbar, and Footer into a shared
component, then update both case-study pages to use it. Remove the repeated
wrapper structure from the page components while preserving their existing
page-specific content.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: fbbfce12-d323-41a3-81d2-37822a3ece9e
⛔ Files ignored due to path filters (2)
apps/web/public/supercode-ddp2.pngis excluded by!**/*.pngapps/web/public/supercode-grayscale.pngis excluded by!**/*.png
📒 Files selected for processing (3)
apps/web/app/(pages)/case-study/dodo-payments/page.tsxapps/web/app/(pages)/case-study/page.tsxapps/web/components/homepage/footer.tsx
| description: | ||
| "A complete payment migration for 100+ paying customers — zero downtime, zero lost revenue. Learn how Supercode switched from Polar to Dodo Payments.", |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Verify the customer count against the case-study index page.
This page states "100+ paying customers" in the metadata description (Line 9) and body copy (Lines 68-69), but apps/web/app/(pages)/case-study/page.tsx states "3200+ customers" for the same case study. See the consolidated comment for all affected sites.
Also applies to: 67-71
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/app/`(pages)/case-study/dodo-payments/page.tsx around lines 8 - 9,
Align the customer count in the dodo-payments case study with the authoritative
count used by the case-study index page. Update both the metadata description
and the corresponding body copy in the page component, preserving the
surrounding wording.
| <div className="flex items-center gap-3 pt-2"> | ||
| <span className="text-[13px] text-muted-foreground">Share</span> | ||
| <button className="w-8 h-8 rounded-lg border border-border bg-card flex items-center justify-center transition-[background-color,transform] duration-150 ease-out [@media(hover:hover)]:hover:bg-accent/30 active:scale-[0.92]"> | ||
| <svg className="w-4 h-4" viewBox="0 0 24 24" fill="currentColor"> | ||
| <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" /> | ||
| </svg> | ||
| </button> | ||
| <button className="w-8 h-8 rounded-lg border border-border bg-card flex items-center justify-center transition-[background-color,transform] duration-150 ease-out [@media(hover:hover)]:hover:bg-accent/30 active:scale-[0.92]"> | ||
| <svg className="w-4 h-4" viewBox="0 0 24 24" fill="currentColor"> | ||
| <path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" /> | ||
| </svg> | ||
| </button> | ||
| </div> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Share buttons are inert and lack accessible names.
Neither <button> has an onClick handler, so clicking them does nothing. Both are icon-only with no aria-label, so screen reader users cannot identify their purpose. Add type="button" too, since these buttons have no submit intent.
🛠️ Proposed fix
- <button className="w-8 h-8 rounded-lg border border-border bg-card flex items-center justify-center transition-[background-color,transform] duration-150 ease-out [`@media`(hover:hover)]:hover:bg-accent/30 active:scale-[0.92]">
+ <button
+ type="button"
+ aria-label="Share on X"
+ onClick={() => {
+ window.open(
+ `https://twitter.com/intent/tweet?url=${encodeURIComponent(window.location.href)}`,
+ "_blank",
+ "noopener,noreferrer"
+ )
+ }}
+ className="w-8 h-8 rounded-lg border border-border bg-card flex items-center justify-center transition-[background-color,transform] duration-150 ease-out [`@media`(hover:hover)]:hover:bg-accent/30 active:scale-[0.92]"
+ >
<svg className="w-4 h-4" viewBox="0 0 24 24" fill="currentColor">
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
</svg>
</button>
- <button className="w-8 h-8 rounded-lg border border-border bg-card flex items-center justify-center transition-[background-color,transform] duration-150 ease-out [`@media`(hover:hover)]:hover:bg-accent/30 active:scale-[0.92]">
+ <button
+ type="button"
+ aria-label="Share on LinkedIn"
+ onClick={() => {
+ window.open(
+ `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(window.location.href)}`,
+ "_blank",
+ "noopener,noreferrer"
+ )
+ }}
+ className="w-8 h-8 rounded-lg border border-border bg-card flex items-center justify-center transition-[background-color,transform] duration-150 ease-out [`@media`(hover:hover)]:hover:bg-accent/30 active:scale-[0.92]"
+ >
<svg className="w-4 h-4" viewBox="0 0 24 24" fill="currentColor">
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" />
</svg>
</button>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/app/`(pages)/case-study/dodo-payments/page.tsx around lines 440 -
452, Update the two share buttons in the Share control block to include
type="button", accessible aria-labels identifying their respective social
platforms, and onClick handlers that perform the intended sharing actions. Keep
the existing icon markup and styling unchanged.
| const caseStudies = [ | ||
| { | ||
| slug: "dodo-payments", | ||
| company: "Supercode", | ||
| title: "How Supercode migrated from Polar to Dodo Payments", | ||
| description: | ||
| "A complete payment migration for 3200+ customers — zero downtime, zero lost revenue.", | ||
| date: "Aug 02, 2026", | ||
| tag: "Payments", | ||
| color: "bg-emerald-100 dark:bg-emerald-900/30", | ||
| }, | ||
| ] |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Generalize the case-study card image and alt text instead of hardcoding Dodo Payments.
caseStudies is rendered generically with .map(), but the <img> at Line 47 hardcodes src="/supercode-ddp.png" and the alt text at Line 48 hardcodes "${study.company} x Dodo Payments". Add an image/imageAlt field to each study entry instead of hardcoding it in the render. Otherwise, adding any non-Dodo-Payments case study renders the wrong image and a misleading alt text. Also, color (Line 14) is defined but never used in the render — either apply it or remove it.
🛠️ Proposed fix
const caseStudies = [
{
slug: "dodo-payments",
company: "Supercode",
title: "How Supercode migrated from Polar to Dodo Payments",
description:
"A complete payment migration for 3200+ customers — zero downtime, zero lost revenue.",
date: "Aug 02, 2026",
tag: "Payments",
- color: "bg-emerald-100 dark:bg-emerald-900/30",
+ color: "bg-emerald-100 dark:bg-emerald-900/30",
+ image: "/supercode-ddp.png",
+ imageAlt: "Supercode x Dodo Payments case study",
},
] <img
- src="/supercode-ddp.png"
- alt={`${study.company} x Dodo Payments`}
+ src={study.image}
+ alt={study.imageAlt}
className="absolute inset-0 w-full h-full object-cover"
/>Also applies to: 46-50
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/app/`(pages)/case-study/page.tsx around lines 5 - 16, Update the
caseStudies entries with image and imageAlt fields, then use those fields in the
mapped card render instead of hardcoded Dodo Payments values for the image
source and alt text. Also either apply each study’s color field in the render or
remove the unused color property, preserving generic rendering for all case
studies.
| description: | ||
| "A complete payment migration for 3200+ customers — zero downtime, zero lost revenue.", |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Verify the customer count against the Dodo Payments detail page.
This description states "3200+ customers", but apps/web/app/(pages)/case-study/dodo-payments/page.tsx states "100+ paying customers" in its metadata description and body copy. See the consolidated comment for all affected sites.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/app/`(pages)/case-study/page.tsx around lines 10 - 11, Update the
case-study metadata description in the page configuration to use the customer
count verified against the Dodo Payments detail page, keeping the description
consistent with the “100+ paying customers” wording used by the detail page.
Description
Type of change
How Has This Been Tested?
Please describe the tests that you ran to verify your changes.
bun testpassesbun run typecheckpassesbun run lintpasses (if applicable)Checklist:
Summary by CodeRabbit