Skip to content

feat(web): full website redesign with shadcn/ui + Magic UI#142

Merged
github-actions[bot] merged 21 commits into
developfrom
feature/website-redesign
Mar 12, 2026
Merged

feat(web): full website redesign with shadcn/ui + Magic UI#142
github-actions[bot] merged 21 commits into
developfrom
feature/website-redesign

Conversation

@tomymaritano

@tomymaritano tomymaritano commented Mar 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

Full rebuild of the marketing site with a modern, minimal design system:

  • Design System: Violet accent (#8b5cf6) on dark zinc base, Inter + JetBrains Mono fonts, dark-mode only
  • shadcn/ui: Button, Card, Badge, Separator, Accordion, Sheet components (new-york style)
  • Magic UI: AnimatedShinyText, BorderBeam, DotPattern, Marquee, NumberTicker, ShimmerButton, TextReveal effects
  • Rebuilt components: Navbar (Sheet mobile nav), Footer (DotPattern bg), Hero (ShimmerButton + BorderBeam), SocialProof (Marquee), Features (BorderBeam hover), WhyLocal (TextReveal), Audience, Pricing (NumberTicker + Accordion), Download (AnimatedShinyText)
  • Cleanup: Removed @headlessui/react, migrated FaqAccordion to shadcn Accordion
  • Design tokens: All pages updated from hardcoded colors to Tailwind v4 CSS custom properties

New Dependencies

  • framer-motion, class-variance-authority, clsx, tailwind-merge, tailwindcss-animate
  • @fontsource/inter, @fontsource-variable/jetbrains-mono
  • @radix-ui/react-slot, @radix-ui/react-accordion, @radix-ui/react-dialog, @radix-ui/react-separator

Removed

  • @headlessui/react

Test plan

  • pnpm build passes (37+ static pages generated)
  • No TypeScript errors in modified files
  • No @headlessui/react imports remain
  • Visual verification of all pages in dev mode
  • Fumadocs docs render correctly with dark theme
  • Mobile nav (Sheet) opens/closes correctly

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Major marketing site redesign: new hero, video guides, testimonials, creator story, and animated landing sections.
    • New UI primitives: cards, accordions, sheet-based mobile menu, animated beams, marquees, shiny text, number ticker, and modal video viewer.
    • Pricing page: live animated pricing display and accordion FAQs; download page unified per-platform cards.
  • Style

    • Unified semantic color tokens, violet-focused palette, updated fonts (Inter + JetBrains Mono), and new animations (marquee, shimmer, grid).

tomymaritano and others added 19 commits March 12, 2026 01:24
shadcn/ui + Magic UI full rebuild with minimal/clean aesthetic,
neutral cool palette with violet accent, dark mode only.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
17-task plan covering shadcn/ui + Magic UI setup, design system rewrite,
component rebuilds (Navbar, Footer, Hero, Features, WhyLocal, Pricing,
Download), and cleanup of @headlessui/react.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Install framer-motion, class-variance-authority, clsx, tailwind-merge,
tailwindcss-animate, and font packages as foundation for the website
redesign with shadcn/ui + Magic UI components.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 8 Magic UI components as source files with required CSS animations:
- animated-shiny-text, border-beam, dot-pattern, marquee
- number-ticker, shimmer-button, text-reveal, animated-grid-pattern

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
motion/react module path doesn't resolve in this project's TS config.
Switch all imports to framer-motion. Fix implicit any on number-ticker.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tor, Accordion, Sheet)

Install Radix UI primitives and create 6 manually-crafted shadcn/ui
"new-york" style components using the design system tokens from
globals.css. All components use CSS custom properties for theming
and are ready for consumption by page sections.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ono fonts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace @headlessui Popover/Dialog with CSS group-hover dropdown for
desktop docs menu and shadcn Sheet for mobile navigation. All links,
sections, and CTAs preserved. Uses Button component for desktop CTAs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove as const and add explicit type annotation to fix property
access on union types.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AnimatedShinyText badge, ShimmerButton CTA, DotPattern background,
BorderBeam on screenshot frame.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Scroll-based word reveal heading + comparison table in shadcn Card.
Deleted standalone ComparisonTable.tsx.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…Accordion

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace hardcoded colors with token classes across FAQ, Philosophy,
Changelog, Plugins, Terms, Privacy pages and FaqAccordion component.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
FaqAccordion now uses shadcn/ui Accordion (Radix-based) instead of
@headlessui/react Disclosure. No more @headlessui dependency.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@github-actions github-actions Bot added dependencies Pull requests that update a dependency file app:web labels Mar 12, 2026
@github-actions github-actions Bot enabled auto-merge (squash) March 12, 2026 05:12
@coderabbitai

coderabbitai Bot commented Mar 12, 2026

Copy link
Copy Markdown

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Large redesign: global theming and animations added; new UI primitives (Card, Button, Badge, Sheet, Accordion, Separator) and Magic UI components (shiny text, beams, patterns, marquee, ticker, etc.); navbar/footer refactor; many landing/marketing pages restyled or rebuilt; several legacy components removed; docs and package deps updated.

Changes

