Skip to content

feat: Landing Page V2 - Complete Redesign#215

Merged
DevanshuNEU merged 13 commits into
OpenCodeIntel:mainfrom
DevanshuNEU:feature/landing-page-v2-complete
Jan 24, 2026
Merged

feat: Landing Page V2 - Complete Redesign#215
DevanshuNEU merged 13 commits into
OpenCodeIntel:mainfrom
DevanshuNEU:feature/landing-page-v2-complete

Conversation

@DevanshuNEU

@DevanshuNEU DevanshuNEU commented Jan 24, 2026

Copy link
Copy Markdown
Collaborator

Landing Page V2 - Complete Redesign

Summary

Complete landing page overhaul with modern design, improved UX, and professional polish.

Changes

Infrastructure

  • Added shadcn/ui component library
  • Added theme provider with light/dark mode support
  • Migrated from npm to bun for faster builds
  • Downgraded Vite to v6 for stability

Sections Implemented

Section Features
Navbar GitHub stars badge, theme toggle, mobile hamburger menu, sticky blur effect
Hero Auto-typing search demo, staggered headline animation, floating gradient orbs, grid pattern background
Features 6 feature cards with spring hover animations, colored icon backgrounds
Pricing 3 tiers (Free/Pro/Enterprise), Pro tier highlighted with "Coming Soon" badge
FAQ 5 questions in accordion UI
Footer Product/Company/Legal links, social icons, branding

Design System

  • Premium dark theme with glassmorphism
  • Full light mode support with theme-aware borders
  • Responsive design (mobile-first)
  • Framer Motion animations throughout

Screenshots

Hero section with auto-typing demo and gradient background
Feature cards with hover lift animations
Pricing section with highlighted Pro tier
FAQ and Footer

Commits (11 total)

e9f43a6 fix: use theme-aware borders for light mode
f7c41d0 fix: remove Lenis, use native scroll
788a2d3 feat(landing): add smooth scroll + enhanced animations
95b2a66 feat(landing): add FAQ section and footer
dca6674 feat(landing): add pricing section with 3 tiers
a2d185f feat(landing): add features section with 6 key capabilities
b02c34e feat(landing): redesign hero with auto-typing demo
3b8d8f1 feat(landing): redesign navbar with theme toggle and mobile menu
ba78f56 chore: migrate from npm to bun, downgrade vite to v6
f3fc231 feat(landing): add theme provider with light/dark mode
acb231e feat(landing): add shadcn ui components

Testing

  • Build passes (bun run build)
  • Light mode works
  • Dark mode works
  • Mobile responsive
  • All animations performant

Bundle Size

dist/assets/index.css     84.43 kB │ gzip: 14.76 kB
dist/assets/index.js   1,731.62 kB │ gzip: 557.86 kB

Summary by CodeRabbit

  • New Features

    • The landing page gains theme support (light/dark) with a theme toggle, animated hero, and new sections: Features, Pricing, FAQ, Footer.
    • Mobile navigation and a GitHub star count badge added.
    • New reusable UI primitives (accordions, dialogs, menus, sheets, tabs, tooltips, switches, separators) and pricing/FAQ components.
  • Chores

    • Ignore list extended for lockfiles, logs, and tooling locals; CI frontend workflow updated for an alternative runtime and install/build commands.
  • Updates

    • Updated animation and motion tooling versions and build tooling.

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

- accordion: FAQ section support
- dialog: modal/waitlist popup
- navigation-menu: navbar dropdowns
- separator: visual dividers
- sheet: mobile menu drawer
- switch: theme toggle
- tabs: tabbed content
- tooltip: hover hints
- update landing barrel exports
- ThemeProvider using next-themes
- wrap App with ThemeProvider + TooltipProvider
- light mode CSS variables for backgrounds, text, accents
- accordion animations in tailwind config
- switch to bun for faster installs (0.6s vs 23s)
- downgrade vite 7.3 -> 6.4.1 (fixes config bug)
- update .gitignore for bun and pnpm artifacts
- remove package-lock.json, add bun.lock
- add GitHub stars badge with live API count + caching
- add ThemeToggle component (sun/moon icon)
- add MobileMenu with slide-out drawer (Sheet)
- add nav links: Features, Pricing, Docs
- sticky navbar with blur on scroll
- responsive desktop/mobile layouts
- useGitHubStars hook with 5min cache
- new headline: 'Stop feeling lost in unfamiliar codebases'
- add 'Now in beta' badge with sparkle icon
- auto-typing animation cycles through demo queries
- auto-triggers search to show live results
- dual CTA: primary 'Index your first repo' + secondary 'View on GitHub'
- improved subheadline copy
- light/dark mode color fixes
- semantic search, context understanding, instant results
- dependency graph, MCP integration, self-host option
- animated grid with staggered reveal on scroll
- hover effects with subtle glow
- fix landing page to use theme bg/text colors
- Free: 3 repos, public only, community support
- Pro $19/mo: unlimited repos, private, API, MCP (waitlist)
- Enterprise: self-host, SSO, dedicated support
- highlighted Pro tier with badge
- animated cards with stagger reveal
- FAQ: 5 common questions with accordion
- Footer: product/company/legal links, social icons
- wired into landing page flow
- minor Pricing cleanup
- install Lenis for butter-smooth momentum scrolling
- hero: scroll-linked parallax on gradient orbs
- hero: staggered text reveal with blur effect
- hero: grid pattern background
- hero: search box glow pulse
- features: spring-based hover lift + colored shadows
- features: icon scale+rotate on hover
- pricing: enhanced card lift animations
- all: better spring physics throughout
- reduced whitespace for tighter flow
- removed @studio-freight/lenis (caused janky scroll)
- removed scroll-linked parallax (too complex)
- keep floating orbs with simple CSS animations
- add CSS scroll-behavior: smooth
- simplify headline stagger animation (remove blur)
- native scroll feels better
- replace hardcoded white/[0.06] with border-border/50
- feature cards, FAQ items, pricing cards now visible in light mode
- footer borders use theme tokens
@vercel

