Skip to content

feat: add web v2 docs and landing updates#197

Merged
maxktz merged 76 commits into
feat/polar-removefrom
feat/web-v2
Jun 6, 2026
Merged

feat: add web v2 docs and landing updates#197
maxktz merged 76 commits into
feat/polar-removefrom
feat/web-v2

Conversation

@maxktz

@maxktz maxktz commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Summary

  • refresh docs sidebar, theme controls, and code block styling
  • add landing placeholders and mobile layout fixes
  • refine landing demo/code surfaces

Testing

  • not run

Summary by CodeRabbit

  • New Features

    • Added blog landing page and sponsor page.
    • Added user feedback section with testimonials.
    • Added package manager selection feature for code examples.
  • Documentation

    • Restructured documentation navigation and organization.
    • Consolidated provider-specific documentation.
    • Updated code examples to use explicit command blocks.
  • UI/UX

    • Updated icon system across the application.
    • Simplified docs layout and removed command menu.
    • Updated theme colors and styling system.

@vercel

vercel Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated (UTC)
paykit Ready Ready Preview, Comment Jun 6, 2026 6:08am

@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown

Looking for one thing? Review this PR in Change Stack to search files, summaries, diffs, and code without losing your place.

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3b91ee0f-7a93-490d-a334-0c9bc861d92d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Large docs and marketing refactor: custom DocsLayout/MDX components, icon library migration, content reorganization and redirects, new package-command UX, CSS/theme updates, and new/removed marketing pages.

Changes

Docs Platform Refactor and Content Reorg

