Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughRedesign of the blog homepage and UI: featured-post layout with Card/Avatar/Badge, added post fields ( Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Comment |
|
The latest updates on your projects. Learn more about Argos notifications ↗︎
|
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (1)
apps/blog/src/components/BlogGrid.tsx (1)
106-113: Avatar source should usepost.authorSrcwhen present.Current rendering checks
post.authorSrcbut still uses a static image path.Proposed fix
{post?.authorSrc && ( <Avatar format="image" - src="/avatar.jpg" - alt="Disabled user" + src={post.authorSrc} + alt={`${post.author ?? "Author"} avatar`} size="lg" disabled /> )}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/blog/src/components/BlogGrid.tsx` around lines 106 - 113, The Avatar in BlogGrid checks post?.authorSrc but mistakenly passes a static src; update the Avatar usage in the BlogGrid component to use post.authorSrc (fallback to a default if needed) by replacing the hard-coded "/avatar.jpg" with post.authorSrc (or a fallback expression) for the src prop while keeping other props (format, alt, size, disabled) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/blog/src/app/`(blog)/page.tsx:
- Line 139: The current call BlogGrid items using items.slice(1, -1)
inadvertently omits the last post; change the slice to items.slice(1) so
BlogGrid receives all posts except the first (featured) one — update the JSX
where BlogGrid is rendered (the expression items.slice(1, -1) inside page.tsx)
to use items.slice(1).
- Line 59: The line constructing the output date (the expression using data.date
and new Date(data.date).toISOString()) can throw RangeError for
invalid/malformed input; update the logic in page.tsx where the object property
is set (the line with "date: data.date ? new Date(data.date).toISOString() :
\"\"") to validate the parsed Date before calling toISOString — for example
parse into a Date object, check isNaN(date.getTime()) (or Date.parse) and only
call toISOString when valid, otherwise fall back to an empty string or a safe
default; you can also wrap the conversion in a small try/catch to ensure
rendering never throws.
- Around line 100-139: The featured-card dereferences items[0] multiple times
and will crash when items is empty; wrap the whole featured-card anchor/Card
block in a guard like if (items?.length > 0) (or render an early
return/fallback) so you only access items[0] when it exists, and leave the
subsequent <BlogGrid items={items.slice(1, -1)} ... /> to receive a safe array;
update any references inside the block (href, img src/alt, formatDate, author
fields) to rely on the guarded items[0] and avoid accessing it unconditionally
in the page component (page.tsx).
- Around line 104-111: Replace the HTML <img> with Next.js Image: import Image
from "next/image" and render <Image src={items[0].imageSrc}
alt={items[0].imageAlt ?? items[0].title} fill sizes="(min-width: 1024px) 33vw,
(min-width: 768px) 50vw, 100vw" className="object-cover transition-transform
duration-300 group-hover:scale-[1.02] max-h-52 h-full w-full sm:max-h-72"
priority={false} />; ensure the immediate wrapper around this Image has
position: relative (e.g., className includes "relative") so the fill layout
works, and use items[0] (not the nonexistent featured variable) for
src/alt/title values.
In `@apps/blog/src/components/BlogGrid.tsx`:
- Line 79: The parent element with className "grid sm:grid-cols-[1fr_384px]
overflow-hidden border-b pb-4 sm:pb-6 border-stroke-neutral" needs the "group"
utility so any child "group-hover:*" rules will apply; update the BlogGrid
parent element (the JSX element using that className) to include "group" in its
class list so the group-hover on the child (the element using group-hover at the
other location) will trigger.
- Around line 84-86: The Badge is rendering a hardcoded "Release" label even
though the component checks post.badge; update the BlogGrid render so the
Badge's label prop uses the actual value (post.badge) instead of the literal
"Release" and keep the existing conditional (post.badge && <Badge ... />) and
className; modify the JSX that creates the Badge (the Badge component instance)
to pass the dynamic label from post.badge.
- Around line 120-127: post.imageSrc is nullable but being passed directly into
Next.js's Image component (Image in BlogGrid.tsx), which will crash if
null/undefined; update the BlogGrid rendering logic to conditionally render the
<Image> only when post.imageSrc is a non-empty string or provide a guaranteed
fallback src (e.g., default placeholder) before passing to Image. Locate the
Image usage in the BlogGrid component (the element with props
src={post.imageSrc} alt={post.imageAlt ?? post.title} ...) and wrap it in a
short guard like checking if (post.imageSrc) or replace src with a computed
safeSrc that falls back to a constant placeholder, ensuring Image never receives
null/undefined.
---
Nitpick comments:
In `@apps/blog/src/components/BlogGrid.tsx`:
- Around line 106-113: The Avatar in BlogGrid checks post?.authorSrc but
mistakenly passes a static src; update the Avatar usage in the BlogGrid
component to use post.authorSrc (fallback to a default if needed) by replacing
the hard-coded "/avatar.jpg" with post.authorSrc (or a fallback expression) for
the src prop while keeping other props (format, alt, size, disabled) unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 7828aaf1-cc5c-480a-8b84-b243569d77e9
📒 Files selected for processing (5)
apps/blog/src/app/(blog)/page.tsxapps/blog/src/app/global.cssapps/blog/src/app/layout.tsxapps/blog/src/components/BlogGrid.tsxpackages/eclipse/src/styles/fonts.css
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (4)
apps/blog/src/app/(blog)/page.tsx (4)
139-139:⚠️ Potential issue | 🟠 Major
slice(1, -1)unintentionally drops the last post.If you have 5 posts and the first is featured,
items.slice(1, -1)returns posts 2-4, dropping post 5. The-1end index excludes the final element.Proposed fix
- <BlogGrid items={items.slice(1, -1)} pageSize={12} /> + <BlogGrid items={items.slice(1)} pageSize={12} />🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/blog/src/app/`(blog)/page.tsx at line 139, The slice call currently used to pass posts to BlogGrid — items.slice(1, -1) — incorrectly omits the final post; change it to slice from index 1 through the end (e.g., items.slice(1)) so the featured first item is removed but the last post is included when rendering BlogGrid (refer to BlogGrid and the items.slice usage).
59-59:⚠️ Potential issue | 🟠 Major
toISOString()can still throw on invalid dates.This line hasn't been updated since the previous review. While
formatDate()now has proper validation (line 22), this path does not. Ifdata.dateis truthy but malformed (e.g.,"not-a-date"),new Date(data.date).toISOString()throwsRangeError.Apply the same defensive pattern used in
formatDate:Proposed fix
- date: data.date ? new Date(data.date).toISOString() : "", + date: (() => { + if (!data.date) return ""; + const d = new Date(data.date); + return Number.isNaN(d.getTime()) ? "" : d.toISOString(); + })(),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/blog/src/app/`(blog)/page.tsx at line 59, The date serialization at date: data.date ? new Date(data.date).toISOString() : "" can throw RangeError for malformed truthy strings; replace it with the same defensive validation used in formatDate: attempt to parse data.date, verify the resulting Date is valid (or use the existing formatDate helper) and only call toISOString() when valid, otherwise fall back to an empty string; update the expression in page.tsx that sets date (referencing data.date and formatDate) to perform this safe-parse/validation before serializing.
100-101:⚠️ Potential issue | 🟠 MajorGuard needed for empty
itemsarray.If
postsis empty,items[0]will beundefined, and accessing.url,.imageSrc, etc. will crash the page. This was flagged previously and still needs addressing.Proposed fix
} > + {items.length === 0 ? ( + <p className="text-center text-foreground-neutral-weak col-span-full py-8"> + No posts yet. + </p> + ) : ( + <> <a href={items[0].url} ... </a> <BlogGrid items={items.slice(1)} pageSize={12} /> + </> + )} </Suspense>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/blog/src/app/`(blog)/page.tsx around lines 100 - 101, The code directly accesses items[0] (e.g., items[0].url, items[0].imageSrc, items[0].title, items[0].description) which will throw when posts/items is empty; add a guard that checks items && items.length > 0 before rendering the hero/link/image block (or render a fallback/early return) inside the page component so you never dereference items[0]; update the conditional around the <a href={items[0].url}> block (and any uses of items[0]) to only render when the array has at least one element and provide a safe fallback UI or return null.
104-111:⚠️ Potential issue | 🟠 Major
<img>element with Next.js Image-specific props.The
fillandpriorityattributes are Next.jsImagecomponent props, not valid HTML<img>attributes. Browsers will silently ignore them, so you lose the benefits of automatic sizing and priority loading.Proposed fix
+import Image from "next/image"; ... - <img - src={items[0].imageSrc} - alt={items[0].imageAlt ?? items[0].title} - fill - sizes="(min-width: 1024px) 33vw, (min-width: 768px) 50vw, 100vw" - className="object-cover transition-transform duration-300 group-hover:scale-[1.02] max-h-52 h-full w-full sm:max-h-72" - priority={false} - /> + <div className="relative w-full h-full min-h-52 sm:min-h-72"> + <Image + src={items[0].imageSrc ?? ""} + alt={items[0].imageAlt ?? items[0].title} + fill + sizes="(min-width: 1024px) 33vw, (min-width: 768px) 50vw, 100vw" + className="object-cover transition-transform duration-300 group-hover:scale-[1.02]" + /> + </div>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/blog/src/app/`(blog)/page.tsx around lines 104 - 111, The <img> element is using Next.js Image-only props (fill, priority) which are invalid on a plain <img>; update the render in the page component that uses items[0] to use Next.js's Image component: import Image from "next/image", replace the <img ... /> with <Image src={items[0].imageSrc} alt={items[0].imageAlt ?? items[0].title} fill sizes="(min-width: 1024px) 33vw, (min-width: 768px) 50vw, 100vw" className="object-cover transition-transform duration-300 group-hover:scale-[1.02] max-h-52 h-full w-full sm:max-h-72" priority={false} />, ensuring the src is a string or acceptable ImageSource and removing the now-invalid <img> usage so Next.js can handle automatic sizing and priority loading.
🧹 Nitpick comments (1)
apps/blog/src/app/(blog)/page.tsx (1)
75-85: Category pills are static placeholders.These Badges have no click handlers or state management, so they're purely decorative. The commented-out code suggests dynamic filtering is planned.
If this is intentional for an initial release, consider adding a
// TODO: implement category filteringcomment to make the intent clear for future developers. Otherwise, either wire up the filtering logic or remove the pills to avoid confusing users who expect them to be interactive.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/blog/src/app/`(blog)/page.tsx around lines 75 - 85, The category Badge elements in the page (Badge component, categories array and activeCat state) are static placeholders without click handlers or state updates; either implement filtering by wiring them up (create state like activeCat, map categories to render Badge with onClick to setActiveCat and apply color based on activeCat, and filter posts accordingly) or clearly mark intent with a TODO comment; update the commented map block to use a unique key prop when re-enabled and ensure Badge accepts an onClick handler (or remove the pills if not used) so future developers can find Badge, categories, and activeCat to complete the feature.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/blog/src/app/`(blog)/page.tsx:
- Around line 62-66: The post item construction in page.tsx currently hardcodes
authorSrc: null and badge: "Release", which makes the Avatar conditional render
(items[0]?.authorSrc) and the badge value dead code; update the item mapping to
set authorSrc to the actual author image (e.g., data.author?.image or
data.authorImage) and set badge from data.badge (or remove if unused), then
update the Avatar usage to read its src from items[0].authorSrc instead of the
hardcoded "/avatar.jpg" so the conditional render works and the real image is
displayed.
In `@packages/eclipse/src/styles/fonts.css`:
- Around line 28-30: The html selector's font-family currently lists only "Mona
Sans VF", causing a Stylelint warning and potential fallback to browser default;
update the html { font-family: ... } declaration in
packages/eclipse/src/styles/fonts.css to include a generic fallback (e.g., add ,
sans-serif after "Mona Sans VF") so the browser uses a sans-serif fallback if
the webfont fails to load.
---
Duplicate comments:
In `@apps/blog/src/app/`(blog)/page.tsx:
- Line 139: The slice call currently used to pass posts to BlogGrid —
items.slice(1, -1) — incorrectly omits the final post; change it to slice from
index 1 through the end (e.g., items.slice(1)) so the featured first item is
removed but the last post is included when rendering BlogGrid (refer to BlogGrid
and the items.slice usage).
- Line 59: The date serialization at date: data.date ? new
Date(data.date).toISOString() : "" can throw RangeError for malformed truthy
strings; replace it with the same defensive validation used in formatDate:
attempt to parse data.date, verify the resulting Date is valid (or use the
existing formatDate helper) and only call toISOString() when valid, otherwise
fall back to an empty string; update the expression in page.tsx that sets date
(referencing data.date and formatDate) to perform this safe-parse/validation
before serializing.
- Around line 100-101: The code directly accesses items[0] (e.g., items[0].url,
items[0].imageSrc, items[0].title, items[0].description) which will throw when
posts/items is empty; add a guard that checks items && items.length > 0 before
rendering the hero/link/image block (or render a fallback/early return) inside
the page component so you never dereference items[0]; update the conditional
around the <a href={items[0].url}> block (and any uses of items[0]) to only
render when the array has at least one element and provide a safe fallback UI or
return null.
- Around line 104-111: The <img> element is using Next.js Image-only props
(fill, priority) which are invalid on a plain <img>; update the render in the
page component that uses items[0] to use Next.js's Image component: import Image
from "next/image", replace the <img ... /> with <Image src={items[0].imageSrc}
alt={items[0].imageAlt ?? items[0].title} fill sizes="(min-width: 1024px) 33vw,
(min-width: 768px) 50vw, 100vw" className="object-cover transition-transform
duration-300 group-hover:scale-[1.02] max-h-52 h-full w-full sm:max-h-72"
priority={false} />, ensuring the src is a string or acceptable ImageSource and
removing the now-invalid <img> usage so Next.js can handle automatic sizing and
priority loading.
---
Nitpick comments:
In `@apps/blog/src/app/`(blog)/page.tsx:
- Around line 75-85: The category Badge elements in the page (Badge component,
categories array and activeCat state) are static placeholders without click
handlers or state updates; either implement filtering by wiring them up (create
state like activeCat, map categories to render Badge with onClick to
setActiveCat and apply color based on activeCat, and filter posts accordingly)
or clearly mark intent with a TODO comment; update the commented map block to
use a unique key prop when re-enabled and ensure Badge accepts an onClick
handler (or remove the pills if not used) so future developers can find Badge,
categories, and activeCat to complete the feature.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 77f874c4-b612-438b-89b5-a87fa2139c4a
⛔ Files ignored due to path filters (3)
apps/blog/public/fonts/MonaSansVF[wdth,wght,opsz,ital].woff2is excluded by!**/*.woff2apps/blog/public/fonts/monaspace_neon_var.woffis excluded by!**/*.woffapps/blog/public/fonts/monaspace_neon_var.woff2is excluded by!**/*.woff2
📒 Files selected for processing (4)
apps/blog/src/app/(blog)/page.tsxapps/blog/src/app/global.csspackages/eclipse/src/styles/fonts.csspackages/eclipse/src/styles/globals.css
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/blog/src/app/global.css
There was a problem hiding this comment.
♻️ Duplicate comments (1)
packages/eclipse/src/styles/fonts.css (1)
28-30:⚠️ Potential issue | 🟡 MinorFix
htmlfont-family for lint compliance and safer fallback.At Line 29,
Intershould be unquoted and paired with a generic fallback. This resolves both stylelint findings and avoids unintended browser-default fallback behavior.🛠️ Proposed fix
html { - font-family: "Inter"; + font-family: Inter, sans-serif; }#!/bin/bash # Verify current declaration and expected fixed declaration rg -n '^\s*font-family:\s*"Inter";' packages/eclipse/src/styles/fonts.css rg -n '^\s*font-family:\s*Inter,\s*sans-serif;' packages/eclipse/src/styles/fonts.css🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/eclipse/src/styles/fonts.css` around lines 28 - 30, Update the html selector's font-family declaration to remove the quotes around Inter and add a generic fallback so linting passes and browsers have a safe fallback; locate the html { font-family: ... } rule (the html selector in the stylesheet) and change its value from "Inter" to Inter, sans-serif.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@packages/eclipse/src/styles/fonts.css`:
- Around line 28-30: Update the html selector's font-family declaration to
remove the quotes around Inter and add a generic fallback so linting passes and
browsers have a safe fallback; locate the html { font-family: ... } rule (the
html selector in the stylesheet) and change its value from "Inter" to Inter,
sans-serif.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 2b7cd03b-c94c-407c-8624-58fce3d1c7ea
📒 Files selected for processing (2)
apps/blog/src/app/global.csspackages/eclipse/src/styles/fonts.css
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/blog/src/app/global.css
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (5)
apps/blog/src/app/(blog)/page.tsx (5)
62-66:⚠️ Potential issue | 🟡 Minor
authorSrc/badgeare dead paths in current mapping.Line 62 hardcodes
authorSrc: nulland Line 66 hardcodesbadge, while the UI still hardcodes badge label and avatar src, so this new data shape is effectively unused.Proposed direction
- authorSrc: null, + authorSrc: (data.authorImage as string | undefined) ?? null, ... - badge: "Release", + badge: (data.badge as string | undefined) ?? "Release", ... - <Badge color="success" label="Release" className="w-min" /> + <Badge color="success" label={items[0].badge ?? "Release"} className="w-min" /> ... - src="/avatar.jpg" + src={items[0].authorSrc}Also applies to: 114-114, 126-133
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/blog/src/app/`(blog)/page.tsx around lines 62 - 66, The mapping currently hardcodes authorSrc: null and badge: "Release" so the new data shape is ignored; update the mapping in page.tsx where authorSrc and badge are set (near getCardImageSrc(post) usage) to pull real values from the post data (e.g., authorSrc -> data.author?.image or data.author?.avatarUrl, and badge -> data.badge or compute from data.tags/categories) so the UI's avatar src and badge label use the actual payload; also update the other occurrences referenced (the other mapping blocks around the same file) to the same dynamic mapping to keep behavior consistent.
139-139:⚠️ Potential issue | 🟠 Major
slice(1, -1)drops the last post unexpectedly.Line 139 excludes both the featured post and the final post. If intent is “all except featured,” use
slice(1).Proposed patch
- <BlogGrid items={items.slice(1, -1)} pageSize={12} /> + <BlogGrid items={items.slice(1)} pageSize={12} />🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/blog/src/app/`(blog)/page.tsx at line 139, The current call to BlogGrid uses items.slice(1, -1) which removes both the featured first item and the final post; update the slice to items.slice(1) so BlogGrid receives all posts except the featured one (locate the BlogGrid usage in page.tsx where items.slice(1, -1) is passed and replace it with items.slice(1)).
100-137:⚠️ Potential issue | 🟠 MajorGuard featured rendering when
itemsis empty.Lines 100–137 dereference
items[0]unconditionally. If there are zero posts, this crashes.Proposed patch
+ if (items.length === 0) { + return ( + <main className="flex-1 w-full max-w-249 mx-auto px-4 py-8"> + <h1 className="stretch-display text-4xl font-bold mb-2 landing-h1 text-center mt-9 font-display"> + Blog + </h1> + <div className="pt-6 pb-12 mt-10"> + <p className="text-center text-foreground-neutral-weak">No posts yet.</p> + </div> + </main> + ); + } + + const featured = items[0]; ... - href={items[0].url} + href={featured.url}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/blog/src/app/`(blog)/page.tsx around lines 100 - 137, The featured post block dereferences items[0] unconditionally and will crash when items is empty; wrap the entire JSX that uses items[0] (the anchor/link with href={items[0].url}, img using items[0].imageSrc/imageAlt, Card contents using formatDate(items[0].date), title, description, author and Avatar) in a guard that checks items && items.length > 0 (or items?.[0]) and return null or an alternate placeholder when there are no items so the component never accesses items[0] on an empty array.
59-59:⚠️ Potential issue | 🟠 MajorGuard
toISOString()against invalid dates.Line 59 can throw
RangeErrorifdata.dateis malformed, which breaks rendering.Proposed patch
- date: data.date ? new Date(data.date).toISOString() : "", + date: (() => { + if (!data.date) return ""; + const d = new Date(data.date as string); + return Number.isNaN(d.getTime()) ? "" : d.toISOString(); + })(),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/blog/src/app/`(blog)/page.tsx at line 59, Guard the toISOString() call by validating data.date before converting: locate the object assignment where you set date: data.date ? new Date(data.date).toISOString() : "" (in apps/blog/src/app/(blog)/page.tsx) and replace it with logic that parses data.date into a Date (e.g., const parsed = new Date(data.date)), checks parsed.getTime() is not NaN (or uses Date.parse), and only calls parsed.toISOString() when valid, otherwise return an empty string; ensure you handle null/undefined and malformed strings so RangeError/invalid-date output cannot occur.
104-111:⚠️ Potential issue | 🟠 MajorUse
next/imageforfillandpriorityprops.Line 104–111 applies Next Image props to
<img>, where they are ignored.Proposed patch
+import Image from "next/image"; ... - <img + <Image src={items[0].imageSrc} alt={items[0].imageAlt ?? items[0].title} fill sizes="(min-width: 1024px) 33vw, (min-width: 768px) 50vw, 100vw" className="object-cover transition-transform duration-300 group-hover:scale-[1.02] max-h-52 h-full w-full sm:max-h-72" priority={false} />#!/bin/bash # Verify Next Image API props are being used on HTML img and Image is not imported. rg -n 'import Image from "next/image"|<img|fill|priority' apps/blog/src/app/\(blog\)/page.tsx -n -C2🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/blog/src/app/`(blog)/page.tsx around lines 104 - 111, The JSX uses a native <img> with Next Image-specific props (fill, priority) which are ignored; replace the <img ... /> element with the Next.js Image component and add an import: import Image from "next/image"; then update the element at the items[0] image block to use <Image src={items[0].imageSrc} alt={items[0].imageAlt ?? items[0].title} fill sizes="(min-width: 1024px) 33vw, (min-width: 768px) 50vw, 100vw" className="object-cover transition-transform duration-300 group-hover:scale-[1.02] max-h-52 h-full w-full sm:max-h-72" priority={false} /> so the fill and priority props are applied by the Image component (ensure Image is imported and remove the old <img>).
🤖 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/eclipse/src/styles/globals.css`:
- Around line 82-87: The CSS font-family declarations violate
value-keyword-case; update the font tokens so all non-generic font names are
quoted—specifically adjust --font-family-display, --font-family-sans-display,
and --font-family-sans (and the inline "Mona Sans VF" in the stacked font list)
to wrap names like Mona Sans VF, Inter, Roboto, Helvetica Neue, and Segoe UI in
quotes where appropriate so they are treated as strings and satisfy stylelint
rules.
---
Duplicate comments:
In `@apps/blog/src/app/`(blog)/page.tsx:
- Around line 62-66: The mapping currently hardcodes authorSrc: null and badge:
"Release" so the new data shape is ignored; update the mapping in page.tsx where
authorSrc and badge are set (near getCardImageSrc(post) usage) to pull real
values from the post data (e.g., authorSrc -> data.author?.image or
data.author?.avatarUrl, and badge -> data.badge or compute from
data.tags/categories) so the UI's avatar src and badge label use the actual
payload; also update the other occurrences referenced (the other mapping blocks
around the same file) to the same dynamic mapping to keep behavior consistent.
- Line 139: The current call to BlogGrid uses items.slice(1, -1) which removes
both the featured first item and the final post; update the slice to
items.slice(1) so BlogGrid receives all posts except the featured one (locate
the BlogGrid usage in page.tsx where items.slice(1, -1) is passed and replace it
with items.slice(1)).
- Around line 100-137: The featured post block dereferences items[0]
unconditionally and will crash when items is empty; wrap the entire JSX that
uses items[0] (the anchor/link with href={items[0].url}, img using
items[0].imageSrc/imageAlt, Card contents using formatDate(items[0].date),
title, description, author and Avatar) in a guard that checks items &&
items.length > 0 (or items?.[0]) and return null or an alternate placeholder
when there are no items so the component never accesses items[0] on an empty
array.
- Line 59: Guard the toISOString() call by validating data.date before
converting: locate the object assignment where you set date: data.date ? new
Date(data.date).toISOString() : "" (in apps/blog/src/app/(blog)/page.tsx) and
replace it with logic that parses data.date into a Date (e.g., const parsed =
new Date(data.date)), checks parsed.getTime() is not NaN (or uses Date.parse),
and only calls parsed.toISOString() when valid, otherwise return an empty
string; ensure you handle null/undefined and malformed strings so
RangeError/invalid-date output cannot occur.
- Around line 104-111: The JSX uses a native <img> with Next Image-specific
props (fill, priority) which are ignored; replace the <img ... /> element with
the Next.js Image component and add an import: import Image from "next/image";
then update the element at the items[0] image block to use <Image
src={items[0].imageSrc} alt={items[0].imageAlt ?? items[0].title} fill
sizes="(min-width: 1024px) 33vw, (min-width: 768px) 50vw, 100vw"
className="object-cover transition-transform duration-300
group-hover:scale-[1.02] max-h-52 h-full w-full sm:max-h-72" priority={false} />
so the fill and priority props are applied by the Image component (ensure Image
is imported and remove the old <img>).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: bd77c9d3-ebd2-4115-9620-5043412b45ec
📒 Files selected for processing (3)
apps/blog/src/app/(blog)/page.tsxapps/blog/src/app/global.csspackages/eclipse/src/styles/globals.css
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/blog/src/app/global.css
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (5)
apps/blog/src/app/(blog)/page.tsx (3)
141-141:⚠️ Potential issue | 🟠 Major
slice(1, -1)is dropping the final post.Line 141 should be
slice(1)if the intent is “all posts except featured”.Suggested fix
- <BlogGrid items={items.slice(1, -1)} pageSize={12} /> + <BlogGrid items={items.slice(1)} pageSize={12} />🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/blog/src/app/`(blog)/page.tsx at line 141, The current use of items.slice(1, -1) in the BlogGrid call incorrectly drops the final post; update the slice to items.slice(1) so BlogGrid receives all posts except the first (featured) one—modify the expression passed to the BlogGrid component (items.slice(1, -1) → items.slice(1)) to fix the bug.
100-140:⚠️ Potential issue | 🟠 MajorGuard the featured block before reading
items[0].On Lines 101–137,
items[0]is accessed unconditionally. If the blog is empty, this throws during render.Suggested fix
+ if (items.length === 0) { + return ( + <main className="flex-1 w-full max-w-249 mx-auto px-4 py-8"> + <h1 className="stretch-display text-4xl font-bold mb-2 landing-h1 text-center mt-9 font-display"> + Blog + </h1> + </main> + ); + } + + const featured = items[0]; ... - <a - href={items[0].url} + <a + href={featured.url} ... - src={items[0].imageSrc as string} + src={featured.imageSrc as string}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/blog/src/app/`(blog)/page.tsx around lines 100 - 140, The featured block reads items[0] unguarded and will throw when items is empty; update the render to first check that items exists and has at least one element (e.g., items && items.length > 0 or items?.length > 0) before rendering the anchor/Card block that references items[0], formatDate(items[0].date), items[0].imageSrc, items[0].title, items[0].description and items[0].author (or alternatively use an optional access pattern like items?.[0] and guard each access), and if no item exists skip rendering the featured block (or render a fallback).
62-67:⚠️ Potential issue | 🟡 Minor
authorSrc/badgeare hardcoded, so this path is not data-driven.On Lines 62 and 66,
authorSrcis alwaysnullandbadgeis always"Release". That makes the added fields effectively dead for real content data.Suggested fix
- authorSrc: null, + authorSrc: (data.authorSrc as string | undefined) ?? null, ... - badge: "Release", + badge: (data.badge as string | undefined) ?? null,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/blog/src/app/`(blog)/page.tsx around lines 62 - 67, authorSrc and badge are hardcoded (authorSrc: null, badge: "Release") so they never reflect actual post data; update the object creation that sets authorSrc and badge (near getCardImageSrc(post), imageAlt, seriesTitle) to pull real values from the post/data model (e.g., authorSrc: data.author?.image || data.author?.src || null) and set badge from a data-driven field (e.g., data.badge || post.type || derive from data.tags || null) while preserving existing fallbacks like null so missing fields remain safe.apps/blog/src/components/BlogGrid.tsx (2)
79-79:⚠️ Potential issue | 🟡 Minor
group-hoverwon’t trigger without agroupparent.Line 126 relies on
group-hover, but Line 79 is missinggroup.Suggested fix
- className="grid sm:grid-cols-[1fr_384px] overflow-hidden border-b pb-4 sm:pb-6 border-stroke-neutral" + className="group grid sm:grid-cols-[1fr_384px] overflow-hidden border-b pb-4 sm:pb-6 border-stroke-neutral"Also applies to: 126-126
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/blog/src/components/BlogGrid.tsx` at line 79, The element in the BlogGrid component that defines className "grid sm:grid-cols-[1fr_384px] overflow-hidden border-b pb-4 sm:pb-6 border-stroke-neutral" is missing the "group" utility needed for descendant "group-hover" styles to work; add "group" to that parent element's className (or wrap the relevant child in a parent with className "group") so the child element that uses "group-hover" can trigger correctly.
84-86:⚠️ Potential issue | 🟡 MinorUse the actual badge value instead of a constant label.
Line 85 always renders
"Release"even whenpost.badgehas a different value.Suggested fix
- <Badge color="success" label="Release" className="w-min" /> + <Badge color="success" label={post.badge} className="w-min" />🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/blog/src/components/BlogGrid.tsx` around lines 84 - 86, The Badge in BlogGrid.tsx is always rendered with the constant label "Release" instead of the actual post.badge value; update the Badge invocation (the JSX that references post.badge and Badge) to pass the real badge text (e.g., label={post.badge} if post.badge is a string, or label={post.badge.label ?? post.badge} if post.badge is an object) and keep the existing props like color and className; ensure you handle a null/undefined post.badge fallback if needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/blog/src/components/BlogGrid.tsx`:
- Around line 106-113: In BlogGrid, the conditional rendering checks
post?.authorSrc but the Avatar component still uses a hardcoded src and alt;
update the Avatar props to use the actual post values (e.g.,
src={post.authorSrc} and alt={post.authorName || post.author}) and remove or
adjust the hardcoded "/avatar.jpg" and "Disabled user" strings so the displayed
image and alt text reflect the post's author; locate this in the BlogGrid
component where Avatar is rendered and replace the hardcoded props with the
post-specific fields.
In `@packages/eclipse/src/components/inline-toc.tsx`:
- Around line 66-73: IntersectionObserver callback only uses the changed entries
and filters out non-intersecting ones, which leaves activeId stale when one
heading exits but others remain visible; fix this by adding a persistent Map/Ref
(e.g., visibleSectionsRef or visibleMapRef) that tracks current intersection
state for each observed target, update that Map for every entry in the
IntersectionObserver callback (using entry.target.id as key and storing
entry.isIntersecting and a latest boundingClientRect.top), then compute the list
of currently visible headings from the Map (entries with isIntersecting ===
true), sort them by their stored top value and call setActiveId with the first
id (or null when none), and ensure this Map is used inside the
observerRef.current callback that creates the IntersectionObserver so activeId
always reflects actual visibility.
- Line 77: The forEach callback in elements.forEach currently uses an expression
body that implicitly returns a value; change it to a block body and call
observerRef.current?.observe(el) so nothing is returned and optional chaining
matches the cleanup logic (avoid the non-null assertion). Update the
elements.forEach callback to use a { ... } body that calls
observerRef.current?.observe(el) for each el, mirroring the cleanup that uses
optional chaining and satisfying the useIterableCallbackReturn rule.
---
Duplicate comments:
In `@apps/blog/src/app/`(blog)/page.tsx:
- Line 141: The current use of items.slice(1, -1) in the BlogGrid call
incorrectly drops the final post; update the slice to items.slice(1) so BlogGrid
receives all posts except the first (featured) one—modify the expression passed
to the BlogGrid component (items.slice(1, -1) → items.slice(1)) to fix the bug.
- Around line 100-140: The featured block reads items[0] unguarded and will
throw when items is empty; update the render to first check that items exists
and has at least one element (e.g., items && items.length > 0 or items?.length >
0) before rendering the anchor/Card block that references items[0],
formatDate(items[0].date), items[0].imageSrc, items[0].title,
items[0].description and items[0].author (or alternatively use an optional
access pattern like items?.[0] and guard each access), and if no item exists
skip rendering the featured block (or render a fallback).
- Around line 62-67: authorSrc and badge are hardcoded (authorSrc: null, badge:
"Release") so they never reflect actual post data; update the object creation
that sets authorSrc and badge (near getCardImageSrc(post), imageAlt,
seriesTitle) to pull real values from the post/data model (e.g., authorSrc:
data.author?.image || data.author?.src || null) and set badge from a data-driven
field (e.g., data.badge || post.type || derive from data.tags || null) while
preserving existing fallbacks like null so missing fields remain safe.
In `@apps/blog/src/components/BlogGrid.tsx`:
- Line 79: The element in the BlogGrid component that defines className "grid
sm:grid-cols-[1fr_384px] overflow-hidden border-b pb-4 sm:pb-6
border-stroke-neutral" is missing the "group" utility needed for descendant
"group-hover" styles to work; add "group" to that parent element's className (or
wrap the relevant child in a parent with className "group") so the child element
that uses "group-hover" can trigger correctly.
- Around line 84-86: The Badge in BlogGrid.tsx is always rendered with the
constant label "Release" instead of the actual post.badge value; update the
Badge invocation (the JSX that references post.badge and Badge) to pass the real
badge text (e.g., label={post.badge} if post.badge is a string, or
label={post.badge.label ?? post.badge} if post.badge is an object) and keep the
existing props like color and className; ensure you handle a null/undefined
post.badge fallback if needed.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 414dd65b-023d-493b-9a92-5dc232ac4a94
📒 Files selected for processing (5)
apps/blog/source.config.tsapps/blog/src/app/(blog)/page.tsxapps/blog/src/app/global.cssapps/blog/src/components/BlogGrid.tsxpackages/eclipse/src/components/inline-toc.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/blog/src/app/global.css
0912152
Summary by CodeRabbit
New Features
Style
Bug Fixes