Vibe-Coding a Research Portfolio
Technical record · updated
The website revamp, a technical record
How the redesign of this site works underneath, and how it changed from February to October 2026: the type and reading column, the time-of-day palettes and tokens, the motion rules, the structure of the homepage and projects, the separate Human and AI routes, the visual QA harness, and the written design memory that carries judgment from one session to the next.
The site is an al-folio v1 fork that owns its identity, layouts, styles, scripts and content. The stages below are design history, not an A/B test; where a move was measured, the entry gives the number and its conditions. Visitor comprehension has not been studied.
- 8 systems
- 39 techniques
- 35 design moves
- 6 open problems
- 36 sources
Each system lists its techniques: what each one does, how it works, the files that hold it, the research it borrows from, what it cannot do yet, and the next moves worth trying. The design history keeps every move in order, with what the result said back.
Programs can read the same record as JSON. In the repository, python bin/design_record_brief.py website-revamp turns it into a brief for the next pass, and new work is appended to _data/design_records/website-revamp.yml.
Type, reading column and image weight
One family, five sizes and one measure. Prose sits in a column of about 68 characters, and images are served at the size they are shown.
Inter in five type roles
Shipped · Sep 14, 2026
Every page uses Inter in five roles (page title, section title, subsection, body, metadata and controls), each a computed size token.
How it works, files and sources
_sass/_themes.scss defines --type-display, --type-heading, --type-subheading, --type-reading and --type-compact as clamped sizes and keeps older names as aliases. Inter’s regular and italic variable files are self-hosted with the SIL OFL in assets/fonts/inter/, and only weights 400 to 700 are used. test/style_contract.js caps raw font-size declarations across _sass at 333 and requires the realignment layer to use type roles, so new styles reach for a role instead of a new size. Inter replaced the Newsreader display face on September 14.
- Files
-
-
_sass/_themes.scssType role tokens and the four palettes. -
assets/fonts/inter/Self-hosted Inter, license and provenance. -
test/style_contract.jsThe font-size ceiling and type-role checks.
-
- Tests
- Sources
- Known limits
-
- 325 legacy raw sizes remain under the 333 ceiling; the cap stops growth rather than paying the debt down.
- Next moves
-
- Ready Move the largest remaining raw sizes in the page-specific partials onto type roles.
A 33.5rem reading column
Shipped · Oct 12, 2026
Prose, headings and the post header share one centered column of about 68 characters, while figures and code reach the wider article width.
How it works, files and sources
_sass/_reading.scss sets --reading-width: 33.5rem for prose and --reading-wide-width: 68ch for figures and code, and the contents rail and trace pages follow it. The column is sized once in rem because ch is the width of “0” in each element’s own font: the old 68ch measured 91 to 95 characters of Inter and grew wider on headings. Bringhurst’s 45 to 75 characters, 66 ideal, is the target.
- Files
-
-
_sass/_reading.scssReading and wide widths for posts and case studies.
-
- Sources
Pixels at display size
Shipped · Oct 12, 2026
Pages request WebP variants sized to how large each image is actually shown, and long GIFs become posters that play on request.
How it works, files and sources
_includes/responsive_variant.liquid prints the URL of the 480, 800 or 1400-pixel WebP variant that the build’s ImageMagick step generates, for gallery slides, thumbnails and teasers. The homepage record art points to 800 px variants with the originals as a fallback. bin/make_gif_posters.py writes a first-frame poster for each animated publication preview, and _layouts/bib.liquid shows the poster with a “Play the animation” control, which also serves reduced-motion visitors without a special case.
- Files
-
-
_includes/responsive_variant.liquidOne WebP variant URL per raster. -
bin/make_gif_posters.pyFirst-frame posters for animated previews. -
_layouts/bib.liquidPoster, zoom and play on request. -
assets/js/home.jsRecord art from 800 px variants with fallbacks.
-
- Sources
- Known limits
-
- Local builds without ImageMagick 404 on variants that only CI generates; pages fall back to the originals.
Moves in this system: A research studio, then one type familyThe screenshot that ran out of memorySixty-eight characters, measured in the wrong unitA poster frame for a moving figureRecord art 40 times larger than its frame
Color, time of day and tokens
Four time-of-day palettes change the atmosphere, never the research story. A small Material-inspired token set keeps surfaces, focus and motion consistent, and a procedural orange is the only identity color.
Four time-of-day palettes
Shipped · May 22, 2026
Morning dawn rose, noon Pacific blue, afternoon sea glass and evening moonlit lavender default from the visitor’s local time.
How it works, files and sources
assets/js/theme.js picks the mode from local time (boundaries at 5, 11, 15 and 20 o’clock) before first paint, remembers a manual choice for the session, and switches automatically at a boundary only if the visitor has not chosen. _sass/_themes.scss holds the four token sets; each one registers through the whole surface hierarchy, from the page field to cards, outlines, shadows and the footer. Accent ink for links and labels stays separate from lighter pastel fills, so contrast holds in every mode.
- Files
-
-
assets/js/theme.jsMode selection before first paint, and Pause motion. -
_sass/_themes.scssThe four palettes.
-
- Sources
Material-Lite tokens
Shipped · Jun 29, 2026
A small set of radius, elevation, tonal-surface, state-layer, focus, spacing and motion tokens, borrowed from Material 3 ideas without its component system.
How it works, files and sources
_sass/_material-lite.scss defines --md-lite-* tokens, and the September foundations pass added spacing and motion durations and easings to them. Filled orange marks the primary action in a local cluster; tonal surfaces carry secondary actions, chips and quiet controls; neutral surfaces carry most of the page. PurgeCSS keeps every --md-lite- variable through its safelist.
- Files
-
-
_sass/_material-lite.scssThe shared tokens. -
docs/material-lite-revamp.mdDesign intent and token use. -
purgecss.config.jsKeeps the token variables in the deployed CSS.
-
- Sources
- Known limits
-
- The homepage’s own partial predates the tokens and still uses many literal values.
A procedural orange mark
Shipped · Jun 29, 2026
The navbar mark is a flat 2D orange whose shape, rind gradient, pores, navel and leaves vary on each page load.
How it works, files and sources
_includes/brand-orange.liquid renders an inline SVG with a no-JavaScript fallback, and assets/js/brand-orange.js varies the shape within a fixed viewbox, the rind gradient, the pores, the calyx details and the leaves, with a small pointer response that stops under reduced motion. ?orangeSeed= reproduces one mark for inspection. The home link owns the accessible label; the SVG is decorative.
- Files
-
-
_includes/brand-orange.liquidInline SVG and fallback. -
assets/js/brand-orange.jsSeeded variation and pointer response. -
_sass/_brand-orange.scssMark styles.
-
- Known limits
-
- Engraving ST into the fruit at navbar size made it read like a glossy app icon, so the mark carries no initials.
A sun you can drag
Shipped · Oct 13, 2026
The theme panel is a day arc. Dragging the sun picks any minute, the theme snaps to that hour’s mode, and the page’s sky glow and the 3D scenes follow.
How it works, files and sources
assets/js/sun-arc.mjs maps minutes onto an arc from 5:00 to 20:00, with a flatter night arc for the moon (sun-arc-math.mjs). The four token sets still carry contrast; only the panel and a sky glow at the top of the page shift color continuously, the glow moving left to right with the sun. The footer coast blends its four authored looks by the minute, and the 3D home previews the hour when the drag ends, through a siteTimeChange event. Now hands everything back to the clock. A theme chosen anywhere else moves the sun but never sets a preview hour. This is direct manipulation in Shneiderman’s sense: a continuous representation, physical action and immediate, reversible feedback.
- Files
-
-
assets/js/sun-arc.mjsThe control and the siteTimeChange event. -
assets/js/sun-arc-math.mjsMinute to arc geometry and theme boundaries. -
_includes/theme_mode_control.liquidPanel markup and the four stops. -
_sass/_sun-arc.scssPanel and sky glow styles.
-
- Sources
- Known limits
-
- The four stops stay, because they are both the quick choice and the test contract.
Grayscale-until-hover thumbnails
Retired · Sep 14, 2026
Fun-project thumbnails sat in grayscale until hover, after React Bits’ Chroma Grid.
What it was and why it was retired
A filter desaturated each Fun thumbnail at rest and restored color on hover or focus, as one of the approved reading enhancements.
- Why it was retired
- Mixed grayscale and color thumbnails made the project index inconsistent. All thumbnails now keep their original color in every state.
1e0e67dbf - Sources
Moves in this system: Material-Lite and an orange markThumbnails stay in colorA sun you can drag, and a switch that stills everything
Motion
Motion explains a state, a comparison or a path, then settles into a readable still frame. A bounded cinematic layer, named springs and scroll-driven CSS carry it; one switch stills everything.
A bounded cinematic layer
Shipped · Sep 5, 2026
Pages that declare cinematic get scroll scenes, staggered entrances, a pointer spotlight and tilt on card grids, and a card-to-hero image morph.
How it works, files and sources
assets/js/cinematic.js runs on GSAP 3.15 and ScrollTrigger, vendored under assets/vendor/gsap/3.15.0/ and loaded only on opted-in pages. Nothing takes over scrolling. Every effect is a still page under reduced motion, without a fine pointer and under automation (navigator.webdriver), unless the URL carries ?cinematic=live, so visual captures stay deterministic. The clicked project image travels into the case page’s hero through a cross-document view transition and back again.
- Files
-
-
assets/js/cinematic.jsScroll scenes, entrances, spotlight, tilt and the morph. -
_sass/_cinematic.scssCinematic styles. -
assets/vendor/gsap/3.15.0/NOTICE.mdVendored library and license.
-
- Known limits
-
- Cinematic captures need
?cinematic=live; ordinary automated captures see the still page.
- Cinematic captures need
The Research Focus sketch
Shipped · May 22, 2026
A semantic drawing explains Design, Evaluate and Situate, with a quiet Paper shader field moving underneath it.
How it works, files and sources
assets/js/research-motion.js draws each mode with a stable number of lines and dots and enough copy to read the metaphor before the motion. A pointer bends the field inside the canvas, easing in and decaying on exit. The Dot Orbit field comes from a vendored minimal closure of @paper-design/shaders 0.0.80 under Apache-2.0, with one WebGL2 context, at most 480,000 processed pixels and a pause offscreen and in hidden tabs. If WebGL fails, the 2D drawing keeps everything a visitor needs. On wide screens the sketch pins beside its three notes inside its own well, and the note in view picks the lens.
- Files
-
-
assets/js/research-motion.jsThe semantic sketch and its modes. -
_includes/home/research_motion.liquidMarkup, notes and credits. -
assets/vendor/paper-shaders/The vendored shader closure with hashes.
-
- Known limits
-
- My first live review found the field perceptually absent; it was strengthened, and its current strength still awaits my judgment.
Springs named by their damping
Shipped · Oct 12, 2026
Buttons and menus answer a press with a damped spring instead of a fixed ease, from two named springs.
How it works, files and sources
_sass/_springs.scss defines a confident spring (ζ 0.8, settling in 0.48 s with 1.5 % overshoot) for buttons and menus and a playful one (ζ 0.55, 0.9 s, 12.6 %) for the desk toys. bin/spring_easing.cjs samples a damped oscillator’s step response for any damping ratio and period into a CSS linear() curve, describing springs by bounce and duration as Apple’s spring guidance does. The theme menu enters with @starting-style, and reading disclosures open through ::details-content. Browsers without linear() keep a similar cubic Bézier.
- Files
-
-
_sass/_springs.scssThe two named springs. -
bin/spring_easing.cjsTurns ζ and T into a `linear()` easing.
-
- Sources
- Known limits
-
- Springs stay on direct manipulation and discrete toggles; ambient motion keeps eases or stops.
Cross-document view transitions
Shipped · Sep 5, 2026
Same-origin navigations crossfade the page root while the navbar and progress line hold still.
How it works, files and sources
_includes/head.liquid emits @view-transition { navigation: auto } on every page except those that manage their own arrival, such as the AI profile and the homepage. _sass/_transitions.scss times the root crossfade with the standard motion tokens and turns it into an instant swap under reduced motion, as do browsers without support. The visual harness is unaffected because it navigates with page.goto and disables animations.
- Files
-
-
_includes/head.liquidEmits the view-transition rule per document. -
_sass/_transitions.scssRoot crossfade timing.
-
- Sources
- Known limits
-
- The root crossfade is still marked a prototype awaiting my live click-through in all four themes.
- Next moves
-
- Needs a decision A live click-through in all four themes, then keep or remove the root crossfade.
A scroll-driven laptop
Shipped · Oct 12, 2026
On the revamp page a CSS laptop opens on the February homepage, then its screen wipes along an orange seam to an October capture of the same view.
How it works, files and sources
_sass/_revamp-device.scss maps scroll progress through the section to the lid angle and the wipe with animation-timeline: view(), which runs on the compositor with no scroll listener. It plays only when the cinematic layer is live and the browser supports scroll timelines; everywhere else the laptop stands open on today’s page with a February button.
- Files
-
-
_sass/_revamp-device.scssThe scroll-driven laptop. -
_projects/website-revamp.mdMarkup and the two captures.
-
- Sources
- Known limits
-
- Worth repeating only where a single comparison carries the story.
One switch that stills everything
Shipped · Oct 13, 2026
Pause motion in the theme panel makes the reduced-motion query match, so every surface that already honors reduced motion stills through the same path.
How it works, files and sources
assets/js/theme.js installs in the head, before any module asks, and lays the pause over matchMedia("(prefers-reduced-motion: reduce)") while keeping each caller’s own list and change events. The 3D home, duh, P, the footer coast, the research sketch and the cinematic scenes all still without a switch of their own, and CSS loops key off html[data-motion].
- Files
-
-
assets/js/theme.jsThe pause laid over the reduced-motion query.
-
- Sources
- Known limits
-
- A first version shared one native list among every caller, and P’s playground then sometimes never heard reduced motion end.
A glass lip under the navigation bar
Shipped · Oct 13, 2026
A 10-pixel lip under the navigation bar refracts what scrolls beneath it, like the rounded edge of a glass slab.
How it works, files and sources
assets/js/liquid-glass.js builds a displacement map whose green channel encodes a vertical offset, so the lip’s top rows show the page 4 px lower and a passing line stretches as it slides under. The lip belongs to the header and anchors to the bar’s bottom edge, because the bar’s view-transition-name makes it a backdrop root. Chromium draws SVG filters inside backdrop-filter; Firefox, Safari, reduced transparency, more contrast and forced colors keep the frosted bar.
- Files
-
-
assets/js/liquid-glass.jsDisplacement map and engine checks. -
_sass/_navbar.scssThe bar, its frost and the lip.
-
- Known limits
-
- Chromium only. A 14 px, 22-scale lip smeared text into a glitch, and a glass theme menu let other words show through, so the menu stays solid.
- Next moves
-
- Needs a decision Try glass where it floats over imagery or the 3D home rather than over paper.
A comic panel that prints in
Shipped · Oct 13, 2026
The HCI Spooder-Man gallery brings each slide in as offset color plates that come into register on twos, with Ben-Day dots receding.
How it works, files and sources
assets/js/spooder-project.js splits the new slide into red, green and blue plates with an SVG filter and brings them into register over three held drawings at 12 per second (9, 5, then 2 px), while magenta and cyan dots recede from 0.85 to 0.25 (_sass/_spooder-verse.scss). A hard cut replaced the cross-fade, so two captions never show at once. Only this page loads it, and reduced motion gets the instant swap with no filter.
- Files
-
-
assets/js/spooder-project.jsPlate offsets and timing. -
_sass/_spooder-verse.scssPrint styles and dots.
-
- Known limits
-
- Kept to slide changes; a print-in on scroll or idle would turn a signature into noise.
Side threads, title drift and gradient fields
Retired · Sep 5, 2026
Scroll-progress threads beside the homepage and publications, gradient fields behind page titles, titles drifting against the page, and a papers-first publications order.
What it was and why it was retired
The first cinematic slices added a thread that filled with scroll and lit the section being read, a slow gradient field behind page titles, headings that drifted slower than the page, and a papers-first reorder of the publications page.
- Why it was retired
- In my review they read as confusion rather than value. They moved without meaning anything, and the Wall of Rejection went back to the top of publications.
74d6c7134
Moves in this system: Skip link, tokens and a cinematic layerA pinned Research Focus storyA scroll-driven laptop, no scriptSprings, named by their dampingA comic panel that prints inGlass that bends only where it can
Structure and wayfinding
The homepage is an editorial thesis and routing hub, the projects index an evidence surface, and every site experiment tells its own story with a reproduction guide and, now, a technical record.
The homepage research sequence
Shipped · Oct 5, 2026
The homepage moves from the opening through the thesis, the full Research Focus, the selected publications and compact updates, then students and contact.
How it works, files and sources
_pages/about.md and the includes in _includes/home/ render the sequence once: the thesis explained once, the complete focus section rendered once under #focus, the papers, then three dated updates. The thesis is fully legible text; an earlier scroll-controlled word opacity was removed. On October 12 a repeated fact strip left the hero.
- Files
-
-
_pages/about.mdHomepage content, thesis and selected paper order. -
_layouts/home.liquidHomepage layout. -
_includes/home/hero.liquidThe opening and the 2D | 3D desk.
-
- Known limits
-
- On 1280 × 800 laptops the portrait column sets the hero’s height, so the thesis still sits below the fold.
An explicit, tested paper order
Shipped · Oct 12, 2026
The homepage lists selected papers in a declared order, with DesignWeaver first, instead of bibliography file order.
How it works, files and sources
selected_paper_order in _pages/about.md is rendered with jekyll-scholar’s nocite tag and --cited_in_order in _includes/home/news_publications.liquid, and test/test_selected_paper_order.py keeps it equal to the bibliography’s selected entries. Order is a claim, because items at the start of a list are remembered best.
- Files
-
-
_pages/about.mdThe declared order. -
_includes/home/news_publications.liquidRenders papers in that order.
-
- Sources
Project cards that open in place
Shipped · May 27, 2026
A project card opens where it is with a cancelable FLIP transition and returns to the same place; on phones the site experiments become one swipeable row.
How it works, files and sources
assets/js/project-cards.js measures the card before and after opening and animates one cancelable clock of 430 ms, read from the shared motion token. A new click cancels stale motion, and reduced motion jumps to the final layout. Below 768 px the experiment grid becomes one scroll-snapped row of cards 84 % wide, so the next one peeks, with a count of the card most in view and arrow-key support; an expanded card widens to the full row.
- Files
-
-
assets/js/project-cards.jsFLIP opening and the phone row count. -
_includes/projects.liquidCard markup, origin lines and outcomes. -
_data/project_cards.ymlCard teasers, origin and evolution lines. -
_sass/_design-details.scssThe phone row.
-
- Sources
A curated command palette
Shipped · Oct 12, 2026
The ⌘K palette offers curated starting routes and Do actions that call the site’s own controls.
How it works, files and sources
_includes/search_data.liquid.js is rendered inline on every page, with Start here routes, writing, projects, contact, and Do actions for the four themes, the 3D home, the AI-readable page, duh and Build Rhythm. Each action clicks or calls the existing control, so it can never disagree with it. The curated data had silently fallen back to the plugin’s defaults after al-folio v1 stopped building _scripts/.
- Files
-
-
_includes/search_data.liquid.jsCurated palette data and actions.
-
- Known limits
-
- It renders on the AI profile too, so its text is held to the publication validator’s rules.
Experiments that tell their own stories
Shipped · Jul 15, 2026
Each site experiment has a case study with its question, change, evidence and limit, a reproduction guide, and a place in the projects index by debut date.
How it works, files and sources
The projects index groups site experiments once and sorts them by debut_date. Each case page leads with what it is and why, then before/after evidence and a technical disclosure, and offers a downloadable reproduction guide from assets/downloads/site-experiments/. test/test_site_experiments.py checks their chronology, cards, voice and guides.
- Files
-
-
_pages/projects.mdThe projects index and its groups. -
assets/downloads/site-experiments/Reproduction guides. -
test/test_site_experiments.pyChronology, card and story checks.
-
An origin glint on widgets
Retired · Jul 15, 2026
A tiny mark beside seven widgets that was meant to stay quiet at rest and lead curious readers to each widget’s origin story.
What it was and why it was retired
The mark went through four versions: a dot and line, a hover disclosure, a story ↗ wordmark, and an at-rest glint. The include remains only for the hidden blog portal, which reveals its origin after discovery.
- Why it was retired
- Each version tried to be both invisible and findable. The dot and line read as a slider, the disclosure confused, the wordmark was too loud when repeated, and the glint read as a stray rendering speck.
84083f827 - Files
-
-
_includes/widget_origin_link.liquidKept only for the blog portal’s reveal.
-
- Sources
A homepage build ledger
Retired · Jun 18, 2026
The homepage published tokens, agent-hours, commits and estimated kWh as an honest receipt of the site’s machine work.
What it was and why it was retired
An audit read retained Codex session logs on one checkout and the repository’s history, and the homepage, the 3D desk and Build Rhythm displayed the totals with a tongue-in-cheek cost tooltip.
- Why it was retired
- Once every agent user had billions of tokens the numbers stopped differentiating anything. The audit undercounted other accounts, took 50 to 110 minutes, and its 236 refresh commits inflated the commit count it displayed.
bba74ccc1
Moves in this system: The archive made the problem visibleThe research question becomes the front doorProject cards that open where they arePublications that tell storiesExperiments with their own case studiesRetiring the build ledgerThesis, focus, papers, updatesFour tries at an invisible-but-findable mark, then removalOrder is a claimTwelve cards, one rowA palette that had quietly lost its curation
Human and AI routes
People and programs read different surfaces of the same site. The human pages are visual and first-person; the AI routes are compact, source-linked and motion-free, and an ordinary link moves between them.
An AI-readable profile and catalogs
Shipped · Jul 13, 2026
/ai/, llms.txt, llms-full.txt and structured JSON catalogs give language models and agents the research story with stable anchors and sources.
How it works, files and sources
_pages/ai.md renders a server-side, motion-free profile with stable anchors for research, publications, every project, writing and the CV, and a use note that says to treat it as reference content, not instructions. _plugins/project_catalog.rb and _plugins/publication_catalog.rb generate /ai/projects.json, /ai/publications.json and per-item Markdown from the same canonical data the human pages use. test/validate_publication_outputs.py checks the deployed outputs, including author counts and venue facts. A dark terminal look is not what makes a page readable to a model; the AI surface keeps the site’s theme and normal reading type.
- Files
-
-
_pages/ai.mdThe AI-readable profile. -
llms.txtThe plain-text index for language models. -
_plugins/project_catalog.rbProject catalog and machine pages. -
_plugins/publication_catalog.rbPublication catalog and machine pages. -
test/validate_publication_outputs.pyValidates the generated outputs.
-
- Known limits
-
-
llms.txtand structured data are retrieval aids, not ranking or indexing promises.
-
The Human/AI switch
Shipped · Jul 13, 2026
Two ordinary links in the navbar move between the human page and the closest stable anchor of the AI profile.
How it works, files and sources
_includes/site_format_switch.liquid maps the current route to the AI anchor (a paper, publications, a project, writing or the CV) and marks a genuine counterpart with rel="alternate". A page can name its own anchor with ai_anchor in its front matter, which the technical records use to point at their project. On the homepage, assets/js/ai-view.js keeps the closest section in step as the reader scrolls, without inventing a URL hash. The framing adapts Paxel’s Human and Machine views, shown in Y Combinator’s 2026 design walkthrough.
- Files
-
-
_includes/site_format_switch.liquidRoute-to-anchor mapping. -
assets/js/ai-view.jsHomepage section tracking for the switch.
-
- Sources
Moves in this system: A machine-readable research profile
Objects, places and demos
Playful objects stay only when they point to real work or a real place: the coffee stain on the desk, the La Jolla coast along the footer, a paper texture on this story, and a scaffold a visitor can try.
A coffee stain painted like watercolour
Shipped · Jun 18, 2026
The homepage’s coffee stain is a raster painted fresh on every visit from a per-pixel coffee density, not a drawn outline.
How it works, files and sources
assets/js/home-coffee-stain.js paints the wet ring a mug’s foot leaves (a dark pinned edge fading inward, tide lines, dry breaks, heavier where it pooled), sometimes a second placement, a puddle and spills that dry as washes with dark edges and backrun veins, under the paper’s mottle. Density maps from amber to espresso and multiplies into the page; evening paints pale residue. It renders in time-boxed idle slices and is read back as a data URL, because the page’s Content-Security-Policy admits data: images but not blob: ones. ?coffeeSeed= reproduces one stain. The ring follows Deegan and colleagues’ account of capillary flow, and the washes Curtis and colleagues’ computer-generated watercolor.
- Files
-
-
assets/js/home-coffee-stain.jsThe seeded density painter.
-
- Sources
- Known limits
-
- The stain is a desk cue; it must stay quiet enough that any text it crosses reads easily.
La Jolla along the footer
Shipped · Sep 14, 2026
A small Blender-authored coast with campus, home and village groups fills the footer and reveals its buildings left to right as it comes into view.
How it works, files and sources
_includes/la-jolla-footer.liquid loads the coast only near visibility, at most 30 fps with capped pixel density, and pauses offscreen and under reduced motion, with a composed fallback image. The buildings form an authored place collage above a sourced map atlas, and the light on the Design and Innovation Building’s third floor is a personal detail, not an occupancy feed. Small screens can pan the coast instead of shrinking every landmark.
- Files
-
-
_includes/la-jolla-footer.liquidFooter scene and fallback. -
docs/la-jolla-footer.mdGeometry, provenance and evidence.
-
- Known limits
-
- The footer still uses the older full-image ambient-occlusion pass; replacing it changes pixels and needs a matched comparison.
- Next moves
-
- Needs a decision Move the footer to the horizon-based contact light the 3D home uses, judged with a matched A/B.
A static paper texture for this story
Shipped · Aug 16, 2026
The revamp story sits on a seeded paper texture rendered once, with no runtime shader.
How it works, files and sources
bin/generate_paper_texture.cjs renders the texture from Paper Shaders’ Paper Texture in @paper-design/shaders 0.0.80, and the recipe beside the asset records the seed, parameters, output hash, generator, license and vendor hashes. It is a story-specific accent, not a sitewide background.
- Files
-
-
bin/generate_paper_texture.cjsDeterministic texture generation. -
assets/img/website-revamp/paper-texture.recipe.jsonSeed, parameters and hashes.
-
- Sources
A dimensional scaffold to try
Shipped · Oct 13, 2026
The DesignWeaver page lets a visitor pick tags in four dimensions and watch a prompt rebuild as a fixed sentence, each phrase underlined in its dimension’s color.
How it works, files and sources
assets/js/designweaver-scaffold.mjs reads the four dimensions and the tags from a study session in the CHI 2025 talk (_data/designweaver_scaffold.yml). It opens on that session’s selection and the prompt DesignWeaver wrote, and any change rebuilds the prompt as a fixed sentence. The label changes from DesignWeaver’s prompt to “Your prompt, as a fixed sentence”, and the note says that the real system uses a language model and that nothing is sent or generated. Without JavaScript the session’s selection still shows. Scaffolding here is Wood, Bruner and Ross’s sense: support that lets a novice do what they could not alone.
- Files
-
-
assets/js/designweaver-scaffold.mjsThe palette and the fixed-sentence prompt. -
_data/designweaver_scaffold.ymlDimensions and tags from the study session. -
_sass/_designweaver-scaffold.scssPalette styles.
-
- Sources
- Known limits
-
- A fixed sentence is terser than the model’s prose, so the counter reports tags across dimensions rather than words.
Moves in this system: La Jolla along the footerThe scaffold, small enough to tryA coffee ring, by the physics of dryingA stain that looked like glass
Visual QA and checks
Evidence matches the decision being made. One screenshot answers a taste question, a four-viewport checkpoint proves a direction, and the full matrix is for a release. Contracts and validators catch what screenshots miss.
Three visual QA lanes
Shipped · Aug 16, 2026
A fast lane takes one screenshot on a running preview, a checkpoint lane runs explicit routes at four viewports, and the release lane runs everything.
How it works, files and sources
test/visual/iteration.config.js defaults to one route, one 1440 × 1000 light viewport, one worker and no trace, refuses a second route, and fails closed after a one-minute budget. test/visual/checkpoint.config.js refuses to run without an explicit VISUAL_ROUTE_IDS list and covers 1440 × 1000, 1280 × 800, 768 × 1024 and 390 × 1000 in light and dark. Captures go under .jekyll-cache/visual-qa/ so Jekyll does not rebuild in response to its own QA output. Scene cases run in named groups with one worker (bin/run_visual_scene_group.cjs).
- Files
-
-
test/visual/iteration.config.jsThe one-screenshot lane. -
test/visual/checkpoint.config.jsThe explicit-route checkpoint lane. -
test/visual/public.config.jsThe public release suites. -
bin/run_visual_scene_group.cjsOne-worker scene groups.
-
- Sources
- Known limits
-
- Linux Chromium can reject later captures after image-heavy and WebGL work share a process, so the public site and scene suites run as separate processes.
Retry after the page settles
Shipped · Oct 12, 2026
A failed screenshot retries only after two animation frames and an idle callback, at 250, 750 and 1,500 ms.
How it works, files and sources
test/visual/helpers.js waits for the page’s current work to finish before a capture, approximating a settled event loop with requestAnimationFrame followed by requestIdleCallback, then retries transient capture errors with backoff; any other error fails at once.
- Files
-
-
test/visual/helpers.jsSettle-then-retry capture.
-
- Sources
- Known limits
-
- The retry hides nothing structural, but a page that stalls a two-core runner also stalls a slow phone.
Invariants on every public route
Shipped · Oct 12, 2026
Every public route keeps one h1, the skip link as the first tab stop, and alt text on every image.
How it works, files and sources
A one-off audit first checked that all 60 route-and-width pairs already met the rules; then three assertions in exercisePublicRoute in test/visual/sitewide.spec.js started keeping them. The skip link and main landmark came with the September foundations pass.
- Files
-
-
test/visual/sitewide.spec.jsPublic route assertions. -
_layouts/default.liquidThe skip link and main landmark.
-
- Known limits
-
- One h1 per page is a convention for heading navigation, not a WCAG requirement.
- Next moves
-
- Ready Behavioral accessibility next, such as focus return after dialogs and disclosures.
Contracts, validators and the override audit
Shipped · May 25, 2026
A style contract, a publication-output validator, Python policy tests and the al-folio override audit guard what screenshots cannot see.
How it works, files and sources
test/style_contract.js checks starter wiring, plugin and visual-workflow contracts and the type ceiling. test/validate_publication_outputs.py checks the built AI outputs. The Python suite in test/ checks content contracts such as the site experiments, selected paper order and math gating. Local overrides of gem-owned files are recorded with hashes in .al-folio-overrides.yml through bundle exec al-folio upgrade overrides audit, so upstream drift is visible after an update.
- Files
-
-
test/style_contract.jsStarter and style contracts. -
test/validate_publication_outputs.pyBuilt AI output checks. -
.al-folio-overrides.ymlRecorded local overrides of gem-owned files.
-
- Sources
Moves in this system: Retry after the page settlesTest the invariants the site already keeps
Design memory
Judgment is carried across sessions and models in writing: living heuristics, an experiment backlog with my decisions, a studio log of moves, agent skills that point to those documents, and these technical records.
Living design heuristics
Shipped · May 22, 2026
One human-readable file holds the decision order, the spine, type, color, motion, content and QA rules, and the lessons from my reviews.
How it works, files and sources
WEBSITE_DESIGN_HEURISTICS.md is the canonical source, published on the site as a teaching artifact. The August pass named the spine “Less, but more Sirui” and added the signature copy locklist; on September 5 the file went from 443 to 328 lines with every canonical heading kept. Agent skills read it by heading instead of copying it, and test/test_agent_guidance.py keeps the canonical headings in place.
- Files
-
-
WEBSITE_DESIGN_HEURISTICS.mdThe living heuristics. -
test/test_agent_guidance.pyCanonical headings and skill links.
-
- Sources
An experiment backlog with decisions
Shipped · Aug 16, 2026
Each visual or interaction idea gets a hypothesis, route, reference, licensing, budget, evidence, my decision and a revisit trigger; removed experiments stay on record.
How it works, files and sources
docs/design-experiment-backlog.md is the durable queue. An entry moves to Completed only with evidence and my decision, and removed ideas such as the origin glint and the build ledger keep their reasons, because knowing why an idea failed is part of the site’s professional vision.
- Files
-
-
docs/design-experiment-backlog.mdThe experiment queue.
-
A studio log of moves
Shipped · Oct 12, 2026
Each design move is a card with its frame, dimensions, move, backtalk, reframe and a concept with its primary source.
How it works, files and sources
docs/studio-log-2026-10.md keeps the loop from Schön’s The Reflective Practitioner: make a move, let the material talk back, reframe. The dimensions name the variables being moved, which turns a vague request into something to reason about. The log is unpublished; the design histories in these records condense it.
- Files
-
-
docs/studio-log-2026-10.mdThe October studio cards.
-
- Sources
Agent skills that route to the living documents
Shipped · Jun 29, 2026
Short repository skills tell coding agents which document and heading to read for critique, writing, the desk scene and upstream sync.
How it works, files and sources
.codex/skills/ holds concise overlays such as website-design-critique and portfolio-writing-voice. They point to the heuristics, the backlog and the scene brief by heading and do not duplicate the long rules.
- Files
-
-
.codex/skills/The repository skills. -
AGENTS.mdRouting rules and the validated commands.
-
Technical records with a next-move brief
Shipped · Oct 15, 2026
Each long-running project keeps its systems, techniques, design history, open problems and sources as data, rendered as a page and served as JSON.
How it works, files and sources
_data/design_records/<slug>.yml holds a record. _includes/design_record.liquid renders it at /projects/<project>/record/, a Liquid page publishes it as JSON under /assets/json/design-records/, and bin/design_record_brief.py <slug> turns it into a brief for the next pass: the current state per system, known limits, candidate moves ranked by stated readiness, sources to read, and the constraints and tests to keep. test/test_design_records.py checks the schema, that every path is in the repository, that every source and system resolves, and that every commit exists in history.
- Files
-
-
_data/design_records/The records. -
_includes/design_record.liquidRenders a record as a page. -
assets/json/design-records/JSON endpoints. -
bin/design_record_brief.pyThe next-move brief. -
test/test_design_records.pySchema and integrity checks.
-
- Known limits
-
- The records condense the studio log and the notes by hand; a move that is never written down is missing from the brief too.
Moves in this system: Less, but more SiruiA studio log of movesTechnical records that the next pass can start from
Design history
Each move follows the loop from Donald Schön's The Reflective Practitioner: frame the problem, make a move, let the result talk back, then reframe. The dimensions are the variables the move changed. Oldest first; new moves are added at the end.
-
The archive made the problem visible
- Frame
- My site listed projects and papers, but it did not tell visitors what I was actually studying.
- Dimensions
- what a visitor learns first; number of competing elements
- Move
- Kept the public homepage as Wayback served it on February 9, so the redesign could critique a concrete page instead of a memory. The capture entered the repository on May 23 (
e4f021520). - Backtalk
- The archive is competent and crowded. Papers, projects, biography and navigation all ask for attention at once.
- Reframe
- Make the research question the front door and the interface quieter.
- Sources
-
The research question becomes the front door
- Frame
- A visitor should understand what I study before decoding my biography or the interface.
- Dimensions
- order of homepage sections; number of actions; where proof sits
- Move
- Rebuilt the homepage around the research claim, affiliation, proof routes and a few actions, with time-of-day themes (
f30191146) and a research motion sketch for Design, Evaluate, Situate. - Backtalk
- Paper, desk objects and motion stayed only where they helped a visitor understand how I design, evaluate and situate AI tools.
- Reframe
- Let the publications and experiments carry their own stories.
-
Project cards that open where they are
- Frame
- Sampling a project meant leaving the projects index and losing my place among the others.
- Dimensions
- where a card opens; what moves while it opens; how focus returns
- Move
- Project cards that expand in place with a FLIP transition and close back into the same spot.
- Backtalk
- People could follow which card opened, but scaling the whole card squeezed its text and images. Accents, takeaways, image zoom and keyframes added in July competed for attention and were removed, leaving one cancelable clock.
- Reframe
- Use one clock for opening and moving, and let reduced motion jump to the final layout.
-
Publications that tell stories
- Frame
- The publications page answered what I published, but hid the rejections and citation history behind the list.
- Dimensions
- what counts as an event; which views share one focus; whose clock a number follows
- Move
- A Steam-style Wall of Rejection with one receipt per rejection event, then a Scholar Lens (
089b29413) whose focus travels between a bibliography row, its citation chip and its annual bars. - Backtalk
- A badge can sit on several shelves without adding another event, so 38 Failure XP means four rejections. Lifetime totals and annual bars refresh on different dates, so both dates stay visible.
- Reframe
- Keep the citation list authoritative and let each view project from one record.
-
Material-Lite and an orange mark
- Frame
- Radii, shadows, focus rings and motion durations were one-off values across many partials.
- Dimensions
- token coverage; where orange may appear; mark legibility at 32 px
- Move
- Material 3-inspired tokens for radius, elevation, tonal surfaces, state layers, focus and motion, and a procedural 2D orange as the brand mark (
f08f22f19). - Backtalk
- Engraving ST into the fruit at navbar size made it read like a glossy app icon instead of a crisp site mark.
- Reframe
- Orange is identity only, and neutral surfaces carry most of the page.
- Sources
-
A machine-readable research profile
- Frame
- Language models and agents read the same decorated pages people do.
- Dimensions
- route addressability; motion; source links; typography of the machine view
- Move
- An AI-readable profile at
/ai/,llms.txtand a Human/AI switch in the navbar, built from the same canonical data as the human pages. - Backtalk
- The machine view needed reading rules of its own, written into the heuristics with it. Server-rendered, source-linked and motion-free, in the site’s normal theme and type, because a dark terminal look is not what makes a page readable to a model.
- Reframe
- Keep the two surfaces separate and connect them with ordinary links to the closest anchor.
- Sources
-
Experiments with their own case studies
- Frame
- The design thinking behind each widget was hidden behind a history icon.
- Dimensions
- where an origin story lives; what a case page leads with; reproducibility
- Move
- Each site experiment got a case study with its question, change, evidence and limit, and a downloadable reproduction guide.
- Backtalk
- The projects index now leads from each experiment back to its origin, and a reader who follows it gets the question and the limit, not merely the commits.
- Reframe
- Origin stories belong to labeled places, the projects index and the case pages, not to marks on the work.
-
Less, but more Sirui
- Frame
- The portfolio had collected containers, repeated explanations and equal-weight actions.
- Dimensions
- containers per section; type roles; repeated explanations
- Move
- Named the spine “Less, but more Sirui”, locked the signature copy, set narrative type roles, separated Human and AI reading surfaces, and added the proportional QA lanes and the experiment backlog.
- Backtalk
- Fewer type levels, containers and actions made the remaining choices feel intentional, and the heuristics became a teaching artifact rather than a wall of rules.
- Reframe
- Record uncertain ideas with a hypothesis and a revisit trigger instead of freezing the style or shipping an effect without evidence.
-
Skip link, tokens and a cinematic layer
- Frame
- I chose the cinematic tier. Walk a reader through one figure, let a card grid answer the pointer, and never take over scrolling.
- Dimensions
- which pages opt in; what plays once and what follows scroll; the still state under reduced motion
- Move
- A skip link, project navigation, spacing and motion tokens and a root view transition (
52e4b1bb7), then GSAP-based scroll scenes, a spotlight and tilt on the projects grid, the DesignWeaver scroll scene, a homepage story thread and the card-to-hero morph. - Backtalk
- My first review kept the projects index, the DesignWeaver scene, the marker and count-ups, the blog rows and the morph, and cut the side threads, the gradient field behind titles, the title drift and the papers-first reorder, because the design modification should be meaningful and add value instead of confusion (
74d6c7134). - Reframe
- When a review calls an element confusing, remove it rather than tune it.
- Sources
-
A pinned Research Focus story
- Frame
- I called the homepage scroll a bit vanilla and pointed at pear.no as a reference.
- Dimensions
- what stays pinned; what the scroll position selects; depth between layers
- Move
- On wide screens the Research Focus sketch pins beside its three lens notes and the note in view picks the lens; the thesis arrived word by word, and shallow parallax separated layers that belong together.
- Backtalk
- The pinned sketch slid into the Exploring row and left its column half empty, because a sticky grid item can travel to the end of the whole grid; it now sits in its own well (
362100480). - Reframe
- Pinned stages need their own well, and any field behind a scene must fade before its box edge.
- Sources
-
Retiring the build ledger
- Frame
- The homepage published what the site cost in machine work, tokens, agent-hours, commits and kWh, as an honest receipt.
- Dimensions
- what the number tells a reader; accounting cost; side effects on the history
- Move
- Removed the ledger, the desk tag, the Build Rhythm token surfaces and every tool behind them. One sentence now links this story and Build Rhythm.
- Backtalk
- Once every agent user had billions of tokens the numbers stopped differentiating anything. The audit read one machine’s logs, and 236 refresh commits inflated the very commit count it displayed.
- Reframe
- Bring a number back only with an exact, privacy-safe source and a story in which the number changes what a reader understands.
-
A research studio, then one type family
- Frame
- The homepage needed concrete selected work before the narrative, and a calmer reading surface everywhere.
- Dimensions
- order of the homepage; display and reading faces; reading column
- Move
- The homepage led with the research question and selected work, a Newsreader display face sat over Inter, and the 3D desk became an optional inhabited home.
- Backtalk
- Two days later I replaced the mixed serif and sans system with Inter throughout, organized by spacing and a small hierarchy (
9c746dfe9). - Reframe
- Spend type contrast through size and weight within one family.
- Sources
-
Thumbnails stay in color
- Frame
- Fun-project thumbnails sat in grayscale until hover, after an approved reading enhancement.
- Dimensions
- thumbnail color at rest; consistency across the index
- Move
- Removed the grayscale treatment; every thumbnail keeps its original color in every state.
- Backtalk
- Mixed grayscale and color thumbnails made the project index read as inconsistent.
- Reframe
- An interaction reference is not a reason to hide the work.
- Sources
-
Thesis, focus, papers, updates
- Frame
- The thesis and the Research Focus were split and repeated, and the thesis faded in word by word with scroll.
- Dimensions
- section order; repetition; legibility of the thesis
- Move
- One sequence (opening, thesis, the full focus once, selected publications, compact updates, students, contact), with the thesis as fully legible text.
- Backtalk
- The first published iteration ended its visual regression run with two failures, a stale manual-scroll direction and lazy print images that had not loaded before capture; the follow-up repaired both.
- Reframe
- Explain the thesis once and render the focus once.
-
A studio log of moves
- Frame
- Design moves were scattered across commits, backlog entries and conversations, so the next session started from scratch.
- Dimensions
- fields per move; where the primary source sits; how a move links to code
- Move
- Started a studio log of cards with frame, dimensions, move, backtalk, reframe and a concept with its primary source.
- Backtalk
- Forty cards in four days, and the dimensions turned vague requests into variables someone could reason about.
- Reframe
- Turn the record itself into the design space that the next move starts from.
- Sources
-
The screenshot that ran out of memory
- Frame
- CI visual checkpoints had been red since the companion landed, because Linux Chromium could not capture the full HCI Spooder-Man page.
- Dimensions
- decoded bitmap bytes per page; image count; capture area
- Move
- The page serves the 480, 800 and 1400-pixel WebP variants CI already generates, sized to how large each image is shown.
- Backtalk
- Transfer fell from 33 MB to 5.2 MB. One 3,838 × 1,588 PNG decodes to about 24 MB of RGBA whatever its 4 MB file size, which is why the failure looked random. The fixed page passed 16 of 16 runs in the Linux Playwright image.
- Reframe
- File size and memory are different budgets; serve pixels at display size.
-
Four tries at an invisible-but-findable mark, then removal
- Frame
- A tiny origin glint beside seven widgets read as a stray rendering speck in my October 12 review.
- Dimensions
- salience at rest against on engagement; repetition; target size; wording
- Move
- Removed the mark; the projects index line that already had a visible label became a plain text link.
- Backtalk
- The history is the evidence. A dot and line read as a slider, a hover disclosure confused, a story wordmark was too loud when repeated, and the glint read as an artifact. Each tried to be both invisible and findable.
- Reframe
- Route-finding belongs to labeled places, not to decorations on the work.
- Sources
-
Sixty-eight characters, measured in the wrong unit
- Frame
- Posts and case studies ran about 95 characters per line at 1440 px.
- Dimensions
- characters per line; the font each element measures ch against; alignment with figures and the contents rail
- Move
- One centered 33.5rem column for prose, headings and the post header, with figures and code reaching 68ch.
- Backtalk
- The first try, max-width 50ch, narrowed paragraphs but not headings; a later rule also reset the margins, and the contents layout pinned prose to the left.
- Reframe
- Size the column once in rem and let every element inherit it; keep ch for single-font contexts such as code.
- Sources
-
Order is a claim
- Frame
- DesignWeaver, the flagship paper, sat third on the homepage because the bibliography lists papers in file order.
- Dimensions
- display order against data order; one source of truth; test coverage
- Move
- A declared
selected_paper_orderrendered withnociteand--cited_in_order, with a test that keeps it equal to the selected entries. - Backtalk
-
nociteworks inside a loop because jekyll-scholar resolves a key as a variable before treating it as a literal. - Reframe
- Ordering is an explicit, tested decision instead of a side effect of file order.
- Sources
-
A poster frame for a moving figure
- Frame
- Two Physion previews were 2.2 MB and 6.9 MB GIFs that every homepage and publications visitor downloaded and watched loop.
- Dimensions
- bytes per listing page; motion by default against on request; descriptive alt text
- Move
- A first-frame poster through responsive WebP variants, which zooms into the original and offers to play the animation.
- Backtalk
- The publications page fell from 7.3 MB to 4.9 MB. A closing brace inside a Liquid output tag ended it early until the filter moved into an assign.
- Reframe
- Motion on request also serves reduced-motion visitors without a special case.
- Sources
-
Retry after the page settles
- Frame
- Visual checkpoints failed with “Unable to capture screenshot” on a different route each run.
- Dimensions
- main-thread idleness at capture time; retry count and backoff; runner cores
- Move
- The harness waits for two animation frames and an idle callback, then retries at 250, 750 and 1,500 ms; any other error still fails at once.
- Backtalk
- The next run was green across every site and scene job, the first fully green visual checkpoints since the companion landed.
- Reframe
- Keep the retry and still make the page cheaper, because work that stalls a two-core runner also stalls a slow phone.
- Sources
-
Record art 40 times larger than its frame
- Frame
- The homepage preloaded four 1024 px record-art PNGs (6.4 MB) for a disc never shown wider than about 340 CSS pixels.
- Dimensions
- device pixels needed; bytes; behavior when a variant is missing
- Move
- The record art points to 800 px WebP variants of 31 to 46 KB each, with the originals as a fallback.
- Backtalk
- The homepage fell from 12.3 MB to 6.1 MB on the local preview, and the 2D and 3D records behave as before.
- Reframe
- What remains is the 3D coast model, three.js, CSS and fonts.
-
Test the invariants the site already keeps
- Frame
- Before adding assertions, check whether the site already meets them, so a test records reality instead of hope.
- Dimensions
- h1 count; the first tab stop; images without alt; 30 routes at two widths
- Move
- A one-off audit, then three assertions on every public route.
- Backtalk
- All 60 route-and-width pairs already passed; the test now keeps them that way.
- Reframe
- The next accessibility work is behavioral, such as a global motion pause and focus return.
-
Twelve cards, one row
- Frame
- On a 390 px phone the twelve site-experiment cards stacked into about 6,650 px of scrolling.
- Dimensions
- section height; how much of the next card shows; position feedback; an expanded card’s width
- Move
- Below 768 px the grid becomes one scroll-snapped row with each card 84 % wide, a “1 / 12” count and arrow keys; an expanded card widens to the full row.
- Backtalk
- The section shrank to about 690 px, and the disclosure test still finds every story with no clipping or overflow.
- Reframe
- The desktop grid stays; a carousel pays off only where the column is one card wide.
- Sources
-
A scroll-driven laptop, no script
- Frame
- This page told its before and after in captions, and the change itself was easy to miss.
- Dimensions
- scroll progress; lid angle; wipe position; which capture each moment shows
- Move
- A CSS laptop pinned while the reader scrolls, opening on the February capture and wiping along an orange seam to an October capture of the same view.
- Backtalk
- The first wipe showed the seam during the lid opening, because an animation’s
bothfill applies its first keyframe early, and the base’s extra width overflowed phones. Both were fixed. - Reframe
- Use the pattern only where a single comparison carries the story.
- Sources
-
Springs, named by their damping
- Frame
- Buttons and menus moved on fixed 180 ms eases, so a press felt like a fade rather than something physical.
- Dimensions
- damping ratio; period; which controls get a bouncier spring
- Move
- A confident spring for buttons and menus and a playful one for the desk toys, generated as CSS
linear()curves. - Backtalk
- Measured in the browser, one disclosure grows from 46 to 477 px in about 160 ms, overshoots to 481 and settles.
- Reframe
- Keep springs on direct manipulation and discrete toggles; ambient motion stays on eases or stops.
- Sources
-
A palette that had quietly lost its curation
- Frame
- The ⌘K palette offered light, dark and system themes this site does not have, and none of its curated starting routes.
- Dimensions
- which data the palette renders; what each action controls; what every page may say
- Move
- The curated data moved to an inline include, with Do actions that call the site’s own controls.
- Backtalk
- The first push broke the deploy, because the palette now renders on the AI profile and its email action used an address the validator forbids, and a comma split one theme description into a nonsense fifth action.
- Reframe
- Run the production build and the output validator before pushing anything that renders on every page.
-
A comic panel that prints in
- Frame
- The Spooder-Man gallery cross-faded like any slideshow, though the page is a love letter to Spider-Verse.
- Dimensions
- plate offset; dot strength; drawings per second; caption overlap
- Move
- Each new slide comes in as red, green and blue plates that move into register over three held drawings at 12 per second, while halftone dots recede.
- Backtalk
- The first version also stepped the old cross-fade, and on its first drawing both captions showed at once; a hard cut keeps one caption.
- Reframe
- Keep the effect on change only.
-
Glass that bends only where it can
- Frame
- I asked for liquid-glass chrome, and the bar was already frosted, so the question was what glass could add on a site that is mostly text on paper.
- Dimensions
- where refraction is visible; bevel height and displacement; legibility; engine support; scroll cost
- Move
- A 10 px lip under the navigation bar refracts what scrolls beneath it, in Chromium only.
- Backtalk
- A 14 px lip smeared text into a glitch, a glass theme menu let words show through, and moving the frost into a pseudo-element broke it outright, because the bar’s view-transition name makes it a backdrop root. Scrolling stays at 60 fps with it on or off.
- Reframe
- Glass reads as glass over images and motion, not over paper.
- Sources
-
The scaffold, small enough to try
- Frame
- The DesignWeaver page described dimensional scaffolding in words and figures, and a visitor never got to feel what it does to a prompt.
- Dimensions
- fidelity to the study; what the page itself writes; what a reader sees change
- Move
- A palette with four dimensions and the tags from a CHI 2025 talk session, opening on that session’s prompt and rebuilding a fixed sentence on any change.
- Backtalk
- A word counter backfired, because the fixed sentence is terser than the model’s prose and adding an eighth tag dropped the count from 26 words to 16; it now counts tags across dimensions.
- Reframe
- The new copy joins the batch for my review.
- Sources
-
A sun you can drag, and a switch that stills everything
- Frame
- Four theme buttons felt static. I asked for a control that feels like the day itself and syncs the 3D scenes, and for a good-looking way to pause motion.
- Dimensions
- where an hour lives; which surfaces follow every move; contrast of continuous color; how many places must learn about paused
- Move
- A sun arc that picks any minute and previews it across the page, the footer coast and the 3D home, and a Pause motion switch laid over the reduced-motion query.
- Backtalk
- Continuous color stays out of text. The first sky glow at 17 % opacity was invisible, while 30 % reads as light without touching contrast, and one of the tests expected 1:20 pm plus four hours to be evening.
- Reframe
- Keep the panel’s four stops; they are both the quick choice and the test contract.
- Sources
-
A coffee ring, by the physics of drying
- Frame
- The coffee stain was a broken ring of dashes, closer to a stamp than a stain, and it nearly vanished in the evening theme.
- Dimensions
- rim sharpness; tide lines; a second ring; drips; strength in light and dark themes
- Move
- The ring drawn the way one dries, with a continuous rim sharp outside and fading inward, tide lines and drips, and a lighter dried palette in the evening.
- Backtalk
- The first interior turned into pale clouds and its fiber displacement sawtoothed the rim.
- Reframe
- The stain is a desk cue, not a feature.
- Sources
-
A stain that looked like glass
- Frame
- I found the redrawn stain lamer than before. In place it read as a pale glass disc, with a perfect thin outline and bubble-like drips.
- Dimensions
- medium; how coffee spreads as it dries; the paper beneath; main-thread cost; what the security policy allows
- Move
- A raster of per-pixel coffee density, painted fresh on every visit as washes with dark edges, backruns and granulation, in time-boxed idle slices.
- Backtalk
- The first rasters were thin and grey, and the puddles looked like stickers until they dried like watercolour. The first integration showed nothing, because the Content-Security-Policy admits data URLs but not blob URLs.
- Reframe
- Keep the stain quiet enough that any text it crosses stays easy to read.
- Sources
-
Technical records that the next pass can start from
- Frame
- I asked for the technical details, key source code and citations to be recorded behind each long-running project, so later agents can build on what has been done.
- Dimensions
- record schema; what a person reads and what a program reads; how a next move is proposed; integrity checks
- Move
- Three records as data, each rendered as a page beside its project, served as JSON and turned into a next-move brief by a script, with a test for paths, sources, systems and commits.
- Backtalk
- Compiling them surfaced real gaps, such as the clifftop planting swaying on its own rule outside the shared wind field. A record route under a project made the AI link point at a missing anchor, so pages can now name their AI anchor.
- Reframe
- Append each new move to its record when it ships, and let the brief rank what to try next.
Open problems
-
Does the redesign help visitors understand the research?
Every comparison here is design history under fixed captures, not a study. Comprehension needs real visitors, a task and a baseline, and the old site exists only as an archive.
Candidate moves
- A small first-glance test with research peers and prospective students, asking what I study after 15 to 30 seconds, on the archived and current homepages.
-
Foundation work still open from the September roadmap
The focus mixin migration, the accessibility spec additions and purge parity as a documented lane each touch many partials or the deploy path, so they keep losing to visible work.
Candidate moves
- Migrate focus styles to one mixin, partial by partial, with the overrides audit after each.
- A documented lane that builds, purges and serves
_sitefor the checkpoint suite.
-
Retell the remaining project stories
Each story deserves the medium its evidence supports, and a uniform template would flatten them. Deep rewrites go one route at a time with fixed before and after captures.
Candidate moves
- Playful provenance stories first, keeping each joke and moving custody details behind it.
- Research artifacts next, leading with the question and the canonical publication.
-
A continuous illustrated world below the desk
A scroll-scrubbed backdrop carrying the desk’s horizon and coast down the homepage needs artwork, must stay quieter than text, and must not move the largest contentful paint away from the hero.
Candidate moves
- A first generated or authored asset reviewed at four viewports, with its prompt, model, date and license recorded first.
Read
-
Margin notes for long posts
No post or project uses footnotes yet, so margin notes have nothing to show.
Candidate moves
- Build sidenotes with the first post that needs footnotes.
-
Bring the homepage onto the shared tokens
The homepage’s own partial predates the Material-Lite and type tokens and is a high-conflict file shared with the desk scene, so changes there need one writer at a time.
Candidate moves
- Adopt the spacing and focus tokens in
_sass/_home.scssin a dedicated pass, checked with the iteration and checkpoint lanes.
- Adopt the spacing and focus tokens in
Before changing anything
Read first
-
WEBSITE_DESIGN_HEURISTICS.mdThe canonical design memory. Decision order, the spine, type roles, motion, content and QA. -
docs/design-experiment-backlog.mdEvery experiment’s hypothesis, evidence, my decision and its revisit trigger, including the removed ones. -
docs/material-lite-revamp.mdThe token grammar and the brand-mark rules. -
docs/site-experience-roadmap.mdThe September staging, the Lighthouse baseline and what is still open. -
docs/studio-log-2026-10.mdThe October moves in full, with dimensions, backtalk and concepts. -
docs/BOUNDARIES.mdWhat this fork owns and what belongs to the al-folio gems. -
AGENTS.mdThe validated commands, the parallel-work contract and proportional visual QA.
Keep intact
- Decision order. Research meaning, credit, accessibility and a working route come before first-glance clarity, which comes before proof proximity, interaction state, and finally atmosphere and delight.
- Keep the signature copy exact, including “Making AI tools that sharpen design judgment.” and “Design, Evaluate, Situate.”
- Brand orange is identity only. Links, controls and focus use the active time-of-day accent, and the four palettes carry contrast.
- Every effect is a complete still page under reduced motion, Pause motion, without a fine pointer, and under automation unless the URL carries
?cinematic=live. - No scroll or wheel hijacking, cursor trails or ambient loops; parallax only between two layers that belong together.
- Human and AI routes stay separate surfaces. AI routes are compact, source-linked and motion-free, and the switch between them is an ordinary link.
- Research figures stay whole and uncropped, with declared dimensions.
- When a review calls an element confusing, remove it rather than tune it.
- New font sizes use a type role; the raw
font-sizeceiling in the style contract stays at 333. - Iterate on one route, state and viewport; checkpoint explicit routes at four viewports; run the full matrix only for a release.
- Render-cost and weight changes must not change the pixels a visitor sees.
Keep these checks green
-
test/style_contract.jsStarter wiring, type roles and the raw font-size ceiling, plugin and visual-workflow contracts.npm.cmd run lint:style-contract -
test/visual/sitewide.spec.jsPublic routes at four viewports, one h1, the skip link first, alt text on every image, overflow and console errors.npm.cmd run test:visual:checkpoint -
test/visual/iteration.config.jsThe one-screenshot iteration lane on an already running preview.npm.cmd run test:visual:iterate -
test/validate_publication_outputs.pyThe AI profile, llms.txt and the structured catalogs.python test/validate_publication_outputs.py _site -
test/test_site_experiments.pySite-experiment case studies, their chronology, cards and reproduction guides.python -m unittest test.test_site_experiments -
test/test_design_records.pyThese technical records, their paths, sources, commits and links.python -m unittest test.test_design_records
Sources
- Internet Archive. Wayback Machine capture of dylantao.github.io, February 9, 2026, 01:34:29 UTC. web.archive.org/web/20260209013429/https://dylantao.github.io/
- Donald A. Schön. The Reflective Practitioner: How Professionals Think in Action. Basic Books, 1983. www.hachettebookgroup.com/titles/donald-a-schon/the-reflective-practi...
- Maruan Al-Shedivat and contributors. al-folio, a Jekyll theme for academics, version 1. github.com/alshedivat/al-folio
- Rasmus Andersson. Inter typeface (SIL Open Font License). rsms.me/inter/
- Google. Material Design 3. m3.material.io/
- Paper. Paper Shaders,
@paper-design/shaders0.0.80 (Apache-2.0). shaders.paper.design/ - GreenSock. GSAP 3.15 and ScrollTrigger, under the GSAP Standard License. gsap.com/
- Jeffrey Heer and George Robertson. Animated Transitions in Statistical Data Graphics. IEEE Transactions on Visualization and Computer Graphics 13(6), 2007. idl.cs.washington.edu/files/2007-AnimatedTransitions-InfoVis.pdf
- Edward Segel and Jeffrey Heer. Narrative Visualization: Telling Stories with Data. IEEE Transactions on Visualization and Computer Graphics 16(6), 2010. idl.cs.washington.edu/files/2010-Narrative-InfoVis.pdf
- Venkatesh Sivaraman and Adam Perer. Counterpoint: Orchestrating Large-Scale Custom Animated Visualizations. CMU Data Interaction Group, 2024. dig.cmu.edu/publications/2024-counterpoint.html
- Frank Elavsky. Chartability, heuristics for accessible data visualization. www.frank.computer/chartability/
- W3C. CSS View Transitions Module Level 2. www.w3.org/TR/css-view-transitions-2/
- W3C. Scroll-driven Animations. www.w3.org/TR/scroll-animations-1/
- W3C. CSS Scroll Snap Module Level 1. www.w3.org/TR/css-scroll-snap-1/
- Apple. Animate with springs, WWDC23. developer.apple.com/videos/play/wwdc2023/10158/
- W3C. CSS Values and Units Module Level 4, font-relative lengths. www.w3.org/TR/css-values-4/
- Bennet B. Murdock. The Serial Position Effect of Free Recall. Journal of Experimental Psychology 64(5), 1962. doi.org/10.1037/h0045106
- Peter Pirolli and Stuart Card. Information Foraging. Psychological Review 106(4), 1999. doi.org/10.1037/0033-295X.106.4.643
- W3C. Understanding Success Criterion 2.2.2, Pause, Stop, Hide, WCAG 2.2. www.w3.org/WAI/WCAG22/Understanding/pause-stop-hide.html
- W3C. Understanding Success Criterion 1.4.3, Contrast (Minimum), WCAG 2.2. www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html
- WHATWG. HTML Living Standard, event loops and the processing model. html.spec.whatwg.org/multipage/webappapis.html#event-loops
- W3C. Understanding Success Criterion 2.4.1, Bypass Blocks, WCAG 2.2. www.w3.org/WAI/WCAG22/Understanding/bypass-blocks.html
- W3C. Understanding Success Criterion 1.1.1, Non-text Content, WCAG 2.2. www.w3.org/WAI/WCAG22/Understanding/non-text-content.html
- Ben Shneiderman. Direct Manipulation: A Step Beyond Programming Languages. IEEE Computer 16(8), 1983. doi.org/10.1109/MC.1983.1654471
- Robert D. Deegan, Olgica Bakajin, Todd F. Dupont, Greg Huber, Sidney R. Nagel and Thomas A. Witten. Capillary Flow as the Cause of Ring Stains from Dried Liquid Drops. Nature 389, 1997. doi.org/10.1038/39827
- Cassidy J. Curtis, Sean E. Anderson, Joshua E. Seims, Kurt W. Fleischer and David H. Salesin. Computer-Generated Watercolor. SIGGRAPH 1997. grail.cs.washington.edu/projects/watercolor/
- W3C. Filter Effects Module Level 2, the backdrop root. drafts.fxtf.org/filter-effects-2/
- W3C. Filter Effects Module Level 1, the
feDisplacementMapfilter primitive. www.w3.org/TR/filter-effects-1/ - David Wood, Jerome S. Bruner and Gail Ross. The Role of Tutoring in Problem Solving. Journal of Child Psychology and Psychiatry 17(2), 1976. doi.org/10.1111/j.1469-7610.1976.tb00381.x
- W3C. Media Queries Level 5, the
prefers-reduced-motionfeature. www.w3.org/TR/mediaqueries-5/#prefers-reduced-motion - Jeremy Howard and contributors. The /llms.txt file, a proposal for language-model-readable site indexes. llmstxt.org/
- Jing Yu Koh, Robert Lo, Lawrence Jang, Vikram Duvvur, Ming Lim, Po-Yu Huang, Graham Neubig, Shuyan Zhou, Russ Salakhutdinov and Daniel Fried. VisualWebArena: Evaluating Multimodal Agents on Realistic Visual Web Tasks. ACL 2024. aclanthology.org/2024.acl-long.50/
- Eve Bouffard with Aaron Epstein. Y Combinator’s 2026 design walkthrough, demonstrating Paxel’s Human and Machine views. youtu.be/VbqaL_eHhKY?t=433
- Pear. pear.no, a reference for one pinned scene whose copy changes as the reader scrolls. pear.no/
- React Bits. Chroma Grid and Folder components, studied as interaction references; no code was copied. reactbits.dev/components/folder
- Microsoft. Playwright, browser automation for the visual harness. playwright.dev/
Compiled on October 15, 2026 by Anthropic’s Claude from the code, the living heuristics, the experiment backlog, the roadmap, the October studio log and the Git history, for Sirui Tao to review and extend.