Cohort / File(s) Summary
Global theming & layout
apps/web/app/globals.css, apps/web/app/layout.tsx
Introduced semantic CSS variables (background/surface/border/text-*), new animation keyframes/utilities, updated glass-card visuals, font imports, dark root class, and body background/text tokens.
Design tokens / marketing pages
apps/web/app/(marketing)/changelog/page.tsx, .../download/page.tsx, .../faq/page.tsx, .../philosophy/page.tsx, .../plugins/page.tsx, .../pricing/page.tsx, .../privacy/page.tsx, .../terms/page.tsx
Replaced hard-coded color classes and border tokens with semantic tokens (text-text-*, border-border); pricing page refactor to client component, Card-based layout, NumberTicker, BorderBeam, Accordion; download page adopts Card/AnimatedShinyText. Removed metadata export from pricing page.
New UI primitives (shadcn-style)
apps/web/components/ui/card.tsx, .../button.tsx, .../badge.tsx, .../accordion.tsx, .../separator.tsx, .../sheet.tsx
Added Card, Button (CVA), Badge, Radix-based Accordion, Separator, and Sheet components with forwardRef, variants, and exports.
Magic UI components
apps/web/components/magicui/animated-shiny-text.tsx, .../animated-grid-pattern.tsx, .../border-beam.tsx, .../dot-pattern.tsx, .../marquee.tsx, .../number-ticker.tsx, .../shimmer-button.tsx, .../text-reveal.tsx, .../animated-beam.tsx, .../hero-video-dialog.tsx
Introduced multiple animated/effect components (shiny text, grid/dot patterns, animated beams, marquee, number ticker, shimmer button, text reveal, hero video dialog) with typed props and framer-motion usage.
Landing / marketing components added or refactored
apps/web/components/landing/Hero.tsx, .../Features.tsx, .../Audience.tsx, .../SocialProof.tsx, .../WhyLocal.tsx, .../CreatorStory.tsx, .../Testimonials.tsx, .../VideoGuides.tsx
Rewrote hero and many landing sections to data-driven Card/grid layouts, added interactive hero (video modal), marquees, and new content components.
UI component removals / replacements
apps/web/components/MobileNav.tsx, apps/web/components/NavDropdown.tsx, apps/web/components/landing/ComparisonTable.tsx, apps/web/components/landing/Audience.tsx
Removed legacy MobileNav and NavDropdown files and ComparisonTable; Navbar reimplemented using Sheet and inline dropdown; Audience/other components replaced with new Card-based implementations.
Navbar & Footer
apps/web/components/Navbar.tsx, apps/web/components/Footer.tsx
Navbar rewritten: Sheet-based mobile menu, Docs inline dropdown, new CTAs and icons. Footer converted to client component, moved to data-driven link/social rendering, newsletter included, and decorative patterns/separators added.
Faq / Accordion usage
apps/web/components/FaqAccordion.tsx, apps/web/components/ui/accordion.tsx
FAQ component migrated from Disclosure/Transition to Radix-based Accordion composition and updated styling tokens. New Accordion primitives exported.
Utilities & small libs
apps/web/lib/utils.ts, apps/web/lib/layout.shared.tsx, apps/web/mdx-components.tsx, apps/web/app/docs/[[...slug]]/page.tsx
Added cn (clsx + twMerge), baseOptions shared layout helper, expanded MDX components map, and consolidated mdxComponents usage on docs page.
Docs, plans & content changes
docs/plans/*.md, apps/web/content/docs/**/*.mdx, apps/web/content/docs/architecture/overview.mdx, apps/web/content/docs/*
Added detailed redesign design/implementation plans and migrated multiple docs pages to MDX UI components (Cards, Tabs, Steps, Callouts), reorganized documentation content and architecture pages.
Package & repo metadata
apps/web/package.json, packages/product-config/src/index.ts
Updated dependencies to include Radix UI, framer-motion, CVA, clsx, tailwind-merge, tailwindcss-animate, font packages; adjusted product-config exports to remove .js extensions.
New animation/layout components & helpers
apps/web/components/magicui/*, apps/web/components/ui/*
Multiple additions of animation-heavy components and UI primitives across magicui and ui directories (see files above).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: a full website redesign using shadcn/ui and Magic UI components. It is concise, specific, and directly reflects the primary objective of the pull request.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/website-redesign
📝 Coding Plan
  • Generate coding plan for human review comments

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.

@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: 30

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/components/FaqAccordion.tsx (1)

108-113: ⚠️ Potential issue | 🟠 Major

Add an accessible name to the FAQ search field.

This input only has a placeholder right now. Once a screen-reader user starts typing, the control no longer exposes its purpose. Add a <label> or at least an aria-label.

Minimal fix
         <input
+          aria-label="Search FAQ questions"
           type="text"
           value={search}
           onChange={e => setSearch(e.target.value)}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/components/FaqAccordion.tsx` around lines 108 - 113, The search
input in the FaqAccordion component lacks an accessible name; update the <input>
(the one using value={search} and onChange={e => setSearch(e.target.value)}) to
include an accessible label—either add a visible <label> associated via
htmlFor/id or add an aria-label (e.g., aria-label="Search FAQs") so screen
readers always expose the control purpose; ensure the id on the input matches
the label if you choose a visible label.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/app/`(marketing)/download/page.tsx:
- Around line 86-97: The SVGs inside the platform CardHeader blocks are
decorative and must be hidden from assistive tech; update each <svg> in the
CardHeader (e.g., the macOS card SVG in the CardHeader containing the h2
"macOS") to include aria-hidden="true" and focusable="false" so they're ignored
by screen readers, and apply the same change to the other platform SVGs in this
file (the other CardHeader SVGs for the other platforms).

In `@apps/web/app/`(marketing)/philosophy/page.tsx:
- Around line 161-164: The Link component's className in page.tsx still
hardcodes hover:bg-white/5 and hover:text-white; update that class string on the
Link (the element with className starting "inline-flex items-center...") to use
the design-system semantic tokens used elsewhere on the page (replace
hover:bg-white/5 with the matching hover:bg-* token and hover:text-white with
the corresponding hover:text-* token) so the hover state aligns with the
tokenized color system.

In `@apps/web/app/`(marketing)/pricing/page.tsx:
- Around line 99-100: Replace the hardcoded hex props passed to BorderBeam
(colorFrom="#8b5cf6" colorTo="#6d28d9") with design-token backed values (CSS
variables or shared semantic tokens) so the beam follows theming, e.g. use
var(--token-name) or your shared token constants instead of literal hex strings;
update the JSX where BorderBeam is used and ensure the BorderBeam prop types
(colorFrom/colorTo) accept CSS variable strings if needed so no runtime/type
errors occur.
- Around line 32-34: The page is rebuilding numeric price values from
proPricing.amountCents (monthlyPrice and annualPrice) and forcing decimalPlaces
for the annual path, duplicating pricing logic and risking incorrect displays;
instead, remove the manual amountCents/100 calculations and any hardcoded
decimalPlaces and use the formatted price labels provided by the product-config
pricing facade (packages/product-config/src/facade.ts) wherever proPricing is
consumed (replace usage in monthlyPrice/annualPrice and NumberTicker rendering
and the similar code around lines 109-131) so all display formatting comes from
the facade's canonical pricing fields.
- Line 1: Remove the top-level 'use client' directive from the pricing page so
the route remains a server component; keep client boundaries on the interactive
children (ensure NumberTicker, Accordion, BorderBeam remain as client components
with their own 'use client' directives) and continue using getProductConfig() on
the server to avoid shipping pricing config/static content to the client bundle.

In `@apps/web/app/globals.css`:
- Around line 83-138: Add a prefers-reduced-motion escape hatch: create an
`@media` (prefers-reduced-motion: reduce) block that targets the animation
utilities animate-shiny-text, animate-marquee, animate-marquee-vertical,
animate-shimmer-slide, and animate-spin-around and override them to disable
motion (e.g., set animation: none !important and reset transforms where
appropriate). Ensure you also neutralize any ongoing transform effects from
keyframes like marquee, shimmer-slide, and spin-around by setting transform:
none !important on the same selectors so users who prefer reduced motion do not
get forced animations.
- Around line 5-25: The CSS uses Tailwind v4 directives (`@theme`, `@utility`,
`@apply`) that Biome and Stylelint don't recognize; update lint configs
(biome.json and .stylelintrc.json) to accept Tailwind v4 syntax by adding the
appropriate parser/plugins or rules for Tailwind directives, or alternatively
add an explicit ignore/exclude for this CSS file in those configs so the linter
skips it; ensure you reference the Tailwind directive tokens (`@theme`, `@utility`,
`@apply`) when adding rules/plugins so the linter stops flagging them as errors.

In `@apps/web/components/FaqAccordion.tsx`:
- Around line 39-40: The AccordionItem is using the array index for both key and
value, which breaks stable UI state when items are filtered or reordered; update
the items.map in FaqAccordion.tsx to use a stable per-item identifier (e.g.,
item.id, item.slug, or a deterministic hash of item.question) for both the React
key and the AccordionItem value instead of `index` so open/closed state remains
tied to the same question (refer to the AccordionItem component and the
items.map call to locate where to change `key={index}` and
`value={`faq-${index}`}`).

In `@apps/web/components/landing/Hero.tsx`:
- Around line 47-53: The CTA currently nests a Link inside ShimmerButton
(creating a <button><a>), which is invalid; update the Hero CTA so the
interactive elements aren't nested: either move Link to be the outer element
wrapping ShimmerButton (render the button visuals inside an anchor) or add
asChild support to ShimmerButton so it can render as an anchor when used with
Link; locate the usage in Hero.tsx (the ShimmerButton + Link block) and adjust
the component composition so a single interactive element is rendered (use
ShimmerButton asChild prop or wrap ShimmerButton with Link) and ensure
keyboard/screen-reader behavior remains intact.

In `@apps/web/components/landing/WhyLocal.tsx`:
- Around line 21-39: The CellValue component renders Check/X icons for boolean
values without accessible text; update CellValue to include a readable text
equivalent for booleans (e.g., "Yes"/"No" or the positive/negative semantic) so
assistive tech can consume it: when typeof value === 'boolean' render the icon
plus either an aria-label on the icon (aria-label={`${positive ? 'Yes' :
'No'}`}) or a visually-hidden span (sr-only) containing the string, ensuring
existing string paths remain unchanged; reference the CellValue function and its
value/positive props when making the change.

In `@apps/web/components/magicui/animated-grid-pattern.tsx`:
- Around line 115-136: The inner decorative <svg> should be a translated <g>
element: replace the <svg x={x} y={y} className="overflow-visible"> wrapper in
the AnimatedGridPattern mapping with a <g> that uses transform={`translate(${x},
${y})`} (and keep className="overflow-visible") so the child motion.rects and
their props (width, height, x, y, key, onAnimationComplete ->
updateSquarePosition) remain unchanged; remove the invalid x/y attributes on the
wrapper and ensure the closing tag is </g> to preserve the same visuals without
adding an extra SVG.
- Around line 8-18: The prop repeatDelay declared on AnimatedGridPatternProps is
never used and currently leaks onto the outer <svg>; update the
AnimatedGridPattern component to destructure repeatDelay from its props (e.g.,
const { repeatDelay, ...rest } = props), remove it from the spread passed to the
outer <svg>, and include it in the motion transition config (e.g., transition: {
duration, repeat: Infinity, repeatDelay } or the existing transition object used
by the motion element). Ensure you reference the repeatDelay variable when
building the transition and do not pass repeatDelay through ...props to the svg.

In `@apps/web/components/magicui/animated-shiny-text.tsx`:
- Around line 22-31: The class list in AnimatedShinyText (in
apps/web/components/magicui/animated-shiny-text.tsx) uses hardcoded neutral
color utilities (`text-neutral-600/70`, `dark:text-neutral-400/70`); replace
those with the design token classes (e.g., `text-text-secondary` or
`text-text-muted` and the corresponding dark-mode token) within the same
className composition so the shine effect keeps its background/gradient classes
(the animate-shiny-text, bg-clip-text, bg-gradient-to-r, etc.) but uses
tokenized text color utilities instead of literal neutral values; update any
references to the component’s className composition to preserve ordering and
specificity.
- Around line 1-3: Remove the blank line separating the import groups so the
React imports (ComponentPropsWithoutRef, CSSProperties, FC) and the local
utility import (cn) are adjacent; update the top of the animated-shiny-text
component file to place the two import statements back-to-back with no empty
line between them.

In `@apps/web/components/magicui/border-beam.tsx`:
- Around line 90-95: The current animation ping-pongs because initial={{
offsetDistance: `${initialOffset}%` }} is always the same while the reverse
branch supplies a two-stop array; change the logic in the BorderBeam component
to compute start and end offsets once (e.g., start = reverse ? `${100 -
initialOffset}%` : `${initialOffset}%`, end = reverse ? `${-initialOffset}%` :
`${100 + initialOffset}%`) and use initial={{ offsetDistance: start }} with
animate={{ offsetDistance: end }} (a single target) so the beam starts at the
correct reverse position and moves in one direction rather than ping-ponging;
reference the initialOffset, reverse, and offsetDistance values when
implementing the fix.

In `@apps/web/components/magicui/marquee.tsx`:
- Around line 42-71: Clamp the incoming repeat value to a safe positive integer
before using Array(repeat) (e.g., coerce via Number.isFinite and Math.max(1,
Math.floor(...)) or clamp to an upper bound) to avoid crashes on negative/NaN
counts, and when rendering the duplicated tracks inside the map (the elements
created in the Marquee component where Array(repeat).fill(0).map(...) produces
child tracks) mark cloned tracks as hidden to assistive tech by adding
attributes like aria-hidden="true" and tabIndex={-1} (only keep the original
items accessible) so screen readers don’t announce duplicates; update the
Marquee props handling to perform the clamp and update the mapped divs to
include the accessibility attributes for clones.

In `@apps/web/components/magicui/number-ticker.tsx`:
- Around line 26-27: The span that renders the initial number must use the same
formatted initial value passed into useMotionValue so the first frame and
decimalPlaces formatting match; change the component to compute an initialSeed =
(direction === 'down' ? value : startValue), format it using the same formatting
logic/decimalPlaces used for the motion value, pass initialSeed to
useMotionValue (motionValue) as now, and use the formattedInitialSeed for the
initial DOM text instead of raw startValue; apply the same change to the other
mount points referenced (the blocks around the useMotionValue calls at the other
two locations).

In `@apps/web/components/magicui/shimmer-button.tsx`:
- Around line 11-12: The ShimmerButton props interface redundantly re-declares
className and children which are already provided by
ComponentPropsWithoutRef<'button'>; remove the explicit className?: string and
children?: React.ReactNode declarations from the ShimmerButtonProps (or
equivalent interface) and rely on extending ComponentPropsWithoutRef<'button'>
so that the ShimmerButton component's props come only from that extension plus
any truly custom props.

In `@apps/web/components/magicui/text-reveal.tsx`:
- Around line 8-12: The TextReveal implementation is dropping all div props from
TextRevealProps (which extends ComponentPropsWithoutRef<'div'>); update the
TextReveal function signature to accept the remaining props (e.g., add a rest
param like ...rest alongside className) and spread those onto the root div
element so id, style, data-*, ARIA attributes, etc. are preserved; apply the
same change to the other TextReveal occurrence mentioned so both
TextRevealProps/TextReveal usages forward all div props to the rendered element.
- Around line 57-63: The Word component's wrapper uses an invalid Tailwind class
"xl:lg-3" and the shadow copy span can be announced by screen readers; update
the wrapper className in Word (currently "xl:lg-3 relative mx-1 lg:mx-1.5") to a
valid spacing utility such as "relative mx-1 lg:mx-1.5 xl:mx-3" (or whichever
correct xl spacing you intend) and add aria-hidden="true" to the absolute shadow
span (the element rendering children before the motion.span) to hide the
duplicate content from assistive technologies.

In `@apps/web/components/Navbar.tsx`:
- Around line 139-140: The dropdown panel in Navbar.tsx is absolutely positioned
and uses the class mt-1 which creates a pointer gap under the Docs trigger;
remove the mt-1 from the panel div (the element with classes "invisible absolute
left-1/2 z-50 ... group-hover:visible") so the panel sits flush with the
trigger; if visual separation is still needed, replace mt-1 with a non-layout
transformation such as a small translateY (e.g., translate-y-0.5) or adjust
top/full positioning rather than using margin to avoid the dead zone.

In `@apps/web/components/ui/accordion.tsx`:
- Around line 46-48: Add missing CSS keyframes and utility classes for the
accordion animations referenced on AccordionPrimitive.Content
(animate-accordion-down and animate-accordion-up): update your globals.css to
define `@keyframes` accordion-down and accordion-up that animate height from 0 to
var(--radix-accordion-content-height) and vice versa, and add utility classes
(or Tailwind plugin utilities) animate-accordion-down and animate-accordion-up
that set animation: accordion-down 0.2s ease-out and animation: accordion-up
0.2s ease-out respectively so the data-[state=open]/[state=closed] classes on
AccordionPrimitive.Content work correctly.

In `@apps/web/components/ui/button.tsx`:
- Around line 31-35: The Button component currently inherits HTML's default
submit behavior; update the Button forwardRef signature to set a default type of
"button" (e.g., destructure type = "button" from props) and ensure that when
rendering the fallback 'button' element (Comp when asChild is false) the type
prop is passed through, while preserving asChild behavior (Slot should continue
to forward whatever type the child provides). Modify the Button component
(symbols: Button, asChild, Comp, buttonVariants, cn) so callers get
type="button" by default without changing existing Slot-as-child semantics.

In `@apps/web/components/ui/card.tsx`:
- Around line 22-35: CardTitle and CardDescription currently render as divs
which removes heading/paragraph semantics; update CardTitle to render a heading
element (e.g., h3 or appropriate level) and CardDescription to render a
paragraph (p), update their forwardRef generic types to HTMLHeadingElement and
HTMLParagraphElement respectively, keep the same className merging via cn and
spread {...props}, and preserve displayName values (CardTitle, CardDescription)
so consumers gain proper document structure and improved accessibility.

In `@docs/plans/2026-03-12-website-redesign-design.md`:
- Around line 109-112: Update the JetBrains Mono package name used in the
dependencies list: replace the string '@fontsource/jetbrains-mono' with the
variable-font package '@fontsource-variable/jetbrains-mono' so it matches the
rest of the repo (package.json, lockfiles, and imports); locate the occurrence
in the document where the bullet list contains '@fontsource/jetbrains-mono' and
change it to '@fontsource-variable/jetbrains-mono'.
- Around line 116-130: The fenced file-tree block in the document triggers
markdownlint MD040 because it lacks a language; update the triple-backtick fence
for the tree (the block starting with "apps/web/") to use a plain-text language
tag by changing ``` to ```text so the code fence is labeled and the file passes
MD040 while preserving the exact tree contents.

In `@docs/plans/2026-03-12-website-redesign-implementation.md`:
- Around line 438-452: The unlabeled fenced code block containing the
"Structure:" diagram (with symbols like DotPattern, AnimatedShinyText, h1, CTAs
row, Trust badges row, Editor screenshot) is missing a language tag and triggers
markdownlint MD040; add a language identifier (for example ```text or ```md) to
the opening fence so the block is labeled, keeping the rest of the block
unchanged.
- Around line 816-835: Expand the visual checklist to include accessibility and
interaction checks for the new components: test keyboard navigation and proper
tab order for the Sheet-based mobile nav (open/close via Enter/Space, focus trap
while open, focus return to trigger, and Escape closes), verify Radix Accordion
items (toggle via Enter/Space, aria-expanded states and focus-visible styles),
assert motion controls for ShimmerButton, BorderBeam, NumberTicker,
AnimatedShinyText and TextReveal respect prefers-reduced-motion and provide
non-animated fallbacks, ensure Marquee and DotPattern are dismissible/pausable
and not focus-trapping, and confirm Fumadocs and other pages expose correct ARIA
labels/roles and visible focus outlines for interactive elements.
- Around line 65-80: Before vendoring Magic UI components, add provenance and
MIT license attribution: record the upstream Magic UI version/commit/URL and
include the MIT copyright header in each new component file (e.g.,
animated-shiny-text.tsx, border-beam.tsx, dot-pattern.tsx, marquee.tsx,
number-ticker.tsx, shimmer-button.tsx, text-reveal.tsx,
animated-grid-pattern.tsx) and create a top-level LICENSE or NOTICE file
documenting the upstream source and license; ensure the original copyright and
license text is preserved in component headers and the LICENSE/NOTICE, and keep
the adapted imports (framer-motion and cn()/@/lib/utils) but do not remove or
alter the required attribution text.
- Around line 25-29: The font packages `@fontsource/inter` and
`@fontsource-variable/jetbrains-mono` are imported from app/layout.tsx and must be
installed as runtime dependencies; replace the dev-only install (pnpm add -D
`@fontsource/inter` `@fontsource-variable/jetbrains-mono`) with regular installs
(pnpm add ...) so they are present in production builds, and verify
app/layout.tsx imports still reference those package names.

---

Outside diff comments:
In `@apps/web/components/FaqAccordion.tsx`:
- Around line 108-113: The search input in the FaqAccordion component lacks an
accessible name; update the <input> (the one using value={search} and
onChange={e => setSearch(e.target.value)}) to include an accessible label—either
add a visible <label> associated via htmlFor/id or add an aria-label (e.g.,
aria-label="Search FAQs") so screen readers always expose the control purpose;
ensure the id on the input matches the label if you choose a visible label.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 52ca6dce-d96b-4868-8d42-9899804165b8

📥 Commits

Reviewing files that changed from the base of the PR and between cfe513d and e4d1295.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (39)
  • apps/web/app/(marketing)/changelog/page.tsx
  • apps/web/app/(marketing)/download/page.tsx
  • apps/web/app/(marketing)/faq/page.tsx
  • apps/web/app/(marketing)/philosophy/page.tsx
  • apps/web/app/(marketing)/plugins/page.tsx
  • apps/web/app/(marketing)/pricing/page.tsx
  • apps/web/app/(marketing)/privacy/page.tsx
  • apps/web/app/(marketing)/terms/page.tsx
  • apps/web/app/globals.css
  • apps/web/app/layout.tsx
  • apps/web/components/FaqAccordion.tsx
  • apps/web/components/Footer.tsx
  • apps/web/components/MobileNav.tsx
  • apps/web/components/NavDropdown.tsx
  • apps/web/components/Navbar.tsx
  • apps/web/components/landing/Audience.tsx
  • apps/web/components/landing/ComparisonTable.tsx
  • apps/web/components/landing/Features.tsx
  • apps/web/components/landing/Hero.tsx
  • apps/web/components/landing/SocialProof.tsx
  • apps/web/components/landing/WhyLocal.tsx
  • apps/web/components/magicui/animated-grid-pattern.tsx
  • apps/web/components/magicui/animated-shiny-text.tsx
  • apps/web/components/magicui/border-beam.tsx
  • apps/web/components/magicui/dot-pattern.tsx
  • apps/web/components/magicui/marquee.tsx
  • apps/web/components/magicui/number-ticker.tsx
  • apps/web/components/magicui/shimmer-button.tsx
  • apps/web/components/magicui/text-reveal.tsx
  • apps/web/components/ui/accordion.tsx
  • apps/web/components/ui/badge.tsx
  • apps/web/components/ui/button.tsx
  • apps/web/components/ui/card.tsx
  • apps/web/components/ui/separator.tsx
  • apps/web/components/ui/sheet.tsx
  • apps/web/lib/utils.ts
  • apps/web/package.json
  • docs/plans/2026-03-12-website-redesign-design.md
  • docs/plans/2026-03-12-website-redesign-implementation.md
💤 Files with no reviewable changes (3)
  • apps/web/components/landing/ComparisonTable.tsx
  • apps/web/components/NavDropdown.tsx
  • apps/web/components/MobileNav.tsx

Comment on lines +86 to +97
<Card className="flex flex-col">
<CardHeader className="flex-row items-center gap-5 space-y-0">
<div className="w-14 h-14 flex items-center justify-center shrink-0 bg-accent/10 rounded-lg text-accent">
<svg viewBox="0 0 24 24" width="32" height="32" fill="currentColor">
<path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.8-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z" />
</svg>
</div>
<div>
<h2 className="text-xl font-bold text-[#f4f4f5] mb-1">macOS</h2>
<span className="text-sm text-[#71717a]">macOS 11 Big Sur or later</span>
<h2 className="text-xl font-bold text-text-primary mb-1">macOS</h2>
<span className="text-sm text-text-muted">macOS 11 Big Sur or later</span>
</div>
</header>
<div className="flex flex-wrap gap-3">
{macAssets.length > 0 ? (
macAssets.map((asset, i) => (
<a
key={asset.name}
href={asset.downloadUrl}
className={`inline-flex items-center gap-2 px-4 py-2.5 rounded-lg text-sm font-medium transition-colors ${i === 0 ? 'bg-accent text-white hover:bg-accent-hover' : 'border border-white/[0.08] text-[#a1a1aa] hover:bg-white/5'}`}
>
{i === 0 && <Download size={16} />}
{primaryLabel(asset)}
<span className="text-xs opacity-70">({formatBytes(asset.size)})</span>
</a>
))
) : (
<>
<span className="inline-flex items-center gap-2 px-4 py-2.5 rounded-lg text-sm font-medium bg-accent/50 text-white/50 cursor-not-allowed">
<Download size={16} />
Apple Silicon
</span>
<span className="inline-flex items-center px-4 py-2.5 rounded-lg text-sm font-medium border border-white/[0.08] text-[#71717a] cursor-not-allowed">
Intel
</span>
</>
)}
</div>
<div className="rounded-lg bg-inset border border-white/[0.06] p-4 font-mono text-xs text-[#a1a1aa] overflow-x-auto">
<p className="text-[#71717a] mb-2"># Install from DMG</p>
<p>hdiutil attach Readied-*.dmg</p>
<p>cp -R /Volumes/Readied/Readied.app /Applications/</p>
<p>hdiutil detach /Volumes/Readied</p>
</div>
</article>
</CardHeader>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Hide the decorative platform SVGs from assistive tech.

Each card already has a visible platform label, so these raw SVGs should be marked decorative. Right now they surface as unnamed graphics and trip the current a11y lint.

Suggested fix
-                <svg viewBox="0 0 24 24" width="32" height="32" fill="currentColor">
+                <svg aria-hidden="true" viewBox="0 0 24 24" width="32" height="32" fill="currentColor">
@@
-                <svg viewBox="0 0 24 24" width="32" height="32" fill="currentColor">
+                <svg aria-hidden="true" viewBox="0 0 24 24" width="32" height="32" fill="currentColor">
@@
-                <svg viewBox="0 0 24 24" width="32" height="32" fill="currentColor">
+                <svg aria-hidden="true" viewBox="0 0 24 24" width="32" height="32" fill="currentColor">

Also applies to: 132-143, 176-187

🧰 Tools
🪛 Biome (2.4.6)

[error] 89-89: Alternative text title element cannot be empty

(lint/a11y/noSvgWithoutTitle)

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

In `@apps/web/app/`(marketing)/download/page.tsx around lines 86 - 97, The SVGs
inside the platform CardHeader blocks are decorative and must be hidden from
assistive tech; update each <svg> in the CardHeader (e.g., the macOS card SVG in
the CardHeader containing the h2 "macOS") to include aria-hidden="true" and
focusable="false" so they're ignored by screen readers, and apply the same
change to the other platform SVGs in this file (the other CardHeader SVGs for
the other platforms).

Comment on lines 161 to 164
<Link
href="/"
className="inline-flex items-center gap-2 rounded-lg border border-white/[0.08] px-7 py-3.5 text-base font-medium text-[#a1a1aa] hover:bg-white/5 hover:text-white"
className="inline-flex items-center gap-2 rounded-lg border border-border px-7 py-3.5 text-base font-medium text-text-secondary hover:bg-white/5 hover:text-white"
>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Keep the secondary CTA on semantic tokens.

Line 163 still hardcodes hover:bg-white/5 hover:text-white, so this state will drift from the tokenized design system the rest of the page now uses. Please switch the hover colors to the matching bg-* / text-* tokens as well.

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

In `@apps/web/app/`(marketing)/philosophy/page.tsx around lines 161 - 164, The
Link component's className in page.tsx still hardcodes hover:bg-white/5 and
hover:text-white; update that class string on the Link (the element with
className starting "inline-flex items-center...") to use the design-system
semantic tokens used elsewhere on the page (replace hover:bg-white/5 with the
matching hover:bg-* token and hover:text-white with the corresponding
hover:text-* token) so the hover state aligns with the tokenized color system.

@@ -1,4 +1,5 @@
import type { Metadata } from 'next';
'use client';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Direct client-only APIs used in apps/web/app/(marketing)/pricing/page.tsx ==="
rg -n '\b(useState|useEffect|useLayoutEffect|useRef|useMemo|useCallback|window|document|localStorage|navigator)\b' 'apps/web/app/(marketing)/pricing/page.tsx' || true

echo
echo "=== File header ==="
sed -n '1,40p' 'apps/web/app/(marketing)/pricing/page.tsx'

Repository: tomymaritano/readide

Length of output: 1509


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Full pricing page content ==="
wc -l 'apps/web/app/(marketing)/pricing/page.tsx'
cat -n 'apps/web/app/(marketing)/pricing/page.tsx'

Repository: tomymaritano/readide

Length of output: 10196


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== getProductConfig implementation ==="
find . -type f -name "*.ts" -o -name "*.tsx" | xargs grep -l "export.*getProductConfig" | head -5

echo
echo "=== Check product-config facade ==="
find . -path "*/product-config/*" -name "facade.ts" -o -name "index.ts" | head -3

Repository: tomymaritano/readide

Length of output: 179


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== getProductConfig from facade.ts ==="
cat -n 'packages/product-config/src/facade.ts'

echo
echo "=== NumberTicker implementation ==="
find . -name "number-ticker.tsx" -o -name "number-ticker.ts" | xargs cat -n 2>/dev/null | head -50

echo
echo "=== Accordion implementation (check if already client) ==="
find . -path "*/ui/accordion*" -name "*.tsx" -o -name "*.ts" | xargs head -5 2>/dev/null

Repository: tomymaritano/readide

Length of output: 50379


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== BorderBeam first 10 lines ==="
find . -name "border-beam.tsx" -o -name "border-beam.ts" | xargs head -10 2>/dev/null

echo
echo "=== Can page import getProductConfig from server? ==="
grep -n "export function getProductConfig" packages/product-config/src/facade.ts
</parameter>

Repository: tomymaritano/readide

Length of output: 493


Keep the pricing route server-rendered.

The page is static composition plus getProductConfig(). Since NumberTicker, Accordion, and BorderBeam are already client components (marked with 'use client'), the entire page doesn't need to be client-rendered. Remove the 'use client' directive and let the interactive leaf components handle their own client boundaries—this avoids shipping the pricing config and static content to the client bundle unnecessarily.

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

In `@apps/web/app/`(marketing)/pricing/page.tsx at line 1, Remove the top-level
'use client' directive from the pricing page so the route remains a server
component; keep client boundaries on the interactive children (ensure
NumberTicker, Accordion, BorderBeam remain as client components with their own
'use client' directives) and continue using getProductConfig() on the server to
avoid shipping pricing config/static content to the client bundle.

Comment on lines +32 to +34
// Extract numeric values from price labels for NumberTicker
const monthlyPrice = proPricing.intervals.monthly.amountCents / 100;
const annualPrice = proPricing.intervals.annual.amountCents / 100;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Do not rebuild plan pricing labels in the page.

