## 1. Project Overview & Quickstart (EleutherAI/model_guide)

# model_guide

Open-source repository EleutherAI/model_guide

### Repository Details
- **Repository:** [EleutherAI/model_guide](https://github.com/EleutherAI/model_guide)
- **Primary Language:** Code

*Note: High-volume repository documentation is actively indexed and synchronized by YakaAI.*

## 2. Official Technical Reference & Guides (EleutherAI/website)

## File: README.md

# EleutherAI Website

This repository contains the Hugo source for the EleutherAI website and blog.

- Main site: [www.eleuther.ai](https://www.eleuther.ai/)
- Blog: [blog.eleuther.ai](https://blog.eleuther.ai/)
- Publication source of truth: [EleutherAI papers Google Sheet](https://docs.google.com/spreadsheets/d/14amb2CM9nVQR_-ZqpGuNPSSdMxsAk0YEoAvetgEyGRw/edit?usp=sharing)

The main site and blog share templates, styles, data, and assets, but Hugo builds them as separate sites for separate Netlify deployments.

**Deployment:** Any changes made to `main` will be automatically deployed via Netlify. This can take a few minutes at times, but changes should be reflected in the live website pretty fast

## Build and view the website

The build requires Python 3.12 or newer, Make, and Hugo Extended 0.158.0. The supported versions are recorded in `.python-version` and `.hugo-version`.

For a new local checkout, install the development dependencies in a virtual environment:

```bash
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install -r requirements-dev.txt
playwright install chromium
make check-tools
```

Playwright is used only for refreshing the Hugging Face download metric. Offline builds and tests do not launch a browser.

From the repository root, build the main site with current online data:

```bash
make build
```

The static output is written to `public/`. To preview the complete website locally, start the main site and blog together:

```bash
make serve-all-offline
open http://127.0.0.1:8067/
```

The main site runs on port `8067` and the blog runs on port `8068`. Navigation automatically moves between the two local previews instead of opening the production websites.

For normal editing with Hugo's live-reloading server:

```bash
make serve-all
```

This refreshes the online data before starting both servers.

Build both the main site and blog:

```bash
make build-all
```

The individual preview commands remain available when only one deployment is needed:

```bash
make serve-offline PORT=8067
make serve-blog-offline PORT=8068
```

When internet access is unavailable, use the checked-in data snapshots:

```bash
make build-offline
make build-all-offline
```

Offline builds do not check the publication Sheet, refresh online metrics, or query YouTube. They validate and use the checked-in snapshots instead.

## Where to add content

Most text should be added to Markdown under `content/` or structured YAML under `data/`. The files under `layouts/` determine how that content is arranged. CSS and public assets live under `site-page.css`, `static/`, and `assets/`.

Files directly under `data/` and `data/projects/` are maintained by people. Everything under `data/generated/` is written by the build scripts and must not be edited directly. Change the relevant Google Sheet, Markdown, YAML, external source, or generator and rebuild.

### Page-by-page guide

| Content | Edit here | Notes |
| --- | --- | --- |
| Homepage hero and section structure | [`layouts/index.html`](layouts/index.html) | The homepage's main prose and arrangement currently live in the template. |
| Homepage metrics, Current Research links, manual news | [`data/home.yaml`](data/home.yaml) | Generated metric values replace entries that have a `source` key. Recent outputs are generated from the papers Sheet and blog front matter. |
| About page | [`content/about.md`](content/about.md) | Donor logos and links are stored separately in `data/donors.yaml`. |
| Community page | [`data/community.yaml`](data/community.yaml) | `content/community.md` contains only the page front matter. |
| Community reading-group cards | [`data/reading_groups.yaml`](data/reading_groups.yaml) | One entry per reading-group series with its YouTube playlist ID (from [the channel's playlists page](https://www.youtube.com/@Eleuther_AI/playlists)). The build refreshes [`data/generated/community_reading_groups.json`](data/generated/community_reading_groups.json) with each series' newest recording; use the repository's `refresh-community-videos` skill when maintaining or troubleshooting it. |
| Staff page | [`data/staff.yaml`](data/staff.yaml) | `teams` mirrors the org chart; give each person a `team` key. Store portraits locally under `static/assets/staff/`. |
| Research page and research areas | [`data/research/areas.yaml`](data/research/areas.yaml) | Area prose, key projects, current directions, and the Major Projects list. Each area also needs a stub under `content/research/`. The intro paragraphs are in [`content/research/_index.md`](content/research/_index.md). Paper lists per area are generated from the Sheet's `Area` column via `research_area_filters.csv`. |
| Research Library | [Google Sheet](https://docs.google.com/spreadsheets/d/14amb2CM9nVQR_-ZqpGuNPSSdMxsAk0YEoAvetgEyGRw/edit?usp=sharing) | `content/papers.md` only defines the route and layout. Do not hand-edit the rendered paper list. |
| SOAR page | [`data/soar.yaml`](data/soar.yaml) | The page title and description are in `content/soar.md`. |
| News post | [`content/news/`](content/news/) | Dated news posts can enter the homepage Latest feed. |
| Manual homepage news item | [`data/home.yaml`](data/home.yaml) under `manual_news` | Give the item a title, URL, and date if it should participate in chronological sorting. |
| Blog post | [`content-blog/`](content-blog/) | Add Markdown front matter with at least `title` and `date`. Write math as plain TeX inside `$…$` or `$$…$$`; MathJax loads automatically on pages that contain it. |
| General standalone page | [`content/`](content/) | Most ordinary Markdown pages use a template under `layouts/_default/`. |
| Header and navigation | [`layouts/partials/header.html`](layouts/partials/header.html) | Shared by the main site and blog. |
| Footer | [`layouts/partials/footer.html`](layouts/partials/footer.html) | Shared by the main site and blog. |
| Shared styling | [`site-page.css`](site-page.css) | Page-specific styles are under `static/`, such as `research-library.css`. |
| Logos and source images | [`assets/`](assets/) | Hugo mounts selected assets into the built sites. |
| Directly served assets | [`static/`](static/) | Files retain their paths in the generated site. |

### Directories that are not content sources

- `public/` and `public-blog/` are generated build outputs. Do not edit them.
- `/blog/` and `blog.html` remain under review as possible deployment artifacts. Do not change or remove them until that deployment is confirmed.
- `generate_blog_pages.py` belongs to the older standalone blog export and is not called by the current Makefile.

## What the build process does

The Makefile coordinates data refreshes and Hugo. The normal main-site build is:

```text
make build
  -> python3 generate_hugo_data.py
  -> python3 scripts/refresh_youtube_reading_groups.py
  -> hugo --cleanDestinationDir
```

Each stage has a different purpose.

### YouTube reading-group refresh

`scripts/refresh_youtube_reading_groups.py` reads `data/reading_groups.yaml`, which lists each reading-group series and its YouTube playlist ID. For every series it fetches the playlist feed (or, with `YOUTUBE_API_KEY` set, the full playlist through the Data API), takes the newest recording, and writes the series name, a link into the playlist at that recording, the session title, date, and a one-sentence overview from the official description to `data/generated/community_reading_groups.json`. A series with no `playlist_id` yet can set `title_pattern` to pick the newest matching channel upload instead; the freshness report flags this as `live_limited` until the playlist ID is added.

The checked-in JSON file is the deterministic offline fallback. A live build warns and uses that snapshot if YouTube is temporarily unavailable; it fails only when neither online discovery nor a valid three-video snapshot is available. `make build-offline` never queries YouTube and validates the snapshot before Hugo runs. `make verify-live` requires `YOUTUBE_API_KEY` so it can prove that the selection came from the complete uploads history.

## Data generation: `generate_hugo_data.py`

The normal build runs this script online. It fetches external data, normalizes publication records, derives display fields, and writes JSON for Hugo.

### 1. Refresh the publication Sheet

The script downloads a cache-busted CSV export of the papers tab and writes it to:

```text
eleutherai_papers.csv
```

The script verifies the full expected header set before replacing the local snapshot. If the Sheet cannot be downloaded, or its schema changes unexpectedly, a live build stops instead of silently claiming that stale publication data is current.

The principal Sheet columns currently used are:

| Sheet column | How the website uses it |
| --- | --- |
| `Title` | Display title and record identity |
| `Date` | Determines whether a paper enters the public library; supplies its displayed year and chronological sort |
| `Highest Impact` | Selects papers for the generated homepage Recent outputs candidate set; checked rows export as `TRUE` |
| `Display Authors` | Author line shown in the Research Library |
| `All Authors` | Complete semicolon-separated author list used for author search and metadata generation |
| `Area` | Semicolon-separated research-area metadata used by generated collections and filters |
| `Paper Link` | Makes the paper entry clickable |
| `Conference or Journal` | Primary archival venue; blank values fall back to a workshop or arXiv |
| `Workshop` | Workshop appearance; may coexist with an archival venue |
| `Superlative` | Oral, spotlight, best-paper, and runner-up text and symbols |

A row must have both a normalized title and a parseable `Date` to appear in the main Research Library and publication count.

### 2. Normalize links, dates, and venues

The script cleans OpenReview tracking parameters and uses a small URL override table for known papers whose links were missing or incorrect in earlier data.

Venue logic is derived from `Conference or Journal` and `Workshop`:

- Papers use the conference or journal, then a workshop if no archival venue exists, then arXiv as a fallback.
- Papers with both an archival venue and a distinct workshop can produce separate appearances in grouped publication data.

The generator maps the simplified Sheet schema into its internal publication model:

- `Date` controls inclusion and the one-record-per-paper library chronology.
- The same date is used for conference and workshop appearance sorting because the Sheet intentionally maintains one date per paper.
- arXiv groups are normalized to January 1 so they are treated as the earliest chronological point in their year and appear after later conference and workshop groups in the newest-first display.
- Workshop sort dates receive a seven-day offset so a corresponding main conference is presented above its workshops.

That final ordering rule is editorial rather than historical: it keeps main conferences visually prominent even when their workshops occurred later.

### 3. Derive publication distinctions

The script cleans the `Superlative` field and associates an award with the appropriate conference or workshop appearance. Commas inside a single award description are preserved. For the Research Library it chooses one marker using this precedence:

1. runner-up or finalist
2. best paper
3. spotlight
4. oral

The generated `marker` value is rendered by `layouts/partials/paper-marker.html`, which keeps symbols and accessible labels consistent across the site.

### 4. Build publication representations

The website needs two related but different publication representations.

#### Publication appearances

`all_papers()` can create more than one record for a paper when it appeared at both a workshop and an archival venue. Each appearance contains:

- title and URL
- publication year
- venue and venue year
- venue kind: conference, workshop, or arXiv
- normalized conference family
- group sort date
- appearance-specific distinctions

These records feed the chronological venue-grouped publication components.

#### Research Library records

`library_papers()` creates exactly one record per dated paper. In addition to title, URL, year, and venue, each record contains:

- authors, displayed as last names and shortened after four names
- status
- primary and additional areas
- lead organization
- EleutherAI contact
- artifact type, currently `Paper`
- distinction marker and text

The current public Research Library does not display every stored metadata field, but the fields remain available to its filters and templates.

### 5. Generate venue groups

`grouped_papers()` groups publication appearances first by conference family and year, then by track or workshop. Examples include a main ICML conference group, a named workshop under ICML, and an arXiv preprint group.

Within a year, the generated order favors:

1. main conferences
2. workshops
3. arXiv

Papers inside each venue are sorted in reverse chronological order.

### 6. Generate research-area paper sets

The script creates `data/generated/research/area_papers.json` in two ways:

- Training Dynamics uses the hand-curated titles, summaries, and optional venue labels in `research_area_papers.csv`.
- Other areas use the broad-area, include-term, and exclude-term rules in `research_area_filters.csv`.

The keyword filters search the paper title, superlative, conference or journal, workshop, and semicolon-separated `Area` values. These generated sets are useful data, but individual research-area pages are intentionally not exposed in the current public release.

The `datasets` key in this file is a filtered set of papers about datasets. It is not a catalog of released dataset artifacts, and the build does not currently query Hugging Face for a dataset inventory.

### 7. Refresh homepage metrics

The generator writes `data/generated/home_generated_metrics.json` from three sources.

#### Publications

It counts unique titled Sheet rows with a valid `Date`, rounds the result down to the nearest 25, and appends `+`. The resulting object uses the key `publication_count`.

#### Citations

It fetches EleutherAI's Google Scholar profile, extracts the total citation count, rounds down to the nearest thousand, and appends `+` when the homepage renders it. The successful response is cached in `data/generated/home_scholar_metrics.json`.

If Scholar cannot be refreshed, the script uses the cached value. If no cache exists, it omits the metric rather than failing the full build.

#### Model downloads

It obtains the Hugging Face model-download value in this order:

1. `HF_MODEL_DOWNLOADS` environment variable, when set
2. the rendered EleutherAI publisher analytics page through Playwright
3. the checked-in cache in `data/generated/hf_model_downloads_cache.json`

If neither a live value nor a cache is available, the metric is omitted. This is a model-download metric only; it does not count dataset downloads.

The homepage reads `data/home.yaml`. Metric entries with a `source` such as `publication_count`, `scholar_citations`, or `model_downloads` are filled from `data/generated/home_generated_metrics.json` during Hugo rendering.

### 8. Build the blog index used by the homepage

The generator scans `content-blog/` recursively. It skips the section index and posts marked `draft: true`, then reads each post's title and date. It writes a sorted list to `data/generated/blog_posts.json` with production blog-subdomain URLs.

The homepage combines these blog entries with `content/news/` and dated `manual_news` entries from `data/home.yaml`. `layouts/index.html` sorts the combined feed and displays the four newest items.

### 9. Write generated research files

The first pass writes:

| Generated file | Contents |
| --- | --- |
| `data/generated/research/papers.json` | All publication appearances, including separate workshop and conference appearances |
| `data/generated/research/homepage_papers.json` | The first 10 publication appearances |
| `data/generated/research/paper_groups.json` | All appearances grouped by venue family, year, and track |
| `data/generated/research/homepage_paper_groups.json` | Grouped data from the first 30 appearances |
| `data/generated/research/area_papers.json` | Curated and keyword-filtered research-area paper sets |
| `data/generated/research/library_papers.json` | One searchable record per dated paper |
| `data/generated/research/paper_collections.json` | Named publication collections such as SOAR |
| `data/generated/home_generated_metrics.json` | Publication, citation, and model-download homepage values |
| `data/generated/home_scholar_metrics.json` | Last successful Scholar response used as a fallback |
| `data/generated/hf_model_downloads_cache.json` | Last supplied or successfully fetched download value |
| `data/generated/blog_posts.json` | Dated blog entries used by the homepage Latest feed |
| `data/generated/home_recent_outputs.json` | Four newest items from highest-impact papers and published blog posts |
| `data/generated/community_reading_groups.json` | One card per configured reading-group series, newest recording first |

Do not edit these files directly. Edit their source data and rebuild.

## Author search

The Sheet's semicolon-separated `all authors` column is the sole source for complete publication authorship. `generate_hugo_data.py` puts every full name into the hidden Research Library search index while continuing to display the shorter `Display Authors` line. A live or offline build stops with a list of affected titles if any paper has a blank `all authors` cell; fix the Sheet rather than adding a local author override.

## Hugo rendering

After data generation, `hugo --cleanDestinationDir` renders the main site with `hugo.toml` and writes `public/`.

Important data connections include:

- `layouts/index.html` reads `data/home.yaml` and generated homepage data under `data/generated/`.
- `layouts/_default/research-library.html` reads `data/generated/research/library_papers.json`.
- `layouts/_default/research.html` and `layouts/partials/publication-groups.html` read the grouped publication data.
- `layouts/_default/community.html` reads `data/community.yaml`.
- `layouts/_default/staff.html` reads `data/staff.yaml`.
- `layouts/_default/soar.html` reads `data/soar.yaml` and the SOAR paper collection.

`make build-all` performs the complete main-site process above and then builds the blog with `hugo-blog.toml` into `public-blog/`. A standalone `make build-blog` does not refresh publication data first; it uses the generated data already present in the checkout.

## Before committing a content change

For ordinary content that does not depend on external data:

```bash
make verify
```

For publications, homepage metrics, news aggregation, or other externally sourced data:

```bash
make verify-live
```

`make verify` runs the tests, regenerates checked-in snapshots offline, builds both deployments with Hugo warnings treated as errors, checks local links and assets, and fails if generated snapshots differ from `HEAD` or the diff contains whitespace errors. GitHub Actions runs the same command.

`make verify-live` additionally requires every external source to be current. Set `YOUTUBE_API_KEY` for complete YouTube uploads discovery and either install Playwright or provide `HF_MODEL_DOWNLOADS`. Run `make freshness` after any build to see which sources were fetched live and which used snapshots.

Review the affected main-site and blog pages locally before committing generated changes.

---

## File: AGENTS.md

# EleutherAI Website Agent Instructions

These instructions apply to AI agents working in this repository. Treat them as project requirements, not optional style suggestions.

## Project purpose

Build a serious, legible, research-first website for EleutherAI. The site should demonstrate EleutherAI's work through concrete papers, models, datasets, tools, people, metrics, and outcomes. It should not read like a generic AI-company landing page or a stylized fake terminal.

The repository produces two related Hugo sites:

- Main site: `https://www.eleuther.ai/`
- Blog: `https://blog.eleuther.ai/`

The sites share layouts, styling, data, and assets but are built and deployed separately.

## Before changing anything

1. Read the relevant content, data, template, and CSS files before proposing a change.
2. Check `git status`, the current branch, and active worktrees. Do not assume the checkout is clean or that another agent is not working nearby.
3. Keep exploratory design work on an isolated feature branch or worktree until Stella approves it.
4. Coordinate preview ports and shared-file ownership with concurrent agents.
5. Never merge, push, or modify `main` unless Stella explicitly authorizes it.
6. Preserve unrelated user and agent changes. Do not clean up or revert work outside the assigned scope.

Do not stage or commit this `AGENTS.md` file unless Stella explicitly asks.

## Design workflow

For layout, information architecture, homepage, navigation, research, community, staff, or visual-polish work, use a design-first process even when Stella does not explicitly request one.

1. Decide what belongs on the page, what belongs on a subpage, and what should be omitted.
2. Sketch the page structure using realistic public content. Do not put editorial notes or implementation labels in the rendered mockup.
3. Critique the proposed structure before implementation. Identify what could feel bloated, gimmicky, generic, thin, or difficult to maintain.
4. Present two or three genuinely distinct directions when the visual choice is unclear.
5. Implement only after the direction is clear unless Stella explicitly requests immediate editing.
6. Build and inspect the result at desktop and mobile sizes.
7. Critique the rendered result for hierarchy, spacing, density, readability, wrapping, overflow, and visual continuity.
8. Iterate before reporting completion. A successful Hugo build is not visual QA.

After every substantive visual change, provide the exact preview URL. When reporting a website change, also provide the build and open commands.

## Source organization

Keep editable content separate from templates and styling.

- `content/`: main-site Markdown and news posts
- `content-blog/`: blog posts and blog front matter
- `data/`: editable structured content; machine-produced Hugo data is isolated under `data/generated/`
- `layouts/`: Hugo templates and shared partials
- `site-page.css`: shared site-wide visual system
- `static/`: page-specific CSS, JavaScript, icons, and public assets
- `assets/`: source images and shared brand assets mounted by Hugo
- `generate_hugo_data.py`: publication, research, homepage-metric, and blog-index generation

Prefer Markdown or YAML for copy changes. Change a template only when page structure or behavior must change. Do not embed maintainable content directly in HTML when it belongs in `content/` or `data/`.

## Data sources and generated files

### Publications

The EleutherAI papers Google Sheet is the source of truth:

`https://docs.google.com/spreadsheets/d/1LcB7_1lHZgO8_EmOkrvfV2BTaOngX95J5v8PJeuN4rM/edit?usp=sharing`

A normal live build downloads the Sheet, regenerates the publication library and homepage publication data, and then builds Hugo.

A paper requires a title, `Sort Date`, and complete semicolon-separated `all authors` value. `Display Authors` supplies the public author line, `all authors` supplies the author-search index, semicolon-separated `Area` values supply research metadata, and `Superlative` supplies distinctions. A link makes the rendered entry clickable.

Do not manually edit these generated files:

- `eleutherai_papers.csv`
- everything under `data/generated/`, including publication representations, homepage feeds and metrics, external-data caches, and Community reading-group recordings

Edit the Sheet or the appropriate editable YAML and regenerate the outputs.

The current `datasets` research grouping is a filtered set of publication records, not an inventory of released dataset artifacts. The build does not currently import a Hugging Face dataset catalog or dataset-download metric. Do not describe it as doing so.

### Homepage and news

Homepage metrics, research priorities, links, and manual news live in `data/home.yaml`.

The homepage `Latest` feed combines:

- posts from `content-blog/`
- news from `content/news/`
- dated manual items from `data/home.yaml`

It sorts the combined feed chronologically and displays the four newest items. Do not create a second hand-ordered copy in a template.

### Community videos

The three Community reading-group recordings come from the official EleutherAI YouTube channel. A normal build refreshes `data/generated/community_reading_groups.json`; an offline build validates and uses that checked-in snapshot. With `YOUTUBE_API_KEY`, the refresh paginates through the complete uploads playlist. Without it, ordinary builds use the limited recent Atom feed and record `live_limited` in the freshness report.

Use the repository skill under `.agents/skills/refresh-community-videos/` when maintaining the selection or summaries. Do not hand-edit the generated JSON. `make verify-live` must fail unless complete uploads discovery and every other external source are live or explicitly provided.

### Staff and assets

Staff data lives in `data/staff.yaml`. Store portraits under `static/assets/staff/`. Do not hotlink staff portraits or core site assets from the old website or third-party CDNs.

## Build and preview

Use the Makefile rather than inventing parallel build commands.

For a new checkout, install `requirements-dev.txt`, install Playwright Chromium, and run `make check-tools`. The supported Python and Hugo versions are recorded in `.python-version` and `.hugo-version`.

### Main site with live data

```bash
make build
make serve-offline PORT=8060
open http://127.0.0.1:8060/
```

For live-reloading development with a fresh data pull:

```bash
make serve PORT=8060
```

### Main site and blog

```bash
make build-all
```

Preview in separate terminals:

```bash
make serve-offline PORT=8060
make serve-blog-offline PORT=8061
```

Then open:

```bash
open http://127.0.0.1:8060/
open http://127.0.0.1:8061/
```

### Offline verification

```bash
make build-offline
make build-all-offline
```

Offline targets use checked-in snapshots and do not check the Google Sheet for new publications. Do not use an offline build to claim live data is current.

If a preview port is occupied on macOS, stop the existing process before starting another server:

```bash
PID=$(lsof -ti tcp:8060); if [ -n "$PID" ]; then kill "$PID"; fi
```

The production main-site Netlify configuration runs `make build` and publishes `public/`. The blog configuration under `netlify/blog/` runs `make build-blog` and publishes `public-blog/`.

## Visual system

### Overall character

- Keep the site dark, minimal, precise, and institutional.
- Prefer authentic research artifacts and project imagery over decoration.
- Do not use fake-terminal styling, generic technology illustrations, decorative gradients, glowing blobs, or invented scientific diagrams when genuine work is available.
- Do not make the site look like a SaaS dashboard or a stack of promotional cards.

### Color

The shared palette is defined in `site-page.css`: green, blue, gold, violet, and coral, with related surface colors.

- Use the palette consistently across the site.
- When a list or sequence gives each item its own highlight color, assign colors in this order: blue, green, violet, gold, coral. For sequences longer than five items, cycle back to blue and repeat the same order.
- Use color for hierarchy, publication distinctions, links, and selected featured material.
- Do not permanently assign one color to each research area. Research areas overlap and the taxonomy will grow.
- Do not make every section a differently colored panel.
- Preserve sufficient contrast in all states.

### Typography and width

- Use the shared page-title scale and established heading levels. Do not invent a new headline system for each page.
- Do not end headings with periods.
- Put explanatory copy below its heading by default. Do not place paragraphs beside section headings unless the composition has a specific content-driven reason.
- The global `.wrap` defines the intended page frame. Do not make text extend to the viewport edges.
- Within that frame, do not add arbitrary `max-width` constraints that make headings or body text wrap earlier than the available layout requires.
- Do not use viewport-scaled font sizes.
- Make text fit at mobile and desktop sizes without overlapping adjacent content.

### Labels, rules, and containers

- Do not add decorative eyebrow labels or small labels that repeat a nearby heading.
- Use horizontal rules sparingly. Prefer spacing, alignment, typography, and background changes for grouping. Retain a rule only when it communicates real structure.
- Use cards for repeated objects such as people, projects, or a deliberately comparable set of items.
- Do not put cards inside cards.
- Do not turn every section into a bordered box or floating panel.
- Avoid highly uniform grids when the content has different importance or evidence. Use imagery, varied scale, and editorial composition when appropriate.
- Keep fixed-format controls dimensionally stable so interaction and dynamic content do not shift the layout.

### Content and evidence

- Prefer proof over explanation: show papers, models, datasets, code, people, metrics, and outcomes.
- Do not add generic filler, temporary marketing copy, or explanations of the site's taxonomy and maintenance logic.
- Do not add visible process narration, mockup ribbons, audience labels, page-logic notes, or instructions for using the page.
- A mockup must contain only material suitable for publication. When copy is genuinely undecided, use `Lorem ipsum` rather than inventing claims.
- Never invent people, organizations, sponsorships, numbers, awards, publications, or links.

### Images

- Use images that show the real project, research result, tool, dataset, model, person, or community.
- Do not use dark atmospheric stock imagery when the visitor needs to inspect the subject.
- Preserve source aspect ratios unless a deliberate crop has been approved.
- Verify that every image loads and remains correctly framed at desktop and mobile widths.

### Publication distinctions

Render publication distinctions through `layouts/partials/paper-marker.html` everywhere they appear:

- `oral`: microphone symbol, blue
- `spotlight`: flashlight symbol, green
- `runnerup`: silver-medal symbol, award color
- `bestpaper`: trophy symbol, award color

Do not create page-specific symbols for the same distinction. Every symbol needs an accessible label. A qualifying recent paper should retain its distinction on the homepage as well as in the Research Library.

## Information architecture

The initial public research architecture is intentionally limited to:

- one Research landing page
- the searchable Research Library
- selected mature project pages such as Pythia

Individual research-area pages are deferred. Do not expose unfinished area routes through navigation, homepage cards, sitemaps, or calls to action. Homepage research themes should link to mature public artifacts or the main Research page.

Research Areas are the normal public vocabulary. Broad categories such as Capabilities, Interpretability, and Safety are separate, overlapping metadata rather than parents in a strict hierarchy. Do not infer a category from an area or force areas into exclusive program ownership.

Keep research communication pages distinct from research artifacts:

- Communication pages explain a project, agenda, or research direction.
- The Research Library provides searchable access to papers.
- Project links should lead to real papers, repositories, models, datasets, and documentation.

## Navigation and accessibility

- Preserve the responsive desktop and mobile navigation.
- Preserve `aria-current` so the current page or parent section is programmatically identifiable.
- Use semantic headings, links, buttons, lists, and navigation elements.
- Keep keyboard focus states visible.
- Use familiar icons for controls and provide tooltips or labels when meaning is not obvious.
- External links opened in a new tab must use `rel="noopener noreferrer"`.
- Do not hide essential navigation at mobile breakpoints.

## Required verification

Before reporting a code or design change as complete:

1. Build the affected site or both sites when shared code changed.
2. Run `git diff --check`.
3. Inspect affected pages in a real browser at desktop and mobile widths.
4. Check horizontal overflow, wrapping, images, navigation, keyboard focus, and console errors.
5. Confirm internal links and local assets resolve.
6. Confirm generated data changed through its source rather than by hand.
7. Compare the result with the surrounding site, not only with the edited component.
8. Keep unapproved experiments isolated from `main`.

Baseline verification:

```bash
make build-all-offline
git diff --check
```

For changes affecting publications, news, blog indexing, citations, or homepage metrics, also run a live build:

```bash
make verify-live
```

For all other changes, run `make verify`. This runs tests, regenerates offline snapshots, treats Hugo warnings as errors, checks local page and asset references, and fails if generated snapshots differ from `HEAD`. Run `make freshness` to report whether each external source was live, provided, limited, cached, offline, or missing.

When changing shared layouts, navigation, CSS, logos, favicons, or social metadata, test both the main site and a representative long technical blog post.

## Reporting

When handing work back to Stella:

- State the branch and commit hash.
- List the files changed and the behavior changed.
- Report the exact build and browser QA performed.
- Give the preview URL.
- Include commands to rebuild and open the site.
- State whether the work is committed, pushed, merged, or still isolated.
- Call out unresolved factual, content, or design decisions without guessing.

---

## File: DESIGN_HANDOFF.md

# EleutherAI Website Design Handoff

Updated: 2026-08-04

## Current state

`main` is at `4a4f52a`. All five recommended design tasks below are complete and committed. The two pending feature branches (`codex/blog-subdomain`, `codex/headcount-netlify`) are also integrated into `main`.

Desktop navigation uses muted inactive links and a white underlined current section. Mobile navigation uses a left-hand marker. Nested pages identify their parent section, and Support Us remains green.

The current homepage research panels are approved. Individual research-area pages, including Training Dynamics, are intentionally excluded from `main` and are not a release blocker.

Use the Hugo source as authoritative. Do not edit the old root HTML files or the material under `mockups/` and `clone/` as though they were the production site.

## Design system — completed

### 1. Headline system ✓

`--title-size: 4rem`, `--title-lh: 1.04`, and `--title-mobile: 2.45rem` are defined in the `:root` block of `site-page.css` and used by all non-homepage hero h1s. Community Impact, SOAR, and Research Library were updated; each also has an explicit mobile override at 680px (the page-specific class selectors would otherwise win over the generic `h1` rule in the media query). The homepage hero (`clamp(3.2rem, 6.2vw, 5.1rem)`) remains the only deliberate exception.

### 2. Color palette ✓

Eight accent tokens are in `:root`: `--green`, `--blue`, `--gold`, `--violet`, `--coral` (bright accents) and `--blue-surface`, `--gold-surface`, `--green-surface`, `--violet-surface` (dark filled-surface colors for the priority cards). The WCAG AA failure on priority-card link hover — `color: #081018` on all four panel backgrounds — is fixed: hover now increases `text-decoration-thickness` from 1px to 2px instead of changing color. The SOAR coral (`--soar-safety`) and the Research Library's `--lib-green` have been aliased to the palette tokens.

### 3. Publication distinctions ✓

`layouts/partials/paper-marker.html` is the single source for the 🎙️ 🔦 🥈 🏆 markers with accessible `role="img"` and `aria-label`. Both `layouts/_default/research-library.html` and `layouts/partials/publication-groups.html` use the partial.

### 4. Interaction and symbol grammar ✓

All `->` link arrows are standardized to `→`. `.link` and `.back-link` now have `text-decoration: underline` on `:hover`/`:focus-visible`. `.button` and `.button.primary` have hover and focus-visible states (border highlight and brightness, respectively). Every interactive element — nav links, cards, publication items, staff icons, donor logos, footer links — has a corresponding `:focus-visible` rule.

### 5. Final visual consistency pass ✓

No oversized h1s remain outside the homepage hero. No `->` arrows remain in templates. No obvious mobile overflow issues. The remaining hardcoded hex values in `site-page.css` are intentional: `#fff` for white text on colored panels, `#f2d77b` for a lighter gold used as badge text (the token `--gold` is too dark for that use), and near-black surface variants (`#0c1118`, `#10161d`, `#111820`) for specific element backgrounds. Do not redesign the main Research page — Stella plans to rewrite it separately.

## Open items

The Support Us page still needs a real contribution or contact destination. Stella is deciding what that should be, so do not invent one.

Local `main` is ahead of `origin/main`; confirm the final commit set before pushing.

## Branch boundaries

- Keep all individual research-area work on `codex/research-area-pages`. Do not merge that branch wholesale into `main`.
- Research Library and the general Research page belong on `main`.
- Staff portraits, personal-site links, Scholar links, GitHub links, metadata, favicons, social previews, and the custom 404 are already integrated into `main`.
- `AGENTS.md` is local project guidance and should not be staged unless Stella explicitly asks.

## Build and preview

For a production-data build:

```bash
cd /Users/stellabiderman/Documents/research/Codex/eleutherai_homepage_draft
make build
```

For a reproducible offline check and local preview:

```bash
cd /Users/stellabiderman/Documents/research/Codex/eleutherai_homepage_draft
make build-offline
make serve-offline PORT=8068
```

Then open:

```bash
open http://127.0.0.1:8068/
```

---

## File: requirements-dev.txt

-r requirements-test.txt
playwright==1.62.0

---

## File: requirements-test.txt

pytest==9.0.2
PyYAML==6.0.2