From 8ab5f70c7cd26b55b4233008457b3087781af258 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Jul 2026 06:48:50 +0000 Subject: [PATCH] Point people at the resource table from the top of both landing pages The table is the fastest way into 653 things and it sat below a page of prose about where they came from. The prose still matters; it is not what someone arrives wanting. On the resources page, two buttons under the lede: search and filter all of them, or browse by topic for anyone who would rather read a curated page than work a filter. On the home page, a panel in the same shape as the portfolio one, above "where to start", naming a few publishers so the scale is concrete rather than a number on its own. The publisher count in that panel is computed, and computed as the sentence actually reads rather than as the easiest thing to count. My first attempt said "around 120", which was a guess. Replacing the guess with the distinct-domain count gave 121, which was still wrong twice: that total includes YouTube, Medium and LinkedIn, which host rather than publish, and it counts First Round twice because they have two domains. Excluding the platforms and the four publishers already named in the sentence gives 98, checked independently against resources.json. --- web/assets/site.css | 3 +++ web/build.mjs | 30 +++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/web/assets/site.css b/web/assets/site.css index 67e35bf..4042469 100644 --- a/web/assets/site.css +++ b/web/assets/site.css @@ -486,6 +486,9 @@ pre:hover > .copy-btn, .codeblock:hover > .copy-btn, .copy-btn:focus-visible { o .hero h1 { color: var(--hero-text); font-size: clamp(1.9rem, 4.6vw, 3rem); font-weight: 800; max-width: 21ch; } .hero p { color: var(--hero-muted); font-size: clamp(0.98rem, 2vw, 1.12rem); max-width: 58ch; margin-top: 14px; } .hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 26px; } +/* the same button row outside the hero, where the surrounding text is prose and + the buttons need a little more air above them than a lede gives */ +.cta-inline { margin-top: 20px; } .hero-search { display: flex; align-items: center; gap: 10px; width: min(520px, 100%); background: color-mix(in srgb, var(--hero-text) 10%, transparent); diff --git a/web/build.mjs b/web/build.mjs index 27e035b..0c240ef 100644 --- a/web/build.mjs +++ b/web/build.mjs @@ -993,9 +993,17 @@ ${grid} `; + /* The table is the fastest way into 653 things, and it was below a page of + prose explaining where they came from. The prose still matters, but it is + not what someone arrives wanting. */ + const jump = `
+ Search and filter all ${RESOURCES.length} ${ICONS.arrow} + Browse by topic instead +
`; + write(page.url, shell({ url: page.url, title: page.title, description: truncate(page.lede, 160), active: page.url, - body: `

${esc(page.title)}

${esc(page.lede)}

+ body: `

${esc(page.title)}

${esc(page.lede)}

${jump}
${mdToHtml(stripTitleAndLede(body, page.lede), ctx)}

Every resource

All ${RESOURCES.length} in one table. Filter by words, narrow to a group or a topic, and sort any column. The resource link opens the original; the topic link goes to it in context.

@@ -1111,6 +1119,17 @@ function readmeParagraph(prefix, { raw = false } = {}) { docs: DOC_PAGES.length, /* counted, not written down, so the home page cannot drift from the folder */ infographics: readdirSync(INFOGRAPHIC_DIR).filter((f) => f.endsWith(".webp")).length, + resources: RESOURCES.length, + /* Counted, not estimated, and counted as the sentence on the home page + actually reads: distinct publishers, so the platforms that host rather + than publish are excluded, and the four named in that sentence are taken + off the total -- First Round counts once despite having two domains. */ + publishers: (() => { + const named = new Set(["ycombinator.com", "toolkit.techstars.com", "firstround.com", "review.firstround.com", "paulgraham.com"]); + const rest = new Set(RESOURCES.map((r) => r.domain) + .filter((d) => !PLATFORM_DOMAINS.has(d) && !d.endsWith(".medium.com") && !named.has(d))); + return rest.size; + })(), }; const card = (href, title, text) => `

${esc(title)}

${esc(text)}

`; @@ -1184,6 +1203,15 @@ ${loopCards}
The method on one page. ${counts.infographics - 1} moresee all of them.
+ +
${ICONS.bookmark}
+
+

${counts.resources} startup resources, in one searchable table

+

Articles, videos, templates and tools from Y Combinator, Techstars, First Round, Paul Graham and ${counts.publishers} other publishers, merged from two curated collections and checked for dead links. Filter by words, narrow to a topic, sort any column. Everything is credited to whoever published it, and none of it was written here.

+
+ ${ICONS.arrow} +
+

Where to start

${card("ai-basics.html", "You have never pointed an AI at your own files", "What actually changed, what the terminal is, what the AI cannot see, and the one rule that never bends. Read this first if the rest of the site assumes something you have not done.")}