The page is reformatting amountCents itself, and the annual path already hardcodes decimalPlaces={0}. That will advertise the wrong amount as soon as the annual price is not a whole-dollar value, and it duplicates pricing-display logic outside the pricing facade.

Based on learnings: All pricing, plans, and business model information must be defined in packages/product-config/src/facade.ts as the single source of truth.

Also applies to: 109-131

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

In `@apps/web/app/`(marketing)/pricing/page.tsx around lines 32 - 34, The page is
rebuilding numeric price values from proPricing.amountCents (monthlyPrice and
annualPrice) and forcing decimalPlaces for the annual path, duplicating pricing
logic and risking incorrect displays; instead, remove the manual amountCents/100
calculations and any hardcoded decimalPlaces and use the formatted price labels
provided by the product-config pricing facade
(packages/product-config/src/facade.ts) wherever proPricing is consumed (replace
usage in monthlyPrice/annualPrice and NumberTicker rendering and the similar
code around lines 109-131) so all display formatting comes from the facade's
canonical pricing fields.

Comment on lines +99 to +100
<Card className="relative overflow-hidden glass-card-glow p-6 sm:p-8">
<BorderBeam size={200} duration={8} colorFrom="#8b5cf6" colorTo="#6d28d9" />

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Use token-backed colors for BorderBeam.

These raw hex values bypass the new design-token system, so future palette/theme updates will miss this effect. Please feed the beam CSS variables or shared semantic tokens instead of hardcoded brand colors.

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

In `@apps/web/app/`(marketing)/pricing/page.tsx around lines 99 - 100, Replace the
hardcoded hex props passed to BorderBeam (colorFrom="#8b5cf6" colorTo="#6d28d9")
with design-token backed values (CSS variables or shared semantic tokens) so the
beam follows theming, e.g. use var(--token-name) or your shared token constants
instead of literal hex strings; update the JSX where BorderBeam is used and
ensure the BorderBeam prop types (colorFrom/colorTo) accept CSS variable strings
if needed so no runtime/type errors occur.

Comment on lines +116 to +130
```
apps/web/
├── components/
│ ├── ui/ ← shadcn/ui (Button, Card, Badge, etc.)
│ ├── magicui/ ← Magic UI (copied source, not npm)
│ ├── layout/ ← Navbar, Footer, MobileNav
│ └── landing/ ← Hero, Features, WhyLocal, Pricing, etc.
├── lib/
│ └── utils.ts ← cn() helper
├── app/
│ ├── globals.css ← Design tokens + shadcn CSS vars
│ ├── layout.tsx ← Root layout with fonts
│ ├── (marketing)/ ← Same routes
│ └── docs/ ← Fumadocs (untouched)
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add a language to the fenced file tree block.

This trips markdownlint MD040 at Line 116. Use a plain-text fence so the doc stays lint-clean.

Suggested fix
-```
+```text
 apps/web/
 ├── components/
 │   ├── ui/              ← shadcn/ui (Button, Card, Badge, etc.)
 │   ├── magicui/         ← Magic UI (copied source, not npm)
 │   ├── layout/          ← Navbar, Footer, MobileNav
 │   └── landing/         ← Hero, Features, WhyLocal, Pricing, etc.
 ├── lib/
 │   └── utils.ts         ← cn() helper
 ├── app/
 │   ├── globals.css      ← Design tokens + shadcn CSS vars
 │   ├── layout.tsx       ← Root layout with fonts
 │   ├── (marketing)/     ← Same routes
 │   └── docs/            ← Fumadocs (untouched)
-```
+```
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 116-116: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

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

In `@docs/plans/2026-03-12-website-redesign-design.md` around lines 116 - 130, The
fenced file-tree block in the document triggers markdownlint MD040 because it
lacks a language; update the triple-backtick fence for the tree (the block
starting with "apps/web/") to use a plain-text language tag by changing ``` to
```text so the code fence is labeled and the file passes MD040 while preserving
the exact tree contents.

Comment on lines +25 to +29
```bash
cd apps/web
pnpm add framer-motion class-variance-authority clsx tailwind-merge tailwindcss-animate
pnpm add -D @fontsource/inter @fontsource-variable/jetbrains-mono
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Install the font packages as runtime dependencies.