Layer / File(s) Summary
Docs architecture and rendering
apps/web/src/app/docs/*, apps/web/src/components/docs/*, apps/web/mdx-components.tsx
Adds DocsLayout, MDX components (headings, callouts, tabs, code surfaces), breadcrumb/footer, sidebar (desktop/mobile), and uses PackageManagerProvider. Removes previous custom layout logic.
Code blocks and package commands
apps/web/src/components/docs/package-*.tsx, apps/web/source.config.ts, apps/web/src/lib/shiki-themes*, apps/web/src/components/ui/code-block*
Introduces package manager–aware command blocks, automatic shell detection/highlighting, dual-theme inline code, Shiki options, and styled code surfaces.
Icon and UI library migration
apps/web/src/components/**/* (ui/, sections/, docs/, layout/), apps/web/src/lib/lucide-react-remix-shim.ts
Replaces lucide-react with react-icons/ri across UI, adds lucide shim alias, updates styles and components accordingly.
Docs content and navigation
apps/web/content/docs/**/*, apps/web/content/docs/meta.json
Converts pages to Steps, updates links/routes, removes providers pages, restructures concepts/flows/plugins, and refreshes CLI/database examples.
Routing, redirects, and providers
apps/web/next.config.js, apps/web/src/components/providers.tsx, apps/web/src/app/api/og/*, apps/web/src/app/llms.txt/*
Adds grouped docs redirects and donate/sponsors redirects, lucide aliasing, search API config, and OG/llms path tweaks.
Marketing pages and sections
apps/web/src/app/(marketing)/*, apps/web/src/components/sections/*
Adds Blog/Sponsor pages, replaces Features with Feedback section, removes Donate/Testimonials, and updates hero/CTA/demo layouts.

Sequence Diagram(s)

[Skipped]

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • getpaykit/paykit#166 — Also refactors mini/primary nav to use BrandMenu, overlapping navigation components.
  • getpaykit/paykit#165 — Touches docs layout/wordmark styling affected by this PR’s docs layout simplification.
  • getpaykit/paykit#121 — Updates CopyMarkdownButton behavior similar to this PR’s expanded copy/dropdown UX.

Poem

A rabbit hops through docs at night,
Rewires sidebars, sets themes right.
Tabs now shimmer, code blocks glow,
Icons swap—ri winds blow.
Redirect paths, a gentle guide—
“Come read,” it squeaks, with whiskered pride. 🐇✨

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/web-v2

@maxktz

maxktz commented Jun 6, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (18)
apps/web/src/components/layout/navigation-bar.tsx (5)

51-51: 💤 Low value

Remove unnecessary separator comment.

As per coding guidelines, keep comments rare and avoid separator comments in TypeScript/JavaScript files.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/layout/navigation-bar.tsx` at line 51, Remove the
unnecessary separator comment line ("// ─── Data
────────────────────────────────────────────────────────────") from the
NavigationBar component in apps/web/src/components/layout/navigation-bar.tsx;
locate the comment near the top of the file (around where module-level
data/constants are defined) and delete that single-line separator so the file
follows the project's guideline of avoiding separator comments.

Source: Coding guidelines


86-86: 💤 Low value

Remove unnecessary separator comment.

As per coding guidelines, keep comments rare and avoid separator comments in TypeScript/JavaScript files.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/layout/navigation-bar.tsx` at line 86, Remove the
unnecessary separator comment "// ─── Tab styles
──────────────────────────────────────────────────────" from the NavigationBar
component in apps/web/src/components/layout/navigation-bar.tsx; simply delete
that standalone comment line (no code changes otherwise) to comply with the
guideline of avoiding separator comments in TypeScript/JavaScript files.

Source: Coding guidelines


15-15: 💤 Low value

Remove unnecessary separator comment.

As per coding guidelines, keep comments rare and avoid separator comments in TypeScript/JavaScript files.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/layout/navigation-bar.tsx` at line 15, Remove the
unnecessary separator comment line "// ─── Shared nav link
─────────────────────────────────────────────────" from the navigation-bar
component; locate the comment above the shared nav link code (around the
SharedNavLink / NavLink related JSX or function) and delete the separator so
only meaningful comments or code remain, following the project's guideline to
avoid decorative separator comments.

Source: Coding guidelines


96-96: 💤 Low value

Remove unnecessary separator comment.

As per coding guidelines, keep comments rare and avoid separator comments in TypeScript/JavaScript files.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/layout/navigation-bar.tsx` at line 96, Remove the
unnecessary separator comment line ("// ─── Component
───────────────────────────────────────────────────────") from the NavigationBar
component file; locate it in the navigation-bar.tsx near the component
declaration and delete that single comment so the file follows the guideline of
avoiding visual separator comments.

Source: Coding guidelines


98-98: ⚡ Quick win

Unused stars parameter and hardcoded value.

The stars parameter is passed as null and never used, while the GitHub button displays a hardcoded "1k" value. Either:

  1. Remove the unused parameter if star count display is not needed
  2. Use the actual stars value when it's available
♻️ Suggested implementation
-export function NavigationBar({ stars: _stars }: { stars: number | null }) {
+export function NavigationBar({ stars }: { stars: number | null }) {
   // ... rest of component
   
   <Button
     render={<Link href={URLs.githubRepo} target="_blank" rel="noopener noreferrer" />}
     nativeButton={false}
     variant="ghost"
     size="sm"
     className="px-2 -mr-2"
   >
     <Icons.GitHubIcon className="size-4.5" />
-    <span className="font-sans text-sm">1k</span>
+    {stars !== null && (
+      <span className="font-sans text-sm">
+        {stars >= 1000 ? `${(stars / 1000).toFixed(1)}k` : stars}
+      </span>
+    )}
   </Button>

Also applies to: 248-249

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/layout/navigation-bar.tsx` at line 98, The
NavigationBar component currently accepts an unused parameter named _stars and
renders a hardcoded "1k"; either remove the unused prop or surface and use the
actual value: change the parameter from { stars: _stars } to { stars } (or
remove it altogether) in the NavigationBar function, replace the hardcoded "1k"
in the GitHub button render with a dynamic display like stars ?? "1k" (or remove
the stars display if you choose to drop the prop), and update any callers that
pass null to NavigationBar to either stop passing the prop or pass the real star
count; also apply the same fix to the other duplicate instance(s) of the
NavigationBar prop usage.
apps/web/src/styles/globals.css (2)

286-288: 💤 Low value

Address stylelint warning.

There should be an empty line before the max-width declaration per stylelint rules.

🔧 Suggested fix
  html {
    `@apply` overflow-x-hidden overflow-y-scroll;
+
    max-width: 100vw;
  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/styles/globals.css` around lines 286 - 288, There is a stylelint
warning because there is no blank line between the `@apply` rule and the
subsequent declaration; update the block containing the declarations "`@apply`
overflow-x-hidden overflow-y-scroll;" and "max-width: 100vw;" by inserting a
single empty line before the "max-width: 100vw;" declaration so the `@apply` and
the following property are separated per stylelint rules.

Source: Linters/SAST tools


96-96: 💤 Low value

Inconsistent color format.

Line 96 uses a hex color (#f5f5f5) while the rest of the theme uses oklch() format. For consistency, consider converting this to oklch as well.

♻️ Suggested fix
-  --secondary: `#f5f5f5`;
+  --secondary: oklch(0.97 0 0);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/styles/globals.css` at line 96, The CSS custom property
--secondary currently uses a hex value (`#f5f5f5`) which is inconsistent with the
rest of the theme that uses oklch(); update the --secondary declaration in
globals.css to an equivalent oklch(...) color so it matches the site's color
space and tone (convert the hex to oklch and replace the value for --secondary).
apps/web/src/components/docs/docs-code-surface.tsx (1)

5-16: ⚡ Quick win

Add JSDoc to document the component's purpose.

This is an exported, user-facing component used throughout the docs rendering system. Based on coding guidelines, JSDoc should be added to document its purpose, parameters, and the default tabIndex behavior.

📝 Suggested JSDoc
+/**
+ * Wrapper for code blocks in documentation pages.
+ * Provides consistent styling and ensures keyboard accessibility by defaulting tabIndex to 0.
+ */
 export function DocsCodeSurface({ className, tabIndex, ...props }: ComponentProps<"pre">) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/docs/docs-code-surface.tsx` around lines 5 - 16, Add
a JSDoc block above the exported DocsCodeSurface function that documents the
component's purpose (renders a styled <pre> wrapper for code blocks in the docs
system), lists its props (including className, tabIndex, and other
ComponentProps<"pre"> passed via ...props), and explicitly states the default
tabIndex behavior (defaults to 0 when tabIndex is undefined). Mention any
accessibility notes (keyboard focusability due to tabIndex) and the fact that it
spreads remaining pre props onto the element; reference the DocsCodeSurface
function name so the comment is colocated with the implementation.

Source: Learnings

apps/web/src/components/docs/package-manager-state.ts (1)

1-21: ⚡ Quick win

Add JSDoc to document the public API.

All exported entities (PackageManager, constants, and functions) form the public API for package manager state management. Based on coding guidelines, these should have JSDoc documentation.

📝 Suggested JSDoc
+/** Supported package managers for command rendering. */
 export type PackageManager = "npm" | "yarn" | "bun" | "pnpm";

+/** List of all supported package managers in display order. */
 export const packageManagers = [
   "pnpm",
   "npm",
   "bun",
   "yarn",
 ] as const satisfies readonly PackageManager[];

+/** Local storage key for persisting package manager preference. */
 export const packageManagerStorageKey = "paykit-package-manager";
+
+/** Default package manager when no preference is stored. */
 export const fallbackPackageManager: PackageManager = "pnpm";

+/**
+ * Type guard to check if a value is a valid PackageManager.
+ */
 export function isPackageManager(value: string | null): value is PackageManager {
   return packageManagers.includes(value as PackageManager);
 }

+/**
+ * Parses and validates a package manager value, falling back to the default if invalid.
+ */
 export function parsePackageManager(value: string | null | undefined): PackageManager {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/docs/package-manager-state.ts` around lines 1 - 21,
Add JSDoc comments to document the module's public API: describe the exported
PackageManager type (allowed values), the packageManagers array (list of
supported managers), packageManagerStorageKey (purpose/key used in storage), and
fallbackPackageManager (default). For functions isPackageManager(value) and
parsePackageManager(value) add JSDoc describing parameters and return
types/guards (e.g., `@param` value - input string|null/undefined; `@returns` boolean
for isPackageManager and PackageManager for parsePackageManager), and a short
usage example or note about behavior (parse returns fallback when invalid).
Place comments immediately above each exported symbol (PackageManager,
packageManagers, packageManagerStorageKey, fallbackPackageManager,
isPackageManager, parsePackageManager).

Source: Learnings

apps/web/src/components/docs/package-command-pre.tsx (1)

60-85: ⚡ Quick win

Add JSDoc to document the component's behavior.

This exported async component has complex behavior (parsing, highlighting, conditional rendering) that would benefit from JSDoc documentation per coding guidelines.

📝 Suggested JSDoc
+/**
+ * Server component that intercepts code blocks to render package manager-specific commands.
+ * Parses single-line npm commands and renders them as interactive tabs for all package managers.
+ * Falls back to default rendering for non-matching content.
+ */
 export async function PackageCommandPre(
   props: ComponentProps<"pre"> & { "data-language"?: string },
 ) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/docs/package-command-pre.tsx` around lines 60 - 85,
Add a JSDoc block to the exported async component PackageCommandPre describing
its behavior and purpose: explain that it normalizes and parses text via
normalizeCommand and extractText, conditionally parses with parsePackageCommand,
checks language with isShellLanguage, generates highlighted entries by mapping
packageManagers and calling highlightShellCommand and commandForManager, and
renders either PackageManagerCommandBlock with highlightedCommands or
DefaultPre; include param description for props (ComponentProps<"pre"> & {
"data-language"?: string }), the return type (JSX.Element |
Promise<JSX.Element>), and note that it performs async highlighting
side-effects.

Source: Learnings

apps/web/src/components/docs/package-command-utils.ts (1)

5-24: ⚡ Quick win

Add JSDoc to document the public API.

The exported PackageCommand interface and commandForManager function form a public API used by other components. Based on coding guidelines, these should have JSDoc documentation explaining their purpose and behavior.

📝 Suggested JSDoc
+/**
+ * Represents a package manager command with its kind and arguments.
+ */
 export interface PackageCommand {
   kind: CommandKind;
   args: string;
 }

+/**
+ * Converts a PackageCommand into the appropriate shell command string for the specified package manager.
+ * `@param` command - The command to convert
+ * `@param` manager - The target package manager (npm, yarn, bun, or pnpm)
+ * `@returns` The formatted shell command string
+ */
 export function commandForManager(command: PackageCommand, manager: PackageManager): string {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/docs/package-command-utils.ts` around lines 5 - 24,
Add JSDoc comments for the exported PackageCommand interface and the
commandForManager function: document PackageCommand purpose and fields (kind:
CommandKind and args: string), and for commandForManager describe purpose,
parameters (command: PackageCommand, manager: PackageManager), behavior for each
CommandKind branch (how npm/yarn/pnpm/bun are mapped), and the return value
(string command). Ensure the JSDoc is placed immediately above the exported
declarations and mentions any edge cases (e.g., defaulting to pnpm for dlx) so
consumers understand the public API.

Source: Learnings

apps/web/src/components/docs/package-command.tsx (2)

35-50: 💤 Low value

Consider whether dual storage persistence is necessary.

The code writes package manager preference to both sessionStorage and localStorage, then reads from both. Since sessionStorage is tab-specific and localStorage is global, and you have a pub/sub pattern for cross-instance sync, this dual-write pattern seems redundant.

Consider using only localStorage for persistent cross-tab preference, or clarify the intent if there's a specific reason for maintaining both.

