agent-pages

Plan: Unify the Viewer Header for Markdown and HTML Pages

Download

Unify the Viewer Header for Markdown and HTML Pages

Problem

The viewer currently renders two intentionally different shell headers:

This split came from the full-screen HTML viewer design, which preserved Markdown as a traditional readable document. The result is that navigation and viewer-owned controls look like two different products even though both page formats belong to the same viewer.

This is a shell inconsistency, not a Markdown rendering or theme bug.

Desired Outcome

Use one compact top toolbar for both Markdown and HTML pages while preserving their different content behavior:

Important Scrolling Constraint

The hide-on-scroll behavior will apply to Markdown pages.

HTML artifacts scroll inside a sandboxed iframe with an opaque origin. The trusted outer viewer cannot inspect that iframe's scroll position or direction. Attempting to do so would require weakening the iframe sandbox or introducing a cooperation protocol with published content, both of which conflict with the current security model.

The HTML toolbar therefore remains visible and fixed. This preserves the existing sandbox boundary and keeps fullscreen and version controls available. The plan must not use wheel-event interception, sandbox relaxation, or injected code as workarounds.

Implementation Plan

1. Create a shared toolbar partial

Add app/templates/viewer/_toolbar.html containing:

Keep the toolbar server-rendered and semantically structured with <header>, <h1>, and <nav> elements.

2. Adopt the shared toolbar in both viewer templates

Update app/templates/viewer/html_host.html to render the shared partial without changing its iframe structure.

Update app/templates/viewer/markdown.html to:

This also reduces the prominent duplicate-heading effect when the page title and the first Markdown # heading contain similar text.

3. Refactor viewer CSS around shared chrome

In app/static/viewer.css:

4. Add Markdown scroll-direction behavior

Add a small trusted static asset such as app/static/viewer-scroll.js. It should run only when body.viewer-markdown-host is present.

Behavior:

Suggested motion is a short 160–220 ms opacity and transform transition. Under prefers-reduced-motion: reduce, remove the animation; the toolbar may still switch visibility immediately.

5. Keep the CSP change narrow

The current shell CSP uses script-src 'none'. Reliable scroll-direction detection is not broadly achievable with CSS alone, so Markdown shell pages need permission to load the trusted external script.

Update the viewer response policy so:

Add a content hash for the JavaScript asset in the same spirit as the existing viewer CSS cache-busting hash.

6. Handle responsive layouts explicitly

Verify the shared toolbar at narrow widths:

If necessary, shorten or selectively hide nonessential action labels at the smallest breakpoint without introducing additional client state.

7. Update automated tests

Update tests/test_viewer_smoke.py:

Update tests/test_viewer_security.py:

Update tests/test_viewer_css.py and theme tests:

Add focused JavaScript behavior tests using a browser-capable test harness, or isolate the scroll-state calculation into a testable function and cover:

Run the complete pytest suite and perform browser-based visual QA.

8. Update documentation

Update README.md, docs/architecture.md, and MEMORY.md to explain:

Add a note to docs/full-screen-html-viewer-plan.md or link to a new decision entry so the historical document no longer appears to describe current intended behavior.

Security and Compatibility Constraints

The change must not alter:

The shell CSP change is limited to the same-origin Markdown viewer script. It must not enable scripts in published HTML.

Acceptance Criteria