feat(display): default HTML pages to fit-width, top-aligned - #4
Conversation
The HTML display pages (/rotation for Visionect and the zero-config root /) fit the image to both viewport axes with object-fit: contain, so a paper whose aspect ratio differs from the panel shrinks to a letterboxed thumbnail with tiny, unreadable text. Default them instead to fitting the viewport width, keeping the aspect ratio, pinning the top of the page to the top of the viewport, and clipping whatever runs past the bottom. This keeps the masthead and lead story large and legible on any panel wider than the paper; where it would clip content, contain's alternative was already an unreadable thumbnail, so width-fit dominates in the one case they differ. - New ?fit= values on the HTML pages: default (width, top), ?fit=contain (previous letterboxed behavior), ?fit=cover (fill, center-crop). fit=width is client-side CSS only; /rotation.png and /api/display still frame with contain/cover server-side. - URL builder's Fit control offers all three for the Visionect target (defaulting to width) and contain/cover for the image/TRMNL targets, omitting fit from the URL when it matches the target default. Behavior change: existing HTML displays render fit-to-width on upgrade; add ?fit=contain to restore the letterboxed layout. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2DKHiUNkAc1jo6gb4Ghi2
|
Warning Review limit reached
Next review available in: 23 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
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. Comment |
There was a problem hiding this comment.
Pull request overview
This PR changes the default framing behavior of the HTML-based display pages so rendered newspaper pages fit the viewport width, remain top-aligned, and clip overflow at the bottom, improving legibility on panels whose aspect ratio would otherwise cause object-fit: contain letterboxing.
Changes:
- Updates
/rotation(Visionect/HTML) and the zero-config root HTML page to default to width-fit + top alignment, with?fit=containand?fit=coveras explicit opt-in modes. - Updates the URL builder to expose the appropriate Fit choices per target and to omit
fitfrom generated URLs when it matches the target default. - Documents the behavior change and the new
fitsemantics inCHANGELOG.md.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| cmd/broadsheet-server/web/templates/builder.html | Updates Fit UI + URL emission rules so Visionect defaults to width-fit while other targets keep contain/cover defaults. |
| cmd/broadsheet-server/rotation.go | Changes /rotation page CSS/JS to default to width-fit/top alignment, with `fit=contain |
| cmd/broadsheet-server/main.go | Changes the zero-config HTML display page to the same default width-fit/top alignment behavior with `fit=contain |
| CHANGELOG.md | Documents the HTML display behavior change and the fit= options. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Problem
The HTML display pages served to clients like Visionect (
/rotation, and the zero-config root/) size the image withobject-fit: contain— it fits both axes, so a newspaper whose aspect ratio differs from the panel shrinks into a letterboxed thumbnail with tiny, unreadable text.Change
Default both HTML pages to fitting the viewport width, keeping the aspect ratio, pinning the top of the page to the top of the viewport, and clipping whatever runs past the bottom.
Why width-fit is the right default: it's a genuinely distinct scale rule (scale-to-width, neither
contain's min norcover's max). On a portrait panel it's equivalent to contain; on a wider panel it fills the glass and keeps the masthead/lead legible. In the one geometry where it would clip content, contain's non-cropped alternative was already an unreadable thumbnail — so width-fit dominates where they differ, and a front page front-loads its value at the top anyway.fit=surface (HTML pages)width)?fit=contain?fit=coverPair with
?margin=0to pin flush to the top-left corner.fit=widthis client-side CSS only —/rotation.pngand/api/displaystill frame withcontain/coverserver-side (unchanged), so the shared vocabulary stays consistent.contain/coverfor the image/TRMNL targets, omittingfitfrom the URL when it matches the target default.Behavior change
Existing HTML displays render fit-to-width on upgrade. Add
?fit=containto the page URL to restore the previous letterboxed layout. Documented in CHANGELOG.Verification
go build ./cmd/...,gofmt, andgo test ./cmd/...all clean; no stalefit=width/body.widthreferences. Visual behavior confirmed against a harness mirroring the final template CSS (a self-contained comparison of the three modes in a landscape panel).🤖 Generated with Claude Code
https://claude.ai/code/session_01E2DKHiUNkAc1jo6gb4Ghi2