These packages are imported later from app/layout.tsx, so putting them in devDependencies can break production installs/builds when dev deps are pruned.

Suggested plan change
- pnpm add -D `@fontsource/inter` `@fontsource-variable/jetbrains-mono`
+ pnpm add `@fontsource/inter` `@fontsource-variable/jetbrains-mono`
When a Next.js app imports `@fontsource/inter` and `@fontsource-variable/jetbrains-mono` from application code, should those packages be regular dependencies or devDependencies?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/plans/2026-03-12-website-redesign-implementation.md` around lines 25 -
29, The font packages `@fontsource/inter` and `@fontsource-variable/jetbrains-mono`
are imported from app/layout.tsx and must be installed as runtime dependencies;
replace the dev-only install (pnpm add -D `@fontsource/inter`
`@fontsource-variable/jetbrains-mono`) with regular installs (pnpm add ...) so
they are present in production builds, and verify app/layout.tsx imports still
reference those package names.

Comment on lines +65 to +80
Magic UI components are copied as source files (not npm). Copy only the free components needed per the design doc.

**Files:**

- Create: `apps/web/components/magicui/animated-shiny-text.tsx`
- Create: `apps/web/components/magicui/border-beam.tsx`
- Create: `apps/web/components/magicui/dot-pattern.tsx`
- Create: `apps/web/components/magicui/marquee.tsx`
- Create: `apps/web/components/magicui/number-ticker.tsx`
- Create: `apps/web/components/magicui/shimmer-button.tsx`
- Create: `apps/web/components/magicui/text-reveal.tsx`
- Create: `apps/web/components/magicui/animated-grid-pattern.tsx`

**Step 1: Create each Magic UI component**

Copy source from the Magic UI docs (https://magicui.design/docs/components/). Each component is a single file that uses `framer-motion` and the `cn()` utility. Adapt imports to use `@/lib/utils`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

What license does Magic UI use, and what attribution or notice requirements apply when copying Magic UI component source files into another repository?

💡 Result:

Magic UI’s open-source component repository (magicuidesign/magicui) is licensed under the MIT License. [2]

When you copy Magic UI component source files into another repository, the MIT license’s notice condition applies: you must include the copyright notice and the MIT permission notice “in all copies or substantial portions of the Software.” In practice, this usually means keeping a LICENSE file (or equivalent NOTICE) in your repo and/or preserving license headers/notices in copied files. [1]

Note: Magic UI Pro uses a separate commercial license that prohibits redistribution/sharing of the product (original or modified). So the above MIT copying rules only apply to the open-source repo components, not Pro-only code. [3]


Document Magic UI provenance and license before vendoring source files.

Magic UI is MIT licensed and requires preserving copyright and license notices in copies. Document the upstream version/commit and include MIT license attribution (e.g., in a LICENSE or NOTICE file and/or in the component headers) now, before these files diverge from upstream.

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

In `@docs/plans/2026-03-12-website-redesign-implementation.md` around lines 65 -
80, Before vendoring Magic UI components, add provenance and MIT license
attribution: record the upstream Magic UI version/commit/URL and include the MIT
copyright header in each new component file (e.g., animated-shiny-text.tsx,
border-beam.tsx, dot-pattern.tsx, marquee.tsx, number-ticker.tsx,
shimmer-button.tsx, text-reveal.tsx, animated-grid-pattern.tsx) and create a
top-level LICENSE or NOTICE file documenting the upstream source and license;
ensure the original copyright and license text is preserved in component headers
and the LICENSE/NOTICE, and keep the adapted imports (framer-motion and
cn()/@/lib/utils) but do not remove or alter the required attribution text.

Comment on lines +438 to +452
```
Structure:
├── DotPattern (absolute, behind everything)
├── AnimatedShinyText badge ("v0.6 · Early access")
├── h1: "Your markdown, your machine, your rules."
│ └── gradient-text on middle line
├── Subtitle paragraph
├── CTAs row:
│ ├── ShimmerButton "Download" (primary)
│ └── Button variant="ghost" "View on GitHub"
├── Trust badges row (Offline, Cross-platform, Free/Pro trial)
└── Editor screenshot
├── <img> (same hero-editor.svg)
└── BorderBeam frame (animated glow border)
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add a language to this fenced block.

Line 438 opens an unlabeled code fence, which triggers markdownlint MD040. Use text or md here.

🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 438-438: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

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

In `@docs/plans/2026-03-12-website-redesign-implementation.md` around lines 438 -
452, The unlabeled fenced code block containing the "Structure:" diagram (with
symbols like DotPattern, AnimatedShinyText, h1, CTAs row, Trust badges row,
Editor screenshot) is missing a language tag and triggers markdownlint MD040;
add a language identifier (for example ```text or ```md) to the opening fence so
the block is labeled, keeping the rest of the block unchanged.

Comment on lines +816 to +835
**Step 2: Visual verification checklist**

```bash
cd apps/web && pnpm dev
```

Verify each page:

- [ ] `/` — Hero with DotPattern, ShimmerButton, BorderBeam screenshot, Marquee social proof, Features with hover BorderBeam, WhyLocal with TextReveal, Audience cards
- [ ] `/pricing` — NumberTicker prices, BorderBeam on Pro card, Accordion FAQs
- [ ] `/download` — AnimatedShinyText version badge, platform Cards
- [ ] `/docs` — Fumadocs renders correctly with dark theme
- [ ] `/faq` — Accordion works
- [ ] `/philosophy` — Restyled with new tokens
- [ ] `/changelog` — Restyled
- [ ] `/plugins` — Restyled
- [ ] `/terms`, `/privacy` — Legal pages render
- [ ] Mobile nav — Sheet opens/closes, all links work
- [ ] Fonts — Inter for headings/body, JetBrains Mono for code/logo/badges

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Expand the final checklist beyond visual verification.

This redesign introduces a Sheet-based mobile nav, Radix Accordion, and several motion-heavy components. Add explicit checks for keyboard navigation, focus trap/return, Escape handling, and prefers-reduced-motion; visual-only QA will miss the most likely accessibility regressions.

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

In `@docs/plans/2026-03-12-website-redesign-implementation.md` around lines 816 -
835, Expand the visual checklist to include accessibility and interaction checks
for the new components: test keyboard navigation and proper tab order for the
Sheet-based mobile nav (open/close via Enter/Space, focus trap while open, focus
return to trigger, and Escape closes), verify Radix Accordion items (toggle via
Enter/Space, aria-expanded states and focus-visible styles), assert motion
controls for ShimmerButton, BorderBeam, NumberTicker, AnimatedShinyText and
TextReveal respect prefers-reduced-motion and provide non-animated fallbacks,
ensure Marquee and DotPattern are dismissible/pausable and not focus-trapping,
and confirm Fumadocs and other pages expose correct ARIA labels/roles and
visible focus outlines for interactive elements.

tomymaritano and others added 2 commits March 12, 2026 12:27
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…atibility

Remove file extensions from imports so both Turbopack (web) and tsc
(licensing) can resolve them with moduleResolution: "bundler".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot merged commit 21be0a5 into develop Mar 12, 2026
12 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app:web dependencies Pull requests that update a dependency file size/XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant