From 85804a64f9aa8c2104b5440468859ce4c4cccd8d Mon Sep 17 00:00:00 2001 From: Taras Mankovski <74687+taras@users.noreply.github.com> Date: Sat, 26 Sep 2026 15:51:46 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Let=20--base=20decide=20where=20?= =?UTF-8?q?the=20built=20site=20lives?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit llms.txt and feed.xml hardcoded https://frontside.com/effection, so every copy advertised production no matter where it was served from: locally llms.txt sent agents away from the dev server they were reading it on, and a preview sent reviewers to production. They now emit the origin that served them, and staticalize 0.3.0 rewrites them on the way out — it honours the path of --base and rewrites textual bodies, neither of which it could do before. That makes --base the only place a deployment says where it lives: the canonical url in production, and its own alias url in a preview, which also settles the html, since previews have been rewriting theirs to production all along. The crawl now passes --concurrency and --retries explicitly. 0.3.0 rejects the invocation without them, where 0.2.6 applied its documented defaults. The pagefind crawl stays on 0.2.7: its base is its own origin, so it has nothing to rewrite, and pinning it forward would make the dev server wait out deno's minimum dependency age on the day of a release. --- .github/workflows/www.yaml | 41 +++++++++++++++++++--- www/deno.json | 2 +- www/routes/blog-feed-route.tsx | 43 +++++++++++++---------- www/routes/llms-txt-route.ts | 64 +++++++++++++++++++++------------- 4 files changed, 101 insertions(+), 49 deletions(-) diff --git a/.github/workflows/www.yaml b/.github/workflows/www.yaml index ee93cf00e..d4abfddaf 100644 --- a/.github/workflows/www.yaml +++ b/.github/workflows/www.yaml @@ -10,6 +10,10 @@ on: permissions: contents: read +env: + # name of the netlify site, used to predict the url of a preview deploy + NETLIFY_SITE_NAME: effection + jobs: deploy-preview: if: github.event_name == 'pull_request' @@ -17,7 +21,8 @@ jobs: timeout-minutes: 15 environment: name: Preview - url: ${{ steps.netlify.outputs.unique-url }} + # the alias deploy, the one this build's urls were written for + url: ${{ steps.netlify.outputs.stable-url }} permissions: contents: read pull-requests: write @@ -33,6 +38,23 @@ jobs: with: deno-version: v2.9.1 + - name: Compute Site URL + id: site + env: + IS_FORK: ${{ github.event.pull_request.head.repo.full_name != github.repository }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + # an alias deploy lands on a predictable url, so a preview can point + # at itself. a fork deploys anonymously to a url that is not known + # until after the deploy, so it points at the netlify site instead. + if [[ "$IS_FORK" == "true" ]]; then + URL="https://${NETLIFY_SITE_NAME}.netlify.app" + else + URL="https://pr-${PR_NUMBER}--${NETLIFY_SITE_NAME}.netlify.app" + fi + echo "url=$URL" >> "$GITHUB_OUTPUT" + echo "Preview will be served from $URL" >> "$GITHUB_STEP_SUMMARY" + - name: Serve Website run: | deno run -A main.tsx & @@ -48,7 +70,7 @@ jobs: - name: Download Staticalize run: | - wget https://github.com/thefrontside/staticalize/releases/download/v0.2.6/staticalize-linux.tar.gz \ + wget https://github.com/thefrontside/staticalize/releases/download/v0.3.0/staticalize-linux.tar.gz \ -O /tmp/staticalize-linux.tar.gz tar -xzf /tmp/staticalize-linux.tar.gz -C /usr/local/bin chmod +x /usr/local/bin/staticalize-linux @@ -58,7 +80,9 @@ jobs: staticalize-linux \ --site=http://127.0.0.1:8000 \ --output=www/built \ - --base=https://effection.netlify.app + --base=${{ steps.site.outputs.url }} \ + --concurrency=75 \ + --retries=3 - name: Deploy Preview to Netlify id: netlify @@ -90,6 +114,11 @@ jobs: DEPLOY_ID=$(echo "$DEPLOY_OUTPUT" | jq -er '.deploy_id') SITE_NAME=$(echo "$DEPLOY_OUTPUT" | jq -er '.site_name') + + if [[ "$SITE_NAME" != "$NETLIFY_SITE_NAME" ]]; then + echo "::warning::deployed to '$SITE_NAME' but urls were built for" \ + "'$NETLIFY_SITE_NAME'; update NETLIFY_SITE_NAME in this workflow" + fi UNIQUE_URL="https://${DEPLOY_ID}--${SITE_NAME}.netlify.app" STABLE_URL="https://pr-${PR_NUMBER}--${SITE_NAME}.netlify.app" fi @@ -144,7 +173,7 @@ jobs: - name: Download Staticalize run: | - wget https://github.com/thefrontside/staticalize/releases/download/v0.2.6/staticalize-linux.tar.gz \ + wget https://github.com/thefrontside/staticalize/releases/download/v0.3.0/staticalize-linux.tar.gz \ -O /tmp/staticalize-linux.tar.gz tar -xzf /tmp/staticalize-linux.tar.gz -C /usr/local/bin chmod +x /usr/local/bin/staticalize-linux @@ -154,7 +183,9 @@ jobs: staticalize-linux \ --site=http://127.0.0.1:8000 \ --output=www/built \ - --base=https://effection.netlify.app + --base=https://frontside.com/effection \ + --concurrency=75 \ + --retries=3 - name: Deploy to Production run: | diff --git a/www/deno.json b/www/deno.json index bae4ccd87..a31e4c3cf 100644 --- a/www/deno.json +++ b/www/deno.json @@ -1,7 +1,7 @@ { "tasks": { "dev": "deno run -A @effectionx/watch deno run -A main.tsx", - "staticalize": "deno run -A jsr:@frontside/staticalize@0.2.2/cli --site http://localhost:8000 --output=built --base=http://localhost:8000", + "staticalize": "deno run -A jsr:@frontside/staticalize@0.3.0/cli --site http://localhost:8000 --output=built --base=http://localhost:8000 --concurrency=75 --retries=3", "test": "deno test --allow-run --allow-write --allow-read --allow-env" }, "lint": { diff --git a/www/routes/blog-feed-route.tsx b/www/routes/blog-feed-route.tsx index 47921e54e..acb6c4428 100644 --- a/www/routes/blog-feed-route.tsx +++ b/www/routes/blog-feed-route.tsx @@ -1,7 +1,8 @@ -import type { Operation } from "effection"; +import { all, type Operation } from "effection"; import { stringify } from "@libs/xml"; import { useBlog } from "../resources/blog.ts"; +import { url } from "../context/url.ts"; /** * RSS 2.0 feed for the blog @@ -11,8 +12,26 @@ export function blogFeedRoute() { *handler(): Operation { let blog = yield* useBlog(); let posts = blog.getPosts(); + let blogUrl = yield* url("/blog"); + let feed = yield* url("/blog/feed.xml"); + let items = yield* all( + posts.slice(0, 20).map(function* (post) { + let postUrl = yield* url(`/blog/${post.id}/`); - let baseUrl = "https://frontside.com/effection"; + return { + title: post.title, + link: postUrl, + guid: { + "@isPermaLink": "true", + "#text": postUrl, + }, + description: post.description, + pubDate: post.date.toUTCString(), + author: post.author, + category: post.tags, + }; + }), + ); let xml = stringify({ "@version": "1.0", @@ -22,31 +41,17 @@ export function blogFeedRoute() { "@xmlns:atom": "http://www.w3.org/2005/Atom", channel: { title: "Effection Blog", - link: `${baseUrl}/blog`, + link: blogUrl, description: "Tutorials, announcements, and insights about structured concurrency in JavaScript with Effection.", language: "en-us", lastBuildDate: new Date().toUTCString(), "atom:link": { - "@href": `${baseUrl}/blog/feed.xml`, + "@href": feed, "@rel": "self", "@type": "application/rss+xml", }, - item: posts.slice(0, 20).map((post) => { - let postUrl = `${baseUrl}/blog/${post.id}/`; - return { - title: post.title, - link: postUrl, - guid: { - "@isPermaLink": "true", - "#text": postUrl, - }, - description: post.description, - pubDate: post.date.toUTCString(), - author: post.author, - category: post.tags, - }; - }), + item: items, }, }, }); diff --git a/www/routes/llms-txt-route.ts b/www/routes/llms-txt-route.ts index dd7c1cd00..a9c2a10c8 100644 --- a/www/routes/llms-txt-route.ts +++ b/www/routes/llms-txt-route.ts @@ -2,6 +2,7 @@ import type { Operation } from "effection"; import { all } from "effection"; import { useWorkspaces } from "../lib/workspaces/mod.ts"; import type { SitemapRoute } from "../plugins/sitemap.ts"; +import { url } from "../context/url.ts"; import type { Package } from "../lib/package/types.ts"; import { groupPackagesByCategory, @@ -45,24 +46,30 @@ export function llmsTxtRoute(): SitemapRoute { ); // Group packages by category - let categorizedContent = groupPackagesByCategory( - categories, - packageEntries, - ).map( - (category) => { - let packageLines = category.packages.map((pkg) => { - let shortDesc = truncateToFirstSentence(pkg.description, 120); - return `- [${pkg.name}](https://frontside.com/effection/x/${pkg.workspaceName}): ${shortDesc}`; - }); - - return [ - `### ${category.label}`, - "", - category.description, - "", - ...packageLines, - ].join("\n"); - }, + let categorizedContent = yield* all( + groupPackagesByCategory( + categories, + packageEntries, + ).map( + function* (category) { + let packageLines = yield* all( + category.packages.map(function* (pkg) { + let shortDesc = truncateToFirstSentence(pkg.description, 120); + let href = yield* url(`/x/${pkg.workspaceName}`); + + return `- [${pkg.name}](${href}): ${shortDesc}`; + }), + ); + + return [ + `### ${category.label}`, + "", + category.description, + "", + ...packageLines, + ].join("\n"); + }, + ), ); let content = [ @@ -73,7 +80,7 @@ export function llmsTxtRoute(): SitemapRoute { "", ...categorizedContent, "", - LLMS_TXT_FOOTER, + yield* llmsTxtFooter(), ].join("\n"); return new Response(content, { @@ -146,16 +153,24 @@ If any other document conflicts with AGENTS.md, **AGENTS.md takes precedence**. --- `; -const LLMS_TXT_FOOTER = `## Optional +function* llmsTxtFooter(): Operation { + let [catalog, blog, api, guides] = yield* all([ + url("/x/"), + url("/blog"), + url("/api/"), + url("/guides/v4"), + ]); + + return `## Optional -- [Full EffectionX catalog with documentation](https://frontside.com/effection/x/) -- [Effection Blog](https://frontside.com/effection/blog) +- [Full EffectionX catalog with documentation](${catalog}) +- [Effection Blog](${blog}) --- [AGENTS.md]: https://raw.githubusercontent.com/thefrontside/effection/v4/AGENTS.md -[API]: https://frontside.com/effection/api/ -[Guides]: https://frontside.com/effection/guides/v4 +[API]: ${api} +[Guides]: ${guides} [Thinking in Effection]: https://raw.githubusercontent.com/thefrontside/effection/v4/docs/thinking-in-effection.mdx [Async Rosetta Stone]: https://raw.githubusercontent.com/thefrontside/effection/v4/docs/async-rosetta-stone.mdx [Operations]: https://raw.githubusercontent.com/thefrontside/effection/v4/docs/operations.mdx @@ -164,3 +179,4 @@ const LLMS_TXT_FOOTER = `## Optional [Spawn]: https://raw.githubusercontent.com/thefrontside/effection/v4/docs/spawn.mdx [Collections]: https://raw.githubusercontent.com/thefrontside/effection/v4/docs/collections.mdx `; +}