vercel Bot commented Jan 24, 2026

Copy link
Copy Markdown

@DevanshuNEU is attempting to deploy a commit to the Dev's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jan 24, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Adds a set of new landing UI components and Radix-based UI primitives, introduces a ThemeProvider and TooltipProvider, adds a GitHub-stars hook, expands theming and CSS (light mode, smooth scrolling), updates frontend dependencies and .gitignore, and switches frontend CI steps to Bun.

Changes

Cohort / File(s) Summary
Gitignore & CI
frontend/.gitignore, .github/workflows/ci.yml
Ignore additional lockfiles, pnpm and Vite/Bun artifacts; CI frontend test steps switch from Node/actions/setup-node to oven-sh/setup-bun and use Bun install/build/tsc commands.
Dependencies & Build config
frontend/package.json, frontend/tailwind.config.js
Added multiple @radix-ui/react-* packages; bumped framer-motion; changed vite and @vitejs/plugin-react versions; added accordion keyframes/animations to Tailwind config.
App providers
frontend/src/App.tsx, frontend/src/components/providers/ThemeProvider.tsx
App now wrapped with ThemeProvider and TooltipProvider; new local ThemeProvider re-exports next-themes provider.
Landing — new sections
frontend/src/components/landing/*
frontend/src/components/landing/Features.tsx, Pricing.tsx, FAQ.tsx, Footer.tsx, GitHubStars.tsx, ThemeToggle.tsx, MobileMenu.tsx
New landing components: animated Features grid, Pricing cards, FAQ accordion, Footer, GitHub star badge, theme toggle, and mobile sheet menu.
Landing — composition & UI changes
frontend/src/components/landing/{Hero.tsx, Navbar.tsx, index.ts}, frontend/src/pages/LandingPage.tsx
Major Hero redesign (typing animation, visual/search updates), Navbar rework with desktop nav, GitHubStars, ThemeToggle, MobileMenu; index exports expanded; LandingPage renders new sections when no search.
UI primitives (Radix wrappers)
frontend/src/components/ui/*
accordion.tsx, dialog.tsx, navigation-menu.tsx, separator.tsx, sheet.tsx, switch.tsx, tabs.tsx, tooltip.tsx
Added Radix-based UI components with forwardRef wrappers, styling utilities, animations and exports for Accordion, Dialog, NavigationMenu, Separator, Sheet, Switch, Tabs, Tooltip.
Hooks & utilities
frontend/src/hooks/useGitHubStars.ts
New useGitHubStars hook that fetches repository star count with localStorage caching (5-minute TTL), returns { stars, loading }.
Styling & CSS
frontend/src/index.css
Added global smooth scrolling and a .light CSS-variable override block for light theme tokens.
Misc — git metadata
frontend/.gitignore
Added ignores for package-lock.json, yarn.lock, pnpm-lock.yaml, pnpm-debug.log, Vite local files, and .bun/.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🐇
I hopped through lines with a nibble and cheer,
New toggles, accordions, and stars shining clear,
Sheets that slide in and tooltips that glow,
A light-mode sunrise and Bun on the go,
I twitched my nose — the landing’s now here!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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 PR title 'feat: Landing Page V2 - Complete Redesign' accurately summarizes the main objective of the changeset, which is a comprehensive overhaul of the landing page with modern design, animations, and infrastructure updates.

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

✨ Finishing touches
  • 📝 Generate docstrings

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

- removed em-dash from hero subtitle
- completely rewrote all 5 FAQ answers
- answers now explain concepts in storytelling format
- mentions open source nature and MIT license
- no more AI-generated vibes
@coderabbitai

coderabbitai Bot commented Jan 24, 2026

Copy link
Copy Markdown

Note

Docstrings generation - SUCCESS
Generated docstrings for this pull request at #216

coderabbitai Bot added a commit that referenced this pull request Jan 24, 2026
Docstrings generation was requested by @DevanshuNEU.

* #215 (comment)

The following files were modified:

* `frontend/src/App.tsx`
* `frontend/src/components/landing/FAQ.tsx`
* `frontend/src/components/landing/Features.tsx`
* `frontend/src/components/landing/Footer.tsx`
* `frontend/src/components/landing/GitHubStars.tsx`
* `frontend/src/components/landing/Hero.tsx`
* `frontend/src/components/landing/MobileMenu.tsx`
* `frontend/src/components/landing/Navbar.tsx`
* `frontend/src/components/landing/Pricing.tsx`
* `frontend/src/components/landing/ThemeToggle.tsx`
* `frontend/src/components/providers/ThemeProvider.tsx`
* `frontend/src/hooks/useGitHubStars.ts`
* `frontend/src/pages/LandingPage.tsx`
- replace setup-node with oven-sh/setup-bun
- replace npm ci with bun install
- replace npm run with bun run
- fixes CI failure due to missing package-lock.json
@vercel

vercel Bot commented Jan 24, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Review Updated (UTC)
opencodeintel Ignored Ignored Preview Jan 24, 2026 5:57am

@DevanshuNEU DevanshuNEU merged commit 90b0cf0 into OpenCodeIntel:main Jan 24, 2026
6 checks passed

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

🤖 Fix all issues with AI agents
In `@frontend/src/components/landing/Footer.tsx`:
- Around line 105-107: The external author credit anchor in the Footer component
currently lacks target and rel attributes; update the <a> element (the author
link in Footer.tsx) to open in a new tab by adding target="_blank" and to be
secure by adding rel="noopener noreferrer" so it matches other external links in
the footer.
- Around line 38-54: The social icon anchor elements wrapping the Github and
Twitter components lack accessible labels; add aria-label attributes to each
anchor (the <a> elements that contain the Github and Twitter components) such as
aria-label="OpenCodeIntel on GitHub" and aria-label="OpenCodeIntel on Twitter"
so screen readers can announce the link destinations; update the anchor elements
near the Github and Twitter components in Footer.tsx to include these
aria-labels while keeping existing target/rel/className attributes.

In `@frontend/src/components/landing/Hero.tsx`:
- Around line 45-74: The typing effect currently includes the search function in
its dependency array causing the effect to restart on every query change; fix it
by creating a stable ref for the search handler (e.g., searchRef) and update
that ref whenever the real search changes, then remove search from the useEffect
deps for the typing animation; inside the typing effect call
searchRef.current(query) (or pass the final currentQuery to the ref call)
instead of calling the captured search closure, and keep the dependency array to
[isTyping, typingIndex, setQuery] so the animation no longer retriggers per
character.
- Around line 49-51: The useEffect in Hero.tsx currently calls onResultsReady
whenever results populate, which lets the auto-typing demo trigger navigation;
add a search source tracker (e.g., const lastSearchSource =
useRef<'demo'|'user'|null>(null)) and set lastSearchSource.current = 'demo'
immediately before the demo calls search() and set lastSearchSource.current =
'user' in the user submit handler (or anywhere user-initiated search is
invoked), then guard the effect that calls onResultsReady (the useEffect
referencing results, query, repo.id, searchTime, onResultsReady) to only invoke
onResultsReady when lastSearchSource.current !== 'demo' (and optionally reset
lastSearchSource.current after handling).

In `@frontend/src/components/landing/MobileMenu.tsx`:
- Line 24: The SheetContent in MobileMenu (component MobileMenu / JSX element
SheetContent) uses hardcoded white-based classes like "border-white/10" and
hover/bg classes that don't adapt to light mode; update these className usages
(on the SheetContent element and the internal divider and hoverable items in
MobileMenu) to use theme-aware variants similar to the Navbar pattern (e.g.,
replace fixed "border-white/10" and "hover:bg-white/5" with dual classes such as
"dark:border-white/10 light:border-black/10" and "dark:hover:bg-white/5
light:hover:bg-black/5" or equivalent Tailwind theme-aware utilities) so borders
and hover backgrounds adapt to dark and light themes.

In `@frontend/src/components/landing/Pricing.tsx`:
- Line 33: The ctaHref in Pricing.tsx currently uses a personal email address
(devanshurajesh@gmail.com); update the value of ctaHref to use a
product-specific or company email such as enterprise@codeintel.dev or
sales@codeintel.dev so production contact goes to an official inbox (locate the
ctaHref assignment in the Pricing component and replace the mailto address
accordingly).

In `@frontend/src/components/landing/ThemeToggle.tsx`:
- Around line 16-22: The button's className in ThemeToggle uses a non-existent
Tailwind variant "light:hover:bg-black/5"; remove the "light:" prefix and apply
the default hover class (hover:bg-black/5) for the light mode while keeping the
dark-mode override (dark:hover:bg-white/5). Locate the button in ThemeToggle.tsx
(the element using setTheme and isDark) and replace the "light:hover:bg-black/5"
token with "hover:bg-black/5" so the hover styles work correctly in the light
theme while preserving dark:hover:bg-white/5.

In `@frontend/src/components/ui/sheet.tsx`:
- Around line 67-70: The SheetPrimitive.Close button may render as a plain
<button> and inadvertently submit surrounding forms; update the
SheetPrimitive.Close usage in sheet.tsx (the Close element) to explicitly set
type="button" (or pass the appropriate prop to ensure a non-submit button) so
clicking it won’t trigger form submission, and verify the Close component still
renders the X icon and sr-only span unchanged.

In `@frontend/src/hooks/useGitHubStars.ts`:
- Around line 19-27: The component assumes localStorage JSON is valid but
JSON.parse can throw on corrupted data in useGitHubStars; wrap the parse in a
try-catch around the retrieval of CACHE_KEY and handle parse failures by
removing the bad cache (localStorage.removeItem(CACHE_KEY)), avoid setting stars
from invalid data, and continue with the normal fetch path (ensure setLoading
remains true until a successful fetch or cached data is used); update the code
surrounding CACHE_KEY/CacheData/JSON.parse to perform defensive parsing and
graceful fallback.
🧹 Nitpick comments (10)
frontend/src/components/ui/navigation-menu.tsx (1)

45-65: Trim redundant group class on the trigger.

navigationMenuTriggerStyle already includes group, so adding it again is redundant.

♻️ Proposed cleanup
-    className={cn(navigationMenuTriggerStyle(), "group", className)}
+    className={cn(navigationMenuTriggerStyle(), className)}
frontend/src/components/providers/ThemeProvider.tsx (1)

1-8: "use client" directive is unnecessary in a Vite-only React app.

The "use client" directive is a Next.js-specific feature for the App Router. In a pure Vite/React application, this directive has no effect. It's harmless but adds noise.

Consider removing it unless there are plans to migrate to Next.js, or keep it for potential future compatibility.

frontend/src/hooks/useGitHubStars.ts (1)

29-49: Consider adding an AbortController for cleanup on unmount.

If the component unmounts while the fetch is in-flight, setStars and setLoading will be called on an unmounted component. This can cause React warnings and potential memory leaks.

Proposed fix with abort signal
   useEffect(() => {
+    const controller = new AbortController()
+
     const fetchStars = async () => {
       // ... cache check ...

       try {
-        const res = await fetch(`https://api.github.com/repos/${REPO}`)
+        const res = await fetch(`https://api.github.com/repos/${REPO}`, {
+          signal: controller.signal
+        })
         // ... rest of logic ...
       } catch {
+        if (controller.signal.aborted) return
         // fallback to cached even if expired
         // ...
       } finally {
         setLoading(false)
       }
     }

     fetchStars()
+    return () => controller.abort()
   }, [])
frontend/src/index.css (1)

13-16: Duplicate scroll-behavior: smooth declaration.

This property is declared here (line 15) and again inside @layer base html (line 198). Consider removing one to avoid redundancy.

Proposed fix

Remove lines 13-16 since the same rule exists in @layer base:

-/* Smooth scroll */
-html {
-  scroll-behavior: smooth;
-}
-
 `@layer` base {
frontend/src/components/landing/MobileMenu.tsx (3)

1-1: Remove unused X import.

The X icon is imported but never used in this component.

🔧 Proposed fix
-import { Menu, X } from 'lucide-react'
+import { Menu } from 'lucide-react'

10-14: Duplicate NAV_LINKS definition—consider extracting to a shared constant.

This same NAV_LINKS array is defined in Navbar.tsx (lines 11-15). Extracting it to a shared location (e.g., constants.ts) would improve maintainability and ensure consistency between desktop and mobile navigation.


20-22: Add aria-label to the mobile menu trigger button for accessibility.

Screen readers need context for icon-only buttons.

♿ Proposed fix
-        <button className="p-2 rounded-lg text-zinc-400 hover:text-foreground hover:bg-white/5 transition-colors md:hidden">
+        <button 
+          className="p-2 rounded-lg text-zinc-400 hover:text-foreground hover:bg-white/5 transition-colors md:hidden"
+          aria-label="Open navigation menu"
+        >
frontend/src/components/landing/Features.tsx (1)

104-104: Remove unused index variable.

The index parameter in the map callback is declared but never used.

🔧 Proposed fix
-          {FEATURES.map((feature, index) => (
+          {FEATURES.map((feature) => (
frontend/src/components/landing/Navbar.tsx (1)

11-15: NAV_LINKS duplication with MobileMenu.tsx.

As noted in the MobileMenu review, this constant is duplicated. Consider extracting to a shared module.

frontend/src/components/landing/Pricing.tsx (1)

109-120: Feature list item animations may re-trigger on scroll.

Each feature <motion.li> has its own whileInView animation. Since these are inside a card that's already animating, and viewport={{ once: true }} is set, they should only animate once. However, the staggered delay based on index (delay: 0.1 * i) may not sync well with the parent card's entrance animation.

Consider whether these per-item animations add value or if they could be simplified by inheriting the parent's staggered animation pattern.

Comment on lines +38 to +54
<a
href="https://github.com/OpenCodeIntel/opencodeintel"
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-foreground transition-colors"
>
<Github className="w-5 h-5" />
</a>
<a
href="https://twitter.com/codeintel"
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-foreground transition-colors"
>
<Twitter className="w-5 h-5" />
</a>
</div>

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 accessible labels to social icon links.

The social links contain only icons without accessible text. Screen reader users won't know what these links are for. Add aria-label attributes to describe the link destinations.

Suggested fix
             <div className="flex gap-4">
               <a
                 href="https://github.com/OpenCodeIntel/opencodeintel"
                 target="_blank"
                 rel="noopener noreferrer"
                 className="text-muted-foreground hover:text-foreground transition-colors"
+                aria-label="GitHub repository"
               >
                 <Github className="w-5 h-5" />
               </a>
               <a
                 href="https://twitter.com/codeintel"
                 target="_blank"
                 rel="noopener noreferrer"
                 className="text-muted-foreground hover:text-foreground transition-colors"
+                aria-label="Twitter profile"
               >
                 <Twitter className="w-5 h-5" />
               </a>
             </div>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<a
href="https://github.com/OpenCodeIntel/opencodeintel"
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-foreground transition-colors"
>
<Github className="w-5 h-5" />
</a>
<a
href="https://twitter.com/codeintel"
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-foreground transition-colors"
>
<Twitter className="w-5 h-5" />
</a>
</div>
<a
href="https://github.com/OpenCodeIntel/opencodeintel"
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-foreground transition-colors"
aria-label="GitHub repository"
>
<Github className="w-5 h-5" />
</a>
<a
href="https://twitter.com/codeintel"
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-foreground transition-colors"
aria-label="Twitter profile"
>
<Twitter className="w-5 h-5" />
</a>
</div>
🤖 Prompt for AI Agents
In `@frontend/src/components/landing/Footer.tsx` around lines 38 - 54, The social
icon anchor elements wrapping the Github and Twitter components lack accessible
labels; add aria-label attributes to each anchor (the <a> elements that contain
the Github and Twitter components) such as aria-label="OpenCodeIntel on GitHub"
and aria-label="OpenCodeIntel on Twitter" so screen readers can announce the
link destinations; update the anchor elements near the Github and Twitter
components in Footer.tsx to include these aria-labels while keeping existing
target/rel/className attributes.

Comment on lines +105 to +107
<p className="text-sm text-muted-foreground/60">
Built with ❤️ by <a href="https://github.com/DevanshuNEU" className="hover:text-foreground transition-colors">Devanshu</a>
</p>

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

External link missing target and rel attributes.

The author credit link opens to GitHub but lacks target="_blank" and rel="noopener noreferrer" for consistency with other external links in the footer.

Suggested fix
           <p className="text-sm text-muted-foreground/60">
-            Built with ❤️ by <a href="https://github.com/DevanshuNEU" className="hover:text-foreground transition-colors">Devanshu</a>
+            Built with ❤️ by <a href="https://github.com/DevanshuNEU" target="_blank" rel="noopener noreferrer" className="hover:text-foreground transition-colors">Devanshu</a>
           </p>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<p className="text-sm text-muted-foreground/60">
Built with ❤️ by <a href="https://github.com/DevanshuNEU" className="hover:text-foreground transition-colors">Devanshu</a>
</p>
<p className="text-sm text-muted-foreground/60">
Built with ❤️ by <a href="https://github.com/DevanshuNEU" target="_blank" rel="noopener noreferrer" className="hover:text-foreground transition-colors">Devanshu</a>
</p>
🤖 Prompt for AI Agents
In `@frontend/src/components/landing/Footer.tsx` around lines 105 - 107, The
external author credit anchor in the Footer component currently lacks target and
rel attributes; update the <a> element (the author link in Footer.tsx) to open
in a new tab by adding target="_blank" and to be secure by adding rel="noopener
noreferrer" so it matches other external links in the footer.

Comment on lines +45 to +74
const [isTyping, setIsTyping] = useState(true)
const [typingIndex, setTypingIndex] = useState(0)
const typingTimeoutRef = useRef<ReturnType<typeof setTimeout>>()

useEffect(() => {
if (results.length) onResultsReady?.(results, query, repo.id, searchTime)
}, [results, query, repo.id, searchTime, onResultsReady])

// Typing animation
useEffect(() => {
if (!isTyping) return
const currentQuery = TYPING_QUERIES[typingIndex]
let charIndex = 0
const typeChar = () => {
if (charIndex <= currentQuery.length) {
setQuery(currentQuery.slice(0, charIndex))
charIndex++
typingTimeoutRef.current = setTimeout(typeChar, 60 + Math.random() * 40)
} else {
typingTimeoutRef.current = setTimeout(() => {
search()
typingTimeoutRef.current = setTimeout(() => {
setTypingIndex((i) => (i + 1) % TYPING_QUERIES.length)
}, 4000)
}, 500)
}
}
typingTimeoutRef.current = setTimeout(typeChar, 1500)
return () => { if (typingTimeoutRef.current) clearTimeout(typingTimeoutRef.current) }
}, [isTyping, typingIndex, setQuery, search])

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:

find frontend -type f -name "Hero.tsx" | head -5

Repository: OpenCodeIntel/opencodeintel

Length of output: 111


🏁 Script executed:

wc -l frontend/src/components/landing/Hero.tsx

Repository: OpenCodeIntel/opencodeintel

Length of output: 115


🏁 Script executed:

cat -n frontend/src/components/landing/Hero.tsx | sed -n '1,100p'

Repository: OpenCodeIntel/opencodeintel

Length of output: 4141


🏁 Script executed:

find frontend -type f -name "*useDemoSearch*" | head -5

Repository: OpenCodeIntel/opencodeintel

Length of output: 106


🏁 Script executed:

cat -n frontend/src/hooks/useDemoSearch.ts

Repository: OpenCodeIntel/opencodeintel

Length of output: 3489


Remove search from the typing effect dependency array to prevent re-triggering on each character.

The typing effect resets every character because search is recreated whenever query changes in the hook's state, and since search is in the dependency array, it triggers a re-run. Use a stable reference via searchRef and pass the query explicitly to search() instead of relying on the closure.

Suggested fix
  const [isTyping, setIsTyping] = useState(true)
  const [typingIndex, setTypingIndex] = useState(0)
  const typingTimeoutRef = useRef<ReturnType<typeof setTimeout>>()
+  const searchRef = useRef(search)
+
+  useEffect(() => {
+    searchRef.current = search
+  }, [search])

  // ... existing code ...

  // Typing animation
  useEffect(() => {
    if (!isTyping) return
    const currentQuery = TYPING_QUERIES[typingIndex]
    let charIndex = 0
    const typeChar = () => {
      if (charIndex <= currentQuery.length) {
        setQuery(currentQuery.slice(0, charIndex))
        charIndex++
        typingTimeoutRef.current = setTimeout(typeChar, 60 + Math.random() * 40)
      } else {
        typingTimeoutRef.current = setTimeout(() => {
-          search()
+          searchRef.current(currentQuery, repo.id)
          typingTimeoutRef.current = setTimeout(() => {
            setTypingIndex((i) => (i + 1) % TYPING_QUERIES.length)
          }, 4000)
        }, 500)
      }
    }
    typingTimeoutRef.current = setTimeout(typeChar, 1500)
    return () => { if (typingTimeoutRef.current) clearTimeout(typingTimeoutRef.current) }
-  }, [isTyping, typingIndex, setQuery, search])
+  }, [isTyping, typingIndex, setQuery, repo.id])
🤖 Prompt for AI Agents
In `@frontend/src/components/landing/Hero.tsx` around lines 45 - 74, The typing
effect currently includes the search function in its dependency array causing
the effect to restart on every query change; fix it by creating a stable ref for
the search handler (e.g., searchRef) and update that ref whenever the real
search changes, then remove search from the useEffect deps for the typing
animation; inside the typing effect call searchRef.current(query) (or pass the
final currentQuery to the ref call) instead of calling the captured search
closure, and keep the dependency array to [isTyping, typingIndex, setQuery] so
the animation no longer retriggers per character.

Comment on lines 49 to 51
useEffect(() => {
if (results.length) onResultsReady?.(results, query, repo.id, searchTime)
}, [results, query, repo.id, searchTime, onResultsReady])

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:

find . -type f -name "*.tsx" -o -name "*.ts" | xargs grep -l "Hero" | grep -E "(landing|hero)" | head -10

Repository: OpenCodeIntel/opencodeintel

Length of output: 205


🏁 Script executed:

git ls-files | grep "landing"

Repository: OpenCodeIntel/opencodeintel

Length of output: 803


🏁 Script executed:

find . -path "*/frontend/src/components/landing/*" -name "*.tsx" -o -name "*.ts" | head -20

Repository: OpenCodeIntel/opencodeintel

Length of output: 1008


🏁 Script executed:

ls -la frontend/src/components/landing/ 2>/dev/null || echo "Directory not found"

Repository: OpenCodeIntel/opencodeintel

Length of output: 1223


🏁 Script executed:

cat -n frontend/src/components/landing/Hero.tsx | head -80

Repository: OpenCodeIntel/opencodeintel

Length of output: 3378


🏁 Script executed:

wc -l frontend/src/components/landing/Hero.tsx

Repository: OpenCodeIntel/opencodeintel

Length of output: 115


🏁 Script executed:

cat -n frontend/src/components/landing/Hero.tsx | sed -n '40,150p'

Repository: OpenCodeIntel/opencodeintel

Length of output: 5815


🏁 Script executed:

rg -l "onResultsReady" frontend/src/components/landing/

Repository: OpenCodeIntel/opencodeintel

Length of output: 111


🏁 Script executed:

rg "onResultsReady" frontend/src/ -A 3 -B 3

Repository: OpenCodeIntel/opencodeintel

Length of output: 2157


🏁 Script executed:

rg "Hero" frontend/src/components/landing/ --include="*.tsx" | grep -v "HeroSearch"

Repository: OpenCodeIntel/opencodeintel

Length of output: 512


🏁 Script executed:

find frontend/src -name "*Landing*" -o -name "*landing*" | grep -v node_modules

Repository: OpenCodeIntel/opencodeintel

Length of output: 137


🏁 Script executed:

cat frontend/src/pages/LandingPage.tsx

Repository: OpenCodeIntel/opencodeintel

Length of output: 4129


🏁 Script executed:

rg "useDemoSearch" frontend/src/ -A 20 -B 2

Repository: OpenCodeIntel/opencodeintel

Length of output: 7143


🏁 Script executed:

grep -n "function useDemoSearch\|export.*useDemoSearch" frontend/src/hooks/*.ts frontend/src/hooks/*.tsx

Repository: OpenCodeIntel/opencodeintel

Length of output: 234


🏁 Script executed:

cat frontend/src/hooks/useDemoSearch.ts

Repository: OpenCodeIntel/opencodeintel

Length of output: 2845


🏁 Script executed:

cat -n frontend/src/components/landing/Hero.tsx | sed -n '75,150p'

Repository: OpenCodeIntel/opencodeintel

Length of output: 4105


🏁 Script executed:

cat -n frontend/src/components/landing/Hero.tsx | sed -n '200,337p'

Repository: OpenCodeIntel/opencodeintel

Length of output: 9303


🏁 Script executed:

cat -n frontend/src/components/landing/HeroSearch.tsx

Repository: OpenCodeIntel/opencodeintel

Length of output: 7572


🏁 Script executed:

cat -n frontend/src/components/landing/Hero.tsx | sed -n '53,75p'

Repository: OpenCodeIntel/opencodeintel

Length of output: 1058


Gate demo results from triggering ResultsView navigation.

The auto-typing demo calls search() (line 65), which populates results and fires the useEffect at lines 49-51. This invokes onResultsReady, causing LandingPage.handleHeroResults() to set hasSearched=true and flip to ResultsView. The demo should loop through results inline without navigating away. Add a source tracker to distinguish demo from user-initiated searches.

🛠️ Suggested guard
+  const lastSearchSource = useRef<'demo' | 'user'>('demo')
+
   useEffect(() => {
-    if (results.length) onResultsReady?.(results, query, repo.id, searchTime)
+    if (!results.length || lastSearchSource.current !== 'user') return
+    onResultsReady?.(results, query, repo.id, searchTime)
   }, [results, query, repo.id, searchTime, onResultsReady])

Wiring (example):

  • Set lastSearchSource.current = 'demo' before search() at line 65
  • Set lastSearchSource.current = 'user' in the form submit handler or before calling search() from user interaction
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
if (results.length) onResultsReady?.(results, query, repo.id, searchTime)
}, [results, query, repo.id, searchTime, onResultsReady])
const lastSearchSource = useRef<'demo' | 'user'>('demo')
useEffect(() => {
if (!results.length || lastSearchSource.current !== 'user') return
onResultsReady?.(results, query, repo.id, searchTime)
}, [results, query, repo.id, searchTime, onResultsReady])
🤖 Prompt for AI Agents
In `@frontend/src/components/landing/Hero.tsx` around lines 49 - 51, The useEffect
in Hero.tsx currently calls onResultsReady whenever results populate, which lets
the auto-typing demo trigger navigation; add a search source tracker (e.g.,
const lastSearchSource = useRef<'demo'|'user'|null>(null)) and set
lastSearchSource.current = 'demo' immediately before the demo calls search() and
set lastSearchSource.current = 'user' in the user submit handler (or anywhere
user-initiated search is invoked), then guard the effect that calls
onResultsReady (the useEffect referencing results, query, repo.id, searchTime,
onResultsReady) to only invoke onResultsReady when lastSearchSource.current !==
'demo' (and optionally reset lastSearchSource.current after handling).

<Menu className="w-5 h-5" />
</button>
</SheetTrigger>
<SheetContent side="right" className="w-[300px] bg-background border-l border-white/10">

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

Hardcoded border-white/10 and hover:bg-white/5 won't adapt to light mode.

Unlike the Navbar which uses dark:border-white/10 light:border-black/10 patterns, this component uses fixed white-based borders and backgrounds. This will cause poor contrast in light mode.

🎨 Proposed fix for theme-aware styling
-      <SheetContent side="right" className="w-[300px] bg-background border-l border-white/10">
+      <SheetContent side="right" className="w-[300px] bg-background border-l border-white/10 dark:border-white/10 light:border-black/10">

Apply similar pattern to divider on line 39 and hover states throughout.

Also applies to: 31-31, 39-39

🤖 Prompt for AI Agents
In `@frontend/src/components/landing/MobileMenu.tsx` at line 24, The SheetContent
in MobileMenu (component MobileMenu / JSX element SheetContent) uses hardcoded
white-based classes like "border-white/10" and hover/bg classes that don't adapt
to light mode; update these className usages (on the SheetContent element and
the internal divider and hoverable items in MobileMenu) to use theme-aware
variants similar to the Navbar pattern (e.g., replace fixed "border-white/10"
and "hover:bg-white/5" with dual classes such as "dark:border-white/10
light:border-black/10" and "dark:hover:bg-white/5 light:hover:bg-black/5" or
equivalent Tailwind theme-aware utilities) so borders and hover backgrounds
adapt to dark and light themes.

description: 'For teams that need control',
features: ['Self-hosted deployment', 'SSO / SAML authentication', 'Dedicated support', 'Custom integrations', 'SLA guarantee', 'On-premise option'],
cta: 'Contact Sales',
ctaHref: 'mailto:devanshurajesh@gmail.com?subject=CodeIntel%20Enterprise',

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

Personal email address in production code.

Using a personal email (devanshurajesh@gmail.com) for enterprise sales contact is not ideal for production. Consider using a product-specific email like enterprise@codeintel.dev or sales@codeintel.dev.

🤖 Prompt for AI Agents
In `@frontend/src/components/landing/Pricing.tsx` at line 33, The ctaHref in
Pricing.tsx currently uses a personal email address (devanshurajesh@gmail.com);
update the value of ctaHref to use a product-specific or company email such as
enterprise@codeintel.dev or sales@codeintel.dev so production contact goes to an
official inbox (locate the ctaHref assignment in the Pricing component and
replace the mailto address accordingly).

Comment on lines +16 to +22
<button
onClick={() => setTheme(isDark ? 'light' : 'dark')}
className="p-2 rounded-lg text-zinc-400 hover:text-foreground hover:bg-white/5 dark:hover:bg-white/5 light:hover:bg-black/5 transition-colors"
aria-label={`Switch to ${isDark ? 'light' : 'dark'} mode`}
>
{isDark ? <Sun className="w-5 h-5" /> : <Moon className="w-5 h-5" />}
</button>

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, find Tailwind config files
fd -e js -e ts -e mjs -e mts | grep -E "(tailwind|theme)" | head -20

Repository: OpenCodeIntel/opencodeintel

Length of output: 131


🏁 Script executed:

#!/bin/bash
# Search for the Tailwind config file and check for light: variant definition
find . -maxdepth 2 -type f \( -name "tailwind.config.*" -o -name "next.config.*" \) 2>/dev/null

Repository: OpenCodeIntel/opencodeintel

Length of output: 100


🏁 Script executed:

#!/bin/bash
# Read the full ThemeToggle.tsx file to see all imports and context
cat -n frontend/src/components/landing/ThemeToggle.tsx 2>/dev/null || echo "File not found"

Repository: OpenCodeIntel/opencodeintel

Length of output: 1039


🏁 Script executed:

#!/bin/bash
# Search for "light:" variant anywhere in config/source files
rg "light:" -t js -t ts --max-count 10

Repository: OpenCodeIntel/opencodeintel

Length of output: 1444


🏁 Script executed:

#!/bin/bash
cat -n frontend/tailwind.config.js

Repository: OpenCodeIntel/opencodeintel

Length of output: 7678


Remove non-functional light: Tailwind variant.

The light:hover:bg-black/5 class uses a light: prefix that isn't defined in Tailwind (neither standard nor custom in tailwind.config.js). With darkMode: ["class"], the pattern is to style the default (light) state without a prefix and use dark: for dark mode overrides.

Suggested fix
     <button
       onClick={() => setTheme(isDark ? 'light' : 'dark')}
-      className="p-2 rounded-lg text-zinc-400 hover:text-foreground hover:bg-white/5 dark:hover:bg-white/5 light:hover:bg-black/5 transition-colors"
+      className="p-2 rounded-lg text-zinc-400 hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 transition-colors"
       aria-label={`Switch to ${isDark ? 'light' : 'dark'} mode`}
     >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button
onClick={() => setTheme(isDark ? 'light' : 'dark')}
className="p-2 rounded-lg text-zinc-400 hover:text-foreground hover:bg-white/5 dark:hover:bg-white/5 light:hover:bg-black/5 transition-colors"
aria-label={`Switch to ${isDark ? 'light' : 'dark'} mode`}
>
{isDark ? <Sun className="w-5 h-5" /> : <Moon className="w-5 h-5" />}
</button>
<button
onClick={() => setTheme(isDark ? 'light' : 'dark')}
className="p-2 rounded-lg text-zinc-400 hover:text-foreground hover:bg-black/5 dark:hover:bg-white/5 transition-colors"
aria-label={`Switch to ${isDark ? 'light' : 'dark'} mode`}
>
{isDark ? <Sun className="w-5 h-5" /> : <Moon className="w-5 h-5" />}
</button>
🤖 Prompt for AI Agents
In `@frontend/src/components/landing/ThemeToggle.tsx` around lines 16 - 22, The
button's className in ThemeToggle uses a non-existent Tailwind variant
"light:hover:bg-black/5"; remove the "light:" prefix and apply the default hover
class (hover:bg-black/5) for the light mode while keeping the dark-mode override
(dark:hover:bg-white/5). Locate the button in ThemeToggle.tsx (the element using
setTheme and isDark) and replace the "light:hover:bg-black/5" token with
"hover:bg-black/5" so the hover styles work correctly in the light theme while
preserving dark:hover:bg-white/5.

Comment on lines +67 to +70
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>

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

Ensure the Close button doesn’t submit surrounding forms.

Same concern as Dialog: if SheetPrimitive.Close renders a plain <button>, default submit behavior can leak into forms. Consider setting type="button" if Radix doesn’t already do so.

🛠️ Suggested fix
-      <SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
+      <SheetPrimitive.Close type="button" className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
<SheetPrimitive.Close type="button" className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
🤖 Prompt for AI Agents
In `@frontend/src/components/ui/sheet.tsx` around lines 67 - 70, The
SheetPrimitive.Close button may render as a plain <button> and inadvertently
submit surrounding forms; update the SheetPrimitive.Close usage in sheet.tsx
(the Close element) to explicitly set type="button" (or pass the appropriate
prop to ensure a non-submit button) so clicking it won’t trigger form
submission, and verify the Close component still renders the X icon and sr-only
span unchanged.

Comment on lines +19 to +27
const cached = localStorage.getItem(CACHE_KEY)
if (cached) {
const data: CacheData = JSON.parse(cached)
if (Date.now() - data.timestamp < CACHE_DURATION) {
setStars(data.stars)
setLoading(false)
return
}
}

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

Wrap JSON.parse in try-catch to handle corrupted cache.

If localStorage contains malformed JSON (e.g., manually edited or corrupted), JSON.parse will throw and crash the component. Consider defensive parsing:

Proposed fix
       // check cache first
       const cached = localStorage.getItem(CACHE_KEY)
       if (cached) {
-        const data: CacheData = JSON.parse(cached)
-        if (Date.now() - data.timestamp < CACHE_DURATION) {
-          setStars(data.stars)
-          setLoading(false)
-          return
+        try {
+          const data: CacheData = JSON.parse(cached)
+          if (Date.now() - data.timestamp < CACHE_DURATION) {
+            setStars(data.stars)
+            setLoading(false)
+            return
+          }
+        } catch {
+          localStorage.removeItem(CACHE_KEY)
         }
       }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const cached = localStorage.getItem(CACHE_KEY)
if (cached) {
const data: CacheData = JSON.parse(cached)
if (Date.now() - data.timestamp < CACHE_DURATION) {
setStars(data.stars)
setLoading(false)
return
}
}
const cached = localStorage.getItem(CACHE_KEY)
if (cached) {
try {
const data: CacheData = JSON.parse(cached)
if (Date.now() - data.timestamp < CACHE_DURATION) {
setStars(data.stars)
setLoading(false)
return
}
} catch {
localStorage.removeItem(CACHE_KEY)
}
}
🤖 Prompt for AI Agents
In `@frontend/src/hooks/useGitHubStars.ts` around lines 19 - 27, The component
assumes localStorage JSON is valid but JSON.parse can throw on corrupted data in
useGitHubStars; wrap the parse in a try-catch around the retrieval of CACHE_KEY
and handle parse failures by removing the bad cache
(localStorage.removeItem(CACHE_KEY)), avoid setting stars from invalid data, and
continue with the normal fetch path (ensure setLoading remains true until a
successful fetch or cached data is used); update the code surrounding
CACHE_KEY/CacheData/JSON.parse to perform defensive parsing and graceful
fallback.

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