Repository navigation
Redesign: page background and topic map, drawn from prepared images - #38
Merged
Merged
Conversation
The paper texture, the corner pattern and the "Best of three" topic map now look as in the prototype without a shader library or WebGL. scripts/make-background.py computes them ahead of time, following the prototype's recipe and Paper Shaders' halftone shader, and writes three small images to src/assets/background/: a 140px paper tile, the corner pattern's ink on a polar grid, and the map's ink. The browser only lays the dots out and draws them once on a canvas, and on resize stretches what is drawn until resizing stops. - Background.astro, behind every page and the 404: the paper, the corner pattern at 6%, the hole around the map and, on articles, the band behind the centred 720px column. - TopicMap.astro: the map, with its orange dots as buttons or links that send a topicmap:pick event, and a data-picked state. - Intro.astro: the two-column intro of Home and About, with the map. - map-preview.astro: a temporary page to review the intro and the map, until the home (#31) uses them. - Scripts are kept out of the HTML, as the Content-Security-Policy only allows the site's own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013MdjUerTCBDeF5DG9puDd2
Brings in the share images and favicon (#37). Layout keeps their share prop and adds textColumn and noindex next to it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013MdjUerTCBDeF5DG9puDd2
|
Preview: https://pr-38-meaningfool.josselin-perrus.workers.dev Built from a26fefa with the latest content. The link stays the same and shows the latest push. Search engines are asked not to index it. |
3 tasks
On a 1x canvas the dots smaller than a pixel lose some of their ink, and the map came out 8% lighter than the prototype's. The shader renders at twice the CSS pixels or more, so draw the map the same way: it is now as dark at 1x and 1.5x as at 2x. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013MdjUerTCBDeF5DG9puDd2
Owner
Author
|
Review checkpoint: accepted at This was an independent review over 2 passes. The Deploy Fix pushed
What I checked
Notes, not blocking
Generated by Claude Code |
meaningfool
marked this pull request as ready for review
November 3, 2026 19:41
This was referenced Nov 3, 2026
Merged
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements #30 (part of #35). It builds on the foundations from #36 and gives #31 (home) and #33 (About) the intro block and the map to fill in.
What changes
scripts/make-background.py(Python, with numpy and Pillow) does the prototype's heavy work ahead of time. It follows the prototype's code and the source of Paper Shaders' Halftone Dots shader (0.0.81), and writes three images tosrc/assets/background/, 91 KB in all. The images are committed with the script that makes them, sobun run buildand CI don't need Python. The script gives the same files on every run. Rerun it after changing its settings orsrc/data/topic-map.json.paper.png(30 KB): a 140px tile of the paper, at 2x. It is the shader's output for a white image (hex grid, gooey dots, dot colour 87%, grain 61%, 10px spacing), computed pixel by pixel and laid at 6% on the white page. The dots repeat every 14px. The grain is the shader's value noise made to wrap around, so the tile has no seam.corner.png(41 KB): the size of every dot of the Ripple pattern (7px, 14°, reach 142%, 3 rings, 60%, twist 165%), after the prototype's blur and tone curve. It is stored on a polar grid around the top-right corner, in units of the reach, so it fits any window.map.png(21 KB): the 420 × 300 grey image the prototype gave the shader for "Best of three". It is made from the prototype's patches, which are now insrc/data/topic-map.jsonwith the labels and dot positions.src/components/Background.astro): the paper and the corner pattern at 6%, fixed. It is behind every page built withLayout, the 404 page, and the not-found view of/documents/. Only the pattern is masked, so the paper keeps going:astro.config.mjs), because the Content-Security-Policy only allows the site's own scripts. No other output changes.redesignis merged in (the share images and favicon, Redesign: share images and favicon #37).Layoutkeeps theirshareprop and addstextColumnandnoindexnext to it.For #31, #32 and #33
Intro(#31, #33)The prototype's
.hero. Two columns, text at 500px and the map from 480px to 636px wide. The map spills 84px above and below without making the intro taller. Below 1120px the map goes under the text, up to 560px wide. The columns are top-aligned, so the label, the title and the map are at the same place on Home and About whatever the text.label: the small line above the title.titleslot: inside the<h1>. A<span>in it is in the accent colour, for the full stop.afterslot: anything under the text, 18px below it.linksandmapLabel: passed to the map (see below).TopicMap: the orange dots (#31, #33)Each dot carries its topic in
data-topic:customer-success,productorai-agents.Clicking a dot sends a
topicmap:pickevent from the<topic-map>element. The event bubbles,event.detail.topicis the dot's topic, and it can be cancelled:preventDefault()stops a link dot from following its link.Setting
data-picked="<topic>"on<topic-map>marks that dot as picked and dims the other two to 40%, as in the prototype. Removing it clears the pick. Button dots getaria-pressedto match.Without
links, the dots are buttons. That fits the home (Redesign: home page #31):With
links, the dots are links. That fits About (Redesign: About page #33):<Intro label="About" links={{ 'customer-success': '#customer-success', product: '#product', 'ai-agents': '#ai-agents' }}>.mapLabelnames the map for screen readers. The default is the prototype's "Map of the writing: Customer success, Product and AI agents".Home to About without a redraw (#33): the map is at the same place on both pages. A normal page load draws it again, which takes about 10ms once its image is cached. To keep it from one page to the next, #33 can use Astro's
<ClientRouter />withtransition:persiston<topic-map>, and on<page-background>too. Both are custom elements that keep their drawing and their listeners when they are moved: moving them in the page redraws nothing. A kept element keeps the markup of the page it was first drawn on: Home's map has buttons and About's has links, so a map kept between the two is best handled throughtopicmap:pickon both pages, with itsdata-pickedcleared on arrival. Keep<page-background>only between Home and About: an article's background has its own mask (data-mask="column").Article band (#32)
Layouthas atextColumnprop. It is on by default whentype="article", which article pages and activity logs already pass, so #32 has nothing to do. The band is computed in CSS for a column ofmin(720px, frame width − 48px)centred in the window. If the column changes, change--edgeinBackground.astro.Temporary, for #31 to remove
To show the map on the preview,
/map-preview/(src/pages/map-preview.astro) shows the intro with the prototype's home text and a note. Clicking a dot there setsdata-picked. The page is linked from nowhere, hasnoindex, and is left out of the sitemap by one line inastro.config.mjs. Both are marked TEMPORARY (#30), and #31 deletes them.Choices to check
/documents/: the not-found view gets the background, so it still renders pixel for pixel like/404.html. The portfolio view keeps its plain page.Validation
Head commit
f72416c43ab827163685f2461981a01759782f6b, on base3df7e3843cdd06cf5d6c73d7b32e6443c3007262(origin/redesign, with #37 merged in). The branch was started at4cf01a4. Node 24.22.1, Bun 1.4.4, content submodule atbf783ba(git submodule update --init --remote). Every check below was run again after the merge. The review's fix,a26fefa(the map's resolution), is described in its checkpoint comment.bun install, thenbun run buildfrom an emptydist/: passes, 63 pages (62, plus/map-preview/).bun run test:documents: 10 tests, 10 passed.astro check(TypeScript 6, in a scratch copy of the merged tree): 0 errors, 0 warnings.python3 scripts/make-background.pygives byte-identical images on every run.No shader library.
dist/has no reference tojsdelivr,paper-designorgoogleapis. In headless Chromium, the preview,/,/about/, an article, a daily log,/404.htmland/documents/request nothing from another host and log no errors.Comparison with the prototype (
docs/redesign/prototype/index.html), with Playwright screenshots in Chromium. The prototype was given a local copy of@paper-design/shaders@0.0.81. Under an emulated 2x screen, headless Chromium reports device-pixel sizes in CSS pixels, so the shader was made to use its fallback size, as a real 2x screen would.a26fefait is drawn at 2x or more on every screen and is 3.5% lighter at 1x, 1.5x, 2x and 3x, most of it in the lightest dots.Resizing: a 30-step drag from 1380px to 1100px draws nothing while it lasts, then each canvas once. A 4% drag draws nothing. No task over 50ms runs during resizing.
Interaction: clicking a dot sends
topicmap:pickwith its topic.data-pickeddims the other dots and setsaria-pressed. Cancelling the event stops a link dot. Dots can be reached with Tab and picked with Enter.Failure: with
corner.pngandmap.pngblocked, there is no script error, and the next resize draws both.Pages outside the issue: I built the base (
3df7e38) and the head and compared them.<main>is identical on all 62 pages.<main>, the only changes are the background's markup, styles and script.rss.xml,_headers,robots.txt, the share images and the favicons are unchanged._redirectsgains/map-preview, andllms*.txtdiffer only in their build timestamp./documents/: the not-found view matches/404.htmlpixel for pixel at 1440px and 375px, and the portfolio view, forced on, matches the base build pixel for pixel.Review gate: 5 passes over the whole change. The first two fixed:
/documents/not-found view, which had lost its match with/404.html;100lvhheight the CSS minifier left without a fallback;The last three passes, the fifth one after the merge, found nothing.
🤖 Generated with Claude Code
https://claude.ai/code/session_013MdjUerTCBDeF5DG9puDd2