Skip to content

feat(marketing): add changelog page#1007

Merged
Kitenite merged 24 commits intomainfrom
kiet-ho/add-changelog
Jan 28, 2026
Merged

feat(marketing): add changelog page#1007
Kitenite merged 24 commits intomainfrom
kiet-ho/add-changelog

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Jan 27, 2026

Summary

Add a comprehensive changelog page to the marketing site with Linear-style inline layout and sticky timeline navigation.

Features

  • Changelog page with Linear-style inline layout showing all updates
  • Sticky timeline navigation with orange indicator aligned to gridline
  • PRBadge component for consistent PR link styling in section headers
  • Featured images for changelog entries with full-width display
  • Inline images support within changelog content (e.g., ports panel screenshot)
  • List styling with proper bullet points for MDX content

Changelog Entries

Updated all 7 changelog entries with:

  • Content from PR release notes (CodeRabbit summaries)
  • PRBadge links in section headers
  • Featured images for each entry
  • Renamed files to match their content

Images Added

  • ghostty.png - Ghostty terminal integration
  • changes.png - Expanded changes sidebar
  • task-list.png - Task list view
  • branches.png - Sidebar/workspaces
  • integrations.png - Linear integration
  • docs.png - Documentation site
  • terminal.png - Multiple terminal tabs
  • ports.png - Port visibility panel

Bug Fixes

  • Fix horizontal scroll caused by GridCross component overflow
  • Proper image aspect ratios (removed forced 16:9)

Test Plan

  • Visit /changelog - verify timeline layout and sticky navigation
  • Click individual entries - verify full content and images display
  • Check PRBadge links work and have correct styling
  • Verify no horizontal scroll on individual entry pages
  • Test responsive layout on mobile

Summary by CodeRabbit

Release Notes

  • New Features
    • Added a dedicated Changelog section displaying product updates and improvements
    • Individual changelog entries now have detail pages with rich content
    • RSS feed available for changelog subscriptions
    • Navigation link added for easy access to the Changelog

✏️ Tip: You can customize this high-level summary in your review settings.

Add a changelog feature similar to Linear's changelog to the marketing site.

- Add changelog lib utilities (changelog.ts, changelog-utils.ts)
- Create changelog list page (/changelog)
- Create individual changelog entry pages (/changelog/[slug])
- Add ChangelogCard and ChangelogEntryLayout components
- Add changelog to header navigation
- Create RSS feed at /changelog.xml
- Update sitemap to include changelog pages
- Add example changelog entry
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 27, 2026

📝 Walkthrough

Walkthrough

This PR introduces a comprehensive changelog feature for the marketing application, including route handlers for RSS feed generation, page components for displaying changelog entries, reusable UI components for changelog cards and entries, utility functions for parsing and formatting changelog data, navigation integration, sitemap updates, and multiple new changelog content entries documenting recent product updates.

Changes

Cohort / File(s) Summary
Changelog RSS Feed & Route Handler
apps/marketing/src/app/changelog.xml/route.ts
New GET route handler that generates an RSS feed with XML serialization, escaping, and HTTP headers for caching and content-type.
Changelog Page Components
apps/marketing/src/app/changelog/page.tsx, apps/marketing/src/app/changelog/[slug]/page.tsx
Page component for changelog index with metadata and entry fetching; detail page with slug-based routing, static generation, SEO metadata, and ArticleJsonLd structured data.
Changelog Layout & Entry Components
apps/marketing/src/app/changelog/[slug]/components/ChangelogEntryLayout/ChangelogEntryLayout.tsx, apps/marketing/src/app/changelog/[slug]/components/ChangelogEntryLayout/index.ts, apps/marketing/src/app/changelog/components/ChangelogEntry/ChangelogEntry.tsx, apps/marketing/src/app/changelog/components/ChangelogEntry/index.ts
Layout component for entry pages with hero header, grid backgrounds, and featured images; entry component for rendering individual entries with MDX content and metadata.
Changelog Card & PR Badge Components
apps/marketing/src/app/changelog/components/ChangelogCard/ChangelogCard.tsx, apps/marketing/src/app/changelog/components/ChangelogCard/index.ts, apps/marketing/src/app/changelog/components/PRBadge/PRBadge.tsx, apps/marketing/src/app/changelog/components/PRBadge/index.ts
Card component for displaying changelog entries as clickable items; PRBadge component for rendering pull request links extracted from URLs.
Changelog MDX Components
apps/marketing/src/app/changelog/components/ChangelogEntry/changelog-mdx-components.tsx
Custom MDX components for changelog rendering, extending base mdxComponents with PRBadge and specialized list styling.
Changelog Utilities & Helpers
apps/marketing/src/lib/changelog-utils.ts, apps/marketing/src/lib/changelog.ts
Utility module defining ChangelogEntry interface and helper functions (formatChangelogDate, slugify); core module for parsing YAML frontmatter, extracting table-of-contents from markdown, and exposing functions to fetch all or individual changelog entries.
Navigation & Sitemap Updates
apps/marketing/src/app/components/Header/Header.tsx, apps/marketing/src/app/sitemap.ts
Added changelog navigation link in header; updated sitemap to include static /changelog route and dynamic entries for each changelog slug with metadata.
Changelog Content Files
apps/marketing/content/changelog/*.mdx (6 files)
New MDX changelog entries documenting product updates: workspace improvements, Electric SQL sync, SQLite features, sidebar/workspace UI changes, task list features, terminal tabs, and organization settings.
Minor Component Update
apps/marketing/src/app/blog/components/GridCross/GridCross.tsx
Added overflow-hidden CSS class to outer container for clipping overflow behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~35 minutes

Possibly related PRs

  • PR #981: Modifies apps/marketing/src/app/sitemap.ts similarly; both PRs update sitemap structure to include new content sections.
  • PR #974: Updates marketing app navigation (Header.tsx) and COMPANY URL constants; overlaps with navigation and routing changes in this PR.
  • PR #929: Touches the GridCross component; both PRs modify the same component file.

Poem

🐰 A changelog was born today, so neat,
With RSS feeds and cards complete,
From slugs to frontmatter, all in place,
Grid crosses dance with elegant grace,
Product tales now have a home—
No more lost in code we roam! 📖✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Title check ✅ Passed The title 'feat(marketing): add changelog page' clearly and specifically describes the main change—adding a changelog page feature to the marketing site.
Description check ✅ Passed The PR description is comprehensive and well-structured with clear sections covering features, changelog entries, images added, bug fixes, and a test plan, addressing the template structure.

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

✨ Finishing touches
  • 📝 Generate docstrings

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
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: 3

🤖 Fix all issues with AI agents
In `@apps/marketing/content/changelog/2026-01-27-january-2026-release.mdx`:
- Around line 1-6: The frontmatter in the changelog references a missing image
(/images/changelog/january-2026.png); either add the PNG asset under
apps/marketing/public/images/changelog named january-2026.png or update the
frontmatter image value in 2026-01-27-january-2026-release.mdx to the correct
existing image path; ensure the filename and path match the site/public image
serving convention so the image resolves at runtime.

In `@apps/marketing/src/app/changelog/page.tsx`:
- Around line 73-77: Replace the React list key to use the canonical identifier:
in the entries.map(...) that renders <ChangelogCard key={entry.url}
entry={entry} /> change the key to entry.slug so the mapping uses the same
identifier used by getChangelogEntry, getAllChangelogSlugs, and the dynamic
[slug] route; update the key expression from entry.url to entry.slug in the map
callback.

In `@apps/marketing/src/lib/changelog.ts`:
- Around line 14-42: The parseFrontmatter function currently swallows errors in
its catch block; update its error handling to catch the exception (e.g., catch
(err)) and log a clear, contextual message including the filePath and the
error/stack (for example: "Error parsing frontmatter for <filePath>: <err>")
before returning null so failures like permission issues or malformed
frontmatter are visible; ensure you modify parseFrontmatter's catch clause only
(no behavioral changes to returned value) and use the existing logging approach
in the project (console.error or the project's logger) for consistency.
🧹 Nitpick comments (7)
apps/marketing/src/app/changelog/components/ChangelogCard/ChangelogCard.tsx (1)

18-27: Consider adding sizes prop to optimize image loading.

When using fill with Next.js Image, providing a sizes prop helps the browser select the appropriate image size for the viewport, reducing unnecessary bandwidth usage.

Suggested improvement
 <Image
 	src={entry.image}
 	alt={entry.title}
 	fill
+	sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
 	className="object-cover transition-transform group-hover:scale-[1.02]"
 />
apps/marketing/src/app/changelog/[slug]/components/ChangelogEntryLayout/ChangelogEntryLayout.tsx (2)

27-34: Consider extracting complex background gradient to a CSS class.

The inline style with multiple calc() expressions is hard to maintain. This could be extracted to a Tailwind arbitrary value or a CSS custom property for better readability.


83-96: Consider adding sizes prop to optimize image loading.

Similar to ChangelogCard, providing a sizes prop helps the browser select the appropriate image size.

Suggested improvement
 <Image
 	src={entry.image}
 	alt={entry.title}
 	fill
 	className="object-cover"
 	priority
+	sizes="(max-width: 768px) 100vw, 768px"
 />
apps/marketing/src/app/changelog/[slug]/page.tsx (1)

26-33: Minor inconsistency in date formatting.

On line 30, publishedTime is converted to ISO format using new Date(entry.date).toISOString(), but in generateMetadata (line 69), publishedTime is passed as entry.date directly without conversion. This inconsistency could lead to different date formats in structured data vs. OpenGraph metadata.

🔧 Suggested fix for consistency
 		openGraph: {
 			title: entry.title,
 			description: entry.description,
 			type: "article",
 			url,
 			siteName: COMPANY.NAME,
-			publishedTime: entry.date,
+			publishedTime: new Date(entry.date).toISOString(),
 			...(entry.image && { images: [entry.image] }),
 		},
apps/marketing/src/app/changelog.xml/route.ts (2)

40-45: Consider using application/rss+xml Content-Type for RSS feeds.

While application/xml works, application/rss+xml is the more semantically correct MIME type for RSS feeds and helps feed readers identify the content type more precisely.

🔧 Suggested change
 	return new Response(rss, {
 		headers: {
-			"Content-Type": "application/xml",
+			"Content-Type": "application/rss+xml; charset=utf-8",
 			"Cache-Control": "public, max-age=3600, s-maxage=3600",
 		},
 	});

8-14: Consider extracting escapeXml to a shared utility.

This XML escaping function is defined inline within the route handler. If XML escaping is needed elsewhere (e.g., other RSS feeds or XML exports), consider moving it to a shared utility module for reusability.

apps/marketing/src/app/changelog/page.tsx (1)

38-45: Magic pixel values in gradient could be extracted to named constants.

The values 384px and 383px appear to define guide line positions relative to the center. Per coding guidelines, consider extracting these to named constants at module top to clarify their purpose (e.g., CONTENT_WIDTH_PX).

Comment thread apps/marketing/content/changelog/2026-01-27-january-2026-release.mdx Outdated
Comment on lines +73 to +77
<div className="flex flex-col gap-8">
{entries.map((entry) => (
<ChangelogCard key={entry.url} entry={entry} />
))}
</div>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find ChangelogEntry type definition
ast-grep --pattern 'type ChangelogEntry = $_'
ast-grep --pattern 'interface ChangelogEntry $_'

# Check for ChangelogEntry in the changelog lib directory
rg -n "ChangelogEntry" --type ts -A 15 apps/marketing/src

Repository: superset-sh/superset

Length of output: 15480


🏁 Script executed:

#!/bin/bash
# Read the full parseFrontmatter function
sed -n '14,43p' apps/marketing/src/lib/changelog.ts

Repository: superset-sh/superset

Length of output: 772


🏁 Script executed:

#!/bin/bash
# Check if url is ever read from frontmatter data or always derived
grep -n "data.url\|url:" apps/marketing/src/lib/changelog.ts

Repository: superset-sh/superset

Length of output: 96


Use entry.slug as the React key instead of entry.url.

The entry.url is always derived as /changelog/${slug}, making it stable. However, entry.slug is the canonical identifier throughout the codebase—it's used by getChangelogEntry(slug), getAllChangelogSlugs(), and the dynamic route [slug]. Using slug as the key is semantically more accurate since it represents what actually identifies each entry in the data model.

🤖 Prompt for AI Agents
In `@apps/marketing/src/app/changelog/page.tsx` around lines 73 - 77, Replace the
React list key to use the canonical identifier: in the entries.map(...) that
renders <ChangelogCard key={entry.url} entry={entry} /> change the key to
entry.slug so the mapping uses the same identifier used by getChangelogEntry,
getAllChangelogSlugs, and the dynamic [slug] route; update the key expression
from entry.url to entry.slug in the map callback.

Comment on lines +14 to +42
function parseFrontmatter(filePath: string): ChangelogEntry | null {
try {
const fileContent = fs.readFileSync(filePath, "utf-8");
const { data, content } = matter(fileContent);

const slug = path.basename(filePath, ".mdx");

let dateValue: string;
if (data.date instanceof Date) {
dateValue = data.date.toISOString().split("T")[0] as string;
} else if (data.date) {
dateValue = String(data.date);
} else {
dateValue = new Date().toISOString().split("T")[0] as string;
}

return {
slug,
url: `/changelog/${slug}`,
title: data.title ?? "Untitled",
description: data.description,
date: dateValue,
image: data.image,
content,
};
} catch {
return null;
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Silent error swallowing in catch block.

The empty catch block swallows all errors without logging, which could hide issues like file permission errors, malformed frontmatter, or encoding problems. Per coding guidelines, errors should at minimum be logged with context.

Proposed fix
 function parseFrontmatter(filePath: string): ChangelogEntry | null {
 	try {
 		const fileContent = fs.readFileSync(filePath, "utf-8");
 		const { data, content } = matter(fileContent);

 		const slug = path.basename(filePath, ".mdx");

 		let dateValue: string;
 		if (data.date instanceof Date) {
 			dateValue = data.date.toISOString().split("T")[0] as string;
 		} else if (data.date) {
 			dateValue = String(data.date);
 		} else {
 			dateValue = new Date().toISOString().split("T")[0] as string;
 		}

 		return {
 			slug,
 			url: `/changelog/${slug}`,
 			title: data.title ?? "Untitled",
 			description: data.description,
 			date: dateValue,
 			image: data.image,
 			content,
 		};
-	} catch {
+	} catch (error) {
+		console.error(`[changelog/parseFrontmatter] Failed to parse ${filePath}:`, error);
 		return null;
 	}
 }
🤖 Prompt for AI Agents
In `@apps/marketing/src/lib/changelog.ts` around lines 14 - 42, The
parseFrontmatter function currently swallows errors in its catch block; update
its error handling to catch the exception (e.g., catch (err)) and log a clear,
contextual message including the filePath and the error/stack (for example:
"Error parsing frontmatter for <filePath>: <err>") before returning null so
failures like permission issues or malformed frontmatter are visible; ensure you
modify parseFrontmatter's catch clause only (no behavioral changes to returned
value) and use the existing logging approach in the project (console.error or
the project's logger) for consistency.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jan 27, 2026

🚀 Preview Deployment

🔗 Preview Links

Service Status Link
Neon Database (Neon) View Branch
Fly.io Electric (Fly.io) View App
Vercel API (Vercel) Open Preview
Vercel Web (Vercel) Open Preview
Vercel Marketing (Vercel) Open Preview
Vercel Admin (Vercel) Open Preview
Vercel Docs (Vercel) Open Preview

Preview updates automatically with new commits

Show full changelog entries with MDX content directly on the list page
instead of linking to separate detail pages. This matches Linear's
changelog design with date headers and full content inline.
Add a sticky timeline sidebar that follows as you scroll through
changelog entries. The timeline shows dates with visual indicators
and highlights the currently visible entry. Clicking a date smoothly
scrolls to that entry.
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

🤖 Fix all issues with AI agents
In
`@apps/marketing/src/app/changelog/components/ChangelogEntry/changelog-mdx-components.tsx`:
- Around line 3-27: ChangelogLink currently spreads {...props} after the badge
className, allowing props.className to overwrite the badge styles; update
ChangelogLink to merge the default badge classes with any incoming
props.className (e.g., use a utility like clsx or classnames) and pass the
combined className to the <a> so custom classes extend rather than replace the
badge styling; ensure you spread the remaining props (excluding className) after
setting className to the merged value in the returned element.
🧹 Nitpick comments (1)
apps/marketing/src/app/changelog/components/ChangelogEntry/changelog-mdx-components.tsx (1)

1-33: Align components folder structure with the “one component per file” rule.

This file defines ChangelogLink plus a component map export under a components path. Consider moving ChangelogLink into ChangelogLink/ChangelogLink.tsx with a barrel export, and keep the MDX mapping in a non-components module (or its own folder) to match the folder convention. As per coding guidelines, please keep one component per file in components paths.

Comment on lines +3 to +27
function ChangelogLink({
href,
children,
...props
}: React.AnchorHTMLAttributes<HTMLAnchorElement>) {
const isGitHubPR =
href?.includes("github.com") && href?.includes("/pull/");

if (isGitHubPR) {
return (
<a
href={href}
className="text-xs font-mono text-muted-foreground no-underline bg-muted px-1.5 py-0.5 rounded ml-1 opacity-70 hover:opacity-100 transition-opacity"
{...props}
>
{children}
</a>
);
}

return (
<a href={href} {...props}>
{children}
</a>
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Avoid losing badge styles when className is provided.

Line 15–16: spreading {...props} after className allows props.className to override the badge styles. Consider merging classes explicitly so custom classes extend (not replace) the badge styling.

🛠️ Proposed fix
-function ChangelogLink({
-	href,
-	children,
-	...props
-}: React.AnchorHTMLAttributes<HTMLAnchorElement>) {
+function ChangelogLink({
+	href,
+	children,
+	className,
+	...props
+}: React.AnchorHTMLAttributes<HTMLAnchorElement>) {
 	const isGitHubPR =
 		href?.includes("github.com") && href?.includes("/pull/");

 	if (isGitHubPR) {
 		return (
 			<a
-				href={href}
-				className="text-xs font-mono text-muted-foreground no-underline bg-muted px-1.5 py-0.5 rounded ml-1 opacity-70 hover:opacity-100 transition-opacity"
-				{...props}
+				{...props}
+				href={href}
+				className={[
+					"text-xs font-mono text-muted-foreground no-underline bg-muted px-1.5 py-0.5 rounded ml-1 opacity-70 hover:opacity-100 transition-opacity",
+					className,
+				]
+					.filter(Boolean)
+					.join(" ")}
 			>
 				{children}
 			</a>
 		);
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function ChangelogLink({
href,
children,
...props
}: React.AnchorHTMLAttributes<HTMLAnchorElement>) {
const isGitHubPR =
href?.includes("github.com") && href?.includes("/pull/");
if (isGitHubPR) {
return (
<a
href={href}
className="text-xs font-mono text-muted-foreground no-underline bg-muted px-1.5 py-0.5 rounded ml-1 opacity-70 hover:opacity-100 transition-opacity"
{...props}
>
{children}
</a>
);
}
return (
<a href={href} {...props}>
{children}
</a>
);
function ChangelogLink({
href,
children,
className,
...props
}: React.AnchorHTMLAttributes<HTMLAnchorElement>) {
const isGitHubPR =
href?.includes("github.com") && href?.includes("/pull/");
if (isGitHubPR) {
return (
<a
{...props}
href={href}
className={[
"text-xs font-mono text-muted-foreground no-underline bg-muted px-1.5 py-0.5 rounded ml-1 opacity-70 hover:opacity-100 transition-opacity",
className,
]
.filter(Boolean)
.join(" ")}
>
{children}
</a>
);
}
return (
<a href={href} {...props}>
{children}
</a>
);
}
🤖 Prompt for AI Agents
In
`@apps/marketing/src/app/changelog/components/ChangelogEntry/changelog-mdx-components.tsx`
around lines 3 - 27, ChangelogLink currently spreads {...props} after the badge
className, allowing props.className to overwrite the badge styles; update
ChangelogLink to merge the default badge classes with any incoming
props.className (e.g., use a utility like clsx or classnames) and pass the
combined className to the <a> so custom classes extend rather than replace the
badge styling; ensure you spread the remaining props (excluding className) after
setting className to the merged value in the returned element.

- Create dedicated PRBadge component for consistent PR link styling
- Move PR badges to section titles for cleaner layout
- Update all changelog entries to use PRBadge component
- Use changelogMdxComponents in individual changelog pages
Fetch and apply release notes from linked PRs for all changelog entries.
Content now reflects actual feature descriptions from CodeRabbit summaries.
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

🤖 Fix all issues with AI agents
In `@apps/marketing/src/app/changelog/components/PRBadge/PRBadge.tsx`:
- Around line 5-14: The PRBadge component extracts prNumber via
url.match(/\/pull\/(\d+)/) which can be undefined; update PRBadge to handle
non-matching URLs by either returning null (early return) or rendering a safe
fallback label (e.g., "PR" or the full url) instead of "#undefined". Locate the
PRBadge function and the prNumber variable and add a guard that checks if
prNumber is truthy before rendering "#{prNumber}" (or substitute the chosen
fallback), ensuring links and accessibility remain intact (href stays url or is
omitted when returning null).

Comment on lines +5 to +14
export function PRBadge({ url }: PRBadgeProps) {
const prNumber = url.match(/\/pull\/(\d+)/)?.[1];

return (
<a
href={url}
className="text-xs font-mono text-muted-foreground no-underline bg-muted px-1.5 py-0.5 rounded opacity-70 hover:opacity-100 transition-opacity"
>
#{prNumber}
</a>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Avoid rendering “#undefined” for non-matching URLs.
Add a safe fallback label (or early return) when the PR number can’t be parsed.

Suggested fix
 export function PRBadge({ url }: PRBadgeProps) {
 	const prNumber = url.match(/\/pull\/(\d+)/)?.[1];
+	const label = prNumber ? `#${prNumber}` : "PR";

 	return (
 		<a
 			href={url}
 			className="text-xs font-mono text-muted-foreground no-underline bg-muted px-1.5 py-0.5 rounded opacity-70 hover:opacity-100 transition-opacity"
 		>
-			#{prNumber}
+			{label}
 		</a>
 	);
 }
🤖 Prompt for AI Agents
In `@apps/marketing/src/app/changelog/components/PRBadge/PRBadge.tsx` around lines
5 - 14, The PRBadge component extracts prNumber via url.match(/\/pull\/(\d+)/)
which can be undefined; update PRBadge to handle non-matching URLs by either
returning null (early return) or rendering a safe fallback label (e.g., "PR" or
the full url) instead of "#undefined". Locate the PRBadge function and the
prNumber variable and add a guard that checks if prNumber is truthy before
rendering "#{prNumber}" (or substitute the chosen fallback), ensuring links and
accessibility remain intact (href stays url or is omitted when returning null).

@Kitenite Kitenite merged commit ef46286 into main Jan 28, 2026
12 checks passed
@Kitenite Kitenite deleted the kiet-ho/add-changelog branch January 28, 2026 00:49
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