Skip to content

fix: restore API docs page#2350

Merged
yohamta0 merged 2 commits into
mainfrom
fix-api-docs-restore
Jul 2, 2026
Merged

fix: restore API docs page#2350
yohamta0 merged 2 commits into
mainfrom
fix-api-docs-restore

Conversation

@yohamta0

@yohamta0 yohamta0 commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • restore the API Docs page and Scalar viewer that were removed with the built-in docs feature
  • wire the API Docs route back into navigation, breadcrumbs, Home, and Integrations
  • restore the Scalar dependency and lockfile entries while keeping built-in docs management removed

Testing

  • pnpm install --frozen-lockfile --prefer-offline
  • pnpm test -- src/pages/api-docs/tests/index.test.tsx
  • pnpm typecheck
  • pnpm build

Closes #2349


Summary by cubic

Restores the API Docs page using @scalar/api-reference-react and 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

    • Added /api-docs route that renders the backend OpenAPI via @scalar/api-reference-react.
    • Added “API Reference” under Integrations in the sidebar and breadcrumbs, plus cards on Home and Integrations.
    • Synced theming with dark mode; added custom layout styles for the viewer.
    • Prefills bearer token for authenticated endpoints; added “Open raw spec” link, reload, and error states.
    • Added tests for route, page behavior (load/retry), menu visibility, breadcrumbs, and Integrations links.
  • Dependencies

    • Re-added @scalar/api-reference-react and its stylesheet; updated pnpm-lock.yaml.
    • Added type declaration for @scalar/api-reference-react.

Written for commit 16ae526. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Added an API documentation page that shows interactive REST API docs and loads the latest OpenAPI schema.
    • Added “API Reference”/“API Docs” navigation links in the app and integrations areas for easier access.
    • The API docs page now supports viewing authenticated endpoints and opening the raw API spec.
  • Bug Fixes

    • Improved breadcrumb and navigation behavior so the new docs page stays correctly highlighted and labeled.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a new API Docs page at /api-docs that fetches and renders /openapi.json via a Scalar-based ScalarViewer component. Includes routing, navigation entries (menu, home, integrations), breadcrumb labeling, new CSS styling, a TypeScript declaration for @scalar/api-reference-react, and tests.

Changes

API Docs Page Feature

Layer / File(s) Summary
ScalarViewer component and type declaration
ui/package.json, ui/src/types/scalar-api-reference-react.d.ts, ui/src/pages/api-docs/ScalarViewer.tsx
Adds the @scalar/api-reference-react dependency, its TypeScript module declaration, and a ScalarViewer component that builds a Scalar configuration (dark mode, optional bearer token auth) and renders ApiReferenceReact.
APIDocsPage data fetching and rendering
ui/src/pages/api-docs/index.tsx, ui/src/pages/api-docs/__tests__/index.test.tsx
Adds APIDocsPage, which fetches /openapi.json, manages loading/error/ready states, derives a preferredBearerToken from localStorage for builtin auth, renders ScalarViewer, and provides reload/raw-JSON controls; includes matching tests.
Routing, navigation, and breadcrumb wiring
ui/src/App.tsx, ui/src/menu.tsx, ui/src/layouts/ContentNavigation.tsx, ui/src/pages/home/index.tsx, ui/src/pages/integrations/index.tsx, ui/src/__tests__/App.test.tsx, ui/src/__tests__/menu.test.tsx, ui/src/pages/integrations/__tests__/index.test.tsx
Registers the /api-docs route, adds an “API Reference”/“API Docs” link to the Integrations menu group, home page, and integrations page, updates breadcrumb label mapping, and updates corresponding tests.
API docs viewer styling
ui/src/styles/global.css
Adds .api-docs-shell/.api-docs-viewer styles with themed background variables and a desktop grid layout with scrollable navigation and content panes.

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
Loading

Related Issues: #2349

Suggested labels: enhancement, ui

Suggested reviewers: yohamta

🐰 A rabbit hops through Scalar's door,
fetching specs it's never seen before,
with tokens tucked and dark mode set,
the docs are back — no need to fret!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: restoring the API docs page.
Linked Issues check ✅ Passed The PR restores the API Docs page, Scalar viewer, and related navigation as requested by #2349.
Out of Scope Changes check ✅ Passed The changes are focused on restoring API docs and supporting UI, dependency, and test updates with no obvious unrelated scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The description is mostly complete, covering summary, testing, and issue closure, with detailed change notes despite not matching the template exactly.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-api-docs-restore

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
ui/src/pages/api-docs/ScalarViewer.tsx (1)

17-26: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Dark mode detection doesn't react to live theme toggles.

darkMode is read once per render via document.documentElement.classList.contains('dark'), but nothing subscribes to changes on that class. If the user toggles the theme while viewing API Docs, forceDarkModeState won'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 win

Label inconsistent with nav/home naming: "API Docs" vs "API Reference".

The sidebar NavItem (ui/src/menu.tsx Line 818), the Home page link (ui/src/pages/home/index.tsx Line 201), and the breadcrumb STATIC_ROUTE_LABELS entry (ui/src/layouts/ContentNavigation.tsx Line 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

📥 Commits

Reviewing files that changed from the base of the PR and between 9b181a1 and b164085.

⛔ Files ignored due to path filters (1)
  • ui/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (14)
  • ui/package.json
  • ui/src/App.tsx
  • ui/src/__tests__/App.test.tsx
  • ui/src/__tests__/menu.test.tsx
  • ui/src/layouts/ContentNavigation.tsx
  • ui/src/menu.tsx
  • ui/src/pages/api-docs/ScalarViewer.tsx
  • ui/src/pages/api-docs/__tests__/index.test.tsx
  • ui/src/pages/api-docs/index.tsx
  • ui/src/pages/home/index.tsx
  • ui/src/pages/integrations/__tests__/index.test.tsx
  • ui/src/pages/integrations/index.tsx
  • ui/src/styles/global.css
  • ui/src/types/scalar-api-reference-react.d.ts

Comment thread ui/src/__tests__/menu.test.tsx Outdated
Comment on lines +257 to +259
expect(
screen.queryByRole('link', { name: 'API Docs' })
).not.toBeInTheDocument();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 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.

Suggested change
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.

Comment thread ui/src/pages/api-docs/index.tsx Outdated
Comment on lines +21 to +22
const appBarContext = React.useContext(AppBarContext);
const { setTitle } = appBarContext;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ 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

Comment thread ui/src/pages/api-docs/index.tsx Outdated
<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>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 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.

Suggested change
<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.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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

Comment thread ui/src/pages/api-docs/index.tsx Outdated
Comment thread ui/src/__tests__/menu.test.tsx Outdated
Comment thread ui/src/pages/api-docs/index.tsx Outdated
@yohamta0 yohamta0 merged commit 2a1cf3a into main Jul 2, 2026
10 checks passed
@yohamta0 yohamta0 deleted the fix-api-docs-restore branch July 2, 2026 04:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: Were API Docs removed by accident?

1 participant