refactor(docs): Replace Sphinx doc pages with typescript pages and reorganize home page.#52
refactor(docs): Replace Sphinx doc pages with typescript pages and reorganize home page.#52AVMatthews wants to merge 3 commits intoy-scope:mainfrom
Conversation
WalkthroughThe pull request migrates the documentation system from a Sphinx-based Python generator to a Next.js-based React application. This includes removing the Sphinx configuration and markdown documentation files, introducing a complete Next.js app structure with React components for layout, navigation, footer, and shared utilities, adding comprehensive build and tooling configurations, and updating the build process to export the static Next.js site. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Navbar
participant ThemeProvider
participant LocalStorage
participant DOM
User->>Navbar: Click theme toggle button
Navbar->>ThemeProvider: Call toggleTheme()
ThemeProvider->>ThemeProvider: Update theme state (light ↔ dark)
ThemeProvider->>LocalStorage: Persist "ui-theme" value
ThemeProvider->>DOM: Set data-bs-theme attribute on body
DOM->>User: Apply theme styles
sequenceDiagram
participant Browser
participant RootLayout
participant ThemeProvider
participant Navbar
participant Page
participant Footer
Browser->>RootLayout: Load page
RootLayout->>ThemeProvider: Initialize with localStorage/system preference
RootLayout->>Navbar: Render navigation component
Navbar->>Navbar: Fetch GitHub stars on mount
RootLayout->>Page: Render page children
RootLayout->>Footer: Render footer component
RootLayout->>Browser: Return complete HTML with theme context
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
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: 58
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
server/src/main.js (1)
30-30: 🧹 Nitpick | 🔵 Trivial
parseIntshould include an explicit radix.Without the radix,
parseIntcan produce unexpected results for strings with leading zeros in non-strict contexts. This is a minor robustness improvement.Proposed fix
- const port = parseInt(process.env.PORT); + const port = parseInt(process.env.PORT, 10);
🤖 Fix all issues with AI agents
In `@docs/.prettyierrc.yaml`:
- Around line 1-6: The config filename is misspelled; rename the file from
.prettyierrc.yaml to .prettierrc.yaml so Prettier will detect and apply the
settings (the content with keys like tabWidth, singleQuote, printWidth,
endOfLine should remain unchanged).
In `@docs/app/assets/scss/styles.scss`:
- Around line 1-28: The .btn-github rules (including selectors .btn-github and
[data-bs-theme="dark"] .btn-github / svg and [data-bs-theme="light"] .btn-github
svg) are defined before Bootstrap's functions/variables/mixins imports—move that
entire block so it appears after the Bootstrap imports so any future use of
Bootstrap variables or mixins inside these rules will compile; keep the
selectors and declarations unchanged, simply relocate the whole block below the
imports.
- Around line 43-54: The three Sass maps $yscope-colors-text,
$yscope-colors-bg-subtle, and $yscope-colors-border-subtle are declared but
never used; either remove them or merge them into the theme maps so they take
effect. Fix by either deleting these unused variables, or merge each into the
appropriate Bootstrap/theme map (e.g., use map-merge to combine
$yscope-colors-text into $theme-colors-text and similarly merge
$yscope-colors-bg-subtle and $yscope-colors-border-subtle into the corresponding
background/border maps) so the colors are actually consumed by the build.
- Around line 56-88: The SCSS currently imports every Bootstrap component which
bloats the CSS; audit which Bootstrap components the docs actually use and
remove unused `@import` lines in styles.scss (start from the TODO near the top),
e.g., drop imports for rarely used modules like toasts, carousel, spinners,
popover, modal, offcanvas, placeholders, etc., keep only core pieces your pages
reference (reboot, type, grid, forms, buttons, nav/navbar, utilities as needed),
update the TODO to reflect that pruning was done, and re-run the
build/asset-size check to verify the bundle shrinks.
In `@docs/app/dev-guide/contrib-guides-cpp/layout.tsx`:
- Line 7: Fix the typo in the metadata title field by changing the value of the
"title" key in layout.tsx from "C++ Contirbution | YScope Developer Guide" to
"C++ Contribution | YScope Developer Guide"; locate the title field in the file
(the metadata variable/constant named title) and update the string accordingly.
In `@docs/app/dev-guide/contrib-guides-cpp/page.tsx`:
- Line 33: The JSX contains no-op empty string expressions `{""}` (appearing
where other code uses `{" "}`) which render nothing; remove these `{""}`
occurrences or replace them with `{" "}` where an actual space is intended so
layout/spacing is preserved—search for all `{""}` tokens in the file and either
delete them or swap to `{" "}` based on nearby elements and spacing needs
(compare with existing `{" "}` usages to decide).
- Around line 1-2: This file disables max-lines and max-lines-per-function for a
large static JSX document; extract the long JSX content out of the single page
component (e.g., the default export, likely named Page or the top-level
component in page.tsx) into MDX (docs/app/dev-guide/contrib-guides-cpp.md x) or
split it into smaller presentational components (e.g., ContribGuideSectionA,
ContribGuideSectionB) that are imported and composed by the page component, then
remove the /* eslint-disable max-lines */ and /* eslint-disable
max-lines-per-function */ headers so ESLint can enforce limits again; ensure the
page.tsx now only composes/imports sections or imports the MDX file and keeps
the function body small and under the configured limits.
- Around line 242-244: Replace the typographic/smart apostrophe used in the text
"file’s" with the HTML entity ' to match the rest of the file and avoid
encoding inconsistencies; locate the snippet around the inline code
<code><FilenameStem_stem></code> and update the following plain text "is
the file’s name without the extension." to use "is the file's name without
the extension." so apostrophe usage is consistent.
- Around line 240-245: Replace the incorrect placeholder text
`FilenameStem_stem` with `FilenameStem` in the docs bit (the list item near the
`<FilenameStem>_internal` example) so the description matches the defined
placeholder; update the string in the JSX for the list item that currently
renders `<FilenameStem_stem>` to `<FilenameStem>` to keep the docs consistent
with the `<FilenameStem>_internal` example.
In `@docs/app/dev-guide/contrib-guides-general/page.tsx`:
- Around line 12-17: Create a reusable CSS class for the repeated inline style
and apply it to the headings instead of inline styles: add a class (e.g.,
.headingBold { font-weight: bolder; }) in the component stylesheet or a shared
CSS/SCSS module, then replace the inline style={{fontWeight: "bolder"}} on the
h1, h2, and h3 elements with className="headingBold" (or import and use the
module-scoped class if using CSS modules). Ensure the class is
imported/available to the page component so the headings render with the same
bold styling without inline repetition.
- Line 1: Remove the top-level "use client" directive from this page component
so it becomes a Server Component; edit the file to delete the "use client" line
and confirm the default export (e.g., export default function Page or the
existing default export) contains only server-compatible code (no React hooks
like useState/useEffect or browser-only APIs) before committing.
In `@docs/app/dev-guide/contrib-guides-overview/layout.tsx`:
- Around line 6-9: The metadata object uses inconsistent casing for the product
name: update the metadata constant (export const metadata: Metadata) so both the
title field ("title") and the description field ("description") use "YScope"
with a capital 'S' instead of "Yscope"; locate the metadata object in layout.tsx
and replace the occurrences inside title and the concatenated description string
to match the other layout files.
In `@docs/app/dev-guide/contrib-guides-overview/page.tsx`:
- Around line 29-38: Replace the plain anchor tags used for internal routes in
the list with Next.js Link components: import Link from "next/link" at the top
of the module and wrap each internal href (e.g., the entries currently using <a
href={"/dev-guide/contrib-guides-general/"}>, <a
href={"/dev-guide/contrib-guides-cpp/"}>, <a
href={"/dev-guide/contrib-guides-taskfiles/"}>) with <Link href="..."> so
client-side routing is used; keep the visible text (the list item content) the
same and remove the plain <a> tags for these internal links.
- Around line 1-2: Remove the unnecessary "use client" directive at the top of
page.tsx because this page has no client-only behavior and the nested Admonition
component already declares "use client"; open page.tsx, delete the "use client"
string literal at the top so the file becomes a Server Component while still
importing and rendering Admonition.
In `@docs/app/dev-guide/contrib-guides-taskfiles/page.tsx`:
- Around line 1-2: The file-level eslint-disable indicates the default exported
component (likely Page in docs/app/dev-guide/contrib-guides-taskfiles/page.tsx)
is too large; split it by extracting logical subsections into separate
components (e.g., PathsSection, SourcesAndGeneratesSection, TaskOrderingSection)
and import them into the Page component, moving related JSX, state, and handlers
into those new components or into custom hooks and passing necessary props (or
callbacks) back to Page; ensure you export the new components or keep them
internal to the module and update any imports/usages accordingly so the
top-level Page becomes a small composition of these focused components.
- Line 23: There are multiple no-op empty JSX string expressions `{""}` in the
page.tsx JSX (they add noise but render nothing); remove all occurrences (e.g.,
the ones around lines 23, 35, 246, 252, 344, 679) from the component markup so
the JSX is clean, then run the TypeScript/JSX compile or formatting
(prettier/tsc) to ensure no trailing commas or formatting issues in the
surrounding components/JSX elements remain.
- Around line 213-217: The code block currently mixes JSX expressions, HTML
entities and backslashes causing smart quotes and literal backslashes to render;
replace the fragmented expressions with a single plain code string containing
the template expression using straight quotes (e.g. use a single JSX string like
"{{.TASK | replace ':' '#'}}" instead of the current escaped/smart-quote
fragments) so the rendered output shows {{.TASK | replace ":" "#" }} exactly as
intended.
In `@docs/app/dev-guide/misc-deploying/page.tsx`:
- Around line 27-28: Remove the no-op JSX empty-string expressions "{""}" found
in the page.tsx JSX (they render nothing); delete each occurrence (the ones
reported on lines near the layout paragraphs) and, if a space was intended,
replace with a real whitespace expression '{" "}' instead so spacing is
explicit; search for the exact token "{""}" in the file and remove or replace it
within the component's JSX.
- Around line 1-2: Remove the "use client" directive at the top of the file so
Next.js can treat the Deploying component as a Server Component; specifically
delete the "use client" line (and keep or adjust the existing /* eslint-disable
max-lines-per-function */ as needed), verify the Deploying component contains no
React hooks, event handlers, or browser-only APIs, and run the build to confirm
it renders as a server component.
In `@docs/app/dev-guide/page.tsx`:
- Line 1: Remove the top-level "use client" directive from this module (the line
containing "use client") so the page.tsx can be rendered as a Server Component;
confirm there are no client-only hooks, state, effects, or event handlers in the
JSX (if any are needed, extract them into a separate Client Component) and keep
the rest of the static JSX unchanged.
- Around line 19-38: Replace plain anchor tags used for internal navigation with
Next.js Link components: add an import for Link from 'next/link' at the top of
the file and change each <a href={"/dev-guide/..."}>...</a> to <Link
href="/dev-guide/...">...</Link> (or use the <Link><a>...</a></Link> pattern if
you need anchor props); update the list items (the links labeled "Overview",
"General Guidelines", "C++", "Taskfiles", "Deploying Main Docs", etc.)
accordingly to enable client-side navigation.
In `@docs/app/Footer.tsx`:
- Around line 79-81: The copyright year in the Footer component is hardcoded as
"2015-2025" and needs to be dynamic; update the Footer (docs/app/Footer.tsx) so
the end year is computed at runtime (e.g., const currentYear = new
Date().getFullYear()) and render "2015-{currentYear}" inside the existing <p>
element instead of the fixed "2015-2025", ensuring no other text changes.
- Around line 33-55: The social anchor elements in Footer.tsx (the <a> tags
wrapping the <i className={"bi bi-linkedin"} />, <i className={"bi bi-youtube"}
/>, and <i className={"bi bi-envelope"} />) need accessible names; update each
anchor to include either an aria-label (e.g., aria-label="LinkedIn", "YouTube",
"Email") or add visually hidden text inside the anchor so screen readers can
announce them, ensuring you keep rel and target attributes unchanged and apply
the same change to the LinkedIn, YouTube, and mailto anchors.
In `@docs/app/layout.tsx`:
- Line 24: Move the ThemeProvider import statement to the top of the file with
the other imports (above the exports like metadata and viewport) so all imports
are grouped together; update the import order for ThemeProvider (from
"./shared/ThemeProvider") to appear before the metadata and viewport exports and
verify there are no import-order or circular dependency side effects in
layout.tsx.
In `@docs/app/Navbar.tsx`:
- Around line 110-310: The two dropdown blocks duplicate structure and behavior
(projectsOpen/setProjectsOpen, devOpen/setDevOpen, the button and dropdown <ul>
markup); extract a reusable NavDropdown component that takes props: label, href
(button click), items (array of {label, href, external?}), isOpen, setIsOpen,
and optional style/class overrides, then replace both instances with
<NavDropdown ...> using the existing state setters (setProjectsOpen/setDevOpen)
and state values (projectsOpen/devOpen) and keep the existing onClick logic for
item clicks (closing dropdown and collapsing navbar via setExpanded(false)).
- Around line 134-137: The onClick handlers in Navbar (the anonymous onClick
that calls setExpanded(false) then window.location.href = "/#projects" and the
similar handler that navigates to "/dev-guide/") cause full page reloads;
replace them with Next.js client-side navigation using next/router's
useRouter().push(...) or wrap the elements with next/link to navigate to
"/#projects" and "/dev-guide/" while still calling setExpanded(false). Locate
the anonymous onClick handlers in Navbar.tsx (the handlers that call setExpanded
and window.location.href) and change them to call router.push('/#projects') or
router.push('/dev-guide/') or use <Link> so navigation is client-side and
SPA-friendly.
- Around line 364-377: The theme toggle button (id "themeSwitcher") is missing
an explicit type, so it defaults to type="submit" and may submit enclosing
forms; update the button element to include type="button" alongside its existing
props (the element with id "themeSwitcher" and onClick handler toggleTheme) to
prevent accidental form submission.
- Around line 58-71: The conditional in useEffect's handleClick uses a negation
operator (!navRef.current.contains(e.target)) which violates the project's
guideline; change that expression to use an explicit comparison to false (e.g.,
replace the ! expression with false == navRef.current.contains(e.target)) so the
if condition reads with an equality comparison; update the handleClick closure
inside the useEffect (referencing navRef, e.target, setProjectsOpen, setDevOpen)
and keep the rest of the event listener add/remove logic unchanged.
- Around line 323-349: The GitHub icon SVG in the Navbar component is decorative
but lacks an accessibility marker; update the SVG element (the GitHub icon SVG
block in Navbar.tsx) to be hidden from assistive tech by adding
aria-hidden={"true"} (keeping the parent <a> with aria-label={"GitHub
repository"} as the accessible name) and ensure there is no empty <title> inside
the SVG so screen readers don't announce it.
- Around line 40-53: The fetch in the useEffect should be cancellable: create an
AbortController inside the effect, pass controller.signal to fetch, and in the
cleanup call controller.abort() so the request is cancelled if the component
unmounts; update the .then/.catch handlers (the effect using useEffect and state
setter setGithubStars) to avoid calling setGithubStars when the fetch was
aborted (e.g., check error.name === 'AbortError' in catch and skip state update)
and ensure you still handle non-OK responses and parsing as before.
In `@docs/app/page.tsx`:
- Around line 46-109: IconLink and Category are currently defined inside the
Home render and are recreated on every render; move their definitions to module
scope (i.e., lift IconLink and Category out of the Home component) so React
won't remount their subtrees on state changes. Update their prop typings if
needed and ensure Home simply uses <IconLink .../> and <Category .../>;
alternatively, if you prefer not to move them, wrap them with React.memo to
memoize (but lifting to module scope is preferred since neither captures Home's
local state). Ensure any references to variables from Home are removed so the
moved components are pure.
- Line 416: Remove the duplicate paragraph element that repeats "Need help? Join
us on one of our community servers:" in the JSX (the <p> element with that exact
text) in docs/app/page.tsx — either delete that <p> or replace its text with an
appropriate alternative such as "For other inquiries:" so the copy before the
"Contact Us" button no longer duplicates the earlier line.
- Around line 32-43: The current useState + useEffect pair (prestoSrc,
setPrestoSrc, mcpSrc, setMcpSrc and the useEffect that watches theme) is
unnecessary; compute the image srcs directly from theme during render and remove
the state and effect to avoid an extra render. Replace the useState declarations
and the useEffect block by deriving constants (e.g., const prestoSrc = theme ===
"dark" ? "...presto_dark.svg" : "...presto_light.svg" and similarly for mcpSrc)
and update any JSX that references prestoSrc/mcpSrc accordingly, then delete the
unused setPrestoSrc/setMcpSrc and the useEffect import/usages.
- Line 58: Replace the non-specific any types: change the imgStyle prop type
from any to React.CSSProperties (import React if needed), and replace items:
Array<any> with a concrete interface (e.g. declare an Item interface matching
the actual object shape used in the component — fields like id, title,
image/src, description, link, etc. based on how items are accessed) and use
items: Item[]; update the Category type/props (the Category component/type
referenced in the diff) to reference the new Item interface so all item property
accesses are strongly typed.
In `@docs/app/shared/Admonition.tsx`:
- Around line 29-36: Admonition currently allows type to be undefined which
yields className "admonition undefined" and aria-label undefined; update the
Admonition component to default type to "note" (e.g., set type = "note" in the
prop destructure for the Admonition function) and keep displayTitle = title ||
titleMap[type] so className (`admonition ${type}`) and aria-label
(`displayTitle`) always have sensible values; ensure references to the
Admonition component, the type prop, displayTitle variable, and titleMap are
used to locate and apply the change.
- Around line 32-37: The component Admonition currently renders a <div
role="region">; replace that element with a semantic <section> element to
satisfy useSemanticElements and improve accessibility — update the JSX in
Admonition (the returned element with aria-label={displayTitle},
className={`admonition ${type}`}, and role={"region"}) to use <section> and
remove the explicit role while preserving aria-label, className, and any other
attributes/children so behavior and styling of Admonition remain unchanged.
In `@docs/app/shared/CodeBlock.tsx`:
- Around line 22-26: The JSDoc contains auto-generated placeholder params
("@param root0" and "@param root0.text") that add no value; for the CodeBlock
component remove these stub `@param` lines (and the similar stub block around the
CodeBlock declaration) or replace them with concise, meaningful descriptions of
the component props (e.g., explain the prop object shape and the "text" prop) so
the JSDoc accurately documents the CodeBlock component and its props.
- Around line 95-97: The code currently renders `language-${language}` for the
<pre> and <code> classNames in the CodeBlock component which produces
`language-undefined` when the language prop is omitted; change the component to
derive a safe fallback like const lang = language || 'none' (or 'text') and use
`language-${lang}` for both <pre> and <code>, or set a default for the language
prop in the component signature, ensuring the className never contains
"undefined".
In `@docs/app/shared/ThemeProvider.tsx`:
- Around line 17-31: The current getInitialTheme approach (used by
ThemeProvider) can cause a flash-of-unchanged-content (FOUC) for dark-mode users
because the app initializes to "light" and then updates in useEffect; to
mitigate, add a small blocking script in the HTML head (via Next.js <Script
strategy="beforeInteractive"> or custom _document) that reads localStorage
"ui-theme" or prefers-color-scheme and sets the initial data-bs-theme attribute
(or inserts a style class) before paint so the ThemeProvider's getInitialTheme
and subsequent useEffect updates won't flash the wrong theme.
- Around line 40-49: The ThemeProvider currently calls getInitialTheme() during
initial render (via useState(getInitialTheme())), risking hydration mismatches;
change to initialize useState with a fixed default (e.g., "light") and move the
getInitialTheme() call into a client-only useEffect that calls setTheme(...)
once; inside that effect also update document.body.setAttribute("data-bs-theme",
theme) and localStorage.setItem("ui-theme", theme) (or keep the existing
theme-change effect but remove the unnecessary typeof window guard since
useEffect is client-only). Ensure you reference ThemeProvider, getInitialTheme,
useState, useEffect, document.body.setAttribute, and localStorage.setItem when
making the change.
In `@docs/eslint.config.mjs`:
- Around line 8-12: The ESLint ignores array currently contains "dist/" and
"node_modules/" but is missing Next.js generated directories; update the ignores
array (the "ignores" symbol in the config) to also include ".next/" and "out/"
so generated build/cache/output files are skipped by ESLint.
In `@docs/next-sitemap.config.js`:
- Line 11: The siteUrl value in next-sitemap.config.js is likely incorrect (it
uses "https://www.docs.yscope.com"); update the siteUrl constant/property to the
correct canonical docs domain (e.g., "https://docs.yscope.com") so sitemap
generation and canonical URLs use the non-www docs host; locate the siteUrl
assignment in next-sitemap.config.js and replace the string accordingly.
- Line 5: The JSDoc type is wrong — replace the Next.js type annotation on the
top-level comment (currently using import('next').NextConfig) with the
next-sitemap config type so the file is correctly typed (use
import('next-sitemap').IConfig in the JSDoc for this file that defines the
sitemap configuration). Locate the comment block containing "/** `@type`
{import('next').NextConfig} */" and update it to reference the next-sitemap
export (IConfig) so tooling and editors pick up the proper types for the sitemap
config.
- Around line 1-3: Replace the incorrect single-line ESLint disable comments
with a single block-level disable using the correct syntax; change the three
lines that currently read "// eslint-disable `@typescript-eslint/require-await`",
"// eslint-disable `@typescript-eslint/no-unsafe-assignment`", and "//
eslint-disable sort-keys" to a single comment like "/* eslint-disable
`@typescript-eslint/require-await`, `@typescript-eslint/no-unsafe-assignment`,
sort-keys */" so ESLint recognizes the file-level disables (update the comment
at the top of the file where these disable directives currently appear).
In `@docs/next.config.ts`:
- Line 22: Replace the CommonJS export with an ES module default export: locate
the statement using module.exports and replace the `module.exports =
nextConfig;` usage with an ES export of the `nextConfig` value (i.e., use
`export default nextConfig`) so the `.ts` file uses ESM syntax consistently.
- Line 1: Remove the top-level "// `@ts-nocheck`" from docs/next.config.ts and fix
any underlying type issues instead: add proper typings to the Next.js export
(e.g., annotate the exported nextConfig with NextConfig or import NextConfig
from 'next'), or if a single line has an intentional type exception, replace the
blanket check with a targeted "// `@ts-expect-error`" immediately above that line;
ensure the file compiles without suppressing all TypeScript errors.
- Around line 9-19: Remove the incompatible rewrites function and the empty
JSDoc: delete the async rewrites() { ... } block (the function named rewrites
that returns the source "/:path*\\.html" -> destination "/:path*") because
rewrites are not supported when using output: "export", and also remove the
empty JSDoc comment immediately above it; keep the rest of the Next config
intact.
- Around line 5-7: The config uses experimental.turboPack: true which is
invalid; replace the boolean with the correct key/shape for your Next.js
version: for Next.js 15.2.x and earlier change experimental.turboPack to
experimental.turbo and set its value to an object (experimental: { turbo: { /*
options */ } }), or for Next.js 15.3+ remove the experimental key and add a
top-level turbopack object (turbopack: { /* options */ }); ensure the value is
an object ({}) not true and update any references to turboPack accordingly.
In `@docs/package.json`:
- Line 34: Replace the unmaintained "npm-run-all" dependency in package.json
with the actively maintained drop-in fork "npm-run-all2": update the dependency
key/value where "npm-run-all" appears, run your package manager to install (npm
install or yarn), and verify existing npm scripts that reference npm-run-all
continue to work (no code changes should be necessary since npm-run-all2 is a
drop-in replacement).
- Line 31: The package.json entry for "bootstrap" currently under
devDependencies must be moved to dependencies so it is installed in production
builds; update package.json to remove "bootstrap": "^5.3.6" from devDependencies
and add the same entry under dependencies (or run npm install --save bootstrap /
yarn add bootstrap) and regenerate the lockfile so CI/build environments install
it; verify any import paths remain valid and that the docs site build picks up
the styles.
- Around line 17-24: Update devDependencies to use eslint-config-next version 16
to match next@^16.0.7 by replacing the existing eslint-config-next@^15.3.3 entry
with the v16 release; after upgrading, migrate ESLint configuration from legacy
.eslintrc (or eslint option in next.config.js) to the new Flat Config format by
adding an eslint.config.mjs and ensuring any Next.js 16-specific rules/plugins
are imported, and remove the deprecated "eslint" option from next config if
present.
In `@docs/README.md`:
- Line 50: The README ends with the link reference "[serve]:
https://www.npmjs.com/package/serve" but lacks a final newline; update the
docs/README.md by adding a single trailing newline character at end of file
(after the "[serve]: https://www.npmjs.com/package/serve" line) so the file
terminates with a newline and satisfies markdownlint MD047.
- Around line 23-29: Replace the inaccurate and awkward phrasing in the README:
change "You can build and serve the viewer in debug mode using:" to "You can
build and serve the site (or docs) in debug mode using:" and change "The website
should then be available at the URL by the command." to "The website should then
be available at the URL printed by the command." Update the two sentences in the
same paragraph where they appear (the lines containing "serve the viewer" and
"available at the URL by the command") to use the suggested replacements.
In `@docs/tsconfig.json`:
- Line 11: The tsconfig currently sets "strict": false which disables all strict
TypeScript checks; update the compilerOptions to enable strict mode by setting
"strict": true in the tsconfig (replace the "strict": false entry) and then fix
any resulting type errors across the docs site (address issues surfaced by
strictNullChecks, noImplicitAny, etc.)—look for and update configuration
referenced by "strict" in tsconfig.json and adjust types in files that fail
compilation after enabling strict.
- Around line 1-36: The project must ensure Next.js is on a patched release to
mitigate CVE-2025-66478: update the "next" dependency in your package.json to
one of the patched versions (e.g., 16.0.7 or the appropriate patched 15.x
listed) and run a clean install/build to pick up the fix, then verify the app
uses the updated runtime (App Router / React Server Components); if the site was
ever live and unpatched before 2025-12-04, rotate all secrets/credentials with
highest priority and redeploy.
In `@taskfiles/docs.yaml`:
- Line 28: Remove the now-unused "venv" dependency from the build task and drop
the G_VENV_CHECKSUM_FILE entry from the build task's sources: locate the build
task definition (the task named "build") and remove "venv" from its dependencies
list and remove the G_VENV_CHECKSUM_FILE from its sources array, leaving the
separate "venv" task and any other tasks that depend on it (like
"download-projects") unchanged.
- Around line 36-37: The comment "Support multiple next versions (some expect a
bare directory argument, others accept -o/--outdir)" is stale because the actual
tasks simply rsync from docs/out; either remove or update the comment to match
current behaviour, or implement version-specific handling: add a variable (e.g.
NEXT_BUILD_OUT or NEXT_VERSION) and branch the export step to call next export
with either a bare directory or -o/--outdir based on that variable, and update
any rsync references to use the chosen output path (look for mentions of
"docs/out" and the stale comment text to locate the spot).
- Around line 31-40: The shell steps that run npm install and npm run build lack
error handling so failures still let the recipe continue to cd - and rsync;
update the task that contains the docs build block (the one using cd docs, npm
install, npm run build, cd - and rsync to "{{.OUTPUT_DIR}}/") to fail fast by
enabling errexit—either add set -e (or an explicit "set -o errexit") at the top
of that shell block or set Taskfile task metadata to set: [errexit]; ensure this
is applied to the same task that references docs/out/ so rsync only runs when
build succeeds.
| tabWidth: 4 | ||
| useTabs: false | ||
| singleQuote: false | ||
| quoteProps: consistent | ||
| printWidth: 100 | ||
| endOfLine: lf |
There was a problem hiding this comment.
Filename typo: .prettyierrc.yaml should be .prettierrc.yaml.
Prettier looks for .prettierrc.yaml (among other recognized names). The transposed letters (ie → ei) mean this config file will be silently ignored and Prettier will fall back to its defaults.
🤖 Prompt for AI Agents
In `@docs/.prettyierrc.yaml` around lines 1 - 6, The config filename is
misspelled; rename the file from .prettyierrc.yaml to .prettierrc.yaml so
Prettier will detect and apply the settings (the content with keys like
tabWidth, singleQuote, printWidth, endOfLine should remain unchanged).
| // Themed GitHub button styles | ||
| .btn-github { | ||
| background: #fff; | ||
| color: #24292e; | ||
| border: 2px solid #444; | ||
| box-shadow: 0 2px 12px 0 rgba(0,123,255,0.22); | ||
| border-radius: 8px; | ||
| display: inline-flex; | ||
| align-items: center; | ||
| font-weight: 500; | ||
| gap: 0.35em; | ||
| padding: 0.18em 0.5em 0.18em 0.45em; | ||
| transition: background 0.2s, color 0.2s, border 0.2s, box-shadow 0.2s; | ||
| } | ||
|
|
||
| [data-bs-theme="dark"] .btn-github { | ||
| background: #24292e; | ||
| color: #fff; | ||
| border: 2px solid #444; | ||
| } | ||
|
|
||
| [data-bs-theme="dark"] .btn-github svg { | ||
| color: #fff; | ||
| } | ||
|
|
||
| [data-bs-theme="light"] .btn-github svg { | ||
| color: #24292e; | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Move .btn-github styles after Bootstrap imports.
These rules are defined before Bootstrap's functions, variables, and mixins are imported (line 29+). While they currently use only raw values and won't break, placing custom styles before the framework's foundation is fragile — any future refactor adding a Bootstrap variable or mixin here will fail silently or with a compile error.
🤖 Prompt for AI Agents
In `@docs/app/assets/scss/styles.scss` around lines 1 - 28, The .btn-github rules
(including selectors .btn-github and [data-bs-theme="dark"] .btn-github / svg
and [data-bs-theme="light"] .btn-github svg) are defined before Bootstrap's
functions/variables/mixins imports—move that entire block so it appears after
the Bootstrap imports so any future use of Bootstrap variables or mixins inside
these rules will compile; keep the selectors and declarations unchanged, simply
relocate the whole block below the imports.
| $yscope-colors-text: ( | ||
| "yscope-primary": #1888fa, | ||
| "yscope-secondary": black, | ||
| ); | ||
| $yscope-colors-bg-subtle: ( | ||
| "yscope-primary": #1888fa, | ||
| "yscope-secondary": black, | ||
| ); | ||
| $yscope-colors-border-subtle: ( | ||
| "yscope-primary": #1888fa, | ||
| "yscope-secondary": black, | ||
| ); |
There was a problem hiding this comment.
Unused colour maps.
$yscope-colors-text, $yscope-colors-bg-subtle, and $yscope-colors-border-subtle are defined but never consumed (no map-merge into Bootstrap's corresponding maps or any other usage). Either integrate them (e.g., $theme-colors-text: map-merge(...)) or remove them.
🤖 Prompt for AI Agents
In `@docs/app/assets/scss/styles.scss` around lines 43 - 54, The three Sass maps
$yscope-colors-text, $yscope-colors-bg-subtle, and $yscope-colors-border-subtle
are declared but never used; either remove them or merge them into the theme
maps so they take effect. Fix by either deleting these unused variables, or
merge each into the appropriate Bootstrap/theme map (e.g., use map-merge to
combine $yscope-colors-text into $theme-colors-text and similarly merge
$yscope-colors-bg-subtle and $yscope-colors-border-subtle into the corresponding
background/border maps) so the colors are actually consumed by the build.
| // Layout & components | ||
| // TODO Remove unused | ||
| @import "../../../node_modules/bootstrap/scss/root"; | ||
| @import "../../../node_modules/bootstrap/scss/reboot"; | ||
| @import "../../../node_modules/bootstrap/scss/type"; | ||
| @import "../../../node_modules/bootstrap/scss/images"; | ||
| @import "../../../node_modules/bootstrap/scss/containers"; | ||
| @import "../../../node_modules/bootstrap/scss/grid"; | ||
| @import "../../../node_modules/bootstrap/scss/tables"; | ||
| @import "../../../node_modules/bootstrap/scss/forms"; | ||
| @import "../../../node_modules/bootstrap/scss/buttons"; | ||
| @import "../../../node_modules/bootstrap/scss/transitions"; | ||
| @import "../../../node_modules/bootstrap/scss/dropdown"; | ||
| @import "../../../node_modules/bootstrap/scss/button-group"; | ||
| @import "../../../node_modules/bootstrap/scss/nav"; | ||
| @import "../../../node_modules/bootstrap/scss/navbar"; | ||
| @import "../../../node_modules/bootstrap/scss/card"; | ||
| @import "../../../node_modules/bootstrap/scss/accordion"; | ||
| @import "../../../node_modules/bootstrap/scss/breadcrumb"; | ||
| @import "../../../node_modules/bootstrap/scss/pagination"; | ||
| @import "../../../node_modules/bootstrap/scss/badge"; | ||
| @import "../../../node_modules/bootstrap/scss/alert"; | ||
| @import "../../../node_modules/bootstrap/scss/progress"; | ||
| @import "../../../node_modules/bootstrap/scss/list-group"; | ||
| @import "../../../node_modules/bootstrap/scss/close"; | ||
| @import "../../../node_modules/bootstrap/scss/toasts"; | ||
| @import "../../../node_modules/bootstrap/scss/modal"; | ||
| @import "../../../node_modules/bootstrap/scss/tooltip"; | ||
| @import "../../../node_modules/bootstrap/scss/popover"; | ||
| @import "../../../node_modules/bootstrap/scss/carousel"; | ||
| @import "../../../node_modules/bootstrap/scss/spinners"; | ||
| @import "../../../node_modules/bootstrap/scss/offcanvas"; | ||
| @import "../../../node_modules/bootstrap/scss/placeholders"; |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Address the TODO: trim unused Bootstrap imports.
The TODO on line 57 acknowledges this. Importing every Bootstrap component (toasts, carousel, spinners, popovers, modals, etc.) inflates the CSS bundle. Consider keeping only the modules actually used by the docs site.
Do you want me to open an issue to track auditing and pruning these imports?
🤖 Prompt for AI Agents
In `@docs/app/assets/scss/styles.scss` around lines 56 - 88, The SCSS currently
imports every Bootstrap component which bloats the CSS; audit which Bootstrap
components the docs actually use and remove unused `@import` lines in styles.scss
(start from the TODO near the top), e.g., drop imports for rarely used modules
like toasts, carousel, spinners, popover, modal, offcanvas, placeholders, etc.,
keep only core pieces your pages reference (reboot, type, grid, forms, buttons,
nav/navbar, utilities as needed), update the TODO to reflect that pruning was
done, and re-run the build/asset-size check to verify the bundle shrinks.
|
|
||
|
|
||
| export const metadata: Metadata = { | ||
| title: "C++ Contirbution | YScope Developer Guide", |
There was a problem hiding this comment.
Typo in metadata title: "Contirbution" → "Contribution".
✏️ Proposed fix
- title: "C++ Contirbution | YScope Developer Guide",
+ title: "C++ Contribution | YScope Developer Guide",📝 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.
| title: "C++ Contirbution | YScope Developer Guide", | |
| title: "C++ Contribution | YScope Developer Guide", |
🤖 Prompt for AI Agents
In `@docs/app/dev-guide/contrib-guides-cpp/layout.tsx` at line 7, Fix the typo in
the metadata title field by changing the value of the "title" key in layout.tsx
from "C++ Contirbution | YScope Developer Guide" to "C++ Contribution | YScope
Developer Guide"; locate the title field in the file (the metadata
variable/constant named title) and update the string accordingly.
| { | ||
| "compilerOptions": { | ||
| "target": "ES2017", | ||
| "lib": [ | ||
| "dom", | ||
| "dom.iterable", | ||
| "esnext" | ||
| ], | ||
| "allowJs": true, | ||
| "skipLibCheck": true, | ||
| "strict": false, | ||
| "noEmit": true, | ||
| "incremental": true, | ||
| "module": "esnext", | ||
| "esModuleInterop": true, | ||
| "moduleResolution": "node", | ||
| "resolveJsonModule": true, | ||
| "isolatedModules": true, | ||
| "jsx": "react-jsx", | ||
| "plugins": [ | ||
| { | ||
| "name": "next" | ||
| } | ||
| ] | ||
| }, | ||
| "include": [ | ||
| "next-env.d.ts", | ||
| ".next/types/**/*.ts", | ||
| ".next/dev/types/**/*.ts", | ||
| "**/*.mts", | ||
| "**/*.ts", | ||
| "**/*.tsx" | ||
| ], | ||
| "exclude": [ | ||
| "node_modules" | ||
| ] |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
CVE-2025-55182 CVE-2025-66478 Next.js RCE vulnerability
💡 Result:
What these CVEs are (React2Shell / Next.js RCE)
- CVE-2025-55182 is a critical (CVSS 10.0) pre-auth remote code execution bug in React Server Components (RSC) / Flight protocol request handling (often described as unsafe deserialization/protocol abuse), enabling RCE via a crafted HTTP request in vulnerable server setups. It impacts the RSC server packages used by frameworks like Next.js App Router. [2]
- CVE-2025-66478 is the Next.js downstream tracking advisory for the impact on Next.js App Router (RSC) apps. Next.js notes it’s rooted in the upstream React issue and provides Next.js-specific affected/fixed versions and guidance. [1]
Who is affected (Next.js)
Next.js states affected apps are those using React Server Components with the App Router on:
- Next.js 15.x
- Next.js 16.x
- Next.js 14.3.0-canary.77 and later canary releases
Not affected per Next.js: Next.js 13.x, Next.js 14.x stable, Pages Router, and Edge Runtime. [1]
Fixed Next.js versions (upgrade targets)
Next.js lists these patched releases as fixed:
- 15.0.5, 15.1.9, 15.2.6, 15.3.6, 15.4.8, 15.5.7, 16.0.7
(And patched canaries: 15.6.0-canary.58, 16.1.0-canary.12.) [1]
Operational guidance (high priority)
- Patch immediately to a fixed version above. [1]
- Next.js additionally advises: if your app was online and unpatched as of Dec 4, 2025 1:00 PM PT, rotate secrets (starting with the most critical). [1]
- Microsoft reports real-world exploitation observed beginning Dec 5, 2025, including follow-on payloads such as cryptominers, reinforcing that this should be treated as an emergency patch. [2]
References
[1] Next.js Security Advisory: CVE-2025-66478 (Dec 3, 2025)
[2] Microsoft Security Blog: Defending against CVE-2025-55182 (React2Shell) (Dec 15, 2025)
🌐 Web query:
Next.js 16.0.7 16.1.6 security patches January 2026
💡 Result:
- Next.js 16.0.7 is a security patch release: it’s the fixed version for CVE-2025-66478 (critical RCE in React Server Components / App Router). Upgrade guidance in the advisory explicitly lists
next@16.0.7as the patched 16.0.x version. [1][2] - Next.js 16.1.6 (published Jan 27, 2026) is a later stable 16.x release and therefore includes the 16.0.7 security fix (and subsequent fixes). [3]
- Separate but relevant to “January 2026” hardening for Next.js apps: Node.js shipped a mitigation for an AsyncLocalStorage/async_hooks-related DoS crash in its Jan 13, 2026 security releases (upgrade Node to 20.20.0 / 22.22.0 / 24.13.0 / 25.3.0 as applicable). [4]
Sources
[1] Next.js Security Advisory: CVE-2025-66478 (fixed versions incl. 16.0.7)
[2] GitLab Advisory Database entry for CVE-2025-66478 (fixed in Next.js 16.0.7)
[3] Snyk package versions for next (shows 16.1.6 published Jan 27, 2026)
[4] Node.js vulnerability post (Jan 13, 2026 patched Node versions list)
🌐 Web query:
Next.js Flight protocol RCE deserialization vulnerability 2025
💡 Result:
In December 2025, a critical unauthenticated RCE was disclosed in React Server Components (RSC) “Flight” protocol caused by insecure deserialization of Flight payloads. It impacts Next.js App Router apps because Next.js exposes/uses the vulnerable RSC/Flight handling. (sentinelone.com)
Identifiers / naming
- CVE-2025-55182 (upstream React/RSC “Flight” insecure deserialization → RCE), widely nicknamed “React2Shell”. (sentinelone.com)
- CVE-2025-66478 was issued for Next.js but is commonly treated as duplicate/related to the upstream React CVE. (sentinelone.com)
- GitHub tracks Next.js impact as GHSA-9qr9-h5gf-34mp. (github.com)
Affected Next.js versions (per GitHub advisory)
Vulnerable next (npm) ranges include (non-exhaustive; see advisory for full list):
>= 14.3.0-canary.77, < 15.0.5- multiple
15.xcanary/stable ranges before patched point releases >= 16.0.0-canary.0, < 16.0.7(github.com)
Fixed versions (Next.js)
Upgrade to one of these patched releases (choose the one matching your major/minor line):
- 15.0.5, 15.1.9, 15.2.6, 15.3.6, 15.4.8, 15.5.7, or 16.0.7 (plus newer canary lines listed in the advisory). (github.com)
Fixed versions (React side)
React advisory guidance (as reflected in the Next.js advisory) indicates fixes in:
- React: 19.0.1, 19.1.2, 19.2.1 (and corresponding patched RSC packages). (github.com)
What attackers do / prerequisites
- Exploitation can be pre-auth (no login) via a specially crafted HTTP request to exposed RSC/Server Function endpoints, leading to arbitrary code execution in the server Node.js process. (sentinelone.com)
What to do now (practical)
- Upgrade
nextto a patched version listed above. (github.com) - Ensure your React/RSC packages resolve to patched React versions (per advisory guidance). (github.com)
- If you can’t patch immediately, reduce exposure by restricting access to RSC/Server Function endpoints at the edge (auth/IP allowlists/WAF), since exploitation is via crafted requests. (censys.com)
Citations:
- 1: https://www.sentinelone.com/blog/protecting-against-critical-react2shell-rce-exposure/?utm_source=openai
- 2: https://www.sentinelone.com/blog/protecting-against-critical-react2shell-rce-exposure/?utm_source=openai
- 3: https://www.sentinelone.com/blog/protecting-against-critical-react2shell-rce-exposure/?utm_source=openai
- 4: https://github.com/advisories/GHSA-9qr9-h5gf-34mp?utm_source=openai
- 5: https://github.com/advisories/GHSA-9qr9-h5gf-34mp?utm_source=openai
- 6: https://github.com/advisories/GHSA-9qr9-h5gf-34mp?utm_source=openai
- 7: https://github.com/advisories/GHSA-9qr9-h5gf-34mp?utm_source=openai
- 8: https://www.sentinelone.com/blog/protecting-against-critical-react2shell-rce-exposure/?utm_source=openai
- 9: https://github.com/advisories/GHSA-9qr9-h5gf-34mp?utm_source=openai
- 10: https://github.com/advisories/GHSA-9qr9-h5gf-34mp?utm_source=openai
- 11: https://censys.com/advisory/cve-2025-55182?utm_source=openai
Patch critical Remote Code Execution vulnerability in React Server Components — upgrade Next.js immediately.
Next.js 15.x and 16.x (using App Router with React Server Components) are vulnerable to CVE-2025-66478 (upstream CVE-2025-55182), a critical pre-auth RCE via insecure deserialization in the Flight protocol. Real-world exploitation has been observed since early December 2025.
Upgrade to a patched version: 16.0.7, 15.0.5, 15.1.9, 15.2.6, 15.3.6, 15.4.8, or 15.5.7 (matching your release line). Your current version 16.0.7 is patched and secure.
If your application was online and unpatched before 4 December 2025, rotate secrets immediately (prioritize the most critical).
🤖 Prompt for AI Agents
In `@docs/tsconfig.json` around lines 1 - 36, The project must ensure Next.js is
on a patched release to mitigate CVE-2025-66478: update the "next" dependency in
your package.json to one of the patched versions (e.g., 16.0.7 or the
appropriate patched 15.x listed) and run a clean install/build to pick up the
fix, then verify the app uses the updated runtime (App Router / React Server
Components); if the site was ever live and unpatched before 2025-12-04, rotate
all secrets/credentials with highest priority and redeploy.
| ], | ||
| "allowJs": true, | ||
| "skipLibCheck": true, | ||
| "strict": false, |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Consider enabling strict mode for a new TypeScript project.
With strict: false, you lose benefits like strictNullChecks, noImplicitAny, and other checks that catch common bugs early. Since this is a greenfield docs site, enabling strict mode now avoids accruing type-safety debt.
✏️ Proposed fix
- "strict": false,
+ "strict": true,📝 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.
| "strict": false, | |
| "strict": true, |
🤖 Prompt for AI Agents
In `@docs/tsconfig.json` at line 11, The tsconfig currently sets "strict": false
which disables all strict TypeScript checks; update the compilerOptions to
enable strict mode by setting "strict": true in the tsconfig (replace the
"strict": false entry) and then fix any resulting type errors across the docs
site (address issues surfaced by strictNullChecks, noImplicitAny, etc.)—look for
and update configuration referenced by "strict" in tsconfig.json and adjust
types in files that fail compilation after enabling strict.
| @@ -28,8 +28,16 @@ tasks: | |||
| - "venv" | |||
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Build task still depends on venv, but no longer uses it.
The build commands (lines 31–40) no longer activate or use the Python virtual environment — they only run npm install and npm run build. The "venv" dependency (and G_VENV_CHECKSUM_FILE in sources on line 19) should be removed from the build task to avoid unnecessary work. The venv task is still needed by download-projects, so it should remain defined.
🤖 Prompt for AI Agents
In `@taskfiles/docs.yaml` at line 28, Remove the now-unused "venv" dependency from
the build task and drop the G_VENV_CHECKSUM_FILE entry from the build task's
sources: locate the build task definition (the task named "build") and remove
"venv" from its dependencies list and remove the G_VENV_CHECKSUM_FILE from its
sources array, leaving the separate "venv" task and any other tasks that depend
on it (like "download-projects") unchanged.
| # Build the Next.js site and copy the exported static output into the | ||
| # task build output directory expected by other tasks. | ||
| cd docs | ||
| npm install --no-audit --no-fund | ||
| npm run build | ||
| # Try exporting static files to "out/". Support multiple next versions | ||
| # (some expect a bare directory argument, others accept -o/--outdir). | ||
| cd - | ||
| mkdir -p "{{.OUTPUT_DIR}}" | ||
| rsync -a docs/out/ "{{.OUTPUT_DIR}}/" |
There was a problem hiding this comment.
No error handling if npm run build fails.
If npm install or npm run build fails, the script continues to cd - and rsync, potentially copying stale or missing output. Consider adding set -e at the top of the block (or using Taskfile's set: [errexit] on the task) to bail out on failure.
🛡️ Proposed fix
- |-
+ set -e
# Build the Next.js site and copy the exported static output into the
# task build output directory expected by other tasks.
cd docs📝 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.
| # Build the Next.js site and copy the exported static output into the | |
| # task build output directory expected by other tasks. | |
| cd docs | |
| npm install --no-audit --no-fund | |
| npm run build | |
| # Try exporting static files to "out/". Support multiple next versions | |
| # (some expect a bare directory argument, others accept -o/--outdir). | |
| cd - | |
| mkdir -p "{{.OUTPUT_DIR}}" | |
| rsync -a docs/out/ "{{.OUTPUT_DIR}}/" | |
| set -e | |
| # Build the Next.js site and copy the exported static output into the | |
| # task build output directory expected by other tasks. | |
| cd docs | |
| npm install --no-audit --no-fund | |
| npm run build | |
| # Try exporting static files to "out/". Support multiple next versions | |
| # (some expect a bare directory argument, others accept -o/--outdir). | |
| cd - | |
| mkdir -p "{{.OUTPUT_DIR}}" | |
| rsync -a docs/out/ "{{.OUTPUT_DIR}}/" |
🤖 Prompt for AI Agents
In `@taskfiles/docs.yaml` around lines 31 - 40, The shell steps that run npm
install and npm run build lack error handling so failures still let the recipe
continue to cd - and rsync; update the task that contains the docs build block
(the one using cd docs, npm install, npm run build, cd - and rsync to
"{{.OUTPUT_DIR}}/") to fail fast by enabling errexit—either add set -e (or an
explicit "set -o errexit") at the top of that shell block or set Taskfile task
metadata to set: [errexit]; ensure this is applied to the same task that
references docs/out/ so rsync only runs when build succeeds.
| # Try exporting static files to "out/". Support multiple next versions | ||
| # (some expect a bare directory argument, others accept -o/--outdir). |
There was a problem hiding this comment.
Stale comment about supporting multiple Next.js versions.
The comment says "Support multiple next versions (some expect a bare directory argument, others accept -o/--outdir)" but none of that logic exists — the commands simply rsync from docs/out/. Either remove the misleading comment or, if version-specific handling is actually intended, implement it.
✏️ Suggested fix
- # Try exporting static files to "out/". Support multiple next versions
- # (some expect a bare directory argument, others accept -o/--outdir).📝 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.
| # Try exporting static files to "out/". Support multiple next versions | |
| # (some expect a bare directory argument, others accept -o/--outdir). |
🤖 Prompt for AI Agents
In `@taskfiles/docs.yaml` around lines 36 - 37, The comment "Support multiple next
versions (some expect a bare directory argument, others accept -o/--outdir)" is
stale because the actual tasks simply rsync from docs/out; either remove or
update the comment to match current behaviour, or implement version-specific
handling: add a variable (e.g. NEXT_BUILD_OUT or NEXT_VERSION) and branch the
export step to call next export with either a bare directory or -o/--outdir
based on that variable, and update any rsync references to use the chosen output
path (look for mentions of "docs/out" and the stale comment text to locate the
spot).
| /* eslint-disable max-lines */ | ||
| /* eslint-disable max-lines-per-function */ |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Disabling max-lines and max-lines-per-function is a code smell for a React component.
This 339-line component is essentially a static document written as JSX. Consider extracting the content into MDX (or a series of smaller section components) so that the eslint rules don't need to be suppressed.
🤖 Prompt for AI Agents
In `@docs/app/dev-guide/contrib-guides-cpp/page.tsx` around lines 1 - 2, This file
disables max-lines and max-lines-per-function for a large static JSX document;
extract the long JSX content out of the single page component (e.g., the default
export, likely named Page or the top-level component in page.tsx) into MDX
(docs/app/dev-guide/contrib-guides-cpp.md x) or split it into smaller
presentational components (e.g., ContribGuideSectionA, ContribGuideSectionB)
that are imported and composed by the page component, then remove the /*
eslint-disable max-lines */ and /* eslint-disable max-lines-per-function */
headers so ESLint can enforce limits again; ensure the page.tsx now only
composes/imports sections or imports the MDX file and keeps the function body
small and under the configured limits.
| {" "} | ||
| for formatting ( | ||
| <a href={"https://github.com/y-scope/yscope-dev-utils/blob/main/lint-configs/.clang-format"}>base config</a> | ||
| {""} |
There was a problem hiding this comment.
Empty string expressions {""} are no-ops.
Several places use {""} (e.g., lines 33, 41, 286, 288, 292, 296) which render nothing. These appear to be remnants or mistakes — contrast with {" "} used elsewhere to insert a space. Either remove them or replace with {" "} if a space was intended.
Also applies to: 41-41, 286-286, 288-288, 292-292, 296-296
🤖 Prompt for AI Agents
In `@docs/app/dev-guide/contrib-guides-cpp/page.tsx` at line 33, The JSX contains
no-op empty string expressions `{""}` (appearing where other code uses `{" "}`)
which render nothing; remove these `{""}` occurrences or replace them with `{"
"}` where an actual space is intended so layout/spacing is preserved—search for
all `{""}` tokens in the file and either delete them or swap to `{" "}` based on
nearby elements and spacing needs (compare with existing `{" "}` usages to
decide).
| <ul> | ||
| <li> | ||
| <code><FilenameStem_stem></code> | ||
| {" "} | ||
| is the file’s name without the extension. | ||
| </li> |
There was a problem hiding this comment.
Typo: FilenameStem_stem should be FilenameStem.
The code block on line 235 defines the placeholder as <FilenameStem>_internal, so the description here should reference <FilenameStem>, not <FilenameStem_stem>.
✏️ Proposed fix
- <code><FilenameStem_stem></code>
+ <code><FilenameStem></code>📝 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.
| <ul> | |
| <li> | |
| <code><FilenameStem_stem></code> | |
| {" "} | |
| is the file’s name without the extension. | |
| </li> | |
| <ul> | |
| <li> | |
| <code><FilenameStem></code> | |
| {" "} | |
| is the file's name without the extension. | |
| </li> |
🤖 Prompt for AI Agents
In `@docs/app/dev-guide/contrib-guides-cpp/page.tsx` around lines 240 - 245,
Replace the incorrect placeholder text `FilenameStem_stem` with `FilenameStem`
in the docs bit (the list item near the `<FilenameStem>_internal` example) so
the description matches the defined placeholder; update the string in the JSX
for the list item that currently renders `<FilenameStem_stem>` to
`<FilenameStem>` to keep the docs consistent with the `<FilenameStem>_internal`
example.
| <code><FilenameStem_stem></code> | ||
| {" "} | ||
| is the file’s name without the extension. |
There was a problem hiding this comment.
Inconsistent apostrophe character on line 244.
Line 244 uses a typographic/smart apostrophe (') in file's, while the rest of the file consistently uses '. Use ' here as well for consistency and to avoid potential encoding issues.
✏️ Proposed fix
- is the file's name without the extension.
+ is the file's name without the extension.📝 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.
| <code><FilenameStem_stem></code> | |
| {" "} | |
| is the file’s name without the extension. | |
| <code><FilenameStem_stem></code> | |
| {" "} | |
| is the file's name without the extension. |
🤖 Prompt for AI Agents
In `@docs/app/dev-guide/contrib-guides-cpp/page.tsx` around lines 242 - 244,
Replace the typographic/smart apostrophe used in the text "file’s" with the HTML
entity ' to match the rest of the file and avoid encoding inconsistencies;
locate the snippet around the inline code <code><FilenameStem_stem></code>
and update the following plain text "is the file’s name without the extension."
to use "is the file's name without the extension." so apostrophe usage is
consistent.
| @@ -0,0 +1,36 @@ | |||
| "use client"; | |||
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Unnecessary "use client" directive — no client interactivity.
Same as other static pages: this component can be a Server Component.
🤖 Prompt for AI Agents
In `@docs/app/dev-guide/contrib-guides-general/page.tsx` at line 1, Remove the
top-level "use client" directive from this page component so it becomes a Server
Component; edit the file to delete the "use client" line and confirm the default
export (e.g., export default function Page or the existing default export)
contains only server-compatible code (no React hooks like useState/useEffect or
browser-only APIs) before committing.
| <ul> | ||
| <li> | ||
| <a href={"/dev-guide/contrib-guides-overview/"}>Overview</a> | ||
| </li> | ||
| <li> | ||
| <a href={"/dev-guide/contrib-guides-general/"}>General Guidelines</a> | ||
| </li> | ||
| <li> | ||
| <a href={"/dev-guide/contrib-guides-cpp/"}>C++</a> | ||
| </li> | ||
| <li> | ||
| <a href={"/dev-guide/contrib-guides-taskfiles/"}>Taskfiles</a> | ||
| </li> | ||
| </ul> | ||
|
|
||
| <h2>Misc</h2> | ||
| <ul> | ||
| <li> | ||
| <a href={"/dev-guide/misc-deploying/"}>Deploying Main Docs</a> | ||
| </li> |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Use Next.js Link for internal navigation.
Plain <a> tags cause full page reloads. Using next/link enables client-side navigation, preserving SPA behaviour and improving performance.
♻️ Proposed fix (apply to all internal links)
+"use client" removal or keep as needed;
+import Link from "next/link";
...
-<a href={"/dev-guide/contrib-guides-overview/"}>Overview</a>
+<Link href={"/dev-guide/contrib-guides-overview/"}>Overview</Link>Apply the same pattern to all <a href={"/dev-guide/..."}> links in this file.
📝 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.
| <ul> | |
| <li> | |
| <a href={"/dev-guide/contrib-guides-overview/"}>Overview</a> | |
| </li> | |
| <li> | |
| <a href={"/dev-guide/contrib-guides-general/"}>General Guidelines</a> | |
| </li> | |
| <li> | |
| <a href={"/dev-guide/contrib-guides-cpp/"}>C++</a> | |
| </li> | |
| <li> | |
| <a href={"/dev-guide/contrib-guides-taskfiles/"}>Taskfiles</a> | |
| </li> | |
| </ul> | |
| <h2>Misc</h2> | |
| <ul> | |
| <li> | |
| <a href={"/dev-guide/misc-deploying/"}>Deploying Main Docs</a> | |
| </li> | |
| <ul> | |
| <li> | |
| <Link href={"/dev-guide/contrib-guides-overview/"}>Overview</Link> | |
| </li> | |
| <li> | |
| <Link href={"/dev-guide/contrib-guides-general/"}>General Guidelines</Link> | |
| </li> | |
| <li> | |
| <Link href={"/dev-guide/contrib-guides-cpp/"}>C++</Link> | |
| </li> | |
| <li> | |
| <Link href={"/dev-guide/contrib-guides-taskfiles/"}>Taskfiles</Link> | |
| </li> | |
| </ul> | |
| <h2>Misc</h2> | |
| <ul> | |
| <li> | |
| <Link href={"/dev-guide/misc-deploying/"}>Deploying Main Docs</Link> | |
| </li> |
🤖 Prompt for AI Agents
In `@docs/app/dev-guide/page.tsx` around lines 19 - 38, Replace plain anchor tags
used for internal navigation with Next.js Link components: add an import for
Link from 'next/link' at the top of the file and change each <a
href={"/dev-guide/..."}>...</a> to <Link href="/dev-guide/...">...</Link> (or
use the <Link><a>...</a></Link> pattern if you need anchor props); update the
list items (the links labeled "Overview", "General Guidelines", "C++",
"Taskfiles", "Deploying Main Docs", etc.) accordingly to enable client-side
navigation.
| useEffect(() => { | ||
| fetch("https://api.github.com/repos/y-scope/clp") | ||
| .then((res) => (res.ok ? | ||
| res.json() : | ||
| null)) | ||
| .then((data: {stargazers_count?: unknown} | null) => { | ||
| if (data && "number" === typeof data.stargazers_count) { | ||
| setGithubStars(data.stargazers_count); | ||
| } | ||
| }) | ||
| .catch(() => { | ||
| setGithubStars(null); | ||
| }); | ||
| }, []); |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Missing AbortController cleanup for the fetch call.
If the component unmounts before the fetch completes, the .then callbacks will attempt to call setGithubStars on an unmounted component. Use an AbortController to cancel the request in the effect cleanup.
♻️ Proposed fix
useEffect(() => {
+ const controller = new AbortController();
- fetch("https://api.github.com/repos/y-scope/clp")
+ fetch("https://api.github.com/repos/y-scope/clp", {signal: controller.signal})
.then((res) => (res.ok ?
res.json() :
null))
.then((data: {stargazers_count?: unknown} | null) => {
if (data && "number" === typeof data.stargazers_count) {
setGithubStars(data.stargazers_count);
}
})
.catch(() => {
- setGithubStars(null);
+ // Ignore abort errors
});
+ return () => {
+ controller.abort();
+ };
}, []);📝 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.
| useEffect(() => { | |
| fetch("https://api.github.com/repos/y-scope/clp") | |
| .then((res) => (res.ok ? | |
| res.json() : | |
| null)) | |
| .then((data: {stargazers_count?: unknown} | null) => { | |
| if (data && "number" === typeof data.stargazers_count) { | |
| setGithubStars(data.stargazers_count); | |
| } | |
| }) | |
| .catch(() => { | |
| setGithubStars(null); | |
| }); | |
| }, []); | |
| useEffect(() => { | |
| const controller = new AbortController(); | |
| fetch("https://api.github.com/repos/y-scope/clp", {signal: controller.signal}) | |
| .then((res) => (res.ok ? | |
| res.json() : | |
| null)) | |
| .then((data: {stargazers_count?: unknown} | null) => { | |
| if (data && "number" === typeof data.stargazers_count) { | |
| setGithubStars(data.stargazers_count); | |
| } | |
| }) | |
| .catch((error) => { | |
| // Ignore abort errors | |
| if (error?.name !== 'AbortError') { | |
| setGithubStars(null); | |
| } | |
| }); | |
| return () => { | |
| controller.abort(); | |
| }; | |
| }, []); |
🤖 Prompt for AI Agents
In `@docs/app/Navbar.tsx` around lines 40 - 53, The fetch in the useEffect should
be cancellable: create an AbortController inside the effect, pass
controller.signal to fetch, and in the cleanup call controller.abort() so the
request is cancelled if the component unmounts; update the .then/.catch handlers
(the effect using useEffect and state setter setGithubStars) to avoid calling
setGithubStars when the fetch was aborted (e.g., check error.name ===
'AbortError' in catch and skip state update) and ensure you still handle non-OK
responses and parsing as before.
| useEffect(() => { | ||
| const handleClick = (e: MouseEvent) => { | ||
| if (navRef.current && e.target instanceof Node && !navRef.current.contains(e.target)) { | ||
| setProjectsOpen(false); | ||
| setDevOpen(false); | ||
| } | ||
| }; | ||
|
|
||
| document.addEventListener("mousedown", handleClick); | ||
|
|
||
| return () => { | ||
| document.removeEventListener("mousedown", handleClick); | ||
| }; | ||
| }, []); |
There was a problem hiding this comment.
Coding guideline violation: use false === instead of !.
Line 60 uses !navRef.current.contains(e.target) which violates the project's coding guidelines.
🔧 Proposed fix
- if (navRef.current && e.target instanceof Node && !navRef.current.contains(e.target)) {
+ if (navRef.current && e.target instanceof Node && false === navRef.current.contains(e.target)) {As per coding guidelines, **/*.{ts,tsx}: "Prefer false == <expression> rather than !<expression>."
📝 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.
| useEffect(() => { | |
| const handleClick = (e: MouseEvent) => { | |
| if (navRef.current && e.target instanceof Node && !navRef.current.contains(e.target)) { | |
| setProjectsOpen(false); | |
| setDevOpen(false); | |
| } | |
| }; | |
| document.addEventListener("mousedown", handleClick); | |
| return () => { | |
| document.removeEventListener("mousedown", handleClick); | |
| }; | |
| }, []); | |
| useEffect(() => { | |
| const handleClick = (e: MouseEvent) => { | |
| if (navRef.current && e.target instanceof Node && false === navRef.current.contains(e.target)) { | |
| setProjectsOpen(false); | |
| setDevOpen(false); | |
| } | |
| }; | |
| document.addEventListener("mousedown", handleClick); | |
| return () => { | |
| document.removeEventListener("mousedown", handleClick); | |
| }; | |
| }, []); |
🤖 Prompt for AI Agents
In `@docs/app/Navbar.tsx` around lines 58 - 71, The conditional in useEffect's
handleClick uses a negation operator (!navRef.current.contains(e.target)) which
violates the project's guideline; change that expression to use an explicit
comparison to false (e.g., replace the ! expression with false ==
navRef.current.contains(e.target)) so the if condition reads with an equality
comparison; update the handleClick closure inside the useEffect (referencing
navRef, e.target, setProjectsOpen, setDevOpen) and keep the rest of the event
listener add/remove logic unchanged.
| <svg | ||
| fill={"currentColor"} | ||
| height={"20"} | ||
| viewBox={"0 0 24 24"} | ||
| width={"20"} | ||
| xmlns={"http://www.w3.org/2000/svg"} | ||
| > | ||
| <path | ||
| d={ | ||
| "M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 " + | ||
| "9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-" + | ||
| ".01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-" + | ||
| "1.61-.546-1.387-1.333-1.757-1.333-1.757-1.089-" + | ||
| ".745.083-.729.083-.729 1.205.084 1.84 1.236 1." + | ||
| "84 1.236 1.07 1.834 2.809 1.304 3.495.997.108-" + | ||
| ".775.418-1.305.762-1.605-2.665-.305-5.466-1.33" + | ||
| "4-5.466-5.93 0-1.31.469-2.381 1.236-3.221-.124" + | ||
| "-.303-.535-1.523.117-3.176 0 0 1.008-.322 3.30" + | ||
| "1 1.23a11.52 11.52 0 0 1 3.003-.404c1.018.005 " + | ||
| "2.045.138 3.003.404 2.291-1.552 3.297-1.23 3.2" + | ||
| "97-1.23.653 1.653.242 2.873.118 3.176.77.84 1." + | ||
| "235 1.911 1.235 3.221 0 4.609-2.803 5.624-5.47" + | ||
| "5 5.921.43.371.823 1.102.823 2.222 0 1.606-.01" + | ||
| "4 2.898-.014 3.293 0 .322.218.694.825.576C20.5" + | ||
| "65 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" | ||
| }/> | ||
| </svg> |
There was a problem hiding this comment.
Accessibility: SVG is missing an accessible label.
The GitHub icon SVG has no <title> element or aria-label. While the parent <a> has aria-label={"GitHub repository"}, adding aria-hidden={"true"} to the decorative SVG is the correct pattern to avoid redundant/empty announcements by screen readers.
♿ Proposed fix
<svg
+ aria-hidden={"true"}
fill={"currentColor"}
height={"20"}
viewBox={"0 0 24 24"}
width={"20"}
xmlns={"http://www.w3.org/2000/svg"}
>🧰 Tools
🪛 Biome (2.3.13)
[error] 323-329: Alternative text title element cannot be empty
For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.
(lint/a11y/noSvgWithoutTitle)
🤖 Prompt for AI Agents
In `@docs/app/Navbar.tsx` around lines 323 - 349, The GitHub icon SVG in the
Navbar component is decorative but lacks an accessibility marker; update the SVG
element (the GitHub icon SVG block in Navbar.tsx) to be hidden from assistive
tech by adding aria-hidden={"true"} (keeping the parent <a> with
aria-label={"GitHub repository"} as the accessible name) and ensure there is no
empty <title> inside the SVG so screen readers don't announce it.
| <button | ||
| id={"themeSwitcher"} | ||
| className={"btn btn-yscope-secondary btn-sm d-inline-flex " + | ||
| "align-items-center"} | ||
| style={{ | ||
| border: "none", | ||
| justifyContent: "center", | ||
| padding: "0.25rem 0.5rem", | ||
| minWidth: "28px", | ||
| }} | ||
| onClick={toggleTheme} | ||
| > | ||
| <span className={"theme-switcher-icon"}/> | ||
| </button> |
There was a problem hiding this comment.
Missing type="button" on the theme toggle button.
Without an explicit type, the button defaults to type="submit", which could cause unintended form submissions if ever placed inside a <form>.
🔧 Proposed fix
<button
id={"themeSwitcher"}
+ type={"button"}
className={"btn btn-yscope-secondary btn-sm d-inline-flex " +📝 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.
| <button | |
| id={"themeSwitcher"} | |
| className={"btn btn-yscope-secondary btn-sm d-inline-flex " + | |
| "align-items-center"} | |
| style={{ | |
| border: "none", | |
| justifyContent: "center", | |
| padding: "0.25rem 0.5rem", | |
| minWidth: "28px", | |
| }} | |
| onClick={toggleTheme} | |
| > | |
| <span className={"theme-switcher-icon"}/> | |
| </button> | |
| <button | |
| id={"themeSwitcher"} | |
| type={"button"} | |
| className={"btn btn-yscope-secondary btn-sm d-inline-flex " + | |
| "align-items-center"} | |
| style={{ | |
| border: "none", | |
| justifyContent: "center", | |
| padding: "0.25rem 0.5rem", | |
| minWidth: "28px", | |
| }} | |
| onClick={toggleTheme} | |
| > | |
| <span className={"theme-switcher-icon"}/> | |
| </button> |
🧰 Tools
🪛 Biome (2.3.13)
[error] 364-375: Provide an explicit type prop for the button element.
The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset
(lint/a11y/useButtonType)
🤖 Prompt for AI Agents
In `@docs/app/Navbar.tsx` around lines 364 - 377, The theme toggle button (id
"themeSwitcher") is missing an explicit type, so it defaults to type="submit"
and may submit enclosing forms; update the button element to include
type="button" alongside its existing props (the element with id "themeSwitcher"
and onClick handler toggleTheme) to prevent accidental form submission.
Description
This PR refactors the main YScope docs pages to move away from the Sphinx markdown framework and move towards a custom typescript page. We refocussed the main landing page to a simplified grid of categorized icons which link to key docs pages, resources, guides, references, etc. We focus on CLP and how out other projects interact with CLP. It's designed to be visual cohesive with the yscope.com main page.
Checklist
breaking change.
Validation performed
Built and served webpage locally
Summary by CodeRabbit
Release Notes
New Features
Documentation