Skip to content

fix(blog): post launch cleanup#7659

Merged
mhartington merged 3 commits intomainfrom
post-launch-cleanup
Mar 16, 2026
Merged

fix(blog): post launch cleanup#7659
mhartington merged 3 commits intomainfrom
post-launch-cleanup

Conversation

@mhartington
Copy link
Copy Markdown
Member

@mhartington mhartington commented Mar 16, 2026

Summary by CodeRabbit

  • New Features

    • Full-featured, responsive navigation menu with desktop dropdowns, mobile submenus, and a consolidated exports surface; mobile menu supports login/signup links.
  • Improvements

    • Blog post tags are now clickable links for tag-based navigation.
    • Star count display improved with better loading states and accessibility.
    • Social icons updated for consistent rendering.
    • Blog image handling adjusted to unoptimized mode.

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 16, 2026

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

Project Deployment Actions Updated (UTC)
blog Ready Ready Preview, Comment Mar 16, 2026 10:04pm
docs Ready Ready Preview, Comment Mar 16, 2026 10:04pm
eclipse Ready Ready Preview, Comment Mar 16, 2026 10:04pm

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 16, 2026

Walkthrough

Adds a typed, React/TypeScript navigation menu suite (desktop + mobile), exports a public Link type with icon fields, enhances StarCount typing/formatting, and small blog and config tweaks (unoptimized images, tag links, whitespace reformats).

Changes

Cohort / File(s) Summary
Navigation Menu Core
packages/ui/src/components/navigation-menu.tsx
Introduces a full navigation menu implementation and subcomponents: Logo, NavigationMenu, NavigationWrapper, NavigationMenuList/Item/Link/Trigger/Content/Positioner/Indicator, Socials, MenuNavigationItem, mobile helpers (MobileMenuItemWithSubmenu, NavigationMobileMenu). Adds conditional rendering, cva-based styles, and re-exports public API.
Navigation Types / Surface
packages/ui/src/components/web-navigation.tsx
Makes Link interface public (export interface Link) and adds optional icon?: string to root and sub items; updates mobile invocation to pass loginHref/signupHref.
Mobile Menu Typing & API
packages/ui/src/components/navigation-menu.tsx (mobile parts)
Changes mobile-related component signatures to use WebNavigationLink types; NavigationMobileMenu now accepts links: WebNavigationLink[], loginHref, and signupHref.
Star Count
packages/ui/src/components/star-count.tsx
Replaces any props with StarCountProps, adds PLACEHOLDER_VALUE, getStarParts helper, formatted/accessible rendering with loading placeholder and aria attributes.
Blog Tag Links & Minor UI
apps/blog/src/app/(blog)/[slug]/page.tsx
Wraps each tag badge in a Link to /?tag={tag} and adjusts Badge className/hover classes; minor formatting changes.
Next config & Search API & CSS newline
apps/blog/next.config.mjs, apps/blog/src/app/api/search/route.ts, packages/ui/src/styles/globals.css
Enables images: { unoptimized: true } in Next config, whitespace-only reformat in search route, and adds trailing newline in globals.css.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title references 'post launch cleanup' which aligns with the PR objectives, but does not clearly convey the specific, substantive changes across multiple areas of the codebase.

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

📝 Coding Plan
  • Generate coding plan for human review comments

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

❤️ Share

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

@argos-ci
Copy link
Copy Markdown

argos-ci bot commented Mar 16, 2026

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) 👍 Changes approved 1 changed Mar 16, 2026, 10:00 PM

Copy link
Copy Markdown
Contributor

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

Caution

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

⚠️ Outside diff range comments (1)
apps/blog/src/components/PostCard.tsx (1)

100-107: ⚠️ Potential issue | 🟠 Major

Keep non-featured card images lazy.

Line 106 makes every PostCard image eager. BlogGrid renders multiple cards per page, and the non-featured image wrapper is hidden sm:block, so this eagerly fetches offscreen or mobile-hidden assets unnecessarily. You already gate priority on Line 107 for the featured card, so this blanket eager load is inconsistent. Combined with images.unoptimized enabled in apps/blog/next.config.mjs (line 229), unoptimized images load at full resolution regardless, making premature eager loading especially costly.

Suggested fix
-            loading="eager"
+            loading={isFeatured ? "eager" : undefined}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/blog/src/components/PostCard.tsx` around lines 100 - 107, The Image
component currently forces eager loading for all PostCard images; change it so
only featured cards load eagerly by making the loading prop conditional on
isFeatured (e.g., loading = "eager" when isFeatured, otherwise "lazy") while
retaining the existing priority={isFeatured} logic; update the Image usage (the
JSX with Image, src via withBlogBasePathForImageSrc, alt, fill, sizes,
className/imageClassName) to use this conditional loading to avoid fetching
offscreen or hidden non-featured images.
🧹 Nitpick comments (1)
\ (1)

282-286: Use the shared navigation link type through the mobile menu flow.

packages/ui/src/components/web-navigation.tsx:21-41 already defines the Link shape passed into NavigationMobileMenu, but this file widens it back to any and MenuNavigationItem requires icon/desc fields that that shared type does not guarantee. Reusing the shared type here will let TypeScript catch missing menu metadata before it renders blank icons or descriptions.

Also applies to: 310-339

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

In @\ around lines 282 - 286, The MenuNavigationItem component is widening the
link prop and requiring icon/desc fields that the shared navigation Link type
does not guarantee; import and use the shared Link type (the exported type from
the web-navigation component used by NavigationMobileMenu) as the prop type for
MenuNavigationItem (and the other similar component at the 310-339 range),
remove the forced icon/desc requirements, and adjust render logic to treat icon
and desc as optional (guard before rendering) so TypeScript will enforce the
correct shape and prevent blank icons/descriptions at runtime.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @\:
- Around line 245-252: The Discord link renders two icons because the old Font
Awesome element is still present; remove the <i className="fa-brands
fa-discord"> element inside the NavigationMenuLink so only the inline SVG
remains; locate the NavigationMenuItem/NavigationMenuLink block and delete that
<i> tag (or replace it with the SVG if you intended to switch), ensuring the SVG
at line with viewBox="0 0 24 24" is the sole icon.
- Around line 354-367: The mobile CTA buttons ("Login" and "Get started")
currently render inert because neither NavigationMenuItem nor Button include
navigation handlers; wire them to their destinations by adding proper navigation
props to the relevant components (e.g., pass an href or onClick to the Button or
NavigationMenuItem that triggers routing to the login route for the "Login"
Button and to the signup/get-started route for the "Get started" Button), using
the Button and NavigationMenuItem instances in this block so the CTAs perform
navigation through your app router (or call a navigation helper like
navigate()/router.push()).

In `@apps/blog/src/app/`(blog)/[slug]/page.tsx:
- Around line 188-205: In page.tsx where page.data?.tags.map renders Link with
href={`/?tag=${tag}`}, stop interpolating the raw tag into the query string and
instead pass the tag as a query parameter (use an object href with pathname '/'
and query { tag } or otherwise encode via URLSearchParams/encodeURIComponent) so
tags containing &, #, = or spaces are correctly encoded and round-trippable;
update the Link invocation that wraps Badge (and remove the redundant key on
Badge if present) to use the object/query approach referencing the Link,
page.data?.tags, and formatTag locations.

In `@apps/blog/src/app/api/search/route.ts`:
- Around line 29-37: The transform function is replacing the incoming relevance
ranking by sorting solely on generated_metadata.date; instead, preserve the
original relevance order and apply date only as a secondary tiebreaker (or
expose a separate "sortByDate" mode). Update transform (the results parameter
and how you sort) to first consult the incoming relevance (e.g., a hit.score or
the original results order) and only use generated_metadata.date (from
generated_metadata cast to GeneratedMetadata) when relevance is equal or within
a chosen tie threshold; alternatively implement an explicit mode flag that
bypasses relevance and sorts strictly by date if requested.

In `@packages/ui/src/components/star-count.tsx`:
- Around line 21-29: The component currently hides itself when not loading and
starCount <= 0, which causes it to disappear on fetch errors from
useStarCount(); update the hook to expose an error flag (e.g., isError) or
return null for starCount on error, then change the isHidden logic in StarCount
to only hide when not loading AND starCount is a valid positive number (e.g.,
const isHidden = !isLoading && !isError && starCount <= 0 or const isHidden =
!isLoading && (starCount == null || starCount <= 0) depending on your hook
change) so the fallback UI remains visible on error; adjust
getStarParts/formatting to handle null/undefined if you choose that route.

---

Outside diff comments:
In `@apps/blog/src/components/PostCard.tsx`:
- Around line 100-107: The Image component currently forces eager loading for
all PostCard images; change it so only featured cards load eagerly by making the
loading prop conditional on isFeatured (e.g., loading = "eager" when isFeatured,
otherwise "lazy") while retaining the existing priority={isFeatured} logic;
update the Image usage (the JSX with Image, src via withBlogBasePathForImageSrc,
alt, fill, sizes, className/imageClassName) to use this conditional loading to
avoid fetching offscreen or hidden non-featured images.

---

Nitpick comments:
In @\:
- Around line 282-286: The MenuNavigationItem component is widening the link
prop and requiring icon/desc fields that the shared navigation Link type does
not guarantee; import and use the shared Link type (the exported type from the
web-navigation component used by NavigationMobileMenu) as the prop type for
MenuNavigationItem (and the other similar component at the 310-339 range),
remove the forced icon/desc requirements, and adjust render logic to treat icon
and desc as optional (guard before rendering) so TypeScript will enforce the
correct shape and prevent blank icons/descriptions at runtime.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5334e208-7484-4b1e-82a3-93dc2b78ecf6

📥 Commits

Reviewing files that changed from the base of the PR and between 7b531ca and c8014c7.

📒 Files selected for processing (8)
  • \
  • apps/blog/next.config.mjs
  • apps/blog/src/app/(blog)/[slug]/page.tsx
  • apps/blog/src/app/api/search/route.ts
  • apps/blog/src/components/PostCard.tsx
  • packages/ui/src/components/navigation-menu.tsx
  • packages/ui/src/components/star-count.tsx
  • packages/ui/src/styles/globals.css

Resolve the actionable review findings by restoring conditional image eager loading, preserving search relevance ordering, encoding tag query links, and tightening mobile navigation behavior and shared link typing.

Made-with: Cursor
@mhartington
Copy link
Copy Markdown
Member Author

Addressed the CodeRabbit actionable feedback in commit 5a1b12dbf.

Updated:

  • Restored conditional eager loading for PostCard images (featured only).
  • Switched blog tag links to query-object hrefs and removed redundant nested key.
  • Preserved upstream search relevance ordering (removed date-only sorting override).
  • Kept StarCount visible on fetch error by factoring in hook error state.
  • Wired mobile Login / Get started CTAs to loginHref / signupHref.
  • Reused shared navigation link typing in mobile menu flow and made icon/desc optional in menu rendering.

The Discord double-icon finding was already resolved in the current branch state (only the SVG remains).

Copy link
Copy Markdown
Contributor

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/ui/src/components/navigation-menu.tsx`:
- Around line 239-241: The GitHub SVG in navigation-menu.tsx is hardcoded with
width="200" height="200" which breaks layout; replace the fixed dimensions on
the SVG element (the inline <svg> in the social row) by removing width/height
attributes and instead rely on the viewBox plus CSS sizing — e.g. add a
className (e.g. "h-5 w-5" or similar tailwind/stylesheet class) or set
width/height to relative units like "1em" so the icon inherits font-size and
fits the nav; ensure fill="currentColor" remains so it respects text color.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 90a1b517-3a5a-4785-9982-74d589674278

📥 Commits

Reviewing files that changed from the base of the PR and between c8014c7 and 5a1b12d.

📒 Files selected for processing (5)
  • apps/blog/src/app/(blog)/[slug]/page.tsx
  • apps/blog/src/app/api/search/route.ts
  • packages/ui/src/components/navigation-menu.tsx
  • packages/ui/src/components/star-count.tsx
  • packages/ui/src/components/web-navigation.tsx
💤 Files with no reviewable changes (1)
  • apps/blog/src/app/api/search/route.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/blog/src/app/(blog)/[slug]/page.tsx

Copy link
Copy Markdown
Contributor

@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.

🧹 Nitpick comments (1)
packages/ui/src/components/navigation-menu.tsx (1)

236-249: Accessibility inconsistency between social icons.

The Discord SVG includes a <title>Discord</title> element for screen readers, but the GitHub SVG lacks equivalent accessible labeling. For consistency and accessibility, consider adding either a <title> element or aria-label to the GitHub icon.

Also, the icon sizes differ (size-4 for GitHub vs size-5 for Discord). If intentional for visual balance, that's fine—but worth confirming this was deliberate.

♿ Suggested accessibility fix for GitHub icon
-          <svg xmlns="http://www.w3.org/2000/svg" className="size-4" viewBox="0 0 32 32" fill="currentColor"><path fill="currentColor" d="M16 .396c-8.839 0-16 7.167-16 16c0 7.073 4.584 13.068 10.937 15.183c.803.151 1.093-.344 1.093-.772c0-.38-.009-1.385-.015-2.719c-4.453.964-5.391-2.151-5.391-2.151c-.729-1.844-1.781-2.339-1.781-2.339c-1.448-.989.115-.968.115-.968c1.604.109 2.448 1.645 2.448 1.645c1.427 2.448 3.744 1.74 4.661 1.328c.14-1.031.557-1.74 1.011-2.135c-3.552-.401-7.287-1.776-7.287-7.907c0-1.751.62-3.177 1.645-4.297c-.177-.401-.719-2.031.141-4.235c0 0 1.339-.427 4.4 1.641a15.436 15.436 0 0 1 4-.541c1.36.009 2.719.187 4 .541c3.043-2.068 4.381-1.641 4.381-1.641c.859 2.204.317 3.833.161 4.235c1.015 1.12 1.635 2.547 1.635 4.297c0 6.145-3.74 7.5-7.296 7.891c.556.479 1.077 1.464 1.077 2.959c0 2.14-.02 3.864-.02 4.385c0 .416.28.916 1.104.755c6.4-2.093 10.979-8.093 10.979-15.156c0-8.833-7.161-16-16-16z" /></svg>
+          <svg xmlns="http://www.w3.org/2000/svg" className="size-4" viewBox="0 0 32 32" fill="currentColor" aria-label="GitHub"><path fill="currentColor" d="M16 .396c-8.839 0-16 7.167-16 16c0 7.073 4.584 13.068 10.937 15.183c.803.151 1.093-.344 1.093-.772c0-.38-.009-1.385-.015-2.719c-4.453.964-5.391-2.151-5.391-2.151c-.729-1.844-1.781-2.339-1.781-2.339c-1.448-.989.115-.968.115-.968c1.604.109 2.448 1.645 2.448 1.645c1.427 2.448 3.744 1.74 4.661 1.328c.14-1.031.557-1.74 1.011-2.135c-3.552-.401-7.287-1.776-7.287-7.907c0-1.751.62-3.177 1.645-4.297c-.177-.401-.719-2.031.141-4.235c0 0 1.339-.427 4.4 1.641a15.436 15.436 0 0 1 4-.541c1.36.009 2.719.187 4 .541c3.043-2.068 4.381-1.641 4.381-1.641c.859 2.204.317 3.833.161 4.235c1.015 1.12 1.635 2.547 1.635 4.297c0 6.145-3.74 7.5-7.296 7.891c.556.479 1.077 1.464 1.077 2.959c0 2.14-.02 3.864-.02 4.385c0 .416.28.916 1.104.755c6.4-2.093 10.979-8.093 10.979-15.156c0-8.833-7.161-16-16-16z" /></svg>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ui/src/components/navigation-menu.tsx` around lines 236 - 249, The
GitHub SVG inside the NavigationMenuItem/NavigationMenuLink lacks accessible
labeling and uses a different size class than the Discord icon; add an
accessible label (e.g., include a <title>GitHub</title> element inside the
GitHub SVG or add aria-label="GitHub" and role="img" on the SVG) so screen
readers can announce it, and confirm/standardize the size class (change
className="size-4" to match the Discord className="size-5" if the visual size
should match) to keep icon sizing consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/ui/src/components/navigation-menu.tsx`:
- Around line 236-249: The GitHub SVG inside the
NavigationMenuItem/NavigationMenuLink lacks accessible labeling and uses a
different size class than the Discord icon; add an accessible label (e.g.,
include a <title>GitHub</title> element inside the GitHub SVG or add
aria-label="GitHub" and role="img" on the SVG) so screen readers can announce
it, and confirm/standardize the size class (change className="size-4" to match
the Discord className="size-5" if the visual size should match) to keep icon
sizing consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 47f05408-f23a-4479-bd6f-496d298ade47

📥 Commits

Reviewing files that changed from the base of the PR and between 5a1b12d and 4e98c76.

📒 Files selected for processing (1)
  • packages/ui/src/components/navigation-menu.tsx

@mhartington mhartington merged commit 91ce78a into main Mar 16, 2026
11 of 12 checks passed
@mhartington mhartington deleted the post-launch-cleanup branch March 16, 2026 22:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant