Skip to content

fix(portal): drop the code block guard Fumadocs 12.1 makes unnecessary - #417

Merged
mehnoorsiddiqui merged 1 commit into
devfrom
fix-370
Oct 2, 2026
Merged

mehnoorsiddiqui merged 1 commit into
devfrom
fix-370

Conversation

@mehnoorsiddiqui

Copy link
Copy Markdown
Contributor

fumadocs-openapi 12.1 now skips a response example that has no value (fuma-nama/fumadocs#3608), so an operation page no longer crashes with Cannot read properties of undefined (reading 'split'). This removes the template's own CodeBlock, which only existed to guard that case (#373), and lets pages render through Fumadocs' default code block.

  • code-block.tsx is deleted, and api-page.tsx no longer passes components: { CodeBlock }.
  • The usage tabs take the code block from useComponents(). The cURL tab renders nothing itself when no example request is available, which the removed guard used to cover.

Verified with the spec from #370, plus a value-less request example and a response whose only example has no value, on 12.1.1: both operation pages render in the browser, the empty example is left out of the response, and a response with only an empty example shows "Empty". Tests, lint and the e2e portal build pass.

Refs #370

🤖 Generated with Claude Code

fumadocs-openapi 12.1 skips a response example that has no `value`
(fuma-nama/fumadocs#3608), so `undefined` no longer reaches the code
block and the operation page no longer crashes. The template's own
CodeBlock, which only existed to skip that case (#373), is removed and
pages render through Fumadocs' default code block.

The usage tabs take the code block from useComponents(), and the cURL
tab renders nothing itself when no example request is available, which
the removed guard used to cover.

Refs #370

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Oct 2, 2026

Copy link
Copy Markdown

@mehnoorsiddiqui

mehnoorsiddiqui commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor Author

QA test cases

What to verify: an API reference page renders when an OpenAPI example has no value, and that example is left out rather than shown blank. Before the fix, the page showed "Something went wrong! Cannot read properties of undefined (reading 'split')" (#370).

This PR also swaps the portal's own code block for Fumadocs' default one, so cases 5–8 check that cURL, SDK samples and response JSON still look and behave the same.

Build under test: branch fix-370 (or dev once this is merged), with fumadocs-openapi 12.1.1. Test in Chrome, plus Firefox or Safari if time allows.

Setup (about 5 minutes)

  1. From a clone of apimatic-cli, run git switch fix-370 && pnpm install && pnpm build.
  2. Sign in with pnpm apimatic auth login. portal serve won't start without sign-in.
  3. Create the project below.
  4. Run pnpm apimatic portal serve -i <path-to>/qa-370 --open.
  5. Keep the DevTools console open for every case.
qa-370/
  src/
    apimatic.json
    content/index.md
    content/nav.json
    spec/Repro.json
src/apimatic.json, src/content/index.md, src/content/nav.json

src/apimatic.json (the typescript block makes the CLI generate SDK code samples, which case 5 needs):

{
  "schemaVersion": 1,
  "portal": {
    "site": { "name": "QA 370", "url": "https://docs.test" }
  },
  "languages": { "typescript": {} }
}

src/content/index.md (the front matter is required; without it the CLI refuses the page):

---
title: QA 370
---

Open the API reference.

src/content/nav.json:

{ "title": "Overview", "pages": ["index", "apimatic:api", "apimatic:sdks"] }
src/spec/Repro.json
  • GET /items: a 200 response with one example that has no value (Default) and one that has a value (Populated). This is the exact case from portal: an operation page crashes when a response example has no value #370.
  • POST /items: a request example with no value (Empty), and a 201 response whose only example has no value.
  • GET /items/{id}: an ordinary operation, used as the control case.
  • Two servers, for case 6.
{
  "openapi": "3.0.0",
  "info": { "title": "Repro", "version": "1.0.0" },
  "servers": [
    { "url": "https://api.repro.test", "description": "Production" },
    { "url": "https://sandbox.repro.test", "description": "Sandbox" }
  ],
  "paths": {
    "/items": {
      "get": {
        "operationId": "listItems",
        "tags": ["items"],
        "parameters": [
          { "name": "limit", "in": "query", "schema": { "type": "integer" }, "example": 10 }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": { "type": "object" },
                "examples": {
                  "Default": {},
                  "Populated": { "summary": "Populated example", "value": { "id": "1" } }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createItem",
        "tags": ["items"],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "type": "object", "properties": { "id": { "type": "string" } } },
              "examples": {
                "Empty": {},
                "Filled": { "summary": "Filled request", "value": { "id": "2" } }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": { "type": "object" },
                "examples": { "OnlyEmpty": {} }
              }
            }
          }
        }
      }
    },
    "/items/{id}": {
      "get": {
        "operationId": "getItem",
        "tags": ["items"],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "example": "1" }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": { "type": "object" },
                "example": { "id": "1", "name": "Widget" }
              }
            }
          }
        }
      }
    }
  }
}

Test cases

# Case Steps Expected result
1 Response example with no value doesn't crash the page Open API Reference → Items → List Items. The page renders fully. No "Something went wrong", and no console error mentioning <Placeholder> or reading 'split'.
2 The value-less example is left out On List Items, look at the 200 response example. It shows only { "id": "1" }. There's no blank or empty Default entry, and no accordion because only one example is left.
3 Response whose only example has no value Open Create Item and look at the 201 response example. The page renders, and the 201 tab shows Empty.
4 Request example with no value On Create Item, open the example dropdown above the code tabs. Pick Filled request, then Empty. Both are listed, and switching never crashes the page. Filled request gives a cURL whose -d body has "id": "2". Empty gives -d '{}'.
5 Code blocks are still highlighted On List Items and Create Item, check the cURL tab, the TypeScript SDK sample tab and the response JSON. Toggle light/dark theme. Each block is syntax-highlighted in both themes, and its Copy button copies the exact text. They look the same as on dev before this PR.
6 cURL follows the server and playground edits On List Items, switch the server to Sandbox, then change limit to 5 in the playground. The cURL URL changes to https://sandbox.repro.test/items?limit=10, then to …?limit=5.
7 Control operation is unaffected Switch the server back to Production (the portal remembers the server picked in case 6), then open Get Item. cURL shows https://api.repro.test/items/1, and the 200 response shows { "id": "1", "name": "Widget" }.
8 Direct load and reload Paste the List Items URL into a new tab, then hard-reload (Ctrl+Shift+R). The page renders the same as in case 1 both times, with no crash.
9 Generated static site Stop serve, run pnpm apimatic portal generate -i <path-to>/qa-370 --destination <path-to>/qa-370-site, serve that folder with npx serve <path-to>/qa-370-site, and open List Items and Create Item. generate succeeds, and both pages behave as in cases 1–4.

Pass criteria and reporting

The PR passes when all 9 cases pass and the console shows no new errors on any operation page.

For a failure, report the case number, the browser and version, a screenshot of the page, and the console output.

@mehnoorsiddiqui
mehnoorsiddiqui merged commit 6c2b5df into dev Oct 2, 2026
10 checks passed
@mehnoorsiddiqui mehnoorsiddiqui self-assigned this Oct 5, 2026
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 2.0.0-beta.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants