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.")}