Back to writing

Building Ellsworth: A Progress Report

Visualizations, museum data, and a real accessibility pass. What's shipped so far on Ellsworth, my AI-powered art history project.

EllsworthArt HistoryWeb DevAccessibility
Building Ellsworth: A Progress Report

This feature review was drafted and summarized by Claude and edited by me.

Ellsworth started as a simple idea: what happens when art history and data visualization actually talk to each other, instead of one just illustrating the other. This is a status report on what's actually shipped as of today (July 5, 2026) and is currently live on Ellsworth.ai.

As of today, the numbers:

MetricCount
Artworks36,186
Artists5,395
Movements107
Museum collections13+
Influence connections mapped192
Nationalities represented126
Span4000 BCE to present

That's a real dataset now, not a demo. Here's what's been built on top of it.


Taking accessibility seriously

This is the part I'm most proud of, because it's the least visible.

I've cared about accessibility since the earliest phases of this project, but building fast still left real gaps: no landmarks, no visible focus states, no keyboard access into what were effectively div-based navigation menus, hover-only tooltips, dialogs with no semantics for a screen reader to latch onto. That's a real problem for a public reference site, and it's easy to let slide when you're moving fast on features people can see.

So I did a full remediation pass, in eleven phases:

  1. Accessibility tooling (eslint-plugin-jsx-a11y, wired to fail the build on real errors)
  2. Landmarks and a skip-to-content link
  3. Proper heading hierarchy across every route
  4. Visible focus states everywhere a :focus was previously suppressed
  5. Full keyboard navigation for menus and interactive elements
  6. Dialog semantics: focus trapping, Escape to close, aria-modal
  7. Form labeling and error association
  8. Alt text audit across every image on the site
  9. Accessible tooltips (not hover-only)
  10. Color contrast fixes, including icon-only controls
  11. prefers-reduced-motion support for anyone sensitive to the site's animation

I didn't skip the hard part either. Timeline, Influence Network, Threads, and Palettes, the four big D3 visualizations later in this post, are fully keyboard-navigable, with focus states, aria-labels, and Enter to activate, the same as anything else on the site. I deliberately didn't bolt on a data-table fallback. A table flattens a network graph into rows and loses the entire point of Influence and Threads, which is the shape of the connections. Instead, the graphs themselves got the accessibility work directly. Color got the same treatment: movement and artist accent colors are drawn from real, per-item data rather than a fixed palette, so they run through an accessibleColor() helper that checks contrast against the background at render time, instead of being hand-picked once and hoped to hold up.

It's backed by more than a linter. CI runs eslint-plugin-jsx-a11y against every PR, and a Playwright + axe-core suite runs 14 tests across every core route in both light and dark mode. On top of that, I ran a real pass with VoiceOver, an actual screen reader, not just automated tooling, and it caught real bugs that axe never would have. Lighthouse now scores 100 on Accessibility with zero failing audits, site-wide, and I trust that number because of what it took to get there.

That's the whole accessibility remediation project done: the foundation phases, the visualization keyboard-access follow-up, a live VoiceOver testing pass, CI wired up and proven green, and now a WCAG 2.2 AA badge on the landing page that's genuinely earned.


Finding things

A few features shipped recently, all in service of the same problem: once there's this much art in one place, browsing isn't always enough. Sometimes you need to find one specific thing.

Browse by color

This might be the feature I'm most excited about in this whole update. You can now filter the entire Works gallery by color: click any color swatch, on a movement's page, on a painting's own palette, and the gallery reloads to show you the closest matches across the whole collection. Or just pick one of six broad color moods above the gallery: Warm, Cool, Earthy, Mono, Vivid, Muted. It opens up a whole new way to move through thousands of years of art, by eye, instead of by name or date.

Ellsworth Works gallery filtered to Renaissance paintings by a deep blue swatch, showing portraits including Raphael's The Niccolini-Cowper Madonna

Under the hood this is intentionally simple: it's comparing plain red, green, and blue values, not the more careful color math the Palettes page uses to build its big aggregate palettes. A filter like this needs to feel instant, so speed won over precision.

Copy CSS or JSON tokens

If you ever want the exact colors from a movement, an artist, or a single painting for something you're building, a website, a design file, anything, you don't have to eyedrop them off a screenshot anymore. Every palette on the site can be copied out as ready-to-use code: pick CSS or JSON, and it's on your clipboard.

Artwork detail panel for Joseph Henry Sharp's White Swan, showing its five-color palette and CSS, JSON, and Copy Tokens controls

Each color gets a real name instead of a bare hex code, too, pulled from a list of about 95 pigment names: burnt sienna, verdigris, Prussian blue, that kind of thing. Here's what copying a palette as CSS actually looks like, using one movement's colors as the example:

/* italian-renaissance */
:root {
  --color-brown: #8B4513;
  --color-gold: #DAA520;
  --color-lead: #1F4E79;
  --color-maroon: #8B0000;
  --color-peach: #F5DEB3;
}

This lives in three places right now: a movement's page, a painting's detail panel, and the Palettes page. It's a small feature, but honestly one I reach for myself more than I expected, whenever I want a quick, real color palette for something else I'm designing.

Search

Search covers movements, artists, and paintings all at once, and you can open it from anywhere with Cmd+K. Type a few letters and it matches names, cities, and some of the writing on movement pages. Nothing clever going on underneath, just a straightforward text match, which is exactly why it's fast.

Search command palette open with the query "the starry night," showing a matched work result and a Discover option

It also has real limits, and I'd rather say so than pretend otherwise. It won't catch typos, so searching "Monay" won't find Monet. A result that starts with what you typed isn't favored over one where your search just happens to show up in the middle of the title. And there's a real gap I want to close: if a painting has been flagged and hidden elsewhere on the site, for a bad image or a copyright problem, it can still turn up in search and link straight through. Every other part of the site already checks for that. Search doesn't, yet.

New entries do get checked before they show up anywhere, including search. When Ellsworth can't find something you searched for and builds a new artist or movement page on the fly, it checks the name against a list of rejected or duplicate entries first, so something already turned away can't quietly sneak back in under a slightly different spelling.

Teaching search to handle typos, and closing that one gap, are next on my list.


Museums, expanded

Ellsworth started with a handful of open-access collections. It now pulls from these, newest addition first:

Minneapolis Institute of Art · National Gallery of Art · Tate · Victoria and Albert Museum · Library of Congress · Princeton University Art Museum · Rijksmuseum · Cleveland Museum of Art · Hammer Museum · Smithsonian Institution · Smithsonian American Art Museum · National Portrait Gallery · Smithsonian National Museum of Asian Art · Art Institute of Chicago · Metropolitan Museum of Art

Plus one collection that isn't a museum at all: the Dorothy and Herbert Vogel Collection, better known as "Fifty Works for Fifty States." Herbert and Dorothy were a postal clerk and a librarian who spent forty years buying minimalist and conceptual art on a civil servant's salary. They amassed thousands of works, then gave nearly all of it away: fifty pieces to a museum in every state. I found the National Gallery's archival index for the collection and imported it in full. 2,041 artworks, 130+ artists, and patron records for both Vogels covering 1962 to 2008. It's one of the better stories in American art collecting, and now it's fully browsable on the site.

Works gallery showing a masonry grid of artwork thumbnails with era, medium, and collection filters

All of this feeds the Works gallery, filterable by era, medium, color, and collection, with a two-column detail view for every piece.


The visualizations

Art history on Ellsworth is treated as a network, not a list, and it's shown that way.

Timeline

The main way into the site. Every movement plotted on a vertical axis from 4000 BCE to today, banded by era (Ancient, Medieval, Early Modern, Modern), with world events layered in for context. Zoom controls, era jump buttons, and 89 historical events you can toggle on top of the movement bands.

Ellsworth timeline view showing art movements plotted chronologically from the 1900s to today, color-coded by category

Influence Network

A force-directed graph of all 107 movements and the 192 documented connections between them: direct influence, parallel development, and reaction (movements that arose against another). Node size is scaled by historical influence score, and you can filter by era or search for a specific movement to see its neighborhood light up.

Force-directed graph of art movement influence connections, with nodes sized by historical influence and colored by movement

Threads

This one's my favorite. Instead of organizing by chronology or influence, Threads clusters art history by theme: Resistance & Protest, Commodification & Market, Trauma & Resilience, Power & Authority, and more. 53 themes, 545 artists, 85 movements, laid out as a constellation you can pan and zoom through. It's the closest thing on the site to actually browsing ideas instead of dates.

Threads visualization showing art history clustered by theme, with labels like Resistance & Protest, Labor & Class, and Power & Authority

Palettes

The most literal answer to "what does art history look like." Every artwork's dominant colors get extracted with k-means clustering and aggregated into chronological color strata, per movement or per artist. You can watch the palette shift in real time: the beiges and umbers of Ancient and Medieval work, the sudden lavenders and aquas of Impressionism once paint came in tubes, the full chromatic range of the 20th century.

Palettes visualization: vertical color bars showing the dominant color palette of each art movement across history

Under the hood, this is 35,000+ artworks pixel-analyzed and clustered in LAB color space, not just tagged with a "primary color" by hand.


What's next

Big new features are in design and development and coming soon.