Skip to content

Conversation

@ComputelessComputer
Copy link
Collaborator

  • 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.
@coderabbitai
Copy link

coderabbitai bot commented Nov 2, 2025

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Adds 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

Cohort / File(s) Change Summary
Analytics & Env
apps/web/.env.sample, apps/web/src/env.ts, apps/web/package.json, apps/web/vite.config.ts, apps/web/src/providers/posthog.tsx, apps/web/src/hooks/use-posthog.ts
Added PostHog deps and env vars; created PostHogProvider, useAnalytics/usePostHog hook wrapper; Vite SSR noExternal for PostHog packages; added LOOPS_KEY env key.
Platform & CTA Logic
apps/web/src/hooks/use-platform.ts, apps/web/src/styles.css
New usePlatform hook and helpers (getPlatformCTA, getHeroCTA); added .animate-shake keyframes used for CTA feedback.
CRM / Server fn
apps/web/src/functions/loops.ts, apps/web/src/env.ts
New server function addContact posting to Loops API using LOOPS_KEY; input validation and error handling added.
Provider & Routing Wrapping
apps/web/src/router.tsx, apps/web/src/routes/__root.tsx
Wrapped app with PostHogProvider; injected external Zendesk script in root head.
Hero Context & Header
apps/web/src/routes/_view/route.tsx, apps/web/src/routes/_view/index.tsx
Introduced HeroContext and useHeroContext; header updated with platform-aware CTA and mobile menu; HeroSection/CTASection now accept heroInputRef; added BlogSection.
Account & Waitlist Flow
apps/web/src/routes/_view/app/account.tsx
Added ProWaitlistCard with form + addContact mutation and analytics; replaced local loading with mutation-driven flows for trial/billing actions.
Redirect Routes
apps/web/src/routes/discord.tsx, apps/web/src/routes/github.tsx, apps/web/src/routes/linkedin.tsx, apps/web/src/routes/x.tsx, apps/web/src/routes/join-waitlist.tsx
New file routes that immediately redirect on beforeLoad to external URLs.
Removed API / Hook
apps/web/src/routes/api/sync.read.ts, apps/web/src/routes/api/sync.write.ts, apps/desktop/src/hooks/useQuery.ts
Deleted legacy sync.read/write API route files and removed desktop useQuery hook.
Component & Layout Tweaks
apps/web/src/components/download-button.tsx, apps/web/src/components/join-waitlist-button.tsx, apps/web/src/components/github-open-source.tsx, apps/web/src/components/social-card.tsx, apps/web/src/components/logo-cloud.tsx, apps/web/src/components/video-modal.tsx, apps/web/src/components/video-thumbnail.tsx
UI adjustments: swapped inline SVGs for Icon, replaced external anchors with internal Link, added decorative dividers, changed cn calls to array form, added poster/aspect-video to player, and adjusted layout classes.
Docs / Blog / Changelog small edits
apps/web/src/routes/_view/blog/$slug.tsx, apps/web/src/routes/_view/blog/index.tsx, apps/web/src/routes/_view/changelog/$slug.tsx, apps/web/src/routes/_view/changelog/index.tsx, apps/web/src/routes/_view/docs/$slug.tsx, apps/web/src/routes/_view/docs/route.tsx
Removed inline JSX comments, reordered imports, switched several cn calls to array form, and added background pattern to blog index.
Download / Pricing / Landing visuals
apps/web/src/routes/_view/download.tsx, apps/web/src/routes/_view/pricing.tsx
Added background patterns, adjusted header/main container structure, switched CTA links to internal /join-waitlist, and composed cn classes as arrays.
UI Config & Styles
packages/ui/components.json, packages/ui/src/styles/globals.css
Added iconLibrary, new registries entry and alias; added theme vars and marquee keyframes for marquee animations.

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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45–60 minutes

  • Pay extra attention to:
    • apps/web/src/routes/_view/app/account.tsx (mutation wiring, form validation, analytics calls).
    • apps/web/src/routes/_view/index.tsx and apps/web/src/routes/_view/route.tsx (heroInputRef threading, HeroContext, header CTA logic).
    • apps/web/src/providers/posthog.tsx, apps/web/src/hooks/use-posthog.ts, and apps/web/vite.config.ts (PostHog initialization and SSR config).
    • apps/web/src/functions/loops.ts and apps/web/src/env.ts (server auth header usage and error handling).
    • Ensure deleted API routes and desktop hook have no lingering references.

Possibly related PRs

  • landing-2 #1598 — overlaps on changes to download-button and other shared UI components.
  • landing wip #1597 — touches landing pages and hero/CTA refactors similar to routes/_view/index.tsx and route.tsx.
  • landing-4 #1602 — related adjustments to GitHub/OpenSource component and similar UI parts.

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title Check ❓ Inconclusive The title "landing page" is extremely vague and generic. While the changeset does involve substantial landing page updates (hero section enhancements, analytics integration, platform-specific CTAs, responsive header improvements), the title fails to convey what specifically changed. A reader scanning through commit history would not understand the primary objectives without additional context. The title uses a non-descriptive term that could apply to almost any landing page modification. Consider revising the title to be more specific about the main changes, such as "Add analytics integration and platform-specific CTAs to landing page" or "Enhance landing page hero with email capture and analytics". This would make the purpose of the PR immediately clear without requiring additional context.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed The PR description directly relates to the changeset and provides meaningful information about the changes. Each bullet point corresponds to actual modifications: marquee animations added, video-thumbnail enhanced, logo-cloud and social-card fixed, hero section updated with email submission via form handling, PostHog analytics integrated with tracking hooks, platform detection and platform-specific CTAs implemented, and responsive header with mobile menu support added. The description is specific enough to convey the scope of work without excessive verbosity.

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be7ef52 and 439afb1.

📒 Files selected for processing (6)
  • apps/web/.env.sample (1 hunks)
  • apps/web/src/env.ts (2 hunks)
  • apps/web/src/providers/posthog.tsx (1 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)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link

@coderabbitai coderabbitai bot left a 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-t on line 120 is not valid Tailwind CSS syntax. Use bg-gradient-to-t instead.

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 cn to always use array format. Additionally, the stopPropagation() on line 77 is redundant since the outer <div> has no onClick handler.

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) to cn(["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: Reconsider aspect-video with h-full.

The aspect-video class (which sets aspect-ratio: 16/9) combined with both w-full and h-full creates a constraint conflict. When both dimensions are explicitly set to 100%, the aspect-ratio property is typically ignored since both dimensions are already constrained. Consider either:

  1. Removing h-full to let aspect-video control the height based on width
  2. Removing aspect-video if the container's dimensions should dictate the size

If 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) with target="_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 Link component with proper external redirect handling

This would make the external navigation intent clearer to future maintainers.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d54995 and eb23f1a.

⛔ Files ignored due to path filters (14)
  • apps/web/public/hyprnote/calendar.jpg is excluded by !**/*.jpg
  • apps/web/public/hyprnote/chat.jpg is excluded by !**/*.jpg
  • apps/web/public/hyprnote/contacts.jpg is excluded by !**/*.jpg
  • apps/web/public/hyprnote/editor.jpg is excluded by !**/*.jpg
  • apps/web/public/hyprnote/no-bots.png is excluded by !**/*.png
  • apps/web/public/hyprnote/no-wifi.png is excluded by !**/*.png
  • apps/web/public/hyprnote/poster-image.png is excluded by !**/*.png
  • apps/web/public/hyprnote/summary.jpg is excluded by !**/*.jpg
  • apps/web/public/hyprnote/transcript.jpg is excluded by !**/*.jpg
  • apps/web/public/patterns/dots.svg is excluded by !**/*.svg
  • apps/web/public/patterns/slash.svg is excluded by !**/*.svg
  • apps/web/src/routeTree.gen.ts is excluded by !**/*.gen.ts
  • packages/ui/src/components/ui/marquee.tsx is excluded by !packages/ui/src/components/ui/**
  • pnpm-lock.yaml is 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.tsx
  • apps/web/src/components/download-button.tsx
  • apps/web/src/routes/_view/github/route.tsx
  • apps/web/src/hooks/use-posthog.ts
  • apps/web/src/components/social-card.tsx
  • apps/web/src/routes/_view/docs/$slug.tsx
  • apps/web/src/routes/_view/linkedin/route.tsx
  • apps/web/src/components/join-waitlist-button.tsx
  • apps/web/src/routes/_view/blog/$slug.tsx
  • apps/web/src/routes/_view/x/route.tsx
  • apps/web/src/components/github-open-source.tsx
  • apps/web/src/components/video-thumbnail.tsx
  • apps/web/src/routes/_view/route.tsx
  • apps/web/src/routes/_view/blog/index.tsx
  • apps/web/src/routes/_view/join-waitlist/route.tsx
  • apps/web/src/routes/_view/index.tsx
  • apps/web/src/providers/posthog.tsx
  • apps/web/src/routes/__root.tsx
  • apps/web/src/hooks/use-platform.ts
  • apps/web/src/routes/_view/discord/route.tsx
  • apps/web/src/routes/api/add-contact.ts
  • apps/web/src/components/video-modal.tsx
  • apps/web/src/routes/_view/app/account.tsx
  • apps/web/src/components/logo-cloud.tsx
  • apps/web/src/routes/_view/download.tsx
  • apps/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, use cn from @hypr/utils
When using cn, always pass an array of class segments
When using cn, split entries by logical grouping for readability
Use motion/react instead of framer-motion

Files:

  • apps/web/src/router.tsx
  • apps/web/src/components/download-button.tsx
  • apps/web/src/routes/_view/github/route.tsx
  • apps/web/src/components/social-card.tsx
  • apps/web/src/routes/_view/docs/$slug.tsx
  • apps/web/src/routes/_view/linkedin/route.tsx
  • apps/web/src/components/join-waitlist-button.tsx
  • apps/web/src/routes/_view/blog/$slug.tsx
  • apps/web/src/routes/_view/x/route.tsx
  • apps/web/src/components/github-open-source.tsx
  • apps/web/src/components/video-thumbnail.tsx
  • apps/web/src/routes/_view/route.tsx
  • apps/web/src/routes/_view/blog/index.tsx
  • apps/web/src/routes/_view/join-waitlist/route.tsx
  • apps/web/src/routes/_view/index.tsx
  • apps/web/src/providers/posthog.tsx
  • apps/web/src/routes/__root.tsx
  • apps/web/src/routes/_view/discord/route.tsx
  • apps/web/src/components/video-modal.tsx
  • apps/web/src/routes/_view/app/account.tsx
  • apps/web/src/components/logo-cloud.tsx
  • apps/web/src/routes/_view/download.tsx
  • apps/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.tsx
  • apps/web/src/routes/_view/docs/$slug.tsx
  • apps/web/src/routes/_view/blog/$slug.tsx
  • apps/web/src/routes/_view/index.tsx
  • 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/docs/$slug.tsx
  • apps/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.tsx
  • apps/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 translateX transforms. 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 utilities ensures it integrates cleanly with the Tailwind CSS utility system.

apps/web/src/components/github-open-source.tsx (2)

94-99: Proper use of cn utility 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.svg exists and will render correctly.

packages/ui/components.json (3)

15-15: Confirm the components alias 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 iconLibrary field 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.png exists in the public directory and is correctly referenced.

apps/web/src/routes/_view/download.tsx (1)

16-30: LGTM! Good use of cn utility.

The header section correctly uses the cn utility 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 --duration variable 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.tsx line 49, the component provides both --duration and --gap via 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.css are reusable, and each component supplies its own variable values inline. The @theme inline syntax is valid in Tailwind CSS v4 and correctly encapsulates the keyframes.

Likely an incorrect or invalid review comment.


83-100: Remove @theme inline wrapper, but use @layer utilities instead of bare @keyframes for Tailwind v3.4 compatibility.

The review comment incorrectly claims @theme inline is non-standard. In fact, @theme inline is a valid, documented Tailwind directive used to define theme variables inline. However, the core concern is valid: @keyframes should not be placed inside @theme inline (which is designed for CSS variables/tokens).

For Tailwind v3.4.18, place @keyframes inside a CSS cascade layer using @layer utilities, or define them in tailwind.config.js. The suggested diff that removes the wrapper and places bare @keyframes at 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 cn with 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 cn with 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 cn with 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 useCallback with 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.

Copy link

@coderabbitai coderabbitai bot left a 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, /linkedin, /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 posthog is 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's type="email" provides basic validation and the server's inputSchema enforces 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, /linkedin, /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 onClick handlers 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 HeroSection or 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

📥 Commits

Reviewing files that changed from the base of the PR and between eb23f1a and 8f5e8e3.

⛔ Files ignored due to path filters (2)
  • .cursor/rules/simple.mdc is excluded by !**/.cursor/**
  • apps/web/src/routeTree.gen.ts is 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.tsx
  • apps/web/vite.config.ts
  • apps/web/src/routes/github.tsx
  • apps/web/src/functions/loops.ts
  • apps/web/src/routes/_view/pricing.tsx
  • apps/web/src/routes/discord.tsx
  • apps/web/src/routes/join-waitlist.tsx
  • apps/web/src/routes/_view/route.tsx
  • apps/web/src/providers/posthog.tsx
  • apps/web/src/routes/_view/app/account.tsx
  • apps/web/src/env.ts
  • apps/web/src/routes/x.tsx
  • apps/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, use cn from @hypr/utils
When using cn, always pass an array of class segments
When using cn, split entries by logical grouping for readability
Use motion/react instead of framer-motion

Files:

  • apps/web/src/routes/linkedin.tsx
  • apps/web/src/routes/github.tsx
  • apps/web/src/routes/_view/pricing.tsx
  • apps/web/src/routes/discord.tsx
  • apps/web/src/routes/join-waitlist.tsx
  • apps/web/src/routes/_view/route.tsx
  • apps/web/src/providers/posthog.tsx
  • apps/web/src/routes/_view/app/account.tsx
  • apps/web/src/routes/x.tsx
  • apps/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.tsx
  • apps/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 noExternal configuration 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 platform in the request body, but reviewing the inputSchema (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 HeroContext provides 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 beforeLoad with throw 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 comingSoon flag properly communicates the feature roadmap.


94-158: LGTM! Component structure properly coordinates hero input interactions.

The heroInputRef enables 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 setOnTrigger was called with a new arrow function on every render has been resolved. The trigger handler is now properly memoized with useCallback, 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-clamp utilities 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.

@yujonglee yujonglee merged commit 9b3d975 into main Nov 3, 2025
4 of 5 checks passed
@yujonglee yujonglee deleted the jj-branch-1 branch November 3, 2025 00:55
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.

3 participants