-
Notifications
You must be signed in to change notification settings - Fork 412
landing page #1611
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
landing page #1611
Conversation
ComputelessComputer
commented
Nov 2, 2025
- Added new assets and marquee component
- Implemented video section
- Fixed logo cloud and social card
- Enhanced hero section with email submission and interaction
- Added analytics and improved landing page interactions
- Implemented platform-specific hero CTA
- Improved responsive header and design elements
Implement email input with dynamic focus and shake animation Add new sections like CoolStuff and Blog Modify feature list with updated coming soon status Introduce platform-specific hero CTA and context handling Improve user interaction with input reference and submission
Add PostHog analytics, improve download button, and optimize routing for join waitlist and Discord links. Implement Zendesk script and remove unused components.
|
Caution Review failedThe pull request is closed. 📝 WalkthroughWalkthroughAdds PostHog analytics and Loops CRM integration, platform detection and platform-aware CTAs, UI/layout/classname adjustments across the web app, new redirect routes, removal of legacy sync endpoints and a desktop hook, and new provider/context wiring for hero interactions. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Browser
participant Header
participant usePlatform
participant HeroSection
participant HeroContext
participant PostHog
participant Server(LoopsAPI)
User->>Browser: navigate/load page
Browser->>usePlatform: detect UA
usePlatform-->>Header: platform type
Header->>User: render platform-aware CTA
User->>HeroSection: click CTA / focus input
HeroSection->>HeroContext: trigger onTrigger
HeroSection->>PostHog: track event (if initialized)
PostHog-->>HeroSection: ack
User->>HeroSection: submit email
HeroSection->>Server: POST /functions/addContact (LOOPS_KEY)
Server-->>HeroSection: success / error
HeroSection->>User: show success/error feedback
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45–60 minutes
Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (1 passed)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (6)
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/web/src/routes/_view/download.tsx (1)
116-128: Fix invalid Tailwind CSS gradient class name in download button.The class
bg-linear-to-ton line 120 is not valid Tailwind CSS syntax. Usebg-gradient-to-tinstead.Apply this diff to fix the gradient class:
<a href={downloadUrl} - className="group w-full px-4 h-11 flex items-center justify-center bg-linear-to-t from-stone-600 to-stone-500 text-white rounded-full shadow-md hover:shadow-lg hover:scale-[102%] active:scale-[98%] transition-all text-base font-medium" + className="group w-full px-4 h-11 flex items-center justify-center bg-gradient-to-t from-stone-600 to-stone-500 text-white rounded-full shadow-md hover:shadow-lg hover:scale-[102%] active:scale-[98%] transition-all text-base font-medium" >apps/web/src/components/social-card.tsx (1)
55-86: Fix cn() array format violation on line 79 and remove redundant stopPropagation.Line 79 violates the coding guideline requiring
cnto always use array format. Additionally, thestopPropagation()on line 77 is redundant since the outer<div>has noonClickhandler.The current design also limits card interactivity to only the icon, which differs from a typical card pattern where users expect to click anywhere on the card. Consider whether full-card clickability should be restored.
Changes needed:
- Line 79: Change
cn("size-5 shrink-0", config.iconColor)tocn(["size-5 shrink-0", config.iconColor])- Line 77: Remove
onClick={(e) => e.stopPropagation()}- Evaluate UX: decide whether the card should be fully clickable or if affordances should clarify icon-only interactivity
🧹 Nitpick comments (2)
apps/web/src/components/video-thumbnail.tsx (1)
24-24: Reconsideraspect-videowithh-full.The
aspect-videoclass (which setsaspect-ratio: 16/9) combined with bothw-fullandh-fullcreates a constraint conflict. When both dimensions are explicitly set to 100%, theaspect-ratioproperty is typically ignored since both dimensions are already constrained. Consider either:
- Removing
h-fullto letaspect-videocontrol the height based on width- Removing
aspect-videoif the container's dimensions should dictate the sizeIf the intent is to maintain 16:9 aspect ratio, apply this diff:
- className="w-full h-full object-cover pointer-events-none aspect-video" + className="w-full object-cover pointer-events-none aspect-video"If the intent is to fill the container regardless of aspect ratio, apply this diff:
- className="w-full h-full object-cover pointer-events-none aspect-video" + className="w-full h-full object-cover pointer-events-none"apps/web/src/components/join-waitlist-button.tsx (1)
5-9: Consider using a router Link or direct external href for clarity.The component uses an internal route (
/join-waitlist) withtarget="_blank", which works because the route redirects externally. However, this pattern obscures the intent and mixes routing concerns with navigation behavior.Consider one of these approaches:
- Keep the external href directly:
href="https://tally.so/r/mJaRDY"- Use TanStack Router's
Linkcomponent with proper external redirect handlingThis would make the external navigation intent clearer to future maintainers.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (14)
apps/web/public/hyprnote/calendar.jpgis excluded by!**/*.jpgapps/web/public/hyprnote/chat.jpgis excluded by!**/*.jpgapps/web/public/hyprnote/contacts.jpgis excluded by!**/*.jpgapps/web/public/hyprnote/editor.jpgis excluded by!**/*.jpgapps/web/public/hyprnote/no-bots.pngis excluded by!**/*.pngapps/web/public/hyprnote/no-wifi.pngis excluded by!**/*.pngapps/web/public/hyprnote/poster-image.pngis excluded by!**/*.pngapps/web/public/hyprnote/summary.jpgis excluded by!**/*.jpgapps/web/public/hyprnote/transcript.jpgis excluded by!**/*.jpgapps/web/public/patterns/dots.svgis excluded by!**/*.svgapps/web/public/patterns/slash.svgis excluded by!**/*.svgapps/web/src/routeTree.gen.tsis excluded by!**/*.gen.tspackages/ui/src/components/ui/marquee.tsxis excluded by!packages/ui/src/components/ui/**pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (34)
apps/web/.env.sample(1 hunks)apps/web/package.json(2 hunks)apps/web/src/components/download-button.tsx(2 hunks)apps/web/src/components/github-open-source.tsx(2 hunks)apps/web/src/components/join-waitlist-button.tsx(1 hunks)apps/web/src/components/logo-cloud.tsx(3 hunks)apps/web/src/components/social-card.tsx(2 hunks)apps/web/src/components/video-modal.tsx(1 hunks)apps/web/src/components/video-thumbnail.tsx(1 hunks)apps/web/src/hooks/use-platform.ts(1 hunks)apps/web/src/hooks/use-posthog.ts(1 hunks)apps/web/src/providers/posthog.tsx(1 hunks)apps/web/src/router.tsx(2 hunks)apps/web/src/routes/__root.tsx(1 hunks)apps/web/src/routes/_view/app/account.tsx(4 hunks)apps/web/src/routes/_view/blog/$slug.tsx(2 hunks)apps/web/src/routes/_view/blog/index.tsx(2 hunks)apps/web/src/routes/_view/changelog/$slug.tsx(0 hunks)apps/web/src/routes/_view/changelog/index.tsx(0 hunks)apps/web/src/routes/_view/discord/route.tsx(1 hunks)apps/web/src/routes/_view/docs/$slug.tsx(1 hunks)apps/web/src/routes/_view/docs/route.tsx(0 hunks)apps/web/src/routes/_view/download.tsx(1 hunks)apps/web/src/routes/_view/github/route.tsx(1 hunks)apps/web/src/routes/_view/index.tsx(28 hunks)apps/web/src/routes/_view/join-waitlist/route.tsx(1 hunks)apps/web/src/routes/_view/linkedin/route.tsx(1 hunks)apps/web/src/routes/_view/pricing.tsx(5 hunks)apps/web/src/routes/_view/route.tsx(8 hunks)apps/web/src/routes/_view/x/route.tsx(1 hunks)apps/web/src/routes/api/add-contact.ts(1 hunks)apps/web/src/styles.css(1 hunks)packages/ui/components.json(1 hunks)packages/ui/src/styles/globals.css(2 hunks)
💤 Files with no reviewable changes (3)
- apps/web/src/routes/_view/docs/route.tsx
- apps/web/src/routes/_view/changelog/$slug.tsx
- apps/web/src/routes/_view/changelog/index.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/simple.mdc)
After a substantial amount of TypeScript changes, run
pnpm -r typecheck
Files:
apps/web/src/router.tsxapps/web/src/components/download-button.tsxapps/web/src/routes/_view/github/route.tsxapps/web/src/hooks/use-posthog.tsapps/web/src/components/social-card.tsxapps/web/src/routes/_view/docs/$slug.tsxapps/web/src/routes/_view/linkedin/route.tsxapps/web/src/components/join-waitlist-button.tsxapps/web/src/routes/_view/blog/$slug.tsxapps/web/src/routes/_view/x/route.tsxapps/web/src/components/github-open-source.tsxapps/web/src/components/video-thumbnail.tsxapps/web/src/routes/_view/route.tsxapps/web/src/routes/_view/blog/index.tsxapps/web/src/routes/_view/join-waitlist/route.tsxapps/web/src/routes/_view/index.tsxapps/web/src/providers/posthog.tsxapps/web/src/routes/__root.tsxapps/web/src/hooks/use-platform.tsapps/web/src/routes/_view/discord/route.tsxapps/web/src/routes/api/add-contact.tsapps/web/src/components/video-modal.tsxapps/web/src/routes/_view/app/account.tsxapps/web/src/components/logo-cloud.tsxapps/web/src/routes/_view/download.tsxapps/web/src/routes/_view/pricing.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/simple.mdc)
**/*.{tsx,jsx}: When many classNames have conditional logic in React components, usecnfrom@hypr/utils
When usingcn, always pass an array of class segments
When usingcn, split entries by logical grouping for readability
Usemotion/reactinstead offramer-motion
Files:
apps/web/src/router.tsxapps/web/src/components/download-button.tsxapps/web/src/routes/_view/github/route.tsxapps/web/src/components/social-card.tsxapps/web/src/routes/_view/docs/$slug.tsxapps/web/src/routes/_view/linkedin/route.tsxapps/web/src/components/join-waitlist-button.tsxapps/web/src/routes/_view/blog/$slug.tsxapps/web/src/routes/_view/x/route.tsxapps/web/src/components/github-open-source.tsxapps/web/src/components/video-thumbnail.tsxapps/web/src/routes/_view/route.tsxapps/web/src/routes/_view/blog/index.tsxapps/web/src/routes/_view/join-waitlist/route.tsxapps/web/src/routes/_view/index.tsxapps/web/src/providers/posthog.tsxapps/web/src/routes/__root.tsxapps/web/src/routes/_view/discord/route.tsxapps/web/src/components/video-modal.tsxapps/web/src/routes/_view/app/account.tsxapps/web/src/components/logo-cloud.tsxapps/web/src/routes/_view/download.tsxapps/web/src/routes/_view/pricing.tsx
🧠 Learnings (3)
📚 Learning: 2025-10-26T00:28:22.035Z
Learnt from: CR
Repo: fastrepl/hyprnote PR: 0
File: .cursor/rules/simple.mdc:0-0
Timestamp: 2025-10-26T00:28:22.035Z
Learning: Applies to **/*.{tsx,jsx} : When many classNames have conditional logic in React components, use `cn` from `hypr/utils`
Applied to files:
apps/web/src/components/download-button.tsxapps/web/src/routes/_view/docs/$slug.tsxapps/web/src/routes/_view/blog/$slug.tsxapps/web/src/routes/_view/index.tsxapps/web/src/routes/_view/pricing.tsx
📚 Learning: 2025-10-26T00:28:22.035Z
Learnt from: CR
Repo: fastrepl/hyprnote PR: 0
File: .cursor/rules/simple.mdc:0-0
Timestamp: 2025-10-26T00:28:22.035Z
Learning: Applies to **/*.{tsx,jsx} : When using `cn`, always pass an array of class segments
Applied to files:
apps/web/src/routes/_view/docs/$slug.tsxapps/web/src/routes/_view/blog/$slug.tsx
📚 Learning: 2025-10-26T00:28:22.035Z
Learnt from: CR
Repo: fastrepl/hyprnote PR: 0
File: .cursor/rules/simple.mdc:0-0
Timestamp: 2025-10-26T00:28:22.035Z
Learning: Applies to **/*.{tsx,jsx} : When using `cn`, split entries by logical grouping for readability
Applied to files:
apps/web/src/routes/_view/docs/$slug.tsxapps/web/src/routes/_view/blog/$slug.tsx
🧬 Code graph analysis (12)
apps/web/src/router.tsx (1)
apps/web/src/providers/posthog.tsx (1)
PostHogProvider(16-18)
apps/web/src/routes/_view/github/route.tsx (4)
apps/web/src/routes/_view/discord/route.tsx (1)
Route(3-9)apps/web/src/routes/_view/join-waitlist/route.tsx (1)
Route(3-9)apps/web/src/routes/_view/linkedin/route.tsx (1)
Route(3-9)apps/web/src/routes/_view/x/route.tsx (1)
Route(3-9)
apps/web/src/components/social-card.tsx (1)
packages/utils/src/cn.ts (1)
cn(20-22)
apps/web/src/routes/_view/linkedin/route.tsx (4)
apps/web/src/routes/_view/discord/route.tsx (1)
Route(3-9)apps/web/src/routes/_view/github/route.tsx (1)
Route(3-9)apps/web/src/routes/_view/join-waitlist/route.tsx (1)
Route(3-9)apps/web/src/routes/_view/x/route.tsx (1)
Route(3-9)
apps/web/src/routes/_view/x/route.tsx (4)
apps/web/src/routes/_view/discord/route.tsx (1)
Route(3-9)apps/web/src/routes/_view/github/route.tsx (1)
Route(3-9)apps/web/src/routes/_view/join-waitlist/route.tsx (1)
Route(3-9)apps/web/src/routes/_view/linkedin/route.tsx (1)
Route(3-9)
apps/web/src/routes/_view/route.tsx (1)
apps/web/src/hooks/use-platform.ts (2)
usePlatform(5-30)getPlatformCTA(32-40)
apps/web/src/routes/_view/join-waitlist/route.tsx (4)
apps/web/src/routes/_view/discord/route.tsx (1)
Route(3-9)apps/web/src/routes/_view/github/route.tsx (1)
Route(3-9)apps/web/src/routes/_view/linkedin/route.tsx (1)
Route(3-9)apps/web/src/routes/_view/x/route.tsx (1)
Route(3-9)
apps/web/src/routes/_view/index.tsx (6)
apps/web/src/components/github-open-source.tsx (1)
GitHubOpenSource(138-289)apps/web/src/hooks/use-platform.ts (3)
usePlatform(5-30)getHeroCTA(42-70)getPlatformCTA(32-40)apps/web/src/routes/_view/route.tsx (1)
useHeroContext(18-20)apps/web/src/hooks/use-posthog.ts (1)
useAnalytics(9-45)apps/web/src/components/download-button.tsx (1)
DownloadButton(6-21)apps/web/src/components/github-stars.tsx (1)
GithubStars(6-36)
apps/web/src/routes/_view/discord/route.tsx (4)
apps/web/src/routes/_view/github/route.tsx (1)
Route(3-9)apps/web/src/routes/_view/join-waitlist/route.tsx (1)
Route(3-9)apps/web/src/routes/_view/linkedin/route.tsx (1)
Route(3-9)apps/web/src/routes/_view/x/route.tsx (1)
Route(3-9)
apps/web/src/routes/_view/app/account.tsx (1)
apps/web/src/hooks/use-posthog.ts (1)
useAnalytics(9-45)
apps/web/src/routes/_view/download.tsx (1)
packages/utils/src/cn.ts (1)
cn(20-22)
apps/web/src/routes/_view/pricing.tsx (1)
packages/utils/src/cn.ts (1)
cn(20-22)
🪛 dotenv-linter (4.0.0)
apps/web/.env.sample
[warning] 18-18: [QuoteCharacter] The value has quote characters (', ")
(QuoteCharacter)
[warning] 19-19: [QuoteCharacter] The value has quote characters (', ")
(QuoteCharacter)
[warning] 21-21: [QuoteCharacter] The value has quote characters (', ")
(QuoteCharacter)
🪛 Gitleaks (8.28.0)
apps/web/src/routes/__root.tsx
[high] 30-30: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🔇 Additional comments (27)
apps/web/src/styles.css (1)
21-45: LGTM!The shake animation is well-implemented using GPU-accelerated
translateXtransforms. The symmetrical oscillation pattern (-4px / +4px) and 0.5s ease-in-out timing are appropriate for subtle UI feedback/emphasis. Proper placement in the@layer utilitiesensures it integrates cleanly with the Tailwind CSS utility system.apps/web/src/components/github-open-source.tsx (2)
94-99: Proper use ofcnutility with array format and logical grouping.The OpenSourceButton's className already follows the coding guidelines:
cn()receives an array of class segments split by logical intent (layout, color/styling, interactions, transitions).
144-147: Asset verified—decorative dividers are correctly styled and referenced.The two new decorative divider blocks create a symmetric frame around the GitHubOpenSource section with consistent neutral styling. The SVG asset at
/patterns/slash.svgexists and will render correctly.packages/ui/components.json (3)
15-15: Confirm thecomponentsalias path is correctly used across the project.The alias updated to
@hypr/ui/components. Ensure all component imports in the codebase that rely on this alias (or the previous path) continue to work correctly.
13-13: No issues found—iconLibrary: "lucide"is a valid, documented configuration option.The
iconLibraryfield is an official part of shadcn/ui's components.json schema and "lucide" is a supported icon library. The configuration is correct as written.
21-23: MagicUI registry URL verified — configuration is valid.All verification items confirmed:
- The MagicUI registry endpoint (
https://magicui.design/r/{name}.json) is publicly accessible and returns valid component definitions conforming to the shadcn/ui registry schema.- shadcn/ui supports the registries field in components.json in current versions.
- The
{name}placeholder substitution works as expected (tested with terminal component, returned HTTP 200 with properly formatted registry item).apps/web/src/components/video-thumbnail.tsx (1)
21-21: Poster image file verified.The poster image at
/hyprnote/poster-image.pngexists in the public directory and is correctly referenced.apps/web/src/routes/_view/download.tsx (1)
16-30: LGTM! Good use ofcnutility.The header section correctly uses the
cnutility with an array format and logical grouping of classes, following the coding guidelines.apps/web/src/components/video-modal.tsx (1)
63-65: LGTM! Follows coding guidelines.The className construction now uses array format with logical grouping, aligning with the project's coding guidelines.
As per coding guidelines.
packages/ui/src/styles/globals.css (2)
59-63: The review comment is incorrect. The--durationvariable is defined at the component level, not globally.The marquee animations use a component-scoped pattern where CSS custom properties are defined where animations are applied. In
packages/ui/src/components/ui/marquee.tsxline 49, the component provides both--durationand--gapvia Tailwind's bracket notation:"group flex [gap:var(--gap)] overflow-hidden p-2 [--duration:40s] [--gap:1rem]"This is the correct design: global keyframe definitions in
globals.cssare reusable, and each component supplies its own variable values inline. The@theme inlinesyntax is valid in Tailwind CSS v4 and correctly encapsulates the keyframes.Likely an incorrect or invalid review comment.
83-100: Remove@theme inlinewrapper, but use@layer utilitiesinstead of bare@keyframesfor Tailwind v3.4 compatibility.The review comment incorrectly claims
@theme inlineis non-standard. In fact,@theme inlineis a valid, documented Tailwind directive used to define theme variables inline. However, the core concern is valid:@keyframesshould not be placed inside@theme inline(which is designed for CSS variables/tokens).For Tailwind v3.4.18, place
@keyframesinside a CSS cascade layer using@layer utilities, or define them intailwind.config.js. The suggested diff that removes the wrapper and places bare@keyframesat root level is valid CSS but suboptimal for Tailwind integration.Replace with:
@layer utilities { @keyframes marquee { from { transform: translateX(0); } to { transform: translateX(calc(-100% - var(--gap))); } } @keyframes marquee-vertical { from { transform: translateY(0); } to { transform: translateY(calc(-100% - var(--gap))); } } }Likely an incorrect or invalid review comment.
apps/web/src/routes/__root.tsx (1)
28-33: LGTM!The Zendesk script is correctly configured with
defer: true. The key in the URL is a public widget identifier intended for client-side use, not a secret credential.apps/web/src/routes/_view/docs/$slug.tsx (1)
212-219: LGTM!The className refactor correctly follows the coding guidelines by passing an array to
cnwith logical grouping for readability.apps/web/.env.sample (1)
18-21: LGTM!The new environment variables correctly support the PostHog and Loops integrations. The quote characters in the sample file are acceptable as placeholders.
apps/web/src/components/download-button.tsx (1)
17-18: Verify platform-specific hardcoding.The button is now hardcoded to show "Download for Mac" with an Apple icon. Given that the PR introduces platform detection hooks (mentioned in the AI summary for
apps/web/src/hooks/use-platform.ts), verify whether this component should dynamically adapt to the user's platform or if Mac-only is intentional.apps/web/package.json (1)
20-20: LGTM!The PostHog dependencies are correctly added to support the analytics integration introduced in this PR.
apps/web/src/routes/_view/blog/$slug.tsx (1)
141-148: LGTM!The className refactors correctly follow the coding guidelines by passing arrays to
cnwith logical grouping for readability.Also applies to: 219-224
apps/web/src/routes/_view/join-waitlist/route.tsx (1)
1-9: LGTM!The redirect route correctly follows the established pattern used in other social/external redirect routes (discord, github, linkedin, x).
apps/web/src/routes/_view/blog/index.tsx (2)
32-36: LGTM!The layout changes correctly layer the dots pattern background behind the content container while preserving the gradient effect.
227-232: LGTM!The className refactor correctly follows the coding guidelines by passing an array to
cnwith logical grouping for readability.apps/web/src/components/logo-cloud.tsx (1)
113-113: Verify the border addition is intentional.The Bain logo card now has a visible border (
border-neutral-100) where previously it had no border classes. This introduces a new visual element that wasn't present before.Please confirm this border addition aligns with the intended design for the logo grid layout.
apps/web/src/hooks/use-posthog.ts (1)
9-45: LGTM! Clean analytics wrapper with proper SSR guards.The implementation correctly:
- Guards against missing PostHog instances (SSR-safe)
- Uses
useCallbackwith appropriate dependencies for stable references- Provides a type-safe interface for analytics tracking
apps/web/src/router.tsx (1)
17-21: LGTM! Standard provider composition pattern.The PostHogProvider correctly wraps the QueryClientProvider, making PostHog context available throughout the application.
apps/web/src/routes/_view/linkedin/route.tsx (1)
3-9: LGTM! Consistent external redirect pattern.This route follows the same clean pattern used by the other external redirect routes (discord, github, x) in this PR. The beforeLoad hook ensures immediate redirection before any component rendering.
apps/web/src/routes/_view/discord/route.tsx (1)
3-9: LGTM! Consistent external redirect implementation.apps/web/src/routes/_view/github/route.tsx (1)
3-9: LGTM! Consistent external redirect implementation.apps/web/src/routes/_view/x/route.tsx (1)
3-9: LGTM! Consistent external redirect implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
♻️ Duplicate comments (2)
apps/web/src/routes/join-waitlist.tsx (1)
1-9: Consider consolidating redirect routes into a single utility.This route shares the same duplication concern as the other redirect routes (
/github,/discord,/x).apps/web/src/routes/_view/index.tsx (1)
1150-1228: Consider implementing navigation for "Learn more" button.Similar to the features grid, the "Learn more" button on line 1220 lacks a click handler or navigation target.
🧹 Nitpick comments (5)
apps/web/src/providers/posthog.tsx (1)
17-21: Consider checking PostHog initialization before capturing.The optional chaining on Line 19 suggests defensive programming, but since
posthogis initialized unconditionally at module level, it's never null. With the suggested fix above to conditionally initialize PostHog, this check becomes meaningful.After applying the conditional initialization, update the hook to verify PostHog is initialized:
export function usePostHogPageView() { useEffect(() => { - posthog?.capture("$pageview"); + if (posthog.__loaded) { + posthog.capture("$pageview"); + } }, []); }apps/web/src/routes/_view/app/account.tsx (1)
254-271: Enhance email validation in the form.Line 257's validation only checks if the value exists (
!value), not whether it's a valid email. While the browser'stype="email"provides basic validation and the server'sinputSchemaenforces email format, client-side validation would improve UX.Apply this diff to add email format validation:
<form.Field name="email" validators={{ - onChange: ({ value }) => !value ? "Email is required" : undefined, + onChange: ({ value }) => { + if (!value) return "Email is required"; + if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) { + return "Please enter a valid email address"; + } + return undefined; + }, }} >Alternatively, use Zod for consistency with the server schema:
+import { z } from "zod"; + +const emailSchema = z.string().email(); + <form.Field name="email" validators={{ - onChange: ({ value }) => !value ? "Email is required" : undefined, + onChange: ({ value }) => { + const result = emailSchema.safeParse(value); + return result.success ? undefined : "Please enter a valid email address"; + }, }} >apps/web/src/routes/github.tsx (1)
1-9: Consider consolidating redirect routes into a single utility.Five redirect routes (
/github,/discord,/join-waitlist,/x) share identical structure with only the target URL differing. You could reduce duplication by creating a shared redirect utility or a data-driven route configuration.Example approach:
// utils/redirect-route.ts export function createRedirectRoute(path: string, href: string) { return createFileRoute(path)({ beforeLoad: () => { throw redirect({ href }); }, }); }Then in each route file:
import { createRedirectRoute } from "@/utils/redirect-route"; export const Route = createRedirectRoute("/github", "https://github.com/fastrepl/hyprnote");apps/web/src/routes/_view/index.tsx (2)
798-976: Consider implementing navigation for "Learn more" buttons.The hover overlays reveal "Learn more" buttons on lines 832, 876, and 920, but these buttons don't have
onClickhandlers or navigation. Consider linking them to feature documentation or demos, or remove them if no destination is planned.
1407-1420: Prefer React state over direct DOM manipulation.Lines 1413-1416 directly manipulate the input's parent classList, which bypasses React's state management and could cause issues if the component unmounts during the timeout. Consider using the existing shake state mechanism from
HeroSectionor implementing a similar state-based approach in the shared hero context.Example approach:
const handleCTAClick = () => { if (platformCTA.action === "waitlist") { window.scrollTo({ top: 0, behavior: "smooth" }); setTimeout(() => { const heroContext = useHeroContext(); if (heroContext?.onTrigger) { heroContext.onTrigger(); } }, 500); } };This would delegate the shake animation to the HeroSection's existing trigger mechanism.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
.cursor/rules/simple.mdcis excluded by!**/.cursor/**apps/web/src/routeTree.gen.tsis excluded by!**/*.gen.ts
📒 Files selected for processing (17)
apps/desktop/src/hooks/useQuery.ts(0 hunks)apps/web/src/components/join-waitlist-button.tsx(2 hunks)apps/web/src/env.ts(1 hunks)apps/web/src/functions/loops.ts(1 hunks)apps/web/src/providers/posthog.tsx(1 hunks)apps/web/src/routes/_view/app/account.tsx(7 hunks)apps/web/src/routes/_view/index.tsx(28 hunks)apps/web/src/routes/_view/pricing.tsx(6 hunks)apps/web/src/routes/_view/route.tsx(8 hunks)apps/web/src/routes/api/sync.read.ts(0 hunks)apps/web/src/routes/api/sync.write.ts(0 hunks)apps/web/src/routes/discord.tsx(1 hunks)apps/web/src/routes/github.tsx(1 hunks)apps/web/src/routes/join-waitlist.tsx(1 hunks)apps/web/src/routes/linkedin.tsx(1 hunks)apps/web/src/routes/x.tsx(1 hunks)apps/web/vite.config.ts(1 hunks)
💤 Files with no reviewable changes (3)
- apps/web/src/routes/api/sync.write.ts
- apps/web/src/routes/api/sync.read.ts
- apps/desktop/src/hooks/useQuery.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/web/src/components/join-waitlist-button.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/simple.mdc)
After a substantial amount of TypeScript changes, run
pnpm -r typecheck
Files:
apps/web/src/routes/linkedin.tsxapps/web/vite.config.tsapps/web/src/routes/github.tsxapps/web/src/functions/loops.tsapps/web/src/routes/_view/pricing.tsxapps/web/src/routes/discord.tsxapps/web/src/routes/join-waitlist.tsxapps/web/src/routes/_view/route.tsxapps/web/src/providers/posthog.tsxapps/web/src/routes/_view/app/account.tsxapps/web/src/env.tsapps/web/src/routes/x.tsxapps/web/src/routes/_view/index.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/simple.mdc)
**/*.{tsx,jsx}: When many classNames have conditional logic in React components, usecnfrom@hypr/utils
When usingcn, always pass an array of class segments
When usingcn, split entries by logical grouping for readability
Usemotion/reactinstead offramer-motion
Files:
apps/web/src/routes/linkedin.tsxapps/web/src/routes/github.tsxapps/web/src/routes/_view/pricing.tsxapps/web/src/routes/discord.tsxapps/web/src/routes/join-waitlist.tsxapps/web/src/routes/_view/route.tsxapps/web/src/providers/posthog.tsxapps/web/src/routes/_view/app/account.tsxapps/web/src/routes/x.tsxapps/web/src/routes/_view/index.tsx
🧠 Learnings (3)
📚 Learning: 2025-10-26T00:28:22.035Z
Learnt from: CR
Repo: fastrepl/hyprnote PR: 0
File: .cursor/rules/simple.mdc:0-0
Timestamp: 2025-10-26T00:28:22.035Z
Learning: Applies to **/*.{tsx,jsx} : When many classNames have conditional logic in React components, use `cn` from `hypr/utils`
Applied to files:
apps/web/src/routes/_view/pricing.tsxapps/web/src/routes/_view/index.tsx
📚 Learning: 2025-10-26T00:28:22.035Z
Learnt from: CR
Repo: fastrepl/hyprnote PR: 0
File: .cursor/rules/simple.mdc:0-0
Timestamp: 2025-10-26T00:28:22.035Z
Learning: Applies to **/*.{tsx,jsx} : When using `cn`, split entries by logical grouping for readability
Applied to files:
apps/web/src/routes/_view/pricing.tsx
📚 Learning: 2025-10-26T00:28:22.035Z
Learnt from: CR
Repo: fastrepl/hyprnote PR: 0
File: .cursor/rules/simple.mdc:0-0
Timestamp: 2025-10-26T00:28:22.035Z
Learning: Applies to **/*.{tsx,jsx} : When using `cn`, always pass an array of class segments
Applied to files:
apps/web/src/routes/_view/pricing.tsx
🧬 Code graph analysis (10)
apps/web/src/routes/linkedin.tsx (4)
apps/web/src/routes/discord.tsx (1)
Route(3-9)apps/web/src/routes/github.tsx (1)
Route(3-9)apps/web/src/routes/join-waitlist.tsx (1)
Route(3-9)apps/web/src/routes/x.tsx (1)
Route(3-9)
apps/web/src/routes/github.tsx (4)
apps/web/src/routes/discord.tsx (1)
Route(3-9)apps/web/src/routes/join-waitlist.tsx (1)
Route(3-9)apps/web/src/routes/linkedin.tsx (1)
Route(3-9)apps/web/src/routes/x.tsx (1)
Route(3-9)
apps/web/src/routes/_view/pricing.tsx (1)
packages/utils/src/cn.ts (1)
cn(20-22)
apps/web/src/routes/discord.tsx (4)
apps/web/src/routes/github.tsx (1)
Route(3-9)apps/web/src/routes/join-waitlist.tsx (1)
Route(3-9)apps/web/src/routes/linkedin.tsx (1)
Route(3-9)apps/web/src/routes/x.tsx (1)
Route(3-9)
apps/web/src/routes/join-waitlist.tsx (4)
apps/web/src/routes/discord.tsx (1)
Route(3-9)apps/web/src/routes/github.tsx (1)
Route(3-9)apps/web/src/routes/linkedin.tsx (1)
Route(3-9)apps/web/src/routes/x.tsx (1)
Route(3-9)
apps/web/src/routes/_view/route.tsx (1)
apps/web/src/hooks/use-platform.ts (2)
usePlatform(5-30)getPlatformCTA(32-40)
apps/web/src/providers/posthog.tsx (1)
apps/web/src/env.ts (1)
env(4-30)
apps/web/src/routes/_view/app/account.tsx (3)
apps/web/src/functions/billing.ts (1)
createPortalSession(53-75)apps/web/src/hooks/use-posthog.ts (1)
useAnalytics(9-45)apps/web/src/functions/loops.ts (1)
addContact(13-42)
apps/web/src/routes/x.tsx (4)
apps/web/src/routes/discord.tsx (1)
Route(3-9)apps/web/src/routes/github.tsx (1)
Route(3-9)apps/web/src/routes/join-waitlist.tsx (1)
Route(3-9)apps/web/src/routes/linkedin.tsx (1)
Route(3-9)
apps/web/src/routes/_view/index.tsx (4)
apps/web/src/hooks/use-platform.ts (3)
usePlatform(5-30)getHeroCTA(42-70)getPlatformCTA(32-40)apps/web/src/routes/_view/route.tsx (1)
useHeroContext(18-20)apps/web/src/hooks/use-posthog.ts (1)
useAnalytics(9-45)apps/web/src/functions/loops.ts (1)
addContact(13-42)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: ci (macos, macos-14)
🔇 Additional comments (17)
apps/web/vite.config.ts (1)
32-34: LGTM! Correct SSR configuration for PostHog.The
noExternalconfiguration properly excludes PostHog client libraries from SSR bundling, which is necessary since PostHog requires browser APIs. This aligns with the PostHog provider implementation.apps/web/src/functions/loops.ts (1)
24-31: Schema-body mismatch: "platform" field inconsistency.Line 30 includes
platformin the request body, but reviewing theinputSchema(lines 4-11), the field is defined as optional. However, ensure the field name matches the Loops API expectations. The code correctly passes all schema fields.apps/web/src/routes/_view/app/account.tsx (1)
200-218: Good analytics integration.The mutation properly tracks the waitlist join event with relevant metadata before calling the server function. The error handling is also well-structured.
apps/web/src/routes/_view/route.tsx (3)
11-20: LGTM! Clean context implementation.The
HeroContextprovides a clean mechanism for coordinating CTA actions between the header and hero section. The pattern allows the hero component to register its form trigger dynamically.
64-89: Responsive navigation structure is well-organized.The header properly separates desktop and mobile navigation with appropriate breakpoints and accessible markup. The conditional rendering based on screen size is clean.
154-221: Mobile menu implementation follows accessibility best practices.The mobile menu includes:
- Overlay backdrop for dismissal (lines 156-159)
- Animation classes for smooth transitions (lines 157, 161)
- Proper z-index layering (lines 157, 161)
- Keyboard-accessible links
apps/web/src/routes/linkedin.tsx (1)
1-9: LGTM! Consistent redirect pattern.The route follows the established pattern for external redirects using
beforeLoadwiththrow redirect(). This is consistent with the other social/external link routes in this PR.apps/web/src/routes/x.tsx (1)
1-9: LGTM! Consistent redirect pattern.The route follows the established pattern for external redirects, consistent with the other social link routes added in this PR.
apps/web/src/routes/discord.tsx (1)
1-9: LGTM! Consistent redirect pattern.The route follows the established pattern for external redirects. All four redirect routes (discord, github, linkedin, x) maintain consistency in their implementation.
apps/web/src/env.ts (1)
24-25: LGTM! PostHog environment configuration is properly typed.The optional API key and default host value provide flexibility for environments where analytics may not be configured.
apps/web/src/routes/_view/index.tsx (7)
1-23: LGTM! Imports properly support the new features.The additions include form handling (
@tanstack/react-form), mutation logic (@tanstack/react-query), routing utilities, analytics hooks, and platform detection—all of which are utilized in the updated components.
24-88: LGTM! Feature configurations updated with image-based content.The transition from video to static images for feature display is well-structured, and the addition of the "Upload Audio" feature with
comingSoonflag properly communicates the feature roadmap.
94-158: LGTM! Component structure properly coordinates hero input interactions.The
heroInputRefenables the CTA section to trigger focus on the hero email input, creating a cohesive user experience across the page.
235-247: LGTM! The infinite render loop has been fixed.The previous issue where
setOnTriggerwas called with a new arrow function on every render has been resolved. The trigger handler is now properly memoized withuseCallback, and the effect correctly manages its registration with the hero context.
263-349: LGTM! Form handling and state management is well-implemented.The email validation, mutation state handling, and user feedback flow are properly coordinated. The disabled states during pending and success prevent duplicate submissions.
1292-1394: LGTM! Blog section is well-implemented.The article sorting, responsive layout, and navigation using TanStack Router Link components are properly structured. The use of
line-clamputilities and lazy loading for images demonstrates good performance practices.
1-1473: LGTM! Styling patterns follow coding guidelines.All
cn()calls properly use array syntax with logical grouping for conditional styles, in accordance with the project's coding guidelines. Based on learnings.