Skip to content

Wardbox/revamp#52

Merged
wardbox merged 10 commits intomainfrom
wardbox/revamp
Dec 10, 2025
Merged

Wardbox/revamp#52
wardbox merged 10 commits intomainfrom
wardbox/revamp

Conversation

@wardbox
Copy link
Copy Markdown
Owner

@wardbox wardbox commented Dec 10, 2025

Summary by CodeRabbit

  • New Features

    • Animated, motion-driven landing with staggered sections, feature cards, and a CTA flow
  • Improvements

    • Stripe client API version updated
    • Framework/dev tooling and Node version bumped; TypeScript stricter module checks
    • Public routes/pages simplified and layout adjusted
    • Tailwind configuration refreshed with new design tokens and animations
  • Documentation

    • New module guides for Auth, Payments, Motion, UI components, Root layout, and Landing
  • Chores

    • Configs migrated to ESM and workspace setup added

✏️ Tip: You can customize this high-level summary in your review settings.

Initializes the basic project layout with authentication, payments, UI components, and animations.

Adds a landing page with feature showcases and a call to action. Configures Stripe for subscription payments.

Includes authentication flow. Sets up a default theme.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Dec 10, 2025

Walkthrough

Adds many module-level CLAUDE.md docs, upgrades Wasp and toolchain versions, converts several configs to ESM, replaces Tailwind config, rewrites LandingPage to use motion, updates Stripe API version, and refactors the Stripe webhook into a typed Wasp handler using context/entities.

Changes

Cohort / File(s) Summary
Top-level docs & README
CLAUDE.md, README.md
Added repository guidance CLAUDE.md; rewrote README.md with "What’s Included", step-by-step setup, project structure, customization checklist, key files, env var docs, and feature addition guidance.
Module-level docs (CLAUDE.md)
src/auth/CLAUDE.md, src/client/components/CLAUDE.md, src/landing/CLAUDE.md, src/motion/CLAUDE.md, src/payment/CLAUDE.md, src/root-components/CLAUDE.md
New per-module documentation describing module scope, files, workflows, examples, and customization; no executable changes.
Wasp manifest / routing
main.wasp
Bumped Wasp version (^0.16.4 → ^0.19.1); removed multiple public region blocks (routes/pages and Stripe public actions/API); adjusted Stripe webhook import path.
Package, CI & TS
package.json, .github/workflows/format.yml, tsconfig.json
Added workspaces, bumped devDependencies (@types/node, typescript, vite), updated GitHub Actions Node to 22.x, and set TS options (moduleDetection: "force", isolatedModules: true).
PostCSS ESM conversion
postcss.config.js
Converted export from CommonJS module.exports → ESM export default without changing config contents.
Tailwind config replacement
tailwind.config.cjs, tailwind.config.js
Removed tailwind.config.cjs; added tailwind.config.js exporting an ESM config with dark mode, content globs, extended theme tokens, keyframes/animations, and plugins (tailwindcss-animate, @tailwindcss/typography).
Type defs
src/vite-env.d.ts
Added triple-slash reference to @testing-library/jest-dom types.
Prisma schema formatting
schema.prisma
Formatting and comment additions inside User model only; no schema field or semantic changes.
UI component formatting
src/client/components/ui/button.tsx, src/client/components/ui/sheet.tsx
Reflowed props/interface extends formatting; no API or behavior changes.
Landing page (UI & motion)
src/landing/LandingPage.tsx
Rewritten to use motion utilities (staggered animations, motion wrappers, reduced-motion compatibility) and UI composition with feature cards; export unchanged.
Motion presets & provider
src/motion/transitionPresets.tsx, src/motion/motion-provider.tsx
Minor type-tightening ('linear' as const) and added reduced-motion handling plus transition replay key increment; no public signature changes.
Stripe client
src/payment/stripe/client.ts
Updated exported Stripe client API version '2025-04-30.basil''2025-08-27.basil'.
Stripe webhook handler
src/payment/stripe/webhooks.ts
Refactored handler signature from Express (req, res) to typed StripeWebhook = async (req, res, context) => {}, switched direct prisma.* calls to context.entities.* updates, and adjusted imports/types.
Misc edits
assorted CLAUDE.md files, small typings
Various documentation additions and small typing/config refinements across modules.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Key areas needing attention:

  • main.wasp: verify removed public regions and import path changes align with Wasp v0.19 semantics.
  • tailwind.config.js / removed tailwind.config.cjs: validate theme tokens, keyframes/animations, and plugin compatibility.
  • src/payment/stripe/webhooks.ts: confirm new StripeWebhook signature, context.entities usage, and DB update semantics.
  • src/landing/LandingPage.tsx and src/motion/motion-provider.tsx: check reduced-motion handling and SSR/rehydration implications.
  • Toolchain upgrades (package.json, CI, tsconfig.json): confirm local build and CI workflows still pass.

