Plan: Responsive Design & Mobile UX

plan-2026-02-27-responsive-design-mobile-ux Plan

plan completed

Vision

pal-e-docs is on a resume and shown in interviews. The browse frontend must be properly responsive — readable, well-spaced, and user-friendly on any screen size. Not flashy, just correct. Nothing should overflow, nothing should feel cramped, and tables should be navigable on a phone.

Projects & Repos Touched

Project/Repo Platform Role in this plan
pal-e-docs (app) Forgejo Templates, CSS, server-side HTML processing, playwright tests

Context

The Browse Frontend Polish plan shipped typography, table styling, and pre blocks (PR #43). But visual QA revealed the site is still broken on mobile. The root cause isn't missing CSS — it's structural:
  • Zero @media queries — one layout for all screen sizes
  • Tables in note content have no wrapper div — the CSS display: block; overflow-x: auto hack breaks table layout semantics
  • Nav overflows on mobile — brand + 5 links + login all compete for one flex row with no breakpoint
  • Doc lists on landing page dump tags inline with titles — chaotic wrapping on narrow screens
  • No automated mobile QA — the existing 3 playwright tests only cover mermaid/lightbox
Key architectural insight: We don't need to touch the 75+ notes in the database. The rendering pipeline is:
We control three layers: server-side HTML processing (table wrapper step), Jinja2 templates (structural divs, nav), and CSS (breakpoints, mobile-first rules). All presentation concerns, zero content changes.

Previous Plan

plan-2026-02-26-browse-frontend-polish — completed. Shipped font, table CSS, pre blocks, XSS sanitization, auto-link slugs. This plan addresses the structural gaps that CSS alone can't fix.

Depends On

None.

Decisions Made

Decision Rationale
Server-side table wrapping, not client-side JS Clean approach. Same HTMLParser pattern as autolink_slugs(). No layout shift on page load. Consistent with existing pipeline.
CSS-only responsive nav, no hamburger menu 5 nav links + login is not enough to justify a hamburger. Flexbox + one @media breakpoint: brand on its own row on mobile, links wrap into a compact second row. Simple, no JS.
Playwright tests define "done" before code changes Tests written first, fail on current state, pass after fixes. CI catches regressions forever.
New plan, not extending the old one Browse Frontend Polish was "make it look decent." This plan is "make the HTML structure correct for responsive design." Different problem, different scope.
Pre-commit framework for ruff enforcement Agents repeatedly failed CI with unformatted code (PRs #37, #46). <code>.pre-commit-config.yaml</code> with ruff-format + ruff check catches this at git commit time.

Phases

Phase 1: Server-side table wrapper + playwright mobile test suite ✓ COMPLETE

Slug: phase-2026-02-27-1-table-wrapper-tests
Goal: Tables in note content are wrapped in scroll containers server-side. Playwright tests define the mobile responsiveness contract.
Owner: Agent (worktree, pal-e-docs repo)
Status: COMPLETE — PR #45 merged
Delivered:
  • PR #45 — wrap_tables.py HTMLParser wrapping outermost <table> elements in <div class="table-scroll">. Nested table depth tracking (no double-wrap). Safety flush for unclosed tables. str | None type signature matching autolink_slugs().
  • Pipeline wired: sanitize → autolink → wrap_tables → template
  • CSS: .table-scroll with overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%. Removed display: block; overflow-x: auto hack from .note-content table.
  • 16 unit tests + 5 integration tests + 5 playwright mobile tests (151 total passing)
  • All 5 playwright mobile tests pass — no horizontal overflow on landing page, tables scrollable in wrapper, nav fits viewport, readable font sizes
Review-fix loop: 2 rounds. Round 1: unclosed table safety flush (blocking), type signature consistency, entity-encoded table-in-pre test, import placement, max-width CSS. Round 2: all fixes verified, clean approval.

Phase 2: Template restructuring + CSS overhaul ✓ COMPLETE

Slug: phase-2026-02-27-2-template-css-overhaul
Goal: All pages render correctly at 375px. No horizontal overflow. Nav is usable on mobile. Proper @media breakpoints.
Owner: Agent (worktree, pal-e-docs repo)
Status: COMPLETE — PR #48 merged
Delivered:
  • PR #48 — Nav restructured with CSS classes (.nav-auth, .nav-links, .user-email, .logout-btn, .login-link). All inline styles removed from all 9 templates.
  • @media (max-width: 600px) breakpoint: brand on own row, nav links on own row, auth on own row right-aligned. Reduced main padding/margin. Card grid forced to single column. h1 size reduced.
  • landing.html: tags wrapped in <div class="tag-row"> below titles. Section headers moved to .section-header class.
  • login.html: all inline styles replaced with CSS classes.
  • tag-row class applied consistently across note.html, tag_notes.html, project_notes.html, landing.html.
  • Form elements inherit Atkinson Hyperlegible via font-family: inherit rule.
  • .pre-commit-config.yaml with ruff-format + ruff check (rev v0.15.2).
  • 151 tests passing, all 5 playwright mobile tests green.
Review-fix loop: 3 rounds. Round 1: remaining inline style in landing.html (blocking), ruff version outdated (blocking), nav-links wrapper suggestion, tag-row consistency, font inheritance. Round 2: note.html tag-row, nav-links mobile gap. Round 3: clean approval.

Phase 3: Visual QA + polish ✓ COMPLETE

Slug: phase-2026-02-27-3-visual-qa-polish
Goal: Final visual pass. Fix the nav wrap bug, improve mobile spacing. Everything looks intentional, not just "not broken."
Owner: Agent (worktree, pal-e-docs repo)
Status: COMPLETE — PR #50 merged
Delivered:
  • PR #50 — flex-basis: 100%flex: 0 0 100% for .brand, .nav-links, .nav-auth in mobile breakpoint. Root cause: flex-shrink: 1 default allowed items to compress below 100% width, preventing proper row stacking.
  • Mobile section spacing: .section { margin-bottom: 3rem; } in mobile breakpoint (up from 2.5rem default).
  • New playwright test test_nav_three_row_layout — validates brand/nav-links/nav-auth have strictly increasing Y positions with 10px minimum gap assertions.
  • 152 total tests passing, all 9 playwright browser tests green.
Review-fix loop: 2 rounds. Round 1: clean approval on CSS fix. Round 2: strengthened test assertions from simple > to > + 10 minimum gap (catches zero-height edge case). Clean approval.

Key Files

Phase File Repo Change
1 ✓ <code>src/pal_e_docs/wrap_tables.py</code> pal-e-docs New — HTMLParser table wrapper
1 ✓ <code>src/pal_e_docs/routes/frontend.py</code> pal-e-docs Wire wrap_tables into rendering pipeline
1 ✓ <code>tests/test_wrap_tables.py</code> pal-e-docs New — 16 unit tests for table wrapping
1 ✓ <code>tests/test_wrap_tables_integration.py</code> pal-e-docs New — 5 integration tests
1 ✓ <code>tests/test_mobile_responsive.py</code> pal-e-docs New — 5 playwright mobile viewport tests
1 ✓ <code>src/pal_e_docs/templates/base.html</code> pal-e-docs CSS: .table-scroll styles, remove display:block hack
2 ✓ <code>src/pal_e_docs/templates/base.html</code> pal-e-docs Nav restructure, @media breakpoints, CSS overhaul, form font inherit
2 ✓ <code>src/pal_e_docs/templates/landing.html</code> pal-e-docs Doc list tag-row layout, section-header class, view-all-link class
2 ✓ <code>src/pal_e_docs/templates/login.html</code> pal-e-docs All inline styles moved to CSS classes
2 ✓ <code>src/pal_e_docs/templates/note.html</code> pal-e-docs tag-row class consistency
2 ✓ <code>src/pal_e_docs/templates/tag_notes.html</code> pal-e-docs tag-row class consistency
2 ✓ <code>src/pal_e_docs/templates/project_notes.html</code> pal-e-docs tag-row class consistency
2 ✓ <code>.pre-commit-config.yaml</code> pal-e-docs New — ruff-format + ruff check hooks (v0.15.2)
3 ✓ <code>src/pal_e_docs/templates/base.html</code> pal-e-docs Nav wrap fix (flex: 0 0 100%), mobile section spacing
3 ✓ <code>tests/test_mobile_responsive.py</code> pal-e-docs New test — test_nav_three_row_layout with 10px gap assertions

Verification

  • [x] Phase 1: wrap_tables() unit tests pass. Table wrapper in pipeline. Playwright mobile tests exist and run in CI. 151 total tests passing. PR #45 merged.
  • [x] Phase 2: ALL playwright mobile tests pass. No horizontal overflow at 375px on any page. Nav usable on mobile. All inline styles removed. Pre-commit config added. PR #48 merged. 3-round review-fix loop.
  • [x] Phase 3: Nav renders as 3 rows on mobile. Mobile spacing improved. 152 total tests passing. PR #50 merged. 2-round review-fix loop.

Next Plan Seeds

  • plan-2026-02-27-browse-ux-enhancements — sort by recency, project detail page redesign, mermaid diagram revision
  • Screenshot regression tests in CI
  • Dark mode (if there's ever demand)
  • project-pal-e-docs — parent project
  • plan-2026-02-26-browse-frontend-polish — predecessor (completed). This plan addresses structural gaps that CSS alone couldn't fix.
  • issue-pal-e-docs-table-wrapper-mobile-tests — resolved, Phase 1 (PR #45)
  • issue-pal-e-docs-template-css-overhaul — resolved, Phase 2 (PR #48)
  • issue-pal-e-docs-visual-qa-polish — resolved, Phase 3 (PR #50)