UI Redesign + Missing images warning + Docs update - #510
Merged
Conversation
joeyballentine
commented
Jul 31, 2026
Contributor
- Redesigns the UI to look slightly better and more modern
- Fixes vulnerabilities by updating many outdated dependencies
- Adds tests, migrates from Jest to Vitest
- Adds a warning to the top of the page about the missing images (working on getting these rehosted)
- Updates docs to remove enhancr and add vapourkit
Most of the inconsistency traced back to components hand-pairing their colors (`bg-white dark:bg-fade-900`, `border-gray-300 dark:border-gray-700`), so nothing agreed across surfaces. Adds semantic tokens (surface, line, ink, ink-muted, ink-subtle) in globals.scss and exposes them to Tailwind, so components name a role rather than a color pair. Notable fixes: - Elevation was inverted in dark mode: cards were darker than the panel they sat on. The page ground is now fade-950, raised surfaces fade-850, with one shadow language instead of a 1px border under a wide shadow. - Removed the floating tinted panel that nested the page inside itself. Content sits on the ground so cards read as raised. - Model cards used two different layouts (paired thumbnails overlaid their details, standalone ones stacked below), so titles landed at different heights across a row. One layout now, with a fixed plate and detail block. - Grouped the simple tag filter by its real categories. Selection behavior is unchanged. - Added a footer; every page previously ended abruptly. - The alpha badge was an `::after` pinned into the wordmark. Removed along with the alpha notice and footer line, per maintainer request. - Model page metadata moved from a right-aligned filled-header table to a spec list; its h1 had no size class at all. Accessibility: adds a global :focus-visible ring (previously only the search input had one) and a prefers-reduced-motion block, which the existing hover transforms had no handling for. Two traps worth knowing about, since this project disables Tailwind Preflight: `border-solid` with a single-side width paints all four sides at the UA `medium` width, and CSS-module declarations override Tailwind utilities. Both are commented where they applied. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The comparison viewer is the site's core proof and was the least explained part of the page. Synchronized zoom and pan were already wired up through react-zoom-pan-pinch, but nothing indicated they existed, and neither half was labelled — a first-time visitor saw a rectangle with a handle in it. Adds shared viewer chrome used by both the comparison and standalone viewers: - Before/After corner labels on comparisons. - A zoom readout with zoom in/out and Fit controls, so the viewer is usable without a scroll wheel. - A persistent "Scroll to zoom / Drag to pan" hint, which adapts to touch and is hidden on small screens. Everything overlays arbitrary image content, so each piece carries its own scrim rather than relying on the surface beneath it. Other fixes on this page: - The carousel's prev/next arrows sat at the far edges of the page, a long way from the thumbnails they page. They are now one centred group with an image counter, and the group wraps rather than overflowing narrow screens. - Metadata was one flat list, giving nine training fields the same weight as the license, which is the field that decides whether a model can be used at all. Split into Model, Rights, and Training. - Tags sat unlabelled above the description and read as decoration; they now sit under a "Good for" heading. - Added a back link to the model list, and a "Using this model" block that points at the existing how-to. The page previously ended after the download with no indication of what runs the file. The standalone viewer needed an explicit content size once wrapped for the chrome: its image is sized in percentages, so the content box otherwise resolved to zero height. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The controls were anchored bottom-right, which is exactly where image captions are pinned — 290 of the 1625 example images carry one — and where example images frequently have their own text baked into the pixels. Controls and the gesture hint are now one group anchored bottom-left, so the four corners are: Before / After on top, controls bottom-left, caption bottom-right. The caption is capped at 55% width and ellipsised so a long one cannot run left into the controls, and the hint drops out below 900px where the two would otherwise meet in the middle. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…-aware Two related layout problems. Most model descriptions are a sentence or two while the metadata sidebar runs the height of the viewport, so the content column ended in a tall void. And the related-model sections sat full-width below both columns, where they read as an afterthought. Moves collections and similar models into the content column, so it always has body and its length tracks the sidebar's. That only works because the card grid no longer keys its column count off the viewport: it used fixed counts at screen-width breakpoints, which would have rendered four cards inside the narrower column and crushed them. It now uses `repeat(auto-fill, minmax(280px, 1fr))`, which is container-relative and reproduces the previous column counts at full page width — verified at 4 columns on the home page at 1440px, 3 in the model page column, 2 at 768px and 1 at 390px. Also drops the "you run it in an upscaling application" explanation. This audience arrives already knowing what a model file is; the two guide links it wrapped now stand on their own. Columns no longer stretch to the row height, so neither pads itself out to match the other. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This reverts commit 775a475.
Move MetadataTable/MetadataRow/isTrue out of the page file into src/elements/components/model-page/metadata-table.tsx so Task 5 can import from it, then wrap the Training rows in a new TrainingDetails disclosure. Training provenance is reference material that 179 of 669 models fill in for only 1-2 of 8 fields, so it now collapses by default and opens automatically in edit mode.
Move the resources sidebar block into DownloadsBlock, rendering it only for multi-resource models in read mode (9% of models) while always rendering it in edit mode. Fixes a latent bug in the process: the per-resource edit handler replaced entries by loop index, which breaks once resources are skipped; it now matches by sha256 like the delete path already did.
The empty-block early return applied to both modes. In edit mode this hid Add Resource for zero-resource models (e.g. models added without a main file via add-model.tsx), the only place in the app that adds a resource - the same regression class already reverted once in this plan (61c561d). Guard now applies to read mode only.
Remove the two-column grid. The identity strip (name, scale/arch badges, authors, primary download) and the image stage now run full container width, prose and metadata sit in a centred 56rem reading column, and the collections/similar card grids stay full width below it. The strip replaces the primary resource with the same semantics as DownloadsBlock — match on sha256, drop resources left with no URLs — so both surfaces edit the resource array identically. In edit mode the primary resource deliberately appears in both: the strip is the page's primary action, the block is the management surface that owns Add Resource. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This reverts commit a3f9966.
…ption Reverts the single-column restructure (a3f9966) at the maintainer's request — the two-column layout reads better. The void it was meant to solve is closed a different way: the training disclosure moves out of the sidebar into the content column, directly under the description, where two thirds of models had run out of body while the sidebar kept going. Two regressions the revert exposed, both fixed here: - `DownloadsBlock` was passed `skip={1}` because the reverted task was going to surface the primary resource in an identity strip above the image. With that strip gone, single-resource models had no download button at all. Back to `skip={0}`, and the "Other downloads" heading becomes "Downloads", shown only when there is more than one resource or edit mode is on. - `SpecCards` used `sm:grid-cols-2`, which is right in a full-width column and wrong in a ~220px sidebar — it wrapped "ESRGAN" mid-word and split "No Liability & Warranty" across three lines. The cards stack now. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The rail sat on bare page background below a bordered image box, so the space between them read as a gap rather than as the image's controls. The card chrome moves from the image box to a wrapper holding both, so the stage is one bordered surface containing the image area and the rail, divided by a hairline. The rail keeps no background of its own — it inherits the stage's, which is what makes it read as part of the same object. `EmptyStage` drops its own border, radius and background for the same reason: it now renders inside the stage card, and keeping them would have nested a card inside an identical card on the 265 models with no images. The mobile full-bleed moves to the wrapper with the rest of the chrome; verified at 390px that margin-left still resolves to -16px from --page-gutter, the side borders and radius still drop, and the rail rides along inside it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Descriptions can embed images, and 16 models do. Nothing was scaling them:
Tailwind Preflight is disabled in this project, so the usual global
`img { max-width: 100% }` does not exist anywhere. A 1440px-wide comparison
strip rendered at full size, ran out of the description column and under the
metadata sidebar.
Adds `max-width: 100%; height: auto` for `img` and `video` inside rendered
markdown, keeping aspect ratio while fitting the column.
Also gives `pre` and `table` `overflow-x: auto` for the same class of problem —
one model already has a markdown table, and a wide one would otherwise push the
column open rather than scrolling within itself.
Scoped to the markdown container rather than set globally, because the image
carousel sizes and transforms its own images deliberately.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The "Showing" / "Subject" / "Purpose" labels were <h4> elements sitting directly under the page <h1>, so the home page outline read H1 -> H4 -> H2. They label a set of filter controls rather than a section of the document, so they are now plain spans and the surrounding div is a labelled role="group" — which is the accurate semantics and also announces the grouping that the headings never did. No visual change: .group is a grid, so the spans blockify exactly as the headings did. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`.main` set `padding: 0 var(--page-gutter)`, and the shorthand also sets padding-top/bottom to 0. Because this module is injected after Tailwind's utilities, that silently beat the `py-4` on the markup — so every page not using `.padded` (model page, docs, palette, collections) rendered with no vertical padding at all, sitting 2px under the 66px fixed header. `.main` now uses padding-left/right longhand and owns no vertical rhythm, and the non-wrapper branch uses a real `.standard` class instead of the dead utility. The model page's "All models" link now clears the header by 26px instead of 2px, and those pages get their bottom padding back. `.padded` pages are unchanged: 24px top, 40px bottom, verified on /. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The rail below the image becomes a three-part toolbar: zoom docked left, thumbnails centred, fullscreen right. Fullscreen keeps the toolbar so images stay switchable without leaving it. Two things worth knowing: The zoom controls are portaled into the toolbar rather than having their state lifted into the carousel. `onTransformed` fires every frame of a pan or zoom, so hoisting the scale would re-render the whole stage — including the TransformWrapper being dragged. The portal moves only where the controls land in the DOM; their state and render cost are unchanged. The rail used to render only when `!readonly || images.length > 1`. Zoom now lives there, so that condition would have removed zoom from every single-image model — the common case. It now governs just the thumbnails, and the toolbar renders whenever there is an image. Fullscreen is keyed off an attribute React sets from `fullscreenchange` rather than the `:fullscreen` pseudo-class: one source of truth, no prefixed selector for older Safari, and the state can be exercised in a test. The toolbar takes layout space there instead of floating, so the caption pinned to the same corner can't end up behind it. Also unifies the image caption with the Before/After chips — it was a corner-pinned gradient banner at 1.125rem next to small inset chips — and sets box-sizing on the toolbar, since Preflight is off and `w-full` plus `px-3` otherwise pushes it wider than the stage, which clips it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The <details> and the MetadataTable inside it carried identical chrome — same 12px radius, same 0.8px border, same surface background — so expanding it revealed a second rounded box sitting a hairline inside the first. MetadataTable now takes `flush` to drop its card chrome, and the training disclosure passes it, since the <details> around it is already the card. The sidebar spec cards are unaffected and keep theirs: that is the caller that genuinely needs the table to be its own card. The summary/content divider and the row separators are unchanged. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Tailwind's Preflight is disabled here, so <button>, <select>, <input> and
<textarea> still render with native OS chrome — a grey face and an `outset`
border that follow `color-scheme` rather than the theme. Read-mode controls
all set their own background, so it never showed. Edit mode is built almost
entirely from bare elements, which is why it looked unthemed: 22 of the 43
buttons on a model page rendered as grey OS buttons, and every select and
input was a native widget.
Buttons are reset to transparent with no border; selects, inputs and
textareas get the surface background, the line-strong border and the
control radius, so they read as part of the same system as everything else.
Two deliberate choices:
Every rule is wrapped in :where(), which has zero specificity. This file is
emitted after `@tailwind utilities`, so a plain `button { ... }` selector
here would beat `bg-accent-600` on every styled button in the app. Verified
that a `bg-accent-600` button keeps its background.
Padding is not reset. Preflight would zero it, but plenty of controls have
no padding class of their own and rely on the UA value; zeroing it collapses
them onto their icons.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`.tagRow` limits tags to a single row with `max-height` plus `overflow: hidden`. In edit mode the tag popover is absolutely positioned inside that row, so it was clipped out of existence — the button looked dead rather than broken. The card already had a `:has([data-headlessui-state='open'])` escape for its own `overflow: hidden`. Either clip alone is enough to hide the panel, so the row needs the same treatment. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TpogQiNgM8Lg8PTTfTGSNk
Edit mode only appears when the local web API is reachable, so its UI never got a look. It had accumulated hand-paired `gray-*`/`dark:gray-*` classes that tracked neither the theme tokens nor each other, buttons with no styling at all, and a `className="btn"` referring to a class that is not defined anywhere in the project. edit-chrome.ts is now the single convention, built from the same semantic tokens as read mode. Popover panels get a real border and `shadow-pop` — `dark:bg-black` had them merging into the page — and their fields get the same micro-type labels as the metadata table. Also drops `border: none` from the shared tag/menu-item rule. That rule existed to undo the OS border on bare buttons, which the `:where()` foundation now handles; leaving it in would have beaten the border utilities, since SCSS modules are injected after Tailwind's utilities. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TpogQiNgM8Lg8PTTfTGSNk
A quarter of the 669 models carry four or more tags, but the card showed one row and clipped the rest with nothing to say so. The row now holds two lines — p90 is five tags, so most models fit outright — and anything past that becomes a `+N` chip listing the remainder in its tooltip. Cards grow from 352px to 376px. The cut-off is measured, not a fixed cap: names run from "Anime" to "Compression Removal", so any constant is wrong for most cards. Widths are read once while every tag is still in the DOM and cached, so the fit is arithmetic and a resize costs no layout thrash. Edit mode keeps the full editor. Its popover lists every tag with its selected state, so the clamp never puts one out of reach. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TpogQiNgM8Lg8PTTfTGSNk
Two things were pushing content apart. The tag row was a max-height, so a card with one row of tags pinned that row to its bottom edge while its neighbour's first row sat a whole row higher — the leftover opened up as a hole between description and tags. And the card's height was hardcoded to the worst case, so every card in the page reserved room for a two-line title it might not have. The tag row is now a fixed two-row plate with its content aligned to the top, so the first row lines up across the grid and the leftover falls below the tags as padding. The card drops its fixed height entirely: the grid already stretches every card in a row to the tallest of that row, which is all the alignment this needed, and it lets a row of short cards be short. Contiguous tags — dropping `margin-top: auto` — was tried and rejected: it removes the hole but leaves the tag rows visibly ragged across a row. The lazy-load placeholder gets its own floor, since it is empty and would otherwise collapse and drag the grid below it upwards. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TpogQiNgM8Lg8PTTfTGSNk
The fixed two-row plate lined the first row up across the grid, but it reserved an empty row under every card that only had one. Back to a cap: one row stays one row, and the card follows it. `margin-top: auto` stays off. Pinning the tags to the card's foot is what turned a short tag row into a hole between the description and the tags in the first place. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TpogQiNgM8Lg8PTTfTGSNk
The redesign locked the thumbnail to 176px and made the details block the flex-grower. That inverted the original: whatever the details did not need collected under the tags as dead space, and no amount of tuning the tag row could fix it, because the space was never the tag row's. Now the details block takes exactly what its content needs and the thumbnail grows into the rest, so a card with one row of tags spends the difference on a bigger image. 176px is its floor, not its height. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TpogQiNgM8Lg8PTTfTGSNk
Two causes, both mine. The edit button got a 1px border in the edit-mode cleanup. `box-sizing` is content-box here (Preflight is off), so that made its row 26px while the pills beside it stayed 24px — 54px of content in a cap that was exactly 52px. The border is gone; the pills it sits among have none either. The cap itself was the deeper problem: `2 rows + 1 gap` is the exact height of two rows, so anything a pixel tall anywhere in the row spills. It is now `2 rows + 2 gaps`, which is precisely where a third row would begin — slack for a tall pill, and still no way for a third row to peek through. Edit mode is no longer capped at all. It renders every tag rather than a `+N` chip, so a tag-heavy model genuinely needs a third row; the card has no fixed height, so it just grows. That replaces the `:has([open])` escape hatch, which was solving the same clipping from the other end. Verified across every card on a page in both modes: no row's scrollHeight exceeds its box. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TpogQiNgM8Lg8PTTfTGSNk
Jest was never a declared dependency — `npm test` worked only because it resolved transitively, and `ts-jest` peer-depended on a package that was not installed. The suite was also Node-only, so nothing could render a component. Vitest runs the existing 54 snapshot tests unchanged; the snapshot format carried over as-is. Testing Library and jsdom cover the rest. Notes on the setup, since none of it is guessable: - `oxc`, not `esbuild`: Vite 8 transforms with rolldown. tsconfig says `jsx: preserve` for Next's benefit, which leaves raw JSX in the test output, so the transform is overridden here rather than in tsconfig. - `vite-plugin-svgr` mirrors the `@svgr/webpack` rule in next.config.js; without it anything importing the logo fails to resolve. - jsdom for every suite, not just component ones, so nobody has to remember an environment docblock. - No injected globals — tests import from vitest, which keeps `tsc --noEmit` honest over the test files. - `@types/node` was pinned at 18 while the engine and CI run 22; Vite refused to resolve against it. `fitCount` moves out of ClampedTags into lib/tag-fit. jsdom has no layout, so the arithmetic was the only testable half, and it is the part most likely to break silently. New coverage is deliberately weighted to what this branch changed: metadata-table's `flush`, training-details' nesting, and the tag clamp. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TpogQiNgM8Lg8PTTfTGSNk
Three majors: 13.2 -> 16.2.12. React stays on 18 (Next 16 supports ^18.2 || ^19) so the framework move is attributable on its own; React 19 is a separate step whenever you want it. Build: `next export` was removed in Next 14. The static export is a different build from the local one — it has no server, so the API routes edit mode talks to cannot exist in it — and that distinction used to be the second CLI step. It is now an env var the build script sets, which keeps API routes working in dev. Verified: the export still warns and skips them exactly as `next export` did. Bundler: Turbopack is the default from Next 16, so the SVGR rule is declared for both bundlers; the webpack half still applies under `--webpack`. Confirmed SVGs still inline as components in dev and build. Storybook 7 does not support Next 16 and pinned React 18 hard enough to block the whole install, so it goes to 10. `addon-essentials`, `addon-interactions`, `blocks` and `testing-library` are no longer separate packages — all folded into core in v9 — and `@storybook/types` is gone. eslint-plugin-storybook is the exception: it stays on 0.12, because v10 needs ESLint 9's flat config. ESLint moves 8.32 -> 8.57 only because `sourceCode.getScope()` landed in 8.37. Type errors the newer checker found, all real: - `ReactNode` gained `bigint` in the React 18.3 types, which broke an `in` narrowing in the markdown text extractor. - `SideBarItem` is imported as a type and also declared as a component in the same file; `isolatedModules` needs the import to say which. - TypeScript 5.7 made `ArrayBufferView` generic, so hashSha256's hand-written union admitted buffers Web Crypto rejects. `BufferSource` is the type the API actually asks for. And one latent bug. tsconfig's `es6` target was too low for the checker to report Unicode property escapes used without the `u` flag, so the search tokenizer's boundary regexes were not matching Unicode categories at all — `\p` degraded to a literal `p`, making the letters p, P and Z word boundaries while missing real punctuation. Raising the target to ES2022 surfaced it; the flag is now set. All 54 tokenizer snapshots are unchanged by the fix, so no search behaviour moved on the current corpus. The snapshots are rewritten because Vitest keys them differently from Jest (`describe > test` rather than `describe test`). The previous commit silently wrote a second copy under the new keys and passed against those rather than verifying the originals; the two sets were compared entry by entry and were byte-identical before the dead Jest-format ones were pruned. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TpogQiNgM8Lg8PTTfTGSNk
`npm audit` reported 26, and `npm audit fix --force` offered to "fix" them by installing next@9.3.3. Splitting the tree with `--omit=dev` put six in the production graph and the rest in lint/build tooling that never reaches a user. Of the six, `next` had no advisory of its own — it was flagged only via two of its dependencies. Both needed overrides rather than a parent upgrade: Next pins postcss 8.4.31 (path traversal, arbitrary .map file disclosure) and ships sharp 0.34.x (four libvips CVEs). No version of Next resolves either, which is why npm's only suggestion was a downgrade. react-syntax-highlighter goes to 16 for the PrismJS DOM-clobbering advisory — the one that genuinely reaches users, via code blocks in rendered markdown. react-markdown and remark-gfm come along because v16 expects them. That migration has two breaking changes worth naming. v9 stopped passing `level` to heading components, so headings bind their tag at module scope instead of switching at render time. And it removed the `inline` flag on code, which is now structural: `pre` renders the fenced block and never renders its `<code>` child, leaving `code` reached only when inline. Tests cover both directions, since nothing else would have caught it. Production tree is now clean. The remaining 38 are all devDependencies. Also drops the "All models" back-link from the model page, now that main's nav carries a Models link. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TpogQiNgM8Lg8PTTfTGSNk
The 38 remaining findings were not 38 problems. Almost all of them were a single advisory — brace-expansion's unbounded-expansion DoS — reaching eslint, stylelint, storybook and the rest through minimatch and glob. npm attributes it to every tool that transitively depends on it, which is why the count looked alarming and why every suggested fix was a major version bump of an unrelated tool. Patching brace-expansion at the root clears all of them, with no ESLint 9 flat-config migration and no stylelint 16 upgrade. Six low findings remain, all one root cause: elliptic, reached through the webpack polyfill plugin @storybook/nextjs uses. Its advisory range is `*` — every published version is affected, so there is nothing to upgrade to. It is dev-only and never reaches the exported site. `npm audit fix --force` "resolves" it by installing @storybook/nextjs@7, which does not support Next 16 and does not fix elliptic either. Verified after the overrides: types, lint, 125 tests, `next build`, and a full Storybook build. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TpogQiNgM8Lg8PTTfTGSNk
enhancr's last release was 0.9.9 in June 2023 and its last commit was January 2024 — roughly two and a half years dormant. The repo is not archived and carries no deprecation notice, which is why it still read as current, so the entry now says what the dates are rather than just asserting it. Moved rather than deleted: people still have it installed and the entry explains what replaced it. VapourKit fills the same slot — fast TensorRT video upscaling — and is actively released (v0.16.1, May 2026). GPL-3.0, free, ONNX models over TensorRT or DirectML, and it bootstraps its own VapourSynth environment instead of expecting you to build one. Windows only, which is worth saying next to Upscayl's Linux focus. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TpogQiNgM8Lg8PTTfTGSNk
Two unrelated things the dev server was complaining about, plus one ask. Sass: `@import` is removed in Dart Sass 3.0. All twelve became `@use ... as *`, which keeps every call site unchanged, so this is a module-system migration rather than a rename. theme.scss needs `@forward './colors'` because `@use` does not re-export — its own comment already described itself as re-exporting colors, which `@import` did for free and `@use` does not. The `if()` in the `themed` mixin is deprecated too, now that CSS has an `if()` of its own. It picked between `&` and nothing depending on whether the mixin was called nested or at the top level; that is now an explicit `@if &` with both branches written out. `next build` emits zero Sass warnings. The notice lives in the page shell rather than being a dismissible toast: someone landing on a model page from a search engine needs the context as much as someone arriving at the home page, and dismissing it would hide the explanation for the very thing they are about to notice. It carries its own amber tokens — caution, not danger — since the theme had nothing between accent and plain text. Remove the component and its use in PageContainer once the images are recovered. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TpogQiNgM8Lg8PTTfTGSNk
No em dash, no "work is underway", no "somewhere that will last". Short sentences, plain verbs, and it says what actually happened rather than narrating around it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TpogQiNgM8Lg8PTTfTGSNk
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TpogQiNgM8Lg8PTTfTGSNk
The datasets page arrived from main built against the pre-redesign models page, so it kept a gradient masthead, the small search bar and a card copied from the old model card. Masthead, search and empty state now match the models page: one accent word instead of a gradient, the large search bar with a count in its placeholder, and the empty state as a card with a clear-filters button rather than loose centred text. The dataset card imported the redesigned model-card module while still carrying `border-gray-300 bg-white shadow-lg` and a `.paired` class that no longer exists. Those were dead weight — a CSS module beats a utility, so the module's own border, surface and shadow were already winning. Its type, author line and tag row now follow the model card, including the two-row clamp with a `+N` chip. Two things syncing the page exposed: the filter row said "All models" on the datasets page, and the placeholder read "Search 1 datasets". Also drops the second sentence from the footer blurb. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TpogQiNgM8Lg8PTTfTGSNk
joeyballentine
force-pushed
the
redesign-attempt
branch
from
July 31, 2026 07:03
47097b4 to
5f1c46b
Compare
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.