Poem

🐇
I hopped through docs and updated the plot,
Tailwind found new colors, motion took a shot,
Stripe now whispers with context in tow,
CLAUDE left breadcrumbs where modules grow,
A tiny carrot cheer — the repo’s set to glow!

Pre-merge checks

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Wardbox/revamp' is vague and does not clearly convey what changes are being made; it reads like a branch name rather than a descriptive summary of the changeset. Consider updating the title to clearly describe the main changes, such as 'Update dependencies, refactor configuration files, and add documentation' or 'Upgrade Wasp framework and modernize project configuration.'
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f76e66 and 2fe12af.

📒 Files selected for processing (1)
  • src/landing/LandingPage.tsx (1 hunks)
🔇 Additional comments (4)
src/landing/LandingPage.tsx (4)

3-18: LGTM!

Clean import organization with proper separation of UI components, icons, and motion utilities.


20-41: LGTM!

Well-structured features array with proper typing. Placeholder content is appropriate for a template project.


100-115: LGTM!

The nested staggerContainer properly inherits animation state from the parent, and the feature card mapping is clean. The icon: Icon destructuring pattern allows direct JSX usage—this is idiomatic.


47-55: Motion patterns look correct; reduced motion is properly handled at provider level.

The stagger animation setup is well-implemented with proper parent-child variant orchestration. The MotionConfig in motion-provider.tsx correctly handles prefers-reduced-motion support globally by using the useReducedMotion() hook and passing reducedMotion={'always' | 'never'} to all descendant motion components. This is the appropriate architectural approach—no per-component handling is needed.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (6)
src/motion/transitionPresets.tsx (1)

303-303: Apply as const consistently to all ease property declarations for uniform literal type inference.

The ease property at line 303 uses as const for stricter type refinement, but all other ease declarations (lines 28, 41, 54, 69, 289, 259, 274) are plain strings. While the type contract (ease: string) accepts both forms, applying as const consistently across all transition configurations would provide uniform type safety and more precise literal type tracking.

src/root-components/CLAUDE.md (1)

20-29: Add language specifier to code block.

The layout structure code block is missing a language specifier. Consider using text or plaintext if no syntax highlighting is needed.

-```
+```text
 ThemeProvider
   MotionProvider
     Nav
     <main>{children}</main>
     Footer
     Toaster
     ScrollToTop
     TransitionPlayground (desktop only)

</blockquote></details>
<details>
<summary>README.md (2)</summary><blockquote>

`29-37`: **Add language specifier to code block.**

The project structure code block should have a language specifier for consistent rendering.


```diff
-```
+```text
 src/
 ├── auth/           # Login, signup, password reset
 ├── payment/        # Stripe subscriptions
 ├── motion/         # Animation presets and provider
 ├── landing/        # Home page (customize this!)
 ├── client/components/  # shadcn/ui components
 └── root-components/    # Nav, footer, theme

---

`85-97`: **Add language specifiers to environment variable code blocks.**

These code blocks would benefit from language specifiers (e.g., `bash` or `env`) for improved readability.


```diff
-```
+```env
 REACT_APP_NAME=Your App Name

Server (.env.server)

- +env
DATABASE_URL=postgresql://...


</blockquote></details>
<details>
<summary>src/payment/stripe/webhooks.ts (2)</summary><blockquote>

`150-156`: **Fragile customer ID extraction in error handling.**

