feat: add /download page and replace navbar login with download button#190
Conversation
- Add /download page with install commands, platform cards, extensions, integrations, and FAQ - Replace Login button in navbar with animated Download button + icon - Add "Download" to desktop nav items - Bump version to v0.1.56 in hero and compare page - Fix npx highlight in hero install commands
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughAdds a new client-side download page with install-command terminal, copy-to-clipboard rows, and extension/integration sections. Updates the navbar to replace the Login CTA with a Download CTA. Bumps version labels in hero and compare pages, fixes an install highlight string, and comments out a hero badge/underline. ChangesDownload Page and Homepage CTA Updates
Estimated code review effort: 2 (Simple) | ~12 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant DownloadPage
participant CopyButton
participant Clipboard
User->>DownloadPage: Open /download page
DownloadPage->>DownloadPage: Render install commands as InstallCommand rows
User->>CopyButton: Click copy icon
CopyButton->>Clipboard: writeText(command)
CopyButton->>User: Show check icon
CopyButton->>CopyButton: Reset icon after 1.5s
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
apps/web/components/homepage/navbar.tsx (1)
231-238: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueRemove commented-out dead code.
The commented-out Login block is dead code. If it needs to be preserved for reference, consider git history instead of leaving commented-out JSX in the source.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/components/homepage/navbar.tsx` around lines 231 - 238, Remove the commented-out Login JSX block from navbar.tsx; the dead code is the commented Link snippet in the homepage navbar component, so delete it entirely rather than leaving commented JSX in place. If you need to reference it later, rely on git history instead of keeping the unused markup in the source.apps/web/components/homepage/hero.tsx (1)
91-96: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueRemove commented-out dead code.
The "live" badge and active-method underline are commented out. If these are temporarily disabled, consider a feature flag or git history rather than leaving commented JSX in the source.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/components/homepage/hero.tsx` around lines 91 - 96, Remove the commented-out dead JSX in the hero component by deleting the inactive “live” badge and active-method underline block from the render path in Hero. Keep the codebase clean by either restoring this logic fully through the relevant method/render branch if it is needed, or removing it entirely from the JSX instead of leaving it commented out. Use the existing hero component and the method/activeMethod conditional rendering as the location to update.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/app/`(pages)/download/page.tsx:
- Line 10: The curl command string in the download page object uses single
quotes, which violates the double-quote string guideline for tsx files. Update
the `cmd` value in the object literal on the `download/page.tsx` page to use
double quotes, matching the other string literals in that file and the project
style.
- Around line 37-52: The CopyButton component updates its copied state before
confirming clipboard success and lacks an accessible label. Update the onClick
handler in CopyButton to await navigator.clipboard.writeText(text) inside
try-catch, only call setCopied(true) after a successful write, and avoid showing
the checkmark on failure; also add a descriptive aria-label to the icon-only
button so it is accessible.
In `@apps/web/components/homepage/navbar.tsx`:
- Line 6: The Navbar component is using a relative import for Button instead of
the configured web app path alias. Update the import in navbar.tsx to use the
absolute alias style already used elsewhere (for example, the same pattern as
the HomepageNavbar import), and make sure the symbol Button still resolves from
the shared ui button module through the alias path.
- Around line 239-248: The Download CTA in navbar should not render a button
inside a link; update the Link/Button composition so the Button uses its
existing asChild support and the anchor semantics come from the Link target
instead of nesting interactive elements. Locate the Download block in navbar.tsx
and adjust the Button usage to pass through to the child element via asChild,
keeping the same styling and SVG/content while avoiding the invalid <a><button>
structure.
---
Nitpick comments:
In `@apps/web/components/homepage/hero.tsx`:
- Around line 91-96: Remove the commented-out dead JSX in the hero component by
deleting the inactive “live” badge and active-method underline block from the
render path in Hero. Keep the codebase clean by either restoring this logic
fully through the relevant method/render branch if it is needed, or removing it
entirely from the JSX instead of leaving it commented out. Use the existing hero
component and the method/activeMethod conditional rendering as the location to
update.
In `@apps/web/components/homepage/navbar.tsx`:
- Around line 231-238: Remove the commented-out Login JSX block from navbar.tsx;
the dead code is the commented Link snippet in the homepage navbar component, so
delete it entirely rather than leaving commented JSX in place. If you need to
reference it later, rely on git history instead of keeping the unused markup in
the source.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 9543f42b-f62d-4aac-83d4-1273db0771c9
📒 Files selected for processing (4)
apps/web/app/(pages)/compare/page.tsxapps/web/app/(pages)/download/page.tsxapps/web/components/homepage/hero.tsxapps/web/components/homepage/navbar.tsx
| import { Check, Copy, ExternalLink, Terminal, Monitor, Apple } from "lucide-react" | ||
|
|
||
| const installCommands: Array<{ label: string; cmd: string }> = [ | ||
| { label: "curl", cmd: 'curl -fsSL https://supercli.dev/install | bash' }, |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use double quotes for strings per coding guidelines.
Line 10 uses single quotes for the cmd string. All other strings in the file use double quotes.
As per coding guidelines for **/*.{ts,tsx}: "Use double quotes for strings".
✏️ Proposed fix
- { label: "curl", cmd: 'curl -fsSL https://supercli.dev/install | bash' },
+ { label: "curl", cmd: "curl -fsSL https://supercli.dev/install | bash" },📝 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.
| { label: "curl", cmd: 'curl -fsSL https://supercli.dev/install | bash' }, | |
| { label: "curl", cmd: "curl -fsSL https://supercli.dev/install | bash" }, |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/app/`(pages)/download/page.tsx at line 10, The curl command string
in the download page object uses single quotes, which violates the double-quote
string guideline for tsx files. Update the `cmd` value in the object literal on
the `download/page.tsx` page to use double quotes, matching the other string
literals in that file and the project style.
Source: Coding guidelines
| function CopyButton({ text }: { text: string }) { | ||
| const [copied, setCopied] = useState(false) | ||
|
|
||
| return ( | ||
| <button | ||
| onClick={() => { | ||
| navigator.clipboard.writeText(text) | ||
| setCopied(true) | ||
| setTimeout(() => setCopied(false), 1500) | ||
| }} | ||
| className="shrink-0 p-1.5 rounded-md hover:bg-white/5 transition-colors text-zinc-500 hover:text-zinc-300" | ||
| > | ||
| {copied ? <Check className="w-4 h-4 text-emerald-400" /> : <Copy className="w-4 h-4" />} | ||
| </button> | ||
| ) | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Handle clipboard write errors and add aria-label to the copy button.
navigator.clipboard.writeText is async but called without try-catch, and setCopied(true) runs unconditionally — users see a "copied" checkmark even if the write fails (e.g., permission denied or non-secure context where navigator.clipboard is undefined, causing a TypeError). Additionally, the button is icon-only with no accessible label.
As per coding guidelines: "Use try-catch for async operations" and "prefer proper null checks over !".
🛡️ Proposed fix
function CopyButton({ text }: { text: string }) {
const [copied, setCopied] = useState(false)
return (
<button
+ aria-label="Copy command"
onClick={() => {
- navigator.clipboard.writeText(text)
- setCopied(true)
- setTimeout(() => setCopied(false), 1500)
+ navigator.clipboard?.writeText(text).then(() => {
+ setCopied(true)
+ setTimeout(() => setCopied(false), 1500)
+ }).catch(() => {})
}}
className="shrink-0 p-1.5 rounded-md hover:bg-white/5 transition-colors text-zinc-500 hover:text-zinc-300"
>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/app/`(pages)/download/page.tsx around lines 37 - 52, The CopyButton
component updates its copied state before confirming clipboard success and lacks
an accessible label. Update the onClick handler in CopyButton to await
navigator.clipboard.writeText(text) inside try-catch, only call setCopied(true)
after a successful write, and avoid showing the checkmark on failure; also add a
descriptive aria-label to the icon-only button so it is accessible.
Source: Coding guidelines
| import React, { useEffect, useState, useCallback } from "react" | ||
| import Link from "next/link" | ||
| import BetaCountdownBanner from "./beta-countdown-banner" | ||
| import { Button } from "../ui/button" |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Use absolute import path alias instead of relative import.
As per coding guidelines for apps/web/**/*.{ts,tsx}: "Use absolute imports with path aliases like @/components/ui/button in the web app." The compare page already uses @/components/homepage/navbar, so the alias is configured.
♻️ Proposed fix
-import { Button } from "../ui/button"
+import { Button } from "`@/components/ui/button`"📝 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.
| import { Button } from "../ui/button" | |
| import { Button } from "`@/components/ui/button`" |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/components/homepage/navbar.tsx` at line 6, The Navbar component is
using a relative import for Button instead of the configured web app path alias.
Update the import in navbar.tsx to use the absolute alias style already used
elsewhere (for example, the same pattern as the HomepageNavbar import), and make
sure the symbol Button still resolves from the shared ui button module through
the alias path.
Source: Coding guidelines
| <Link href="/download"> | ||
| <Button className="bg-white text-black hover:bg-white/90 active:scale-[0.97] cursor-pointer group"> | ||
| <svg className="w-4 h-4 transition-transform duration-[160ms] group-hover:translate-y-0.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"> | ||
| <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /> | ||
| <polyline points="7 10 12 15 17 10" /> | ||
| <line x1="12" y1="15" x2="12" y2="3" /> | ||
| </svg> | ||
| Download | ||
| </Button> | ||
| </Link> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Avoid nesting <button> inside <a> — use asChild on Button.
<Link><Button>...</Button></Link> renders <a><button>...</button></a>, which is invalid HTML (interactive element nested inside interactive element). The Button component already supports asChild via Radix Slot, which merges props onto the child element and avoids the nested tag.
🔧 Proposed fix using `asChild`
- <Link href="/download">
- <Button className="bg-white text-black hover:bg-white/90 active:scale-[0.97] cursor-pointer group">
- <svg className="w-4 h-4 transition-transform duration-[160ms] group-hover:translate-y-0.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
- <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
- <polyline points="7 10 12 15 17 10" />
- <line x1="12" y1="15" x2="12" y2="3" />
- </svg>
- Download
- </Button>
- </Link>
+ <Button asChild className="bg-white text-black hover:bg-white/90 active:scale-[0.97] cursor-pointer group">
+ <Link href="/download">
+ <svg className="w-4 h-4 transition-transform duration-[160ms] group-hover:translate-y-0.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
+ <polyline points="7 10 12 15 17 10" />
+ <line x1="12" y1="15" x2="12" y2="3" />
+ </svg>
+ Download
+ </Link>
+ </Button>📝 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.
| <Link href="/download"> | |
| <Button className="bg-white text-black hover:bg-white/90 active:scale-[0.97] cursor-pointer group"> | |
| <svg className="w-4 h-4 transition-transform duration-[160ms] group-hover:translate-y-0.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"> | |
| <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /> | |
| <polyline points="7 10 12 15 17 10" /> | |
| <line x1="12" y1="15" x2="12" y2="3" /> | |
| </svg> | |
| Download | |
| </Button> | |
| </Link> | |
| <Button asChild className="bg-white text-black hover:bg-white/90 active:scale-[0.97] cursor-pointer group"> | |
| <Link href="/download"> | |
| <svg className="w-4 h-4 transition-transform duration-[160ms] group-hover:translate-y-0.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"> | |
| <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /> | |
| <polyline points="7 10 12 15 17 10" /> | |
| <line x1="12" y1="15" x2="12" y2="3" /> | |
| </svg> | |
| Download | |
| </Link> | |
| </Button> |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/components/homepage/navbar.tsx` around lines 239 - 248, The Download
CTA in navbar should not render a button inside a link; update the Link/Button
composition so the Button uses its existing asChild support and the anchor
semantics come from the Link target instead of nesting interactive elements.
Locate the Download block in navbar.tsx and adjust the Button usage to pass
through to the child element via asChild, keeping the same styling and
SVG/content while avoiding the invalid <a><button> structure.
Description
Please include a summary of the change and which issue is fixed.
Fixes #(issue)
Type of change
How Has This Been Tested?
Please describe the tests that you ran to verify your changes.
bun testpassesbun run typecheckpassesbun run lintpasses (if applicable)Checklist:
Summary by CodeRabbit
New Features
Bug Fixes
npxoption.