Skip to content

Commit 0460202

Browse files
Add SEO, agent-readable surfaces and a static browse page; fix date sort
The site had no sitemap, no robots.txt, no favicon, no meta description and no social tags, and its default sort was noise. Vercel deploys docs/ on push to main, so the committed build output is the deployed artefact. Discoverability: - astro.config.mjs now sets `site`, without which canonical URLs, Open Graph URLs and @astrojs/sitemap all silently produce nothing. - BaseLayout emits canonical, Open Graph, Twitter card, favicon and optional JSON-LD; every page passes a real description. Repo pages carry SoftwareSourceCode schema, /browse/ carries an ItemList. - Added sitemap (253 URLs), robots.txt, 1200x630 og-image, favicon set. Agent-readable: - /llms.txt, generated at build time from tagged_repos.json so it cannot drift from the index. Lists every repo by category plus the JSON endpoints and the marketplace install commands. - robots.txt points agents at the JSON surfaces. Navigation: - /browse/ is a static listing of all 236 repos. The home page renders its list client-side, so a crawler without JS saw "Loading repositories..." and found no repo links at all. This puts them in the initial HTML. - Hero now leads with the plugin marketplace: a CTA to the install guide and the `/plugin marketplace add` command inline. Accessibility: - Skip link, visible focus rings, prefers-reduced-motion, labelled search input, aria-live result count, aria-expanded on the nav toggle and dropdown, Escape closes menus and restores focus, rel="noopener" on external links. Fixes: - The "Newest" sort was meaningless. created_date fell back to added_date, which fell back to *today* on every build, because site_state.json history is capped at 50 entries and older repos fall off it. 125 of 236 repos claimed they were created 2026-08-10. Real GitHub creation dates are now fetched into data/repo_created_dates.json by the new scripts/fetch_created_dates.py, and added dates persist in data/repo_added_dates.json. - 26 links on the ideas/ essay pages pointed at repo detail pages that are never generated. All 24 target repos are gone from GitHub entirely, confirmed against all 2444 repos on the account including private. Unlinked, prose kept. - scripts/check_links.py now gates the build on broken internal links, since dropping a repo from the index silently 404s every essay-page mention of it. notes/dead-repo-mentions.md records the deleted repos and the editorial cleanup still outstanding. CLAUDE.md documents the deploy path, the SEO surfaces, why /browse/ must stay static, and the date persistence rule. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 0b4ae11 commit 0460202

305 files changed

Lines changed: 3975 additions & 1775 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CLAUDE.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,56 @@ either:
310310
Compare results against the category files before adding anything; the script
311311
does not know which repos were deliberately excluded.
312312

313+
## The deployed site
314+
315+
Live at **https://claude.danielrosehill.com**, deployed by **Vercel** on push to
316+
`main` (`vercel.json` sets `outputDirectory: docs`). `docs/` is the committed
317+
Astro build output — so **run `npm run build` and commit the result**; this repo
318+
is not one where the build can be left to CI.
319+
320+
`npm run build` is three steps: `build:data` (the Python pipeline that regenerates
321+
`README.md`, the split markdown pages and `data/*.json`), `build:site` (Astro), and
322+
`check:links`, which fails the build on a broken internal link.
323+
324+
### SEO and machine-readable surfaces
325+
326+
`astro.config.mjs` sets `site:` — this is load-bearing. Without it canonical URLs,
327+
Open Graph URLs and `@astrojs/sitemap` all silently produce nothing.
328+
329+
`BaseLayout.astro` takes `description`, `image`, `isHome` and `schema` props and
330+
emits the canonical link, Open Graph and Twitter tags, and JSON-LD. **Pass a
331+
`description` on every new page** — the fallback is the site-wide one, which is
332+
fine for a stray page but poor if it ends up on many.
333+
334+
| Surface | Source | Notes |
335+
| --- | --- | --- |
336+
| `/sitemap-index.xml` | `@astrojs/sitemap` | every page, generated |
337+
| `/robots.txt` | `public/robots.txt` | static; points at the sitemap |
338+
| `/llms.txt` | `src/pages/llms.txt.ts` | generated from `tagged_repos.json`, cannot drift |
339+
| `/browse/` | `src/pages/browse/index.astro` | static listing of every repo |
340+
| `/og-image.png` | `public/` | 1200×630 |
341+
342+
**Why `/browse/` exists:** the home page renders its repo list client-side from
343+
`tagged_repos.json`, so a crawler that does not run JS sees only "Loading
344+
repositories…" and finds no repo links at all. `/browse/` is the static
345+
counterpart that puts all 236 in the initial HTML. Keep it working; do not fold it
346+
into the client-rendered index.
347+
348+
### Dates: both are persisted, deliberately
349+
350+
`created_date` (real GitHub creation date, `data/repo_created_dates.json`, filled
351+
by `scripts/fetch_created_dates.py`) drives the site's default "Newest" sort.
352+
`added_date` (`data/repo_added_dates.json`) is when the repo entered this index.
353+
354+
Both files exist because both values used to be recomputed as *today* on every
355+
build whenever a lookup missed — `site_state.json` history is capped at 50 entries,
356+
so older repos fell off and got restamped. On 2026-08-10 that had left 125 of 236
357+
repos claiming they were created that day, which made the default sort meaningless.
358+
Never reintroduce a `datetime.now()` fallback that is not written back to disk.
359+
360+
After adding repos, run `python3 scripts/fetch_created_dates.py` before building,
361+
or the new entries sort to the top with a fabricated date.
362+
313363
## This repo's own name
314364

315365
Canonical slug: **`danielrosehill/Claude-Code-Projects-Index`**. It has been

astro.config.mjs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import { defineConfig } from 'astro/config';
2+
import sitemap from '@astrojs/sitemap';
23

4+
// `site` is required for canonical URLs, Open Graph tags and the sitemap —
5+
// without it Astro emits relative URLs only and @astrojs/sitemap is a no-op.
36
export default defineConfig({
7+
site: 'https://claude.danielrosehill.com',
48
outDir: './docs',
59
build: {
610
format: 'directory',
711
},
12+
integrations: [sitemap()],
813
});

0 commit comments

Comments
 (0)