Redraw the hero, retire the automaton, and rebuild the catalog - #20
Merged
Conversation
The hero texture was a Conway automaton: pretty, but random, permanently in motion, and it never said anything about eggzec. astral.sh does the opposite behind its headline — the logo is one filled shape revealed through an alpha track matte of rounded bars whose widths grow from zero on staggered in-points, with trimmed strokes tracing in alongside. It plays once and resolves into the mark. This is that construction in eggzec's own geometry. The egg silhouette from brand/eggzec-mark.svg clips a stack of kiwi bars that grow out from the centre line and then swell to close the gaps; stepped violet traces run in from outside the frame and spark magenta where they land on the outline; the nine byte cells punch in last. Bar easing is read off the reference's own keyframes. It is one SVG plus CSS keyframes, delays driven by a --i index per element, so JS only builds markup and flips animation-play-state when the host scrolls in. No animation loop, no canvas, no per-frame work once it settles, and reduced motion gets the finished frame. Also drops the automaton references from the 404 copy and the README, and scopes positioning to the SVG rather than the host so the component works in an in-flow strip as well as an absolute panel. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The plate behind the hero was the egg mark building itself. Pretty, but it said nothing: the logo is already in the nav, and drawing it twice is decoration rather than content. What the site is actually about is the numerics, so that is what the plate draws now. The anchor is ∇ℒ, traced out of brand/icons/nlpql.svg — the gradient of the Lagrangian, which is literally what that solver differentiates. The nabla is outlined and then filled through a bar matte, the way the reference reveals its own mark; the script L is a run-merged bitmap in the icon, so it is kept as blocks and written on stroke by stroke. Around it: a contour plot with a descent stepping to the optimum, a residual curve falling to tolerance, a Wiener sample path for the SDE solvers with pollen suspended off it, a block of binary, and the methods set as equations — gradient descent, Ito, Gauss-Kronrod. All of it is set in eggzec Block, the display font, extended with the nine maths glyphs the equations needed. So every glyph on the plate is drawn on the same grid, with the same merged runs and quarter turns, as the nabla beside it. `bitmapPath` is now exported and reads its grid from the spec instead of assuming 5x7, which is what lets those glyphs exist. Two things worth knowing: The pollen is the only thing still moving once the plate resolves. It drifts on three staggered keyframe tracks, transforms only, and stops dead under prefers-reduced-motion. Placement transforms and animated transforms cannot share an element. A CSS transform *replaces* the SVG attribute rather than composing with it, so every glyph that carries a translate/scale is wrapped in a `<g>` and the animation runs on the path inside. Without that the whole binary block collapsed onto the origin, stacked on top of itself. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sixteen of the nineteen repositories are scientific computing, so that claim stays. But ogrep, bb and gnspy are not numerics, some of it is Go rather than Python, and the hero admitted none of that — the lede opened "We build the numerical layer" and never came back from it. The headline now runs to four lines. Block lettering fits every line to one rendered width by solving for tracking, so lines have to stay in a similar character range: TOOLS on its own would have been stretched to the width of COMPUTING AND and read as broken. 11/10/13/16 is the split that holds. Knockouts move with it, to the N of OPEN and the T of TOOLS. Four lines also want less height than three, so the display is held back from the full measure rather than run edge to edge. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The plate carries a few grains off its Wiener path. This is that at page scale: a fixed canvas behind every section, holding pollen in water. The page scrolls past it rather than dragging it along, which is what looking through a glass actually looks like. Each grain integrates a damped random walk — momentum, plus a fresh impulse every frame — rather than replaying a keyframe loop. That matters for how it reads: a looped path oscillates and the eye locks onto the period, while an integrated walk wanders and never repeats. The cursor is a disturbance in that water. Grains inside its radius are pushed off it with a force that falls away with distance, and they excite: brighter, swollen, spun up, and switched from their soft dot to the sharp pixel form. Excitement decays on its own, so a grain is back to drifting about a second after the cursor has left. Two things that needed bounding. Push is capped and speed is clamped, or a fast cursor flings grains off screen and the field thins out. And the void the cursor carves is left to refill by diffusion rather than by pulling grains home — that is what the walk is for, and a restoring force would have made it read as elastic instead of suspended. One canvas, one loop, one pass per frame; it stops with the tab, and under reduced motion it never starts at all — that case gets a single static scatter, which keeps the texture and drops the movement. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
They were reading as content: pixel squares and crosses big enough to look deliberate, competing with the plate rather than sitting behind it. Now they are small circles and nothing else — at this size anything with a corner reads as an artefact — fainter, and denser to compensate. Renamed from pollen to motes on the way through. The plate's grains off the Wiener path are the pollen; these are page dust, and having one word for both made the two hard to talk about. Dropping shape and rotation also drops the per-speck transform stack: the paint pass is now one arc each, no save/restore. Position was already right — a fixed layer at a negative z-index sits behind every section and behind the hero plate, which is its own stacking context. Nothing needed moving; they just needed to stop shouting. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The rename to motes updated the markup but not the stylesheet: the class selector stayed .pollen while the canvas started emitting class="motes". With no rule matching, the canvas lost position, z-index and sizing, and fell back into normal flow at the top of the document — above the header, drawing specks over it. That is what shipped in the previous commit. The edit that renamed it matched on LF while the file is CRLF, so the replacement silently did nothing. Typecheck and build both passed, since neither has any idea whether a class name resolves. Also masks the field out of the band the header occupies. The bar is only 78% opaque with a backdrop blur, so once the canvas was behind it again, specks still read through the glass as though they were on it — and at the top of the page there is no content behind the bar, so they were the only thing showing through. The mask measures against the tallest, unscrolled header height, so the exclusion holds when it shrinks. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Content pass across the whole site. Catalog. polpack, NULAPACK, sparse_grid and cordic are deprecated and gone. Every project now carries the name it should be read as — PyDOE, MCERP, SOERP, PySwarm, NLPQL, SDEPack, SmolPack, Kronrod, Vatic — while ad, bb, gnspy, ogrep and spinterp keep their lowercase names because that is what they are called. New icons for kronrod, smolpack, spinterp and vatic; the other nine already matched the assets exactly. kronrod and spinterp are published and were not marked as such, so PyPI goes from ten to twelve. PyOpt, bb and ogrep have same-named packages on PyPI that belong to other people, so they stay unclaimed. Every count on the site is derived from the catalog, so all four stats moved on their own: 15 projects, 12 packages, 10 docs sites, 4 maintainers. Used by. The shipping carousel listed our own packages back to us, which proves nothing. It now lists the projects that depend on them, read off GitHub's dependency graph and checked one repository at a time against the API: NASA, LLNL, Sandia, LANL, IBM, PayPal, TerraPower, NANOGrav, CMU and others. Only pydoe (1,203 dependents), pyswarm, mcerp and soerp have any at all, and individual paper repos are filtered out — they are real dependents but they are not what "used by" is claiming. Each entry links to the repository, because a claim like this is only worth making if it can be checked. The toolchain section is gone with it. Naming our own build tools was inward-facing in the same way. Community. No avatars, no handles, no badge walls, and no per-maintainer pages: a name, what they do here, and how they describe their work. The card links to their GitHub rather than to a page about them. Saif ur Rehman added. The footer drops the maintainer mailto links and the personal email address. Copy. The hero lede stopped reciting the Fortran-and-C++ paragraph, and so did the org blurb and the meta description. The catalog page also drops its featured block — thirteen of fifteen projects carry an icon now, so "featured" separated nothing and showed the same card twice. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Which projects lead was computed from which ones had a brand icon. Nearly all of them do now — fourteen of fifteen, with gnspy's icon added here — so that signal had stopped selecting anything and the grid was just the catalog again. `LEAD` names them explicitly and in order: PyDOE, ad, PySwarm, SOERP, MCERP, bb. What a first-time visitor sees first is a decision, so it is written down as one. The nav menu takes the first four from the same list. Note the display names stay lowercase for ad and bb, per the naming pass — they are written in caps in the request the way one writes an identifier, not a label. Of the fifteen icons in the asset folder only gnspy differed from what was already committed; the rest are byte-identical. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The strip listed repository names ranked by stars, taken from GitHub's dependents index. That index turned out not to be trustworthy on its own: several entries had since dropped the dependency, and nanograv/holodeck only had it as a commented-out line. So every entry here was checked one at a time against the live dependency graph, either the repository's SBOM or its manifest on the default branch. Anything that could not be confirmed was left off however good the name would have looked, and that cost some big ones: IBM, PayPal, TerraPower and NANOGrav all appear in the dependents index but declare nothing now. Seventeen organisations survived, shown as their own GitHub avatars desaturated at build time rather than in CSS, so the strip stays even and nothing flashes colour while it loads. Orgs whose avatar is an identicon, a photograph or clipart were dropped: a logo strip only works with logos. NASA is included on the strength of pyDOE3 in GlennOPT's manifest, per the note that pyDOE3 folds back into pyDOE. Worth knowing that PyPI does not show that yet: pydoe3 1.6.2 still points at github.com/relf/pyDOE3, and pydoe2 at clicumu/pyDOE2, both separate from ours. If the merge is not finished, that one entry is the one to pull. Also drops the implementation detail from the pillars and the catalog callout, per the note that this is the org site and not a project site, takes the dash out of the used-by tooltip, updates the pyswarm tagline, refreshes the gnspy icon, and sets Noor's and Saif's descriptions. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bumped from 34px to 52px. Worth recording what the check turned up: GitHub's own "Used by" widget runs at 24px, which is *smaller* than what we had, because it is a dense sidebar list of user avatars. This is a landing-page logo strip doing a different job, so matching that number would have made visibility worse rather than better. Roughly double it is the right answer for marks meant to be recognised in passing. Hover darkens the logo and does nothing else. The strip is moving, so anything that changes size or position under the cursor reads as a glitch rather than as feedback. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
What this is
A pass over the whole site: a new hero animation, a page-wide particle
layer, and a content rebuild of the catalog, the community page and the
copy.
The hero
The background was Conway's Game of Life. It was random, permanently in
motion, and said nothing about eggzec. It is now a plate that draws
itself once and holds, built on the technique astral.sh uses behind its
own headline: a filled shape revealed through an alpha track matte of
rounded bars whose widths grow from zero on staggered in-points, with
trimmed strokes tracing in alongside. The bar easing here is read off
that Lottie's own keyframes.
The subject is what we actually build:
brand/icons/nlpql.svg, the gradient of theLagrangian. The nabla is outlined then filled through its bar matte;
the script L is a run-merged bitmap in the icon, so it is kept as
blocks and written on stroke by stroke.
curve falling to tolerance, a Wiener sample path with pollen off it,
binary, and the methods set as equations.
All of it is set in eggzec Block, the display font, extended with nine
maths glyphs.
bitmapPathnow reads its grid from the spec instead ofassuming 5x7, which is what lets those glyphs exist.
One SVG plus CSS keyframes, delays from a
--iindex per element. Noanimation loop, no canvas, no per-frame work once it settles.
Motes
A fixed canvas behind every section holding specks in water. Each one
integrates a damped random walk rather than replaying a keyframe loop,
so the drift wanders instead of oscillating. The cursor pushes them off
it and excites them; they settle about a second later. Reduced motion
gets a single static scatter and no loop at all.
Catalog
polpack, NULAPACK, sparse_grid and cordic are retired. Everything else
carries the name it should be read as. kronrod and spinterp were
published and unmarked, so PyPI goes 10 → 12; PyOpt, bb and ogrep have
same-named packages on PyPI owned by other people and stay unclaimed.
Counts derive from the catalog, so all four stats moved on their own:
15 projects, 12 packages, 10 docs sites, 4 maintainers.
Used by
The shipping carousel listed our own packages back to us. It now shows
seventeen organisations that build on them, as their own GitHub avatars
desaturated at build time.
Every entry was verified one at a time against the live dependency
graph, either the repository's SBOM or its manifest on the default
branch. The dependents index alone was not trustworthy: IBM, PayPal,
TerraPower and NANOGrav all appear in it but declare nothing now, and
nanograv/holodeckonly had it as a commented-out line. They are offthe strip.
pyDOE3in GlennOPT'smanifest, per the note that pyDOE3 folds back into pyDOE. PyPI does
not show that yet:
pydoe3 1.6.2points atgithub.com/relf/pyDOE3andpydoe2atclicumu/pyDOE2, both separate from ours. If that merge isnot finished, this is the one entry to pull.
Community and copy
No avatars, handles, badge walls or per-maintainer pages: a name, a
role, a description. Saif ur Rehman added. The footer drops the
maintainer mailto links and the personal email.
Implementation detail is out of the site copy — this is the org site,
not a project site, and the build details live in the API docs.
Checks
npm run typecheckandnpm run buildpass. Every page was renderedand inspected at each step.