Dev --> Prod#133
Conversation
Emit per-page <slug>.md companions, an llms.txt index, and a hand-authored home .md for /docs/test-management/ during gatsby build. Add <link rel="alternate" type="text/markdown"> to every page's head, configure S3 Content-Type for .md, and ship a "Copy page" dropdown next to the page title with Copy / View / Open in ChatGPT / Claude / Perplexity actions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CopyPageMenu: coerce non-string slug to '' and read window.location.origin (with prod URL fallback for SSR) so the .md URL works in local dev and staging without hardcoding a production host. seo.jsx: default slug to '' in the alternate link href so the SEO render won't crash if a future caller forgets to pass slug. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add LLM-friendly markdown outputs and Copy page menu
📝 WalkthroughWalkthroughThis PR implements a complete markdown companion export pipeline: the build process now generates LLM-friendly markdown companions for test-management documentation, serves them from S3 with correct MIME types, advertises them via SEO link tags, and provides a "Copy Page" UI menu for users to copy/share markdown and open content in external LLM services. ChangesLLM-Friendly Markdown Companion Export and Copy Menu
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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 `@src/components/CopyPageMenu.jsx`:
- Around line 89-95: The mdUrl construction uses safeSlug that can be empty and
yields an invalid URL like "https://testsigma.com.md"; normalize/fallback slug
before building mdUrl by creating a normalizedSlug: if slug is a non-empty
string ensure it begins with a single leading "/" (add one if missing) and strip
any trailing "/" (use safeSlug logic), otherwise fall back to "/" (root). Then
build mdUrl with `${origin}${normalizedSlug.replace(/\/$/, '')}.md` (or more
simply concatenate origin + normalizedSlug ensuring a separator) so
functions/variables referenced (slug, safeSlug, mdUrl, prompt) produce a valid
URL for Copy/View/Open actions.
- Around line 116-118: The setTimeout created after calling setCopied(true) (in
the copy handler) can fire after the component unmounts; store the timeout id
(from setTimeout) in a ref or component state inside the copy handler (e.g.,
timeoutRef or copyTimeoutId) and assign the result of setTimeout to it, then add
a useEffect cleanup that clears that timeout via
clearTimeout(timeoutRef.current) on unmount; also clear any existing timeout
before setting a new one in the copy handler to avoid multiple pending timers.
Ensure you update the handler name where used (e.g., handleCopy / setCopied) and
reference the timeoutRef in the cleanup.
In `@src/components/seo.jsx`:
- Around line 204-208: The markdown alternate link in src/components/seo.jsx
currently renders for every page and when slug is falsy can produce invalid
URLs; change the rendering so the <link rel='alternate' type='text/markdown'
.../> is only output when slug is truthy and matches the docs/test-management
paths (e.g. test the slug with a startsWith or a regex like
^/docs/test-management(/|$)); use that guarded slug value instead of
unconditionally using (slug || '') so you never emit "https://testsigma.com.md"
or alternates for pages that don't have emitted .md files.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 97a11a12-34ca-42ef-955f-9afa4c25f31c
📒 Files selected for processing (6)
gatsby-config.jsgatsby-node.jssrc/components/CopyPageMenu.jsxsrc/components/CopyPageMenu.scsssrc/components/seo.jsxsrc/templates/page.jsx
| const safeSlug = typeof slug === 'string' ? slug : ''; | ||
| const origin = | ||
| typeof window !== 'undefined' | ||
| ? window.location.origin | ||
| : 'https://testsigma.com'; | ||
| const mdUrl = `${origin}${safeSlug.replace(/\/$/, '')}.md`; | ||
| const prompt = `Read ${mdUrl} and help me with: `; |
There was a problem hiding this comment.
Normalize/fallback slug before constructing mdUrl.
If slug is empty/non-string, Line 94 builds an invalid URL (https://testsigma.com.md), so Copy/View/Open actions break instead of degrading gracefully.
Proposed fix
- const safeSlug = typeof slug === 'string' ? slug : '';
+ const safeSlug = typeof slug === 'string' ? slug.trim() : '';
+ const pathFromLocation =
+ typeof window !== 'undefined' ? window.location.pathname : '';
+ const rawPath = safeSlug || pathFromLocation;
+ const normalizedPath = rawPath
+ ? (rawPath.startsWith('/') ? rawPath : `/${rawPath}`).replace(/\/$/, '')
+ : '';
const origin =
typeof window !== 'undefined'
? window.location.origin
: 'https://testsigma.com';
- const mdUrl = `${origin}${safeSlug.replace(/\/$/, '')}.md`;
+ const mdUrl = normalizedPath ? `${origin}${normalizedPath}.md` : '';📝 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.
| const safeSlug = typeof slug === 'string' ? slug : ''; | |
| const origin = | |
| typeof window !== 'undefined' | |
| ? window.location.origin | |
| : 'https://testsigma.com'; | |
| const mdUrl = `${origin}${safeSlug.replace(/\/$/, '')}.md`; | |
| const prompt = `Read ${mdUrl} and help me with: `; | |
| const safeSlug = typeof slug === 'string' ? slug.trim() : ''; | |
| const pathFromLocation = | |
| typeof window !== 'undefined' ? window.location.pathname : ''; | |
| const rawPath = safeSlug || pathFromLocation; | |
| const normalizedPath = rawPath | |
| ? (rawPath.startsWith('/') ? rawPath : `/${rawPath}`).replace(/\/$/, '') | |
| : ''; | |
| const origin = | |
| typeof window !== 'undefined' | |
| ? window.location.origin | |
| : 'https://testsigma.com'; | |
| const mdUrl = normalizedPath ? `${origin}${normalizedPath}.md` : ''; | |
| const prompt = `Read ${mdUrl} and help me with: `; |
🤖 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 `@src/components/CopyPageMenu.jsx` around lines 89 - 95, The mdUrl construction
uses safeSlug that can be empty and yields an invalid URL like
"https://testsigma.com.md"; normalize/fallback slug before building mdUrl by
creating a normalizedSlug: if slug is a non-empty string ensure it begins with a
single leading "/" (add one if missing) and strip any trailing "/" (use safeSlug
logic), otherwise fall back to "/" (root). Then build mdUrl with
`${origin}${normalizedSlug.replace(/\/$/, '')}.md` (or more simply concatenate
origin + normalizedSlug ensuring a separator) so functions/variables referenced
(slug, safeSlug, mdUrl, prompt) produce a valid URL for Copy/View/Open actions.
| setCopied(true); | ||
| setTimeout(() => setCopied(false), 1500); | ||
| } catch (err) { |
There was a problem hiding this comment.
Clear the copied-state timeout on unmount.
Line 117 schedules state updates without cleanup; navigating away quickly can trigger stale updates after unmount.
Proposed fix
-import React, { useState } from 'react';
+import React, { useEffect, useRef, useState } from 'react';
@@
const [open, setOpen] = useState(false);
const [copied, setCopied] = useState(false);
+ const copiedTimerRef = useRef(null);
@@
- setCopied(true);
- setTimeout(() => setCopied(false), 1500);
+ setCopied(true);
+ clearTimeout(copiedTimerRef.current);
+ copiedTimerRef.current = setTimeout(() => setCopied(false), 1500);
@@
+ useEffect(() => {
+ return () => clearTimeout(copiedTimerRef.current);
+ }, []);🤖 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 `@src/components/CopyPageMenu.jsx` around lines 116 - 118, The setTimeout
created after calling setCopied(true) (in the copy handler) can fire after the
component unmounts; store the timeout id (from setTimeout) in a ref or component
state inside the copy handler (e.g., timeoutRef or copyTimeoutId) and assign the
result of setTimeout to it, then add a useEffect cleanup that clears that
timeout via clearTimeout(timeoutRef.current) on unmount; also clear any existing
timeout before setting a new one in the copy handler to avoid multiple pending
timers. Ensure you update the handler name where used (e.g., handleCopy /
setCopied) and reference the timeoutRef in the cleanup.
| <link | ||
| rel='alternate' | ||
| type='text/markdown' | ||
| href={`https://testsigma.com${(slug || '').replace(/\/$/, '')}.md`} | ||
| /> |
There was a problem hiding this comment.
Gate markdown alternate links to pages that actually have emitted .md files.
Line 207 currently emits a markdown alternate URL for every page. The build only generates companion markdown for /docs/test-management/**, so this creates broken alternates on other pages; with missing slug, it can also produce https://testsigma.com.md.
Suggested fix
+ const safeSlug = typeof slug === 'string' ? slug : '';
+ const isMarkdownCompanionPage = safeSlug.startsWith('/docs/test-management/');
+ const markdownHref = isMarkdownCompanionPage
+ ? `https://testsigma.com${safeSlug.replace(/\/$/, '')}.md`
+ : null;
...
- <link
- rel='alternate'
- type='text/markdown'
- href={`https://testsigma.com${(slug || '').replace(/\/$/, '')}.md`}
- />
+ {markdownHref && (
+ <link rel='alternate' type='text/markdown' href={markdownHref} />
+ )}🤖 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 `@src/components/seo.jsx` around lines 204 - 208, The markdown alternate link
in src/components/seo.jsx currently renders for every page and when slug is
falsy can produce invalid URLs; change the rendering so the <link
rel='alternate' type='text/markdown' .../> is only output when slug is truthy
and matches the docs/test-management paths (e.g. test the slug with a startsWith
or a regex like ^/docs/test-management(/|$)); use that guarded slug value
instead of unconditionally using (slug || '') so you never emit
"https://testsigma.com.md" or alternates for pages that don't have emitted .md
files.
Feat: Add LLM friendly docs
Summary by CodeRabbit
New Features
Chores