A lineage tree of 20th and 21st century design movements. Click any movement to see what it inherits, what it rebels against, and what it became. Click any term — the movement title, a designer, a "see it in" fragment, a canonical example, or the camera icon on a lineage pill — to open a Google Images search for it in a new tab.
It's a pure static site — no build step, no dependencies.
python3 -m http.server 8000
# then visit http://localhost:8000(npx serve . also works. Opening index.html directly via file:// works in most browsers since ES modules are now widely supported there, but a server is friendlier.)
- Go to https://app.netlify.com/drop
- Drag the entire
design-dnafolder onto the page. - Done. You'll get a
*.netlify.appURL immediately.
- Push this repo to GitHub.
- In Netlify, click "Add new site" → "Import an existing project" → pick this repo.
- Build command: (leave blank). Publish directory:
.(the root). - Deploy.
- Push this repo to GitHub.
- Repo Settings → Pages → Source: Deploy from a branch →
main// (root). - Site goes live at
https://<user>.github.io/design-dna/.
design-dna/
├── index.html # The shell
├── style.css # All styles
├── js/
│ ├── data.js # Movements + branch layouts (the thing to edit)
│ ├── tree.js # Tree rendering and state
│ ├── detail.js # Right-hand info panel
│ ├── images.js # Builds Google Images URLs (+ no-op scaffolding for a future inline gallery)
│ └── main.js # Entry point
├── netlify.toml # Netlify defaults (cache headers, fallback)
└── README.md
The vertical axis is lineage depth, not strict chronology. Row 0 is the root, row 1 is everything one inheritance step down, and so on. Siblings sit at the same generation even if their actual founding years differ by decades — this keeps parent-to-child arrows short and the tree readable.
If you want a strict-chronology view, that's a future addition: add a numeric startYear to each movement and render an alternate layout that uses year-to-y mapping instead of row index. The data and rendering layers are decoupled.
In js/data.js:
- Add a new entry to
MOVEMENTS:my_movement: { name: "...", years: "1990s–present", region: "...", color: "scandi" | "modernist" | "reaction" | "neutral", defining: "One-sentence elevator pitch.", designers: [ { name: "Some Designer", interiors: true }, // interiors: true appends "interiors" to the image search ], inherits: ["parent_id_1", "parent_id_2"], rebels: ["thing it reacts against"], children: [], seeIn: "Where you encounter it.", seeInAppendInteriors: true, // append "interiors" to each see-in fragment search appendInteriorsToName: true, // append "interiors" to the movement-name search examples: [ { term: "Specific search term", note: "Why this is canonical" }, ], }
- Add the ID to the
childrenarray on every parent. - Place it in one or more
BRANCHESlayouts as[id, xPercent].
Clicking any of these opens a new tab with a Google Images search:
- The movement title (h3)
- Each designer name in the panel
- Each "see it in" fragment between commas
- Each canonical example
- The 📷 icon on inheritance/descendant chips (clicking the chip itself still navigates the tree)
The interiors-research focus is baked into the search terms via three flags in data.js:
appendInteriorsToName— when true, "interiors" is added to the movement-name search (e.g. "Bauhaus interiors" instead of "Bauhaus", since bare "Bauhaus" returns mostly posters)seeInAppendInteriors— when true, every see-in fragment gets "interiors" appended{ interiors: true }on a designer — appends "interiors" for that designer specifically (good for interior/architecture designers; off for painters, graphic designers, popularizers)
Earlier iterations tried scraping Google Images with a Playwright script and storing a 50–500 MB image cache in the repo. The scraping turned out to be fragile (Google's HTML structure rotates) and stale within months (a research tool benefits from live results), and the open APIs that would be stable (Wikimedia, Openverse, Unsplash, Are.na, museum collections) all have uneven coverage across the movement tree.
The thing that does work reliably and gives consistently good results: opening a new tab with a Google Images search for a well-chosen term. The data layer is set up to generate well-chosen terms, so the affordances all just become "open this query."
The image-loading scaffolding (openImagePanelById, getSearchId) is preserved in js/images.js as a no-op, so a future inline gallery — backed by a curated image cache, a real API, or any other source — can be added without touching the detail panel.
- A "compare" mode that diffs two movements field by field
- Style fingerprints (palette swatches, material icons, ornament level) as a quick visual diagnostic
- A guessing-game quiz mode: show an interior, guess the style, reveal the lineage path
- A strict-chronology layout toggle (data is already there)
- Adding more movements: Shaker, Streamline Moderne, Hollywood Regency, Memphis-era postmodern subspecies, regional vernaculars (Mediterranean Revival proper, Spanish Colonial)
- An "evolution" animation that walks down a lineage step by step
- A layered inline image source (Are.na for contemporary, museum APIs for historical) using the preserved
openImagePanelByIdinterface
The code here is MIT-licensed; do whatever you like with it.