♻️ Potential simplification
 function readStoredManager(): PackageManager | null {
-  const storedValue =
-    sessionStorage.getItem(packageManagerStorageKey) ??
-    localStorage.getItem(packageManagerStorageKey);
+  const storedValue = localStorage.getItem(packageManagerStorageKey);

   return isPackageManager(storedValue) ? storedValue : null;
 }

 function setStoredManager(value: PackageManager) {
-  sessionStorage.setItem(packageManagerStorageKey, value);
   localStorage.setItem(packageManagerStorageKey, value);

   for (const listener of packageManagerListeners) {
     listener(value);
   }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/docs/package-command.tsx` around lines 35 - 50, The
code currently persists package manager selections to both sessionStorage and
localStorage in setStoredManager and reads from both in readStoredManager;
decide on a single storage medium (prefer localStorage for cross-tab
persistence) and simplify by writing only to localStorage and reading only from
localStorage using packageManagerStorageKey, leaving packageManagerListeners and
isPackageManager logic unchanged; if session-scoped behavior is required,
document the intent or add a separate explicit function, otherwise remove
sessionStorage calls to avoid redundant writes and confusing read fallback
behavior.

176-182: ⚡ Quick win

Extract duplicated extractText utility.

The extractText function is duplicated in both package-command.tsx (lines 176-182) and package-command-pre.tsx (lines 11-17). Extract this to a shared utility module to follow DRY principles.

♻️ Suggested refactor

Create apps/web/src/components/docs/utils.ts:

import type { ReactNode } from "react";
import { isValidElement } from "react";

/**
 * Recursively extracts text content from React nodes.
 */
export function extractText(node: ReactNode): string {
  if (node === null || node === undefined || typeof node === "boolean") return "";
  if (typeof node === "string" || typeof node === "number") return String(node);
  if (Array.isArray(node)) return node.map(extractText).join("");
  if (isValidElement<{ children?: ReactNode }>(node)) return extractText(node.props.children);
  return "";
}

Then import from both files:

+import { extractText } from "`@/components/docs/utils`";
-
-function extractText(node: ReactNode): string {
-  // ... (remove duplicate implementation)
-}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/docs/package-command.tsx` around lines 176 - 182,
Extract the duplicated extractText function into a single shared utility: create
a new utils module that exports extractText, import isValidElement from "react"
and keep the same implementation/typing, then replace the local copies in the
package-command and package-command-pre components with an import from the new
utility and delete the duplicate definitions.
apps/web/src/components/docs/mdx-tabs.tsx (2)

32-68: ⚡ Quick win

Consider adding JSDoc to exported components.

These components form a user-facing MDX API and would benefit from brief JSDoc describing their purpose and key props. As per coding guidelines, JSDoc should be added on most functions in the library core and on APIs used in many places or user-facing.

📝 Example JSDoc additions
/**
 * Root tabs component for MDX documentation.
 * Supports controlled tab selection with optional items array.
 */
export function MdxTabs({ ... }: MdxTabsProps) {
  // ...
}

/**
 * Tab list container with animated indicator.
 */
export function MdxTabsList({ ... }) {
  // ...
}

/**
 * Individual tab trigger button.
 */
export function MdxTabsTab({ ... }) {
  // ...
}

/**
 * Tab content panel.
 */
export function MdxTabsPanel({ ... }) {
  // ...
}

/**
 * Convenience wrapper that resolves tab value from context.
 * `@throws` {Error} If no tab value can be resolved from props or context.
 */
export function MdxTab({ ... }) {
  // ...
}

Also applies to: 70-100, 102-116, 118-129, 131-140

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/docs/mdx-tabs.tsx` around lines 32 - 68, Add concise
JSDoc comments to each exported MDX tabs component to document their purpose and
key props: add a brief description above MdxTabs explaining it's the root tabs
component and noting controlled selection props (items,
defaultIndex/defaultValue, label), add a short comment above MdxTabsList
describing it as the tab list container with indicator, above MdxTabsTab
describing it as the individual tab trigger and key props (value, children),
above MdxTabsPanel describing it as the content panel, and above MdxTab
describing it as a convenience wrapper that resolves value from props or context
and include a `@throws` note stating it throws if no tab value can be resolved;
keep each JSDoc short (one-two sentences) and include prop highlights where
helpful.

Source: Coding guidelines


49-52: 💤 Low value

Silent return on invalid tab change could be confusing.

When items is provided and nextValue is not in the list, the handler silently returns without updating state or providing feedback. Consider adding a development-time warning to help debug issues.

💡 Optional enhancement
 onValueChange={(nextValue) => {
   if (items && !items.includes(nextValue)) {
+    console.warn(`Tab value "${nextValue}" is not in the items list:`, items);
     return;
   }
   setValue(nextValue);
 }}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/docs/mdx-tabs.tsx` around lines 49 - 52, The
onValueChange handler in mdx-tabs.tsx currently silently returns if items is set
and nextValue isn't included; update the handler (the onValueChange callback
that checks items, nextValue, and calls setValue) to emit a development-time
warning when this occurs (e.g., guard with NODE_ENV !== 'production' or a
dev-only logger) so developers see why the state wasn't updated, then still
return without changing state; keep the existing items/includes/ setValue logic
but add a clear message referencing nextValue and the items list.
apps/web/src/components/docs/docs-mdx-components.tsx (1)

262-298: ⚡ Quick win

Add JSDoc to the exported docsMdxComponents.

This constant forms the public API for MDX component overrides and would benefit from documentation. As per coding guidelines, JSDoc should be added on APIs used in many places or user-facing.

📝 Suggested JSDoc
/**
 * MDX component overrides for documentation pages.
 * Maps standard HTML/MDX elements to styled React components.
 * Includes custom components like Callout, Card, Steps, and Tabs.
 */
export const docsMdxComponents = {
  // ...
} satisfies MDXComponents;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/docs/docs-mdx-components.tsx` around lines 262 - 298,
Add a brief JSDoc block immediately above the export const docsMdxComponents
declaration that describes this symbol as the MDX component overrides used by
documentation pages: state that it maps standard HTML/MDX elements (e.g.,
h1..h6, p, a, code, ul/ol/li, table, etc.) to styled React components and also
exposes custom components like Callout, Card, Cards,
Steps/Step/StepContent/StepTitle, Tabs/MdxTabs/MdxTab, Features, etc.; note that
it satisfies the MDXComponents type and is a public API for MDX rendering. Keep
the comment short and descriptive per coding guidelines.

Source: Coding guidelines

apps/web/content/docs/quickstart.mdx (1)

6-6: Docs links: /docs/* targets exist.

The referenced MDX pages exist in apps/web/content/docs: installation.mdx, plans-and-features.mdx, subscriptions.mdx, and entitlements.mdx, so the /docs/installation, /docs/plans-and-features, /docs/subscriptions, and /docs/entitlements links should resolve.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/content/docs/quickstart.mdx` at line 6, Update the doc links in
apps/web/content/docs/quickstart.mdx so they point to the existing MDX pages:
replace or verify the link text in the sentence "This page assumes you have
completed the [installation](/docs/installation) steps..." and any other
references to docs with the exact route slugs that exist (/docs/installation,
/docs/plans-and-features, /docs/subscriptions, /docs/entitlements) to ensure
they resolve to installation.mdx, plans-and-features.mdx, subscriptions.mdx, and
entitlements.mdx respectively.
apps/web/src/components/sections/feedback-section.tsx (1)

78-78: ⚡ Quick win

Use tweet.link as the key for better uniqueness.

The current key ${tweet.handle}-${tweet.text} could collide if the same user posts similar text. Since each tweet has a unique link field, using tweet.link as the key would be more robust and align with React best practices.

♻️ Proposed fix
-                <TweetCard key={`${tweet.handle}-${tweet.text}`} tweet={tweet} />
+                <TweetCard key={tweet.link} tweet={tweet} />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/sections/feedback-section.tsx` at line 78, Replace
the current fragile list key generation for TweetCard with the tweet's unique
link: locate where TweetCard is rendered (the TweetCard component usage in
feedback-section.tsx) and change the key from the template
`${tweet.handle}-${tweet.text}` to use `tweet.link` so each rendered TweetCard
uses the stable unique identifier `tweet.link` as the React key.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@AGENTS.md`:
- Around line 26-30: Fix typos and tighten the sentence in AGENTS.md: replace
"clonned" with "cloned", capitalize the sentence start after the comma, and
rephrase the guidance to read clearly (e.g., "If you need to inspect source code
of libraries or packages, prefer inspecting the cloned source repository when
available, rather than the library dist. These directories already contain
source checkouts for some packages: `~/ref/fumadocs` - fumadocs framework /
package."). Update the sentence containing "clonned" and the following line
referencing `~/ref/fumadocs`.

In `@apps/web/src/app/`(marketing)/page.tsx:
- Line 3: The codebase now renders FeedbackSection while FeaturesSection has no
remaining references; confirm whether FeaturesSection (the component defined as
FeaturesSection in features-section.tsx) is intentionally retired—if yes, delete
the FeaturesSection component file or mark it deprecated/moved and remove its
export; if it's still needed, rewire the page to import and render
FeaturesSection where appropriate (replace or combine with FeedbackSection) and
update any exports/imports so FeaturesSection is actually referenced.

In `@apps/web/src/components/docs/docs-mdx-components.tsx`:
- Around line 56-58: The heading ID generation in getHeadingId can produce
collisions (e.g., "What's new?" and "Whats new" both become "whats-new"); fix by
switching to a robust slugger or adding collision detection: import and use a
slug library like GithubSlugger and call slugger.slug(children?.toString() ??
'') inside getHeadingId, or maintain a module-level Set (e.g., usedIds) and,
after creating the base slug from children, append a numeric suffix while
usedIds.has(id) to ensure uniqueness, then add the final id to usedIds before
returning; update getHeadingId to use one of these approaches.

---

Nitpick comments:
In `@apps/web/content/docs/quickstart.mdx`:
- Line 6: Update the doc links in apps/web/content/docs/quickstart.mdx so they
point to the existing MDX pages: replace or verify the link text in the sentence
"This page assumes you have completed the [installation](/docs/installation)
steps..." and any other references to docs with the exact route slugs that exist
(/docs/installation, /docs/plans-and-features, /docs/subscriptions,
/docs/entitlements) to ensure they resolve to installation.mdx,
plans-and-features.mdx, subscriptions.mdx, and entitlements.mdx respectively.

In `@apps/web/src/components/docs/docs-code-surface.tsx`:
- Around line 5-16: Add a JSDoc block above the exported DocsCodeSurface
function that documents the component's purpose (renders a styled <pre> wrapper
for code blocks in the docs system), lists its props (including className,
tabIndex, and other ComponentProps<"pre"> passed via ...props), and explicitly
states the default tabIndex behavior (defaults to 0 when tabIndex is undefined).
Mention any accessibility notes (keyboard focusability due to tabIndex) and the
fact that it spreads remaining pre props onto the element; reference the
DocsCodeSurface function name so the comment is colocated with the
implementation.

In `@apps/web/src/components/docs/docs-mdx-components.tsx`:
- Around line 262-298: Add a brief JSDoc block immediately above the export
const docsMdxComponents declaration that describes this symbol as the MDX
component overrides used by documentation pages: state that it maps standard
HTML/MDX elements (e.g., h1..h6, p, a, code, ul/ol/li, table, etc.) to styled
React components and also exposes custom components like Callout, Card, Cards,
Steps/Step/StepContent/StepTitle, Tabs/MdxTabs/MdxTab, Features, etc.; note that
it satisfies the MDXComponents type and is a public API for MDX rendering. Keep
the comment short and descriptive per coding guidelines.

In `@apps/web/src/components/docs/mdx-tabs.tsx`:
- Around line 32-68: Add concise JSDoc comments to each exported MDX tabs
component to document their purpose and key props: add a brief description above
MdxTabs explaining it's the root tabs component and noting controlled selection
props (items, defaultIndex/defaultValue, label), add a short comment above
MdxTabsList describing it as the tab list container with indicator, above
MdxTabsTab describing it as the individual tab trigger and key props (value,
children), above MdxTabsPanel describing it as the content panel, and above
MdxTab describing it as a convenience wrapper that resolves value from props or
context and include a `@throws` note stating it throws if no tab value can be
resolved; keep each JSDoc short (one-two sentences) and include prop highlights
where helpful.
- Around line 49-52: The onValueChange handler in mdx-tabs.tsx currently
silently returns if items is set and nextValue isn't included; update the
handler (the onValueChange callback that checks items, nextValue, and calls
setValue) to emit a development-time warning when this occurs (e.g., guard with
NODE_ENV !== 'production' or a dev-only logger) so developers see why the state
wasn't updated, then still return without changing state; keep the existing
items/includes/ setValue logic but add a clear message referencing nextValue and
the items list.

In `@apps/web/src/components/docs/package-command-pre.tsx`:
- Around line 60-85: Add a JSDoc block to the exported async component
PackageCommandPre describing its behavior and purpose: explain that it
normalizes and parses text via normalizeCommand and extractText, conditionally
parses with parsePackageCommand, checks language with isShellLanguage, generates
highlighted entries by mapping packageManagers and calling highlightShellCommand
and commandForManager, and renders either PackageManagerCommandBlock with
highlightedCommands or DefaultPre; include param description for props
(ComponentProps<"pre"> & { "data-language"?: string }), the return type
(JSX.Element | Promise<JSX.Element>), and note that it performs async
highlighting side-effects.

In `@apps/web/src/components/docs/package-command-utils.ts`:
- Around line 5-24: Add JSDoc comments for the exported PackageCommand interface
and the commandForManager function: document PackageCommand purpose and fields
(kind: CommandKind and args: string), and for commandForManager describe
purpose, parameters (command: PackageCommand, manager: PackageManager), behavior
for each CommandKind branch (how npm/yarn/pnpm/bun are mapped), and the return
value (string command). Ensure the JSDoc is placed immediately above the
exported declarations and mentions any edge cases (e.g., defaulting to pnpm for
dlx) so consumers understand the public API.

In `@apps/web/src/components/docs/package-command.tsx`:
- Around line 35-50: The code currently persists package manager selections to
both sessionStorage and localStorage in setStoredManager and reads from both in
readStoredManager; decide on a single storage medium (prefer localStorage for
cross-tab persistence) and simplify by writing only to localStorage and reading
only from localStorage using packageManagerStorageKey, leaving
packageManagerListeners and isPackageManager logic unchanged; if session-scoped
behavior is required, document the intent or add a separate explicit function,
otherwise remove sessionStorage calls to avoid redundant writes and confusing
read fallback behavior.
- Around line 176-182: Extract the duplicated extractText function into a single
shared utility: create a new utils module that exports extractText, import
isValidElement from "react" and keep the same implementation/typing, then
replace the local copies in the package-command and package-command-pre
components with an import from the new utility and delete the duplicate
definitions.

In `@apps/web/src/components/docs/package-manager-state.ts`:
- Around line 1-21: Add JSDoc comments to document the module's public API:
describe the exported PackageManager type (allowed values), the packageManagers
array (list of supported managers), packageManagerStorageKey (purpose/key used
in storage), and fallbackPackageManager (default). For functions
isPackageManager(value) and parsePackageManager(value) add JSDoc describing
parameters and return types/guards (e.g., `@param` value - input
string|null/undefined; `@returns` boolean for isPackageManager and PackageManager
for parsePackageManager), and a short usage example or note about behavior
(parse returns fallback when invalid). Place comments immediately above each
exported symbol (PackageManager, packageManagers, packageManagerStorageKey,
fallbackPackageManager, isPackageManager, parsePackageManager).

In `@apps/web/src/components/layout/navigation-bar.tsx`:
- Line 51: Remove the unnecessary separator comment line ("// ─── Data
────────────────────────────────────────────────────────────") from the
NavigationBar component in apps/web/src/components/layout/navigation-bar.tsx;
locate the comment near the top of the file (around where module-level
data/constants are defined) and delete that single-line separator so the file
follows the project's guideline of avoiding separator comments.
- Line 86: Remove the unnecessary separator comment "// ─── Tab styles
──────────────────────────────────────────────────────" from the NavigationBar
component in apps/web/src/components/layout/navigation-bar.tsx; simply delete
that standalone comment line (no code changes otherwise) to comply with the
guideline of avoiding separator comments in TypeScript/JavaScript files.
- Line 15: Remove the unnecessary separator comment line "// ─── Shared nav link
─────────────────────────────────────────────────" from the navigation-bar
component; locate the comment above the shared nav link code (around the
SharedNavLink / NavLink related JSX or function) and delete the separator so
only meaningful comments or code remain, following the project's guideline to
avoid decorative separator comments.
- Line 96: Remove the unnecessary separator comment line ("// ─── Component
───────────────────────────────────────────────────────") from the NavigationBar
component file; locate it in the navigation-bar.tsx near the component
declaration and delete that single comment so the file follows the guideline of
avoiding visual separator comments.
- Line 98: The NavigationBar component currently accepts an unused parameter
named _stars and renders a hardcoded "1k"; either remove the unused prop or
surface and use the actual value: change the parameter from { stars: _stars } to
{ stars } (or remove it altogether) in the NavigationBar function, replace the
hardcoded "1k" in the GitHub button render with a dynamic display like stars ??
"1k" (or remove the stars display if you choose to drop the prop), and update
any callers that pass null to NavigationBar to either stop passing the prop or
pass the real star count; also apply the same fix to the other duplicate
instance(s) of the NavigationBar prop usage.

In `@apps/web/src/components/sections/feedback-section.tsx`:
- Line 78: Replace the current fragile list key generation for TweetCard with
the tweet's unique link: locate where TweetCard is rendered (the TweetCard
component usage in feedback-section.tsx) and change the key from the template
`${tweet.handle}-${tweet.text}` to use `tweet.link` so each rendered TweetCard
uses the stable unique identifier `tweet.link` as the React key.

In `@apps/web/src/styles/globals.css`:
- Around line 286-288: There is a stylelint warning because there is no blank
line between the `@apply` rule and the subsequent declaration; update the block
containing the declarations "`@apply` overflow-x-hidden overflow-y-scroll;" and
"max-width: 100vw;" by inserting a single empty line before the "max-width:
100vw;" declaration so the `@apply` and the following property are separated per
stylelint rules.
- Line 96: The CSS custom property --secondary currently uses a hex value
(`#f5f5f5`) which is inconsistent with the rest of the theme that uses oklch();
update the --secondary declaration in globals.css to an equivalent oklch(...)
color so it matches the site's color space and tone (convert the hex to oklch
and replace the value for --secondary).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 48260000-d479-462e-958f-a01c96a8bad9

📥 Commits

Reviewing files that changed from the base of the PR and between 7cfdcb9 and ddccd8c.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (115)
  • AGENTS.md
  • apps/web/content/docs/cli.mdx
  • apps/web/content/docs/client.mdx
  • apps/web/content/docs/concepts/meta.json
  • apps/web/content/docs/concepts/payment-providers.mdx
  • apps/web/content/docs/customers.mdx
  • apps/web/content/docs/dashboard.mdx
  • apps/web/content/docs/database.mdx
  • apps/web/content/docs/entitlements.mdx
  • apps/web/content/docs/flows/meta.json
  • apps/web/content/docs/get-started/meta.json
  • apps/web/content/docs/guides/meta.json
  • apps/web/content/docs/installation.mdx
  • apps/web/content/docs/introduction.mdx
  • apps/web/content/docs/meta.json
  • apps/web/content/docs/metered-usage.mdx
  • apps/web/content/docs/plans-and-features.mdx
  • apps/web/content/docs/plugins.mdx
  • apps/web/content/docs/plugins/meta.json
  • apps/web/content/docs/providers/meta.json
  • apps/web/content/docs/providers/stripe.mdx
  • apps/web/content/docs/quickstart.mdx
  • apps/web/content/docs/skills.mdx
  • apps/web/content/docs/subscription-billing.mdx
  • apps/web/content/docs/subscriptions.mdx
  • apps/web/content/docs/typescript.mdx
  • apps/web/content/docs/webhook-events.mdx
  • apps/web/content/drafts/docs-index.mdx
  • apps/web/mdx-components.tsx
  • apps/web/next.config.js
  • apps/web/package.json
  • apps/web/source.config.ts
  • apps/web/src/app/(marketing)/blog/page.tsx
  • apps/web/src/app/(marketing)/contact/contact-form.tsx
  • apps/web/src/app/(marketing)/donate/page.tsx
  • apps/web/src/app/(marketing)/layout.tsx
  • apps/web/src/app/(marketing)/page.tsx
  • apps/web/src/app/(marketing)/sponsor/page.tsx
  • apps/web/src/app/api/og/[[...slug]]/route.tsx
  • apps/web/src/app/docs/[[...slug]]/page.tsx
  • apps/web/src/app/docs/layout.tsx
  • apps/web/src/app/llms.txt/route.ts
  • apps/web/src/app/not-found.tsx
  • apps/web/src/components/command-menu.tsx
  • apps/web/src/components/docs/copy-markdown-button.tsx
  • apps/web/src/components/docs/docs-code-surface.tsx
  • apps/web/src/components/docs/docs-icons.tsx
  • apps/web/src/components/docs/docs-layout.tsx
  • apps/web/src/components/docs/docs-mdx-components.tsx
  • apps/web/src/components/docs/docs-page.tsx
  • apps/web/src/components/docs/features.tsx
  • apps/web/src/components/docs/mdx-tabs.tsx
  • apps/web/src/components/docs/mdx-text.tsx
  • apps/web/src/components/docs/package-command-pre.tsx
  • apps/web/src/components/docs/package-command-utils.ts
  • apps/web/src/components/docs/package-command.tsx
  • apps/web/src/components/docs/package-manager-state.ts
  • apps/web/src/components/docs/sidebar-category-accordion.tsx
  • apps/web/src/components/docs/sidebar-collapse-button.tsx
  • apps/web/src/components/docs/toc-footer.tsx
  • apps/web/src/components/icons/index.tsx
  • apps/web/src/components/layout/mini-nav-bar.tsx
  • apps/web/src/components/layout/navigation-bar.tsx
  • apps/web/src/components/layout/section.tsx
  • apps/web/src/components/providers.tsx
  • apps/web/src/components/sections/cta-section.tsx
  • apps/web/src/components/sections/demo/demo-app-window.tsx
  • apps/web/src/components/sections/demo/demo-backend-panel.tsx
  • apps/web/src/components/sections/demo/demo-types.tsx
  • apps/web/src/components/sections/demo/index.tsx
  • apps/web/src/components/sections/features-section.tsx
  • apps/web/src/components/sections/feedback-content.ts
  • apps/web/src/components/sections/feedback-section.tsx
  • apps/web/src/components/sections/footer-section.tsx
  • apps/web/src/components/sections/hero-section.tsx
  • apps/web/src/components/sections/readme-code-content.ts
  • apps/web/src/components/sections/testimonials-section.tsx
  • apps/web/src/components/sidebar-content.tsx
  • apps/web/src/components/theme-switcher.tsx
  • apps/web/src/components/ui/accordion.tsx
  • apps/web/src/components/ui/breadcrumb.tsx
  • apps/web/src/components/ui/button-group.tsx
  • apps/web/src/components/ui/button.tsx
  • apps/web/src/components/ui/calendar.tsx
  • apps/web/src/components/ui/carousel.tsx
  • apps/web/src/components/ui/checkbox.tsx
  • apps/web/src/components/ui/code-block-content.tsx
  • apps/web/src/components/ui/code-block.tsx
  • apps/web/src/components/ui/combobox.tsx
  • apps/web/src/components/ui/command.tsx
  • apps/web/src/components/ui/context-menu.tsx
  • apps/web/src/components/ui/dialog.tsx
  • apps/web/src/components/ui/dropdown-menu.tsx
  • apps/web/src/components/ui/dynamic-code-block.tsx
  • apps/web/src/components/ui/frame-corners.tsx
  • apps/web/src/components/ui/input-otp.tsx
  • apps/web/src/components/ui/menubar.tsx
  • apps/web/src/components/ui/native-select.tsx
  • apps/web/src/components/ui/navigation-menu.tsx
  • apps/web/src/components/ui/pagination.tsx
  • apps/web/src/components/ui/select.tsx
  • apps/web/src/components/ui/sheet.tsx
  • apps/web/src/components/ui/sidebar.tsx
  • apps/web/src/components/ui/sonner.tsx
  • apps/web/src/components/ui/spinner.tsx
  • apps/web/src/components/web/brand-menu.tsx
  • apps/web/src/components/web/footer.tsx
  • apps/web/src/components/web/hero-code-block.tsx
  • apps/web/src/components/web/hero-title.tsx
  • apps/web/src/lib/consts.ts
  • apps/web/src/lib/lucide-react-remix-shim.ts
  • apps/web/src/lib/shiki-themes.ts
  • apps/web/src/lib/shiki-themes/shiki-aura-theme.ts
  • apps/web/src/styles/globals.css
  • dev/DESIGN.md
💤 Files with no reviewable changes (15)
  • apps/web/content/docs/concepts/meta.json
  • apps/web/content/docs/concepts/payment-providers.mdx
  • apps/web/content/docs/providers/stripe.mdx
  • apps/web/src/components/docs/sidebar-collapse-button.tsx
  • apps/web/content/docs/introduction.mdx
  • apps/web/content/docs/providers/meta.json
  • apps/web/content/docs/plugins/meta.json
  • apps/web/src/app/(marketing)/donate/page.tsx
  • apps/web/content/docs/guides/meta.json
  • apps/web/src/components/sections/testimonials-section.tsx
  • apps/web/content/docs/flows/meta.json
  • apps/web/content/docs/get-started/meta.json
  • apps/web/src/components/command-menu.tsx
  • apps/web/src/components/docs/sidebar-category-accordion.tsx
  • apps/web/src/lib/consts.ts

Comment thread AGENTS.md Outdated
Comment on lines +26 to +30
If need to inspect source code of libraries or packages, prefer inspected clonned source repo while exists, instead of inspecting library dist.

those directories already contain the source checkout of some packages:

- `~/ref/fumadocs` - fumadocs framework / package.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix wording/typos in the new references guidance.

The new guidance has grammar/typo issues (clonned, lowercase sentence start) that make the rule harder to parse quickly. Tightening the wording will avoid ambiguity.

Suggested edit
-If need to inspect source code of libraries or packages, prefer inspected clonned source repo while exists, instead of inspecting library dist.
-
-those directories already contain the source checkout of some packages:
+If you need to inspect source code of libraries or packages, prefer an inspected cloned source repository (when available) instead of library dist artifacts.
+
+These directories already contain source checkouts of some packages:
📝 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
If need to inspect source code of libraries or packages, prefer inspected clonned source repo while exists, instead of inspecting library dist.
those directories already contain the source checkout of some packages:
- `~/ref/fumadocs` - fumadocs framework / package.
If you need to inspect source code of libraries or packages, prefer an inspected cloned source repository (when available) instead of library dist artifacts.
These directories already contain source checkouts of some packages:
- `~/ref/fumadocs` - fumadocs framework / package.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@AGENTS.md` around lines 26 - 30, Fix typos and tighten the sentence in
AGENTS.md: replace "clonned" with "cloned", capitalize the sentence start after
the comma, and rephrase the guidance to read clearly (e.g., "If you need to
inspect source code of libraries or packages, prefer inspecting the cloned
source repository when available, rather than the library dist. These
directories already contain source checkouts for some packages: `~/ref/fumadocs`
- fumadocs framework / package."). Update the sentence containing "clonned" and
the following line referencing `~/ref/fumadocs`.

import { CTASection } from "@/components/sections/cta-section";
import { DemoSection } from "@/components/sections/demo";
import { FeaturesSection } from "@/components/sections/features-section";
import { FeedbackSection } from "@/components/sections/feedback-section";

Copy link
Copy Markdown

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
# Description: Verify FeaturesSection usage and confirm it's intentionally removed

# Check for FeaturesSection imports or references
rg "FeaturesSection" apps/web/src -g '*.{ts,tsx}'

# Look for the FeaturesSection component file
fd FeaturesSection apps/web/src

# Check if FeedbackSection exists and is properly implemented
fd FeedbackSection apps/web/src

Repository: getpaykit/paykit

Length of output: 150


Confirm the FeaturesSection component is intentionally retired (and remove it if unused).

  • apps/web/src/app/(marketing)/page.tsx now imports/renders FeedbackSection.
  • FeaturesSection has no remaining references under apps/web/src—it only exists as the definition in apps/web/src/components/sections/features-section.tsx.
    If FeaturesSection is intentionally removed, delete it or mark it deprecated/moved; otherwise rewire it where it’s supposed to be used.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/app/`(marketing)/page.tsx at line 3, The codebase now renders
FeedbackSection while FeaturesSection has no remaining references; confirm
whether FeaturesSection (the component defined as FeaturesSection in
features-section.tsx) is intentionally retired—if yes, delete the
FeaturesSection component file or mark it deprecated/moved and remove its
export; if it's still needed, rewire the page to import and render
FeaturesSection where appropriate (replace or combine with FeedbackSection) and
update any exports/imports so FeaturesSection is actually referenced.

Comment on lines +56 to +58
function getHeadingId(children: ComponentPropsWithoutRef<"h2">["children"]) {
return children?.toString().replace(/ /g, "-").replace(/'/g, "").replace(/\?/g, "").toLowerCase();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Heading ID generation could produce collisions.

The getHeadingId function uses simple string replacement that may produce duplicate IDs for different headings. For example, "What's new?" and "Whats new" would both become whats-new. Consider using a more robust slug generation library or adding collision detection.

🔧 Suggested improvement

Consider using a library like github-slugger for robust, collision-free ID generation:

import GithubSlugger from 'github-slugger';

const slugger = new GithubSlugger();

function getHeadingId(children: ComponentPropsWithoutRef<"h2">["children"]) {
  return slugger.slug(children?.toString() ?? '');
}

Or implement collision detection:

const usedIds = new Set<string>();

function getHeadingId(children: ComponentPropsWithoutRef<"h2">["children"]) {
  let id = children?.toString().replace(/ /g, "-").replace(/'/g, "").replace(/\?/g, "").toLowerCase();
  let counter = 1;
  let uniqueId = id;
  while (usedIds.has(uniqueId)) {
    uniqueId = `${id}-${counter++}`;
  }
  usedIds.add(uniqueId);
  return uniqueId;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/docs/docs-mdx-components.tsx` around lines 56 - 58,
The heading ID generation in getHeadingId can produce collisions (e.g., "What's
new?" and "Whats new" both become "whats-new"); fix by switching to a robust
slugger or adding collision detection: import and use a slug library like
GithubSlugger and call slugger.slug(children?.toString() ?? '') inside
getHeadingId, or maintain a module-level Set (e.g., usedIds) and, after creating
the base slug from children, append a numeric suffix while usedIds.has(id) to
ensure uniqueness, then add the final id to usedIds before returning; update
getHeadingId to use one of these approaches.

@maxktz maxktz merged commit 4612be4 into feat/polar-remove Jun 6, 2026
6 checks passed
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