The customer ID extraction from the error message (`error.meta?.cause?.split(' ')?.pop()`) is brittle and depends on Prisma's error message format remaining stable. Since this is only used for logging and the response is already graceful, this is low-risk but could be improved.


Consider extracting the customer ID from the event data before the switch statement so it's available in the catch block:

```diff
   try {
+    // Extract customer ID early for error logging
+    const eventCustomerId = (event.data.object as any)?.customer as string | undefined
+
     switch (event.type) {

Then use eventCustomerId in the error handler instead of parsing the error message.


69-74: Consider more specific error typing.

The err: any type loses type safety. Stripe errors typically have a type property that can help distinguish signature errors from other failures.

-  } catch (err: any) {
-    console.error(`Webhook signature verification failed: ${err.message}`)
-    return res.status(400).send(`Webhook Error: ${err.message}`)
+  } catch (err) {
+    const message = err instanceof Error ? err.message : 'Unknown error'
+    console.error(`Webhook signature verification failed: ${message}`)
+    return res.status(400).send(`Webhook Error: ${message}`)
   }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 33f30fc and b403bd5.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (22)
  • CLAUDE.md (1 hunks)
  • README.md (1 hunks)
  • main.wasp (2 hunks)
  • package.json (2 hunks)
  • postcss.config.js (1 hunks)
  • schema.prisma (2 hunks)
  • src/auth/CLAUDE.md (1 hunks)
  • src/client/components/CLAUDE.md (1 hunks)
  • src/client/components/ui/button.tsx (1 hunks)
  • src/client/components/ui/sheet.tsx (1 hunks)
  • src/landing/CLAUDE.md (1 hunks)
  • src/landing/LandingPage.tsx (1 hunks)
  • src/motion/CLAUDE.md (1 hunks)
  • src/motion/transitionPresets.tsx (1 hunks)
  • src/payment/CLAUDE.md (1 hunks)
  • src/payment/stripe/client.ts (1 hunks)
  • src/payment/stripe/webhooks.ts (5 hunks)
  • src/root-components/CLAUDE.md (1 hunks)
  • src/vite-env.d.ts (1 hunks)
  • tailwind.config.cjs (0 hunks)
  • tailwind.config.js (1 hunks)
  • tsconfig.json (1 hunks)
💤 Files with no reviewable changes (1)
  • tailwind.config.cjs
🧰 Additional context used
🧬 Code graph analysis (1)
src/landing/LandingPage.tsx (4)
src/motion/motion-provider.tsx (1)
  • useMotion (48-54)
src/motion/transitionPresets.tsx (3)
  • staggerContainer (167-184)
  • staggerItem (186-199)
  • fadeIn (74-84)
src/client/components/ui/button.tsx (1)
  • Button (57-57)
src/client/components/ui/card.tsx (4)
  • Card (79-79)
  • CardHeader (79-79)
  • CardTitle (79-79)
  • CardDescription (79-79)
🪛 LanguageTool
src/motion/CLAUDE.md

[uncategorized] ~27-~27: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...hildren animations - pageTransition - Full page transitions - hoverScale / `hoverTilt...

(EN_COMPOUND_ADJECTIVE_INTERNAL)

src/auth/CLAUDE.md

[grammar] ~7-~7: Ensure spelling is correct
Context: ....tsx- Page components (Login, Signup, EmailVerification, PasswordReset) -auth.css` - Custom s...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🪛 markdownlint-cli2 (0.18.1)
src/client/components/CLAUDE.md

88-88: Bare URL used

(MD034, no-bare-urls)

CLAUDE.md

29-29: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


85-85: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


91-91: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

src/root-components/CLAUDE.md

20-20: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

README.md

29-29: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


85-85: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


91-91: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (11)
src/vite-env.d.ts (1)

2-2: LGTM!

The Jest DOM type reference properly extends global typings for testing matchers, complementing the typeRoots configuration in tsconfig.json.

src/client/components/ui/sheet.tsx (1)

50-53: LGTM!

The multi-line formatting of the extends clause improves readability without altering the type signature.

tsconfig.json (1)

23-24: LGTM!

The moduleDetection: "force" and isolatedModules: true options are best practices for modern TypeScript with Vite. They ensure consistent module treatment and enable faster per-file transpilation.

package.json (1)

4-7: LGTM!

The workspaces configuration properly integrates with Wasp's build output structure.

postcss.config.js (1)

1-6: LGTM!

The migration from CommonJS to ES module syntax aligns with the "type": "module" declaration in package.json and the broader codebase modernization.

src/auth/CLAUDE.md (1)

1-60: LGTM!

Comprehensive documentation for the auth module. The structure is clear, covering setup, customization, and route configuration effectively.

schema.prisma (1)

1-55: LGTM!

The formatting and documentation improvements enhance schema readability without altering any field definitions or database structure.

tailwind.config.js (1)

1-109: LGTM! Well-structured Tailwind configuration.

The configuration is comprehensive and properly set up:

  • Correct use of resolveProjectPath for Wasp integration
  • Extensive design token system with CSS variables
  • Proper plugin integration for animations and typography
  • Clean accordion keyframes for Radix UI components
src/landing/LandingPage.tsx (1)

24-25: MotionProvider is already properly configured in the parent component tree.

The useMotion hook is correctly set up—MotionProvider is already instantiated in src/RootPage.tsx (line 21), which wraps all routed components including LandingPage. The hook will throw an error if used outside the provider context, but your code is safe as-is.

main.wasp (1)

116-118: Import path update looks correct.

Removing the .ts extension from the webhook import path aligns with Wasp's module resolution conventions.

src/payment/stripe/webhooks.ts (1)

59-60: Good migration to Wasp's context-based entity access.

The refactor from direct Prisma access to context.entities.User aligns with Wasp's recommended patterns and ensures proper entity scoping within the API handler.

wardbox and others added 3 commits December 10, 2025 11:27
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Improves the landing page's accessibility by disabling animations for users who prefer reduced motion.

Updates the Node.js version used in the format workflow.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/landing/LandingPage.tsx (2)

83-87: Nested stagger animation may fire prematurely.

The features grid declares its own initial and animate props alongside variants. When explicit animation props are provided, they override parent orchestration—meaning this grid will start animating immediately on mount rather than waiting for the parent staggerItem to reveal this section.

To ensure the cards animate only after the section becomes visible, remove the explicit props and let the parent orchestrate:

         <motion.div
           variants={reduceMotion ? undefined : staggerContainer}
-          initial={reduceMotion ? 'show' : 'hidden'}
-          animate='show'
           className='grid gap-6 sm:grid-cols-2 lg:grid-cols-4'
         >

However, if immediate independent animation is intentional, consider documenting this behavior with a comment.


146-151: CTA animates independently from page stagger flow.

The CTA section uses fadeIn (with initial/animate keys) and declares its own animation props, so it won't participate in the parent's staggerContainer orchestration (which uses hidden/show keys). This means:

  • Hero and Features sections animate as staggered children
  • CTA section fades in immediately on mount

If you want the CTA to be part of the page stagger, use staggerItem and remove the explicit initial/animate props:

       <motion.section
         id='cta'
-        variants={reduceMotion ? undefined : fadeIn}
-        initial={reduceMotion ? 'animate' : 'initial'}
-        animate='animate'
-        transition={reduceMotion ? { duration: 0 } : undefined}
+        variants={reduceMotion ? undefined : staggerItem}
         className='flex flex-col items-center gap-6 rounded-lg bg-muted/50 p-8 text-center lg:p-12'
       >

If the independent fade-in is intentional, a brief comment would clarify the design intent.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f7df0b1 and d40faee.

📒 Files selected for processing (2)
  • .github/workflows/format.yml (1 hunks)
  • src/landing/LandingPage.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/landing/LandingPage.tsx (3)
src/motion/motion-provider.tsx (1)
  • useMotion (48-54)
src/motion/components/use-reduced-motion.ts (1)
  • useReducedMotion (3-19)
src/motion/transitionPresets.tsx (3)
  • staggerContainer (167-184)
  • staggerItem (186-199)
  • fadeIn (74-84)
🔇 Additional comments (2)
.github/workflows/format.yml (1)

20-20: Aligns with Wasp 0.19+ requirements and the PR's modernization goals.

Node.js 22.x meets Wasp's requirement of version ≥ 22.12, and the jump from Node.js 20 to 22 brings performance improvements, new features like stable require(esm), and enhanced security. This version bump is consistent with the PR's shift toward ES module configuration files. The constraint '22.x' will resolve to the latest LTS release within the 22 series.

src/landing/LandingPage.tsx (1)

24-26: Reduced motion support properly implemented.

The useReducedMotion hook is now used to respect user's motion preferences. This addresses the previous accessibility concern and follows the pattern applied consistently throughout the component.

Updates documentation to improve clarity and provide better
instructions for setting up webhooks.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/motion/CLAUDE.md (1)

27-27: Minor grammar fix: Hyphenate compound adjective.

In the context "Full page transitions," the compound adjective modifying "transitions" should be hyphenated: "Full-page transitions."

Apply this diff:

- `staggerContainer` / `staggerItem` - Staggered children animations
- `pageTransition` - Full page transitions
+ `staggerContainer` / `staggerItem` - Staggered children animations
+ `pageTransition` - Full-page transitions
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d40faee and 59d6e96.

📒 Files selected for processing (2)
  • src/motion/CLAUDE.md (1 hunks)
  • src/payment/CLAUDE.md (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/payment/CLAUDE.md
🧰 Additional context used
🪛 LanguageTool
src/motion/CLAUDE.md

[uncategorized] ~27-~27: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...hildren animations - pageTransition - Full page transitions - hoverScale / `hoverTilt...

(EN_COMPOUND_ADJECTIVE_INTERNAL)

Refactors animation logic on the landing page for improved clarity and maintainability.

Removes the explicit fadeIn animation variant and leverages staggerItem for a more cohesive animation strategy across different sections.
This also reduces animation code duplication.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 59d6e96 and 867a021.

📒 Files selected for processing (2)
  • src/landing/LandingPage.tsx (1 hunks)
  • src/motion/CLAUDE.md (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/motion/CLAUDE.md
🧰 Additional context used
🧬 Code graph analysis (1)
src/landing/LandingPage.tsx (5)
src/motion/motion-provider.tsx (1)
  • useMotion (48-54)
src/motion/components/use-reduced-motion.ts (1)
  • useReducedMotion (3-19)
src/motion/transitionPresets.tsx (2)
  • staggerContainer (167-184)
  • staggerItem (186-199)
src/client/components/ui/button.tsx (1)
  • Button (57-57)
src/client/components/ui/card.tsx (4)
  • Card (79-79)
  • CardHeader (79-79)
  • CardTitle (79-79)
  • CardDescription (79-79)
🔇 Additional comments (1)
src/landing/LandingPage.tsx (1)

26-34: Excellent implementation of reduced motion support!

The root motion wrapper correctly implements the accessibility pattern requested in the previous review. When reduceMotion is true, animations are effectively disabled by setting variants and exit to undefined, initial to 'show', and transition duration to 0.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/landing/LandingPage.tsx (2)

21-37: Reduced-motion handling at the root container is sound (optional micro‑tweak).

reduceMotion correctly short-circuits variants, exit, and transition so users who prefer reduced motion avoid animations while still seeing the page in the “show” state.

If you want to be extra explicit, you could also skip the animate prop when motion is reduced:

-      animate='show'
+      animate={reduceMotion ? undefined : 'show'}

Not required, just a clarity/intent improvement.


63-137: DRY up the repeated feature card JSX via a features config array.

The four feature blocks only differ by icon, title, and description; factoring them into data + a .map will make future edits less error‑prone.

One way to do it:

Add a features array (e.g. above the component or at the top of Landing):

const features = [
  {
    icon: Lightning,
    title: 'Feature One',
    description: 'Describe this feature and its benefit to users.',
  },
  {
    icon: ShieldCheck,
    title: 'Feature Two',
    description: 'Describe this feature and its benefit to users.',
  },
  {
    icon: CreditCard,
    title: 'Feature Three',
    description: 'Describe this feature and its benefit to users.',
  },
  {
    icon: Sparkle,
    title: 'Feature Four',
    description: 'Describe this feature and its benefit to users.',
  },
]

Then replace the duplicated card JSX inside the grid:

-          {/* Feature 1 - Replace icon, title, and description */}
-          {/* Each card uses staggerItem variant */}
-          <motion.div variants={reduceMotion ? undefined : staggerItem}>
-            <Card>
-              <CardHeader>
-                <Lightning size={32} className='mb-2 text-primary' />
-                <CardTitle>Feature One</CardTitle>
-                <CardDescription>
-                  Describe this feature and its benefit to users.
-                </CardDescription>
-              </CardHeader>
-            </Card>
-          </motion.div>
-
-          {/* Feature 2 */}
-          <motion.div variants={reduceMotion ? undefined : staggerItem}>
-            <Card>
-              <CardHeader>
-                <ShieldCheck size={32} className='mb-2 text-primary' />
-                <CardTitle>Feature Two</CardTitle>
-                <CardDescription>
-                  Describe this feature and its benefit to users.
-                </CardDescription>
-              </CardHeader>
-            </Card>
-          </motion.div>
-
-          {/* Feature 3 */}
-          <motion.div variants={reduceMotion ? undefined : staggerItem}>
-            <Card>
-              <CardHeader>
-                <CreditCard size={32} className='mb-2 text-primary' />
-                <CardTitle>Feature Three</CardTitle>
-                <CardDescription>
-                  Describe this feature and its benefit to users.
-                </CardDescription>
-              </CardHeader>
-            </Card>
-          </motion.div>
-
-          {/* Feature 4 */}
-          <motion.div variants={reduceMotion ? undefined : staggerItem}>
-            <Card>
-              <CardHeader>
-                <Sparkle size={32} className='mb-2 text-primary' />
-                <CardTitle>Feature Four</CardTitle>
-                <CardDescription>
-                  Describe this feature and its benefit to users.
-                </CardDescription>
-              </CardHeader>
-            </Card>
-          </motion.div>
+          {features.map(({ icon: Icon, title, description }) => (
+            <motion.div
+              key={title}
+              variants={reduceMotion ? undefined : staggerItem}
+            >
+              <Card>
+                <CardHeader>
+                  <Icon size={32} className='mb-2 text-primary' />
+                  <CardTitle>{title}</CardTitle>
+                  <CardDescription>{description}</CardDescription>
+                </CardHeader>
+              </Card>
+            </motion.div>
+          ))}

This keeps the layout the same while centralizing copy and icon choices.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 867a021 and 139482d.

📒 Files selected for processing (1)
  • src/landing/LandingPage.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/landing/LandingPage.tsx (5)
src/motion/motion-provider.tsx (1)
  • useMotion (48-54)
src/motion/components/use-reduced-motion.ts (1)
  • useReducedMotion (3-19)
src/motion/transitionPresets.tsx (2)
  • staggerContainer (167-184)
  • staggerItem (186-199)
src/client/components/ui/button.tsx (1)
  • Button (57-57)
src/client/components/ui/card.tsx (4)
  • Card (79-79)
  • CardHeader (79-79)
  • CardTitle (79-79)
  • CardDescription (79-79)
🔇 Additional comments (2)
src/landing/LandingPage.tsx (2)

3-18: Imports correctly align with the app’s motion & UI system.

Using the project’s Card primitives, Phosphor icons, motion/react, and the custom useReducedMotion + useMotion combo is consistent and resolves the earlier inconsistency around reduced-motion imports.


38-60: Hero and CTA sections are wired cleanly with routing and motion.

The hero and CTA use semantic headings, consistent motion patterns, and Button+Link asChild for routing to /signup and /login, which is straightforward and idiomatic for this stack.

Also applies to: 139-155

Removes the `useReducedMotion` check from the landing page component, relying instead on the global `MotionConfig` within the `MotionProvider`.

This change centralizes motion reduction logic, making the landing page code cleaner and easier to maintain.
Replaces static feature cards with a dynamically rendered list.

This makes it easier to add, remove, or modify features on the landing page.
@wardbox wardbox merged commit 20be866 into main Dec 10, 2025
1 of 2 checks passed
@wardbox wardbox deleted the wardbox/revamp branch December 10, 2025 20:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant