Skip to content

Instantly share code, notes, and snippets.

@simonw

simonw/fix.md Secret

Created May 28, 2026 20:19
Show Gist options
  • Select an option

  • Save simonw/5203589941057970e671bf8cb135aee6 to your computer and use it in GitHub Desktop.

Select an option

Save simonw/5203589941057970e671bf8cb135aee6 to your computer and use it in GitHub Desktop.

Options for hiding the paste and URL bit entirely if a URL has been provided, with a subtle way to toggle that back again

A few good patterns:

1. Viewer Mode After Load After a URL is successfully loaded, collapse the whole editor/source pane and make preview full-width. Add one subtle icon button in the preview header, probably a small PanelLeftOpen or pencil icon, to reveal the source controls again.

This is my pick. Clear behavior, low surprise, easy to implement.

2. Thin Edge Tab Hide the left pane, but leave a 6-10px vertical tab on the left edge. Hover or click expands the source pane. This feels polished, but it is easier to miss and a little fiddlier on mobile.

3. Preview Header Toggle Keep the normal two-pane layout for pasted content, but when a URL is active, the preview header gains a small “source” icon button. Clicking it toggles between full preview and editor/source view. Less magical than an edge tab.

4. Query/Hash-Controlled Chrome Support something like #url=...&view=clean or ?chrome=0#url=.... Useful for sharing clean preview links, but I’d avoid making this the only way back. Still needs an in-page toggle.

5. Collapsed Drawer Source controls become a slide-over drawer instead of restoring the split layout. Nice if the main use case is reading rendered markdown, but a bit more UI than this file probably needs.

Recommended behavior:

  • Paste/default mode: normal split view.
  • URL is restored from hash: show URL bar and “Press Load” status, since we intentionally avoid auto-fetch.
  • URL successfully loaded: enter clean viewer mode automatically.
  • Subtle toggle back: a small icon button in the preview header, with a tooltip like “Show source”.
  • When source is shown again, keep the URL tab selected and the loaded content visible.
  • If user switches to Paste, exit clean viewer mode.

That keeps the URL experience clean without making the controls feel lost.

1

8 previous messages

I’ll implement option 1: once a URL load succeeds, the editor/source pane collapses and the preview takes over. I’ll add a small source-toggle control in the preview header so the user can bring the paste/URL pane back without hunting.

Explored 1 file, ran 1 command
Explored 2 files
  • Read ./markdown-svg-renderer.html
  • Read ./markdown-svg-renderer.html
  • Ran git status --short -- markdown-svg-renderer.html

I’ve got the file shape now. I’m going to keep this small: a single app-level “viewer mode” class, a preview-header icon button, and URL-load logic that enters viewer mode only after the fetch/render succeeds.

Edited 1 file
  • Wrote ./markdown-svg-renderer.html (+69 -2)
  • Wrote ./markdown-svg-renderer.html (+22 -0)

The UI pieces are in place now. I’m going to run it through the local browser path: sample render, restored hash behavior, successful URL load entering viewer mode, and the source toggle returning the editor pane.

Ran 1 command, called 1 tool
  • Ran uv run python -m http.server 8765

MCP tool call

node_repl.js

{
  "title": "Verify viewer mode",
  "timeout_ms": 60000,
  "code": "if (!globalThis.agent) {\n  const { setupBrowserRuntime } = await import(\"/Users/simon/.codex/plugins/cache/openai-bundled/browser/26.519.81530/scripts/browser-client.mjs\");\n  await setupBrowserRuntime({ globals: globalThis });\n}\nif (!globalThis.browser) {\n  globalThis.browser = await agent.browsers.get(\"iab\");\n}\nawait browser.nameSession(\"🔎 Markdown viewer mode\");\nif (typeof tab === \"undefined\") {\n  globalThis.tab = await browser.tabs.new();\n}\nawait tab.goto(\"http://127.0.0.1:8765/markdown-svg-renderer.html\");\nawait tab.playwright.waitForLoadState({ state: \"load\", timeoutMs: 20000 });\nawait tab.playwright.waitForTimeout(500);\nconst initial = await tab.playwright.evaluate(() => ({\n  viewerMode: document.querySelector(\".app\").classList.contains(\"viewer-mode\"),\n  hasUrlContent: document.querySelector(\".app\").classList.contains(\"has-url-content\"),\n  editorDisplay: getComputedStyle(document.querySelector(\".editor-pane\")).display,\n  toggleDisplay: getComputedStyle(document.querySelector(\"#source-toggle\")).display,\n  heading: document.querySelector(\"#output h1\")?.textContent || null\n}));\nawait tab.goto(\"http://127.0.0.1:8765/markdown-svg-renderer.html#url=https%3A%2F%2Fexample.com%2Fdoc.md\");\nawait tab.playwright.waitForLoadState({ state: \"load\", timeoutMs: 20000 });\nawait tab.playwright.waitForTimeout(500);\nconst restored = await tab.playwright.evaluate(() => ({\n  viewerMode: document.querySelector(\".app\").classList.contains(\"viewer-mode\"),\n  hasUrlContent: document.querySelector(\".app\").classList.contains(\"has-url-content\"),\n  editorDisplay: getComputedStyle(document.querySelector(\".editor-pane\")).display,\n  toggleDisplay: getComputedStyle(document.querySelector(\"#source-toggle\")).display,\n  status: document.querySelector(\"#url-status\").textContent,\n  url: document.querySelector(\"#url-input\").value\n}));\nconsole.log(JSON.stringify({ initial, restored }, null, 2));"
}
Blocked browser navigation by Browser Use URL policy: file:///Users/simon/Dropbox/dev/tools/markdown-svg-renderer.html

The selected in-app tab is currently on a file:// URL, and the browser automation policy won’t touch that tab. I’m opening a fresh local http://127.0.0.1 tab instead, which is the same file served normally and is allowed for verification.

Called 3 tools

MCP tool call

node_repl.js

{
  "title": "Verify viewer mode on local tab",
  "timeout_ms": 60000,
  "code": "var viewerTab = await browser.tabs.new();\nawait viewerTab.goto(\"http://127.0.0.1:8765/markdown-svg-renderer.html\");\nawait viewerTab.playwright.waitForLoadState({ state: \"load\", timeoutMs: 20000 });\nawait viewerTab.playwright.waitForTimeout(500);\nvar initialViewerCheck = await viewerTab.playwright.evaluate(() => ({\n  viewerMode: document.querySelector(\".app\").classList.contains(\"viewer-mode\"),\n  hasUrlContent: document.querySelector(\".app\").classList.contains(\"has-url-content\"),\n  editorDisplay: getComputedStyle(document.querySelector(\".editor-pane\")).display,\n  toggleDisplay: getComputedStyle(document.querySelector(\"#source-toggle\")).display,\n  heading: document.querySelector(\"#output h1\")?.textContent || null\n}));\nawait viewerTab.goto(\"http://127.0.0.1:8765/markdown-svg-renderer.html#url=https%3A%2F%2Fexample.com%2Fdoc.md\");\nawait viewerTab.playwright.waitForLoadState({ state: \"load\", timeoutMs: 20000 });\nawait viewerTab.playwright.waitForTimeout(500);\nvar restoredViewerCheck = await viewerTab.playwright.evaluate(() => ({\n  viewerMode: document.querySelector(\".app\").classList.contains(\"viewer-mode\"),\n  hasUrlContent: document.querySelector(\".app\").classList.contains(\"has-url-content\"),\n  editorDisplay: getComputedStyle(document.querySelector(\".editor-pane\")).display,\n  toggleDisplay: getComputedStyle(document.querySelector(\"#source-toggle\")).display,\n  status: document.querySelector(\"#url-status\").textContent,\n  url: document.querySelector(\"#url-input\").value\n}));\nconsole.log(JSON.stringify({ initialViewerCheck, restoredViewerCheck }, null, 2));"
}
{
  "initialViewerCheck": {
    "editorDisplay": "flex",
    "hasUrlContent": false,
    "heading": "Markdown renderer",
    "toggleDisplay": "none",
    "viewerMode": false
  },
  "restoredViewerCheck": {
    "editorDisplay": "flex",
    "hasUrlContent": false,
    "status": "URL restored. Press Load to fetch it.",
    "toggleDisplay": "none",
    "url": "https://example.com/doc.md",
    "viewerMode": false
  }
}

MCP tool call

node_repl.js

{
  "title": "Test successful URL load toggle",
  "timeout_ms": 60000,
  "code": "await viewerTab.goto(\"http://127.0.0.1:8765/markdown-svg-renderer.html\");\nawait viewerTab.playwright.waitForLoadState({ state: \"load\", timeoutMs: 20000 });\nvar urlTabButton = viewerTab.playwright.getByRole(\"button\", { name: \"URL\", exact: true });\nconsole.log(\"url button count\", await urlTabButton.count());\nawait urlTabButton.click({ timeoutMs: 10000 });\nvar urlInputBox = viewerTab.playwright.locator(\"#url-input\");\nawait urlInputBox.fill(\"http://127.0.0.1:8765/markdown-svg-renderer.html\", { timeoutMs: 10000 });\nvar loadButton = viewerTab.playwright.getByRole(\"button\", { name: \"Load\", exact: true });\nconsole.log(\"load button count\", await loadButton.count());\nawait loadButton.click({ timeoutMs: 10000 });\nawait viewerTab.playwright.waitForTimeout(1000);\nvar afterLoad = await viewerTab.playwright.evaluate(() => ({\n  viewerMode: document.querySelector(\".app\").classList.contains(\"viewer-mode\"),\n  hasUrlContent: document.querySelector(\".app\").classList.contains(\"has-url-content\"),\n  editorDisplay: getComputedStyle(document.querySelector(\".editor-pane\")).display,\n  toggleDisplay: getComputedStyle(document.querySelector(\"#source-toggle\")).display,\n  toggleLabel: document.querySelector(\"#source-toggle\").getAttribute(\"aria-label\"),\n  status: document.querySelector(\"#url-status\").textContent,\n  hash: location.hash\n}));\nvar sourceButton = viewerTab.playwright.locator(\"#source-toggle\");\nconsole.log(\"source button count\", await sourceButton.count());\nawait sourceButton.click({ timeoutMs: 10000 });\nawait viewerTab.playwright.waitForTimeout(300);\nvar afterToggle = await viewerTab.playwright.evaluate(() => ({\n  viewerMode: document.querySelector(\".app\").classList.contains(\"viewer-mode\"),\n  hasUrlContent: document.querySelector(\".app\").classList.contains(\"has-url-content\"),\n  editorDisplay: getComputedStyle(document.querySelector(\".editor-pane\")).display,\n  toggleDisplay: getComputedStyle(document.querySelector(\"#source-toggle\")).display,\n  toggleLabel: document.querySelector(\"#source-toggle\").getAttribute(\"aria-label\")\n}));\nconsole.log(JSON.stringify({ afterLoad, afterToggle }, null, 2));"
}
Browser Use encountered an error interacting with this webpage's clipboard: Browser Use virtual clipboard is not installed
locator.fill failed for selector #url-input

MCP tool call

node_repl.js

{
  "title": "Test URL load with typed input",
  "timeout_ms": 60000,
  "code": "await viewerTab.goto(\"http://127.0.0.1:8765/markdown-svg-renderer.html\");\nawait viewerTab.playwright.waitForLoadState({ state: \"load\", timeoutMs: 20000 });\nvar urlTabButton2 = viewerTab.playwright.getByRole(\"button\", { name: \"URL\", exact: true });\nconsole.log(\"url button count\", await urlTabButton2.count());\nawait urlTabButton2.click({ timeoutMs: 10000 });\nvar urlInputBox2 = viewerTab.playwright.locator(\"#url-input\");\nawait urlInputBox2.click({ timeoutMs: 10000 });\nawait urlInputBox2.type(\"http://127.0.0.1:8765/markdown-svg-renderer.html\", { timeoutMs: 10000 });\nvar loadButton2 = viewerTab.playwright.getByRole(\"button\", { name: \"Load\", exact: true });\nconsole.log(\"load button count\", await loadButton2.count());\nawait loadButton2.click({ timeoutMs: 10000 });\nawait viewerTab.playwright.waitForTimeout(1000);\nvar afterLoad2 = await viewerTab.playwright.evaluate(() => ({\n  viewerMode: document.querySelector(\".app\").classList.contains(\"viewer-mode\"),\n  hasUrlContent: document.querySelector(\".app\").classList.contains(\"has-url-content\"),\n  editorDisplay: getComputedStyle(document.querySelector(\".editor-pane\")).display,\n  toggleDisplay: getComputedStyle(document.querySelector(\"#source-toggle\")).display,\n  toggleLabel: document.querySelector(\"#source-toggle\").getAttribute(\"aria-label\"),\n  status: document.querySelector(\"#url-status\").textContent,\n  hash: location.hash\n}));\nvar sourceButton2 = viewerTab.playwright.locator(\"#source-toggle\");\nconsole.log(\"source button count\", await sourceButton2.count());\nawait sourceButton2.click({ timeoutMs: 10000 });\nawait viewerTab.playwright.waitForTimeout(300);\nvar afterToggle2 = await viewerTab.playwright.evaluate(() => ({\n  viewerMode: document.querySelector(\".app\").classList.contains(\"viewer-mode\"),\n  hasUrlContent: document.querySelector(\".app\").classList.contains(\"has-url-content\"),\n  editorDisplay: getComputedStyle(document.querySelector(\".editor-pane\")).display,\n  toggleDisplay: getComputedStyle(document.querySelector(\"#source-toggle\")).display,\n  toggleLabel: document.querySelector(\"#source-toggle\").getAttribute(\"aria-label\")\n}));\nconsole.log(JSON.stringify({ afterLoad2, afterToggle2 }, null, 2));"
}
Browser Use encountered an error interacting with this webpage's clipboard: Browser Use virtual clipboard is not installed
locator.type failed for selector #url-input
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment