Skip to content

feat(frontend): Lucky brand identity on landing page - #693

Merged
LucasSantana-Dev merged 6 commits into
mainfrom
feat/landing-brand-redesign
Apr 17, 2026
Merged

LucasSantana-Dev merged 6 commits into
mainfrom
feat/landing-brand-redesign

Conversation

@LucasSantana-Dev

@LucasSantana-Dev LucasSantana-Dev commented Apr 17, 2026 •

Copy link
Copy Markdown
Owner

Summary

Complete redesign of the landing page to showcase Lucky's neon arcade brand identity. No more generic AI-style design.

Visual Changes

  • Logo Hero: Animated glowing Lucky cat (maneki-neko) as the centerpiece with subtle pulse animation
  • Neon Palette: Shifted from Discord blurple to vibrant pink (#ec4899) and orange (#fb923c) with neon glow effects
  • Fonts: Upgraded to Sora (display) and Manrope (body) for distinctive brand voice
  • Icons: Replaced emoji placeholders with lucide-react icons wrapped in colored orbs (pink/orange/purple/blue/cyan/amber)
  • Feature Cards: Gradient backgrounds with inner glow effect on hover, smooth animations with framer-motion
  • Stats Section: Monospace numbers with gradient text and status pulse indicator
  • FAQ: Smooth accordion with ChevronDown icon rotation animation
  • Footer: Logo tile with "Built for vibes" tagline
  • Animations: Staggered scroll reveals, hover effects, reduced-motion support throughout

Code Changes

  • Landing.tsx: Refactored into composable sub-sections (HeroSection, FeatureSection, StatsSection, FAQSection, FooterSection)
  • index.css: Updated font imports (Sora, Manrope), changed brand CSS vars to neon palette, updated gradient tokens
  • Landing.test.tsx: Updated tests to match new structure, added tests for logo, gradient text, smooth accordions

Preserved

  • All data flows: useCountUp, api.stats.getPublic(), useAuthStore integration
  • All existing functionality: Discord invite URL, dashboard login, FAQ content
  • Accessibility: ARIA labels, keyboard navigation, reduced-motion respects

Before/After

  • Before: Generic dark gradient with emoji icons, no personality
  • After: Distinctive neon arcade aesthetic, brand-forward design that matches the Lucky cat logo

Test locally: pnpm --filter frontend test should pass all tests. Build may need full dependency install.

Summary by CodeRabbit

New Features

  • Added smooth animations throughout the landing page (hero, features, stats, and footer sections).
  • Redesigned FAQ with improved accordion interactions.

Style

  • Updated brand color scheme to vibrant neon pink and orange.
  • Switched typography to new font families (Sora and Manrope).
  • Enhanced visual design with gradient effects and interactive hover states.

@vercel

vercel Bot commented Apr 17, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lucky Ready Ready Preview, Comment Apr 17, 2026 9:10pm

Request Review

@LucasSantana-Dev
LucasSantana-Dev enabled auto-merge (squash) April 17, 2026 20:31
@coderabbitai

coderabbitai Bot commented Apr 17, 2026 •

Copy link
Copy Markdown

Warning

Rate limit exceeded

@LucasSantana-Dev has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 45 minutes and 0 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 45 minutes and 0 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3794b109-ac38-48b2-a5bc-933f5b8b4869

📥 Commits

Reviewing files that changed from the base of the PR and between be0594b and e09c70b.

📒 Files selected for processing (1)
  • packages/frontend/src/pages/Landing.test.tsx
📝 Walkthrough

Walkthrough

The PR updates the frontend design system with new fonts (Sora, Manrope) and a neon pink/orange color palette, then refactors the Landing page into composable sections with Framer Motion animations, redesigning the hero with logo integration and updating feature and FAQ presentations.

Changes

Cohort / File(s) Summary
Design System Tokens
packages/frontend/src/index.css
Updated Google Fonts to load Sora and Manrope; switched font variables from Inter to Sora (display) and Manrope (body); changed brand color palette from Discord blurple (#5865f2, #4752c4) to neon pink (#ec4899, #db2777) and accent from blurple to neon orange (#fb923c, #fdba74); updated gradient variables; added new neon color token variables.
Landing Page Refactor
packages/frontend/src/pages/Landing.tsx, packages/frontend/src/pages/Landing.test.tsx
Refactored Landing page into composable sections (Hero, Feature, Stats, FAQ, Footer) with Framer Motion animations; replaced hardcoded emoji cards with lucide-react icons; redesigned hero with logo integration and gradient effects; reimplemented FAQ from native <details>/<summary> to custom controlled accordion with animated transitions; updated test mocks and assertions for new landing copy and component structure.

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: implementing Lucky's neon brand identity on the landing page, which is the primary focus across all file modifications (CSS tokens, Landing component refactor, and test updates).
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/landing-brand-redesign

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.

❤️ Share

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

vi.mock('framer-motion') auto-mocks motion.* to undefined, breaking
render of all 19 Landing tests. Replace with factory that proxies
motion.X to plain HTML elements + stubs AnimatePresence + useReducedMotion.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (2)
packages/frontend/src/pages/Landing.test.tsx (2)

61-70: Make this test assert reduced-motion behavior, not just renderability.

The test name says reduced motion is respected, but it only verifies that the page renders. A regression where entrance/scroll animations still run with prefersReducedMotion: true would pass here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frontend/src/pages/Landing.test.tsx` around lines 61 - 70, The test
currently only checks renderability; update it to assert that
animations/transitions are disabled when setupMocks({ prefersReducedMotion: true
}) is used: after render(<Landing />) and locating the container (variable
container), call window.getComputedStyle on the element(s) that normally animate
(e.g., the container or a specific animated element you can target via class or
data-testid) and assert that computedStyle.animationDuration === '0s' and
computedStyle.transitionDuration === '0s' (or computedStyle.animationName ===
'none'), ensuring the Landing component respects reduced-motion; keep using
setupMocks and the same render flow but add these assertions.

135-169: Avoid locking in FAQ answers as always exposed.

For an accordion, collapsed answers should not be visible/readable before expansion. These assertions currently require every answer to be present before any click, and the motion passthrough mock won’t apply collapsed height/opacity styles. Prefer asserting FAQ buttons render, then verify aria-expanded and answer visibility after interaction.

Example test shape
-        faqs.forEach(({ q, a }) => {
-            expect(screen.getByText(q)).toBeInTheDocument()
-            expect(screen.getByText(a)).toBeInTheDocument()
-        })
+        faqs.forEach(({ q }) => {
+            expect(screen.getByRole('button', { name: q })).toBeInTheDocument()
+        })
-        const firstQuestion = screen.getByText('Is Lucky free?')
-        const firstButton = firstQuestion.closest('button')
+        const firstButton = screen.getByRole('button', { name: 'Is Lucky free?' })
 
         expect(firstButton).toBeInTheDocument()
+        expect(firstButton).toHaveAttribute('aria-expanded', 'false')
 
-        await user.click(firstButton!)
+        await user.click(firstButton)
 
-        const answer = screen.getByText('Yes, Lucky is completely free with no premium tier.')
-        expect(answer).toBeInTheDocument()
+        expect(firstButton).toHaveAttribute('aria-expanded', 'true')
+        expect(screen.getByText('Yes, Lucky is completely free with no premium tier.')).toBeVisible()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frontend/src/pages/Landing.test.tsx` around lines 135 - 169, The
current tests lock in FAQ answers being visible; update both tests to assert
questions render as buttons and that answers are hidden until expansion: in the
"renders FAQ section..." test (render(<Landing />) and the faqs array) stop
asserting screen.getByText(a) for each answer and instead assert each question
button exists (e.g., use screen.getByText(q).closest('button') or getByRole) and
that its aria-expanded is 'false' initially; in the "FAQ items are expandable
via button clicks" test (userEvent.setup(), firstButton) after clicking assert
the button's aria-expanded becomes 'true' and then assert the answer text is
visible (screen.getByText(a)); keep references to Landing, userEvent.setup(),
firstButton, and aria-expanded to locate the code to change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/frontend/src/index.css`:
- Around line 69-73: The runtime aliases (--lucky-brand, --lucky-brand-strong,
--lucky-accent, --lucky-accent-soft) still point to legacy blurple; update their
assignments to reference the new neon semantic tokens (map each --lucky-* alias
to the corresponding --color-lucky-* token) so existing components using
--lucky-* pick up the neon redesign; apply the same mapping fix where these
aliases are defined again (the other occurrence noted around lines 371-381) to
ensure consistency across the stylesheet.
- Line 1: Stylelint is failing because the `@import` uses url(...) notation;
update the import in packages/frontend/src/index.css to use string import
notation instead of url(...) (replace the `@import` line that references the
Google Fonts URL so it uses a plain quoted string); ensure the same font
families and query params are preserved inside the quoted string so the browser
still loads the fonts.

In `@packages/frontend/src/pages/Landing.tsx`:
- Around line 106-111: The hero logo img element (src='/lucky-logo.png',
className='h-32 w-32 mx-auto drop-shadow-2xl filter saturate-150') is being
lazy-loaded; remove the loading='lazy' attribute (or set loading='eager') so the
above-the-fold LCP image loads immediately.
- Around line 132-134: The Button onClick in Landing.tsx currently calls
window.open(BOT_INVITE_URL, '_blank') which leaves window.opener exposed; update
the call to include a feature string (e.g., 'noopener,noreferrer') as the third
argument to window.open to prevent the opened Discord OAuth page from gaining
access to window.opener, and adjust any tests that assert the window.open call
(or its arguments) to expect the feature string as well; locate the handler on
the Button element in Landing.tsx that references BOT_INVITE_URL and update the
test assertion(s) accordingly.
- Around line 249-255: The Users strip incorrectly always appends '+' even when
userCount is 0 or loading; update the value expression in Landing.tsx (the Users
block using statsLoading and userCount) to match the Servers logic by returning
'---' when statsLoading is true and only appending '+' when userCount > 0 (e.g.,
`${userCount.toLocaleString()}${userCount > 0 ? '+' : ''}`), ensuring
consistency with the Servers/guildCount formatting.
- Around line 350-373: The FAQ accordion lacks ARIA state and doesn’t hide
collapsed content from assistive tech; update the button and answer container to
expose state and hide collapsed content: add aria-expanded={openIdx === idx} and
aria-controls={`faq-${idx}`} to the button (function setOpenIdx / variable
openIdx, idx), give the answer wrapper a stable id={`faq-${idx}`} and a11y
role/label (e.g., role="region" and aria-labelledby pointing to the button), and
when closed set aria-hidden="true" (and remove from tab sequence with
tabIndex={-1}) on the answer element and aria-hidden="false" (tabIndex={0}) when
open so screen readers won’t read collapsed answers.
- Around line 56-78: Wrap the page root in Framer Motion's MotionConfig with
reducedMotion="user" and remove scattered manual prefersReducedMotion checks
(e.g., the logoAnimation creation that uses prefersReducedMotion and any feature
hover/entry checks) so all animations (HeroSection, FeatureSection,
StatsSection, FAQSection, FooterSection) automatically respect OS
reduced-motion: replace manual conditionals by relying on MotionConfig
reducedMotion="user" at the top-level component and update/remove per-component
guards (like the logoAnimation logic and hover/entrance guards) so children no
longer need to inspect prefersReducedMotion themselves.

---

Nitpick comments:
In `@packages/frontend/src/pages/Landing.test.tsx`:
- Around line 61-70: The test currently only checks renderability; update it to
assert that animations/transitions are disabled when setupMocks({
prefersReducedMotion: true }) is used: after render(<Landing />) and locating
the container (variable container), call window.getComputedStyle on the
element(s) that normally animate (e.g., the container or a specific animated
element you can target via class or data-testid) and assert that
computedStyle.animationDuration === '0s' and computedStyle.transitionDuration
=== '0s' (or computedStyle.animationName === 'none'), ensuring the Landing
component respects reduced-motion; keep using setupMocks and the same render
flow but add these assertions.
- Around line 135-169: The current tests lock in FAQ answers being visible;
update both tests to assert questions render as buttons and that answers are
hidden until expansion: in the "renders FAQ section..." test (render(<Landing
/>) and the faqs array) stop asserting screen.getByText(a) for each answer and
instead assert each question button exists (e.g., use
screen.getByText(q).closest('button') or getByRole) and that its aria-expanded
is 'false' initially; in the "FAQ items are expandable via button clicks" test
(userEvent.setup(), firstButton) after clicking assert the button's
aria-expanded becomes 'true' and then assert the answer text is visible
(screen.getByText(a)); keep references to Landing, userEvent.setup(),
firstButton, and aria-expanded to locate the code to change.
🪄 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

Run ID: 79cfb701-2f7e-437f-ae2b-93ec52b1a8d0

📥 Commits

Reviewing files that changed from the base of the PR and between 956eb9c and be0594b.

📒 Files selected for processing (3)
  • packages/frontend/src/index.css
  • packages/frontend/src/pages/Landing.test.tsx
  • packages/frontend/src/pages/Landing.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Quality Gates
  • GitHub Check: SonarCloud Scan
🧰 Additional context used
🪛 Stylelint (17.7.0)
packages/frontend/src/index.css

[error] 1-1: Expected "url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Sora:wght@400;500;600;700&family=Manrope:wght@400;500;600;700&display=swap')" to be "'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Sora:wght@400;500;600;700&family=Manrope:wght@400;500;600;700&display=swap'" (import-notation)

(import-notation)

Comment thread packages/frontend/src/index.css
Comment thread packages/frontend/src/index.css
Comment thread packages/frontend/src/pages/Landing.tsx
Comment thread packages/frontend/src/pages/Landing.tsx
Comment thread packages/frontend/src/pages/Landing.tsx
Comment thread packages/frontend/src/pages/Landing.tsx
Comment thread packages/frontend/src/pages/Landing.tsx
@sonarqubecloud

Copy link
Copy Markdown

@LucasSantana-Dev
LucasSantana-Dev merged commit 1b216e8 into main Apr 17, 2026
12 of 13 checks passed
LucasSantana-Dev added a commit that referenced this pull request May 13, 2026
* feat(frontend): redesign landing page with Lucky neon brand identity

* fix(frontend): drop unused prefersReducedMotion + containerAnimation vars

* test(frontend): mock framer-motion with passthrough motion proxy

vi.mock('framer-motion') auto-mocks motion.* to undefined, breaking
render of all 19 Landing tests. Replace with factory that proxies
motion.X to plain HTML elements + stubs AnimatePresence + useReducedMotion.

* test(frontend): set window.open spy before render to capture click

* test(frontend): use fireEvent.click for CTA buttons (userEvent flaky w/ motion mock)
@LucasSantana-Dev
LucasSantana-Dev deleted the feat/landing-brand-redesign branch May 23, 2026 02:21

This branch was successfully deployed

1 active deployment
Preview — e09c70be Deployed Apr 17, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant