fix: restore API docs page#2350
Conversation
📝 WalkthroughWalkthroughAdds a new API Docs page at ChangesAPI Docs Page Feature
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant APIDocsPage
participant fetchJson
participant ScalarViewer
participant ApiReferenceReact
User->>APIDocsPage: Navigate to /api-docs
APIDocsPage->>fetchJson: GET /openapi.json
fetchJson-->>APIDocsPage: resolve spec or reject with error
alt fetch succeeds
APIDocsPage->>APIDocsPage: derive preferredBearerToken (if builtin auth)
APIDocsPage->>ScalarViewer: render(spec, preferredBearerToken)
ScalarViewer->>ApiReferenceReact: render(configuration)
else fetch fails
APIDocsPage-->>User: show error UI with retry option
end
Related Issues: Suggested labels: enhancement, ui Suggested reviewers: yohamta 🐰 A rabbit hops through Scalar's door, 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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: 3
🧹 Nitpick comments (2)
ui/src/pages/api-docs/ScalarViewer.tsx (1)
17-26: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low valueDark mode detection doesn't react to live theme toggles.
darkModeis read once per render viadocument.documentElement.classList.contains('dark'), but nothing subscribes to changes on that class. If the user toggles the theme while viewing API Docs,forceDarkModeStatewon't update until an unrelated re-render happens.♻️ Suggested fix using a MutationObserver
+ const [darkMode, setDarkMode] = React.useState( + () => typeof document !== 'undefined' && document.documentElement.classList.contains('dark') + ); + + React.useEffect(() => { + if (typeof document === 'undefined') return; + const observer = new MutationObserver(() => { + setDarkMode(document.documentElement.classList.contains('dark')); + }); + observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] }); + return () => observer.disconnect(); + }, []); - const darkMode = - typeof document !== 'undefined' && document.documentElement.classList.contains('dark');🤖 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 `@ui/src/pages/api-docs/ScalarViewer.tsx` around lines 17 - 26, The dark mode state in ScalarViewer is only read once from document.documentElement.classList.contains('dark'), so forceDarkModeState won’t update when the theme changes live. Update ScalarViewer to subscribe to class changes on the document element (for example with a MutationObserver) and store dark mode in component state so configuration is recomputed whenever the dark class toggles.ui/src/pages/integrations/index.tsx (1)
21-25: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winLabel inconsistent with nav/home naming: "API Docs" vs "API Reference".
The sidebar
NavItem(ui/src/menu.tsxLine 818), the Home page link (ui/src/pages/home/index.tsxLine 201), and the breadcrumbSTATIC_ROUTE_LABELSentry (ui/src/layouts/ContentNavigation.tsxLine 27) all label this route "API Reference". This card alone uses "API Docs" for the same destination, which is a minor but visible naming inconsistency across the app.♻️ Proposed fix
{ to: '/api-docs', - label: 'API Docs', + label: 'API Reference', description: 'Explore authenticated REST API endpoints.', },🤖 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 `@ui/src/pages/integrations/index.tsx` around lines 21 - 25, The '/api-docs' integration card uses a different label than the rest of the app, creating an inconsistent name for the same destination. Update the label in the integrations page item to match the existing “API Reference” naming used by NavItem, the home page link, and STATIC_ROUTE_LABELS so the route is labeled consistently everywhere.
🤖 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 `@ui/src/__tests__/menu.test.tsx`:
- Around line 257-259: The menu collapse test is asserting against a link name
that never exists, so it does not validate the intended behavior. Update the
`menu.test.tsx` assertion to query the actual `NavItem` label used in
`ui/src/menu.tsx` for this route, which is `API Reference`, and keep the check
in the same collapsed/expanded test case so it verifies the Integrations group
visibility correctly.
In `@ui/src/pages/api-docs/index.tsx`:
- Around line 21-22: The API docs page is ignoring the selected remote node, so
`loadSpec` and the “Raw JSON” link can hit the wrong node in multi-node setups.
Update the API requests in `ui/src/pages/api-docs/index.tsx` to use
`appBarContext.selectedRemoteNode` when calling `fetchJson` and when building
the raw OpenAPI URL via `config.apiURL`, and keep the `AppBarContext`/`setTitle`
usage aligned with those changes. Ensure the relevant logic in `loadSpec` and
the raw JSON link both route through the same remote-node-aware API path.
- Line 84: The API docs page is rendering literal backticks in the descriptive
copy instead of inline code formatting. Update the JSX in the api-docs page near
the fetching message so the `/openapi.json` path is rendered as proper inline
code markup rather than included inside a plain text string. Use the existing
component text in the api-docs page to locate and adjust the affected paragraph.
---
Nitpick comments:
In `@ui/src/pages/api-docs/ScalarViewer.tsx`:
- Around line 17-26: The dark mode state in ScalarViewer is only read once from
document.documentElement.classList.contains('dark'), so forceDarkModeState won’t
update when the theme changes live. Update ScalarViewer to subscribe to class
changes on the document element (for example with a MutationObserver) and store
dark mode in component state so configuration is recomputed whenever the dark
class toggles.
In `@ui/src/pages/integrations/index.tsx`:
- Around line 21-25: The '/api-docs' integration card uses a different label
than the rest of the app, creating an inconsistent name for the same
destination. Update the label in the integrations page item to match the
existing “API Reference” naming used by NavItem, the home page link, and
STATIC_ROUTE_LABELS so the route is labeled consistently everywhere.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 0de2ec86-0a94-40eb-afbc-bad6a4b2ed27
⛔ Files ignored due to path filters (1)
ui/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (14)
ui/package.jsonui/src/App.tsxui/src/__tests__/App.test.tsxui/src/__tests__/menu.test.tsxui/src/layouts/ContentNavigation.tsxui/src/menu.tsxui/src/pages/api-docs/ScalarViewer.tsxui/src/pages/api-docs/__tests__/index.test.tsxui/src/pages/api-docs/index.tsxui/src/pages/home/index.tsxui/src/pages/integrations/__tests__/index.test.tsxui/src/pages/integrations/index.tsxui/src/styles/global.cssui/src/types/scalar-api-reference-react.d.ts
| expect( | ||
| screen.queryByRole('link', { name: 'API Docs' }) | ||
| ).not.toBeInTheDocument(); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Test asserts a link name that never exists — assertion is vacuously true.
The actual NavItem text for this route is "API Reference" (ui/src/menu.tsx Line 818), not "API Docs". Querying for a link named 'API Docs' will always return null regardless of whether the Integrations group is expanded or collapsed, so this assertion doesn't actually verify the intended collapse behavior.
🐛 Proposed fix
expect(
- screen.queryByRole('link', { name: 'API Docs' })
+ screen.queryByRole('link', { name: 'API Reference' })
).not.toBeInTheDocument();📝 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.
| expect( | |
| screen.queryByRole('link', { name: 'API Docs' }) | |
| ).not.toBeInTheDocument(); | |
| expect( | |
| screen.queryByRole('link', { name: 'API Reference' }) | |
| ).not.toBeInTheDocument(); |
🤖 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 `@ui/src/__tests__/menu.test.tsx` around lines 257 - 259, The menu collapse
test is asserting against a link name that never exists, so it does not validate
the intended behavior. Update the `menu.test.tsx` assertion to query the actual
`NavItem` label used in `ui/src/menu.tsx` for this route, which is `API
Reference`, and keep the check in the same collapsed/expanded test case so it
verifies the Integrations group visibility correctly.
| const appBarContext = React.useContext(AppBarContext); | ||
| const { setTitle } = appBarContext; |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Missing remoteNode parameter on API calls.
loadSpec calls fetchJson('/openapi.json') and the "Raw JSON" link uses config.apiURL directly, both ignoring appBarContext.selectedRemoteNode. In multi-node deployments this always fetches the local node's OpenAPI document even when the user has selected a different remote node in the AppBar, which is misleading.
🔧 Suggested fix
const appBarContext = React.useContext(AppBarContext);
- const { setTitle } = appBarContext;
+ const { setTitle, selectedRemoteNode } = appBarContext;
+ const remoteNode = selectedRemoteNode || 'local';
const config = useConfig();
const [state, setState] = React.useState<LoadState>({ status: 'loading' });
...
const loadSpec = React.useCallback(async () => {
setState({ status: 'loading' });
try {
- const spec = await fetchJson<OpenAPIDocument>('/openapi.json');
+ const spec = await fetchJson<OpenAPIDocument>(
+ `/openapi.json?remoteNode=${encodeURIComponent(remoteNode)}`
+ );
setState({ status: 'ready', spec });
} catch (error) {
setState({
status: 'error',
message: error instanceof Error ? error.message : 'Failed to load the API reference.',
});
}
- }, []);
+ }, [remoteNode]);
...
- <a href={`${config.apiURL}/openapi.json`} target="_blank" rel="noreferrer">
+ <a
+ href={`${config.apiURL}/openapi.json?remoteNode=${encodeURIComponent(remoteNode)}`}
+ target="_blank"
+ rel="noreferrer"
+ >As per coding guidelines: "All API calls MUST include the remoteNode parameter to route requests to the correct node in multi-node Dagu deployments."
Also applies to: 30-42, 70-74
🤖 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 `@ui/src/pages/api-docs/index.tsx` around lines 21 - 22, The API docs page is
ignoring the selected remote node, so `loadSpec` and the “Raw JSON” link can hit
the wrong node in multi-node setups. Update the API requests in
`ui/src/pages/api-docs/index.tsx` to use `appBarContext.selectedRemoteNode` when
calling `fetchJson` and when building the raw OpenAPI URL via `config.apiURL`,
and keep the `AppBarContext`/`setTitle` usage aligned with those changes. Ensure
the relevant logic in `loadSpec` and the raw JSON link both route through the
same remote-node-aware API path.
Source: Coding guidelines
| <RefreshCw className="h-5 w-5 animate-spin text-muted-foreground" /> | ||
| <div> | ||
| <p className="font-medium text-foreground">Loading API reference</p> | ||
| <p className="text-sm text-muted-foreground">Fetching `/openapi.json` with the current auth context.</p> |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Literal backticks shown in rendered UI text.
`/openapi.json` renders as plain text with literal backtick characters, not as code-formatted text.
💚 Proposed fix
- <p className="text-sm text-muted-foreground">Fetching `/openapi.json` with the current auth context.</p>
+ <p className="text-sm text-muted-foreground">
+ Fetching <code>/openapi.json</code> with the current auth context.
+ </p>📝 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.
| <p className="text-sm text-muted-foreground">Fetching `/openapi.json` with the current auth context.</p> | |
| <p className="text-sm text-muted-foreground"> | |
| Fetching <code>/openapi.json</code> with the current auth context. | |
| </p> |
🤖 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 `@ui/src/pages/api-docs/index.tsx` at line 84, The API docs page is rendering
literal backticks in the descriptive copy instead of inline code formatting.
Update the JSX in the api-docs page near the fetching message so the
`/openapi.json` path is rendered as proper inline code markup rather than
included inside a plain text string. Use the existing component text in the
api-docs page to locate and adjust the affected paragraph.
There was a problem hiding this comment.
3 issues found across 15 files
Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.
Re-trigger cubic
Summary
Testing
Closes #2349
Summary by cubic
Restores the API Docs page using
@scalar/api-reference-reactand wires it back into navigation, breadcrumbs, Home, and Integrations. Loads the latest OpenAPI spec with token-aware viewing; built-in docs remain disabled. Closes #2349.New Features
@scalar/api-reference-react.Dependencies
@scalar/api-reference-reactand its stylesheet; updatedpnpm-lock.yaml.@scalar/api-reference-react.Written for commit 16ae526. Summary will update on new commits.
Summary by CodeRabbit
New Features
Bug Fixes