From 9dbe7b9df2e7537c56db1261742c5db10b62a73d Mon Sep 17 00:00:00 2001 From: Charles Lowell Date: Wed, 14 Jan 2026 15:35:44 -0600 Subject: [PATCH 1/5] fix urls We were using the base url "/" for every alternate url, and also for the og:url. This is incorrect. Use the canonical url for everything --- .github/workflows/www.yaml | 2 +- www/plugins/rebase.ts | 2 -- www/routes/app.html.tsx | 7 +++---- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/www.yaml b/.github/workflows/www.yaml index a4da4bfde..96d88a2fd 100644 --- a/.github/workflows/www.yaml +++ b/.github/workflows/www.yaml @@ -53,7 +53,7 @@ jobs: staticalize-linux \ --site=http://127.0.0.1:8000 \ --output=www/built \ - --base=https://effection-www.deno.dev/ + --base=https://effection.deno.dev/ - run: npx pagefind --site built working-directory: ./www diff --git a/www/plugins/rebase.ts b/www/plugins/rebase.ts index 1e38dab22..14e7c427f 100644 --- a/www/plugins/rebase.ts +++ b/www/plugins/rebase.ts @@ -90,7 +90,5 @@ export function* useCanonicalUrl(options: { base: string; }): Operation let req = new URL(request.url); let url = new URL(options.base); url.pathname = `${url.pathname}${req.pathname}`; - return String(url); - } diff --git a/www/routes/app.html.tsx b/www/routes/app.html.tsx index 4ee9e4fb6..05da81b12 100644 --- a/www/routes/app.html.tsx +++ b/www/routes/app.html.tsx @@ -26,7 +26,6 @@ export function* useAppHtml({ let twitterImageURL = yield* useAbsoluteUrl( "/assets/images/meta-effection.png", ); - let homeURL = yield* useAbsoluteUrl("/"); let canonicalURL = yield* useCanonicalUrl({ base: "https://frontside.com/effection" }); @@ -39,15 +38,15 @@ export function* useAppHtml({ {title} - + - - + + Date: Wed, 14 Jan 2026 15:42:15 -0600 Subject: [PATCH 2/5] Use proper absolute image url --- www/routes/app.html.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/routes/app.html.tsx b/www/routes/app.html.tsx index 05da81b12..96bbe17b5 100644 --- a/www/routes/app.html.tsx +++ b/www/routes/app.html.tsx @@ -36,7 +36,7 @@ export function* useAppHtml({ {title} - + From fd150cd5eb1690563f9e0d5172cba1630b39e28e Mon Sep 17 00:00:00 2001 From: Charles Lowell Date: Wed, 14 Jan 2026 17:04:21 -0600 Subject: [PATCH 3/5] fix stuff --- .github/workflows/www.yaml | 4 +- www/main.tsx | 6 +-- www/plugins/current-request.ts | 50 ++++++++++++++++++ www/plugins/rebase.ts | 94 ---------------------------------- www/plugins/sitemap.ts | 2 +- www/routes/app.html.tsx | 2 +- 6 files changed, 58 insertions(+), 100 deletions(-) create mode 100644 www/plugins/current-request.ts delete mode 100644 www/plugins/rebase.ts diff --git a/.github/workflows/www.yaml b/.github/workflows/www.yaml index 96d88a2fd..73583893a 100644 --- a/.github/workflows/www.yaml +++ b/.github/workflows/www.yaml @@ -12,6 +12,8 @@ jobs: www: runs-on: ubuntu-latest timeout-minutes: 15 + env: + DEPLOY_NAME: ${{ github.ref_name == 'v4' && '' || format('--{0}', github.ref_name) }} permissions: id-token: write # Needed for auth with Deno Deploy @@ -53,7 +55,7 @@ jobs: staticalize-linux \ --site=http://127.0.0.1:8000 \ --output=www/built \ - --base=https://effection.deno.dev/ + --base=https://effection${{ env.DEPLOY_NAME }}.deno.dev - run: npx pagefind --site built working-directory: ./www diff --git a/www/main.tsx b/www/main.tsx index 23728bc49..feb2763cd 100644 --- a/www/main.tsx +++ b/www/main.tsx @@ -2,7 +2,6 @@ import { main, suspend } from "effection"; import { createRevolution, ServerInfo } from "revolution"; import { etagPlugin } from "./plugins/etag.ts"; -import { rebasePlugin } from "./plugins/rebase.ts"; import { route, sitemapPlugin } from "./plugins/sitemap.ts"; import { tailwindPlugin } from "./plugins/tailwind.ts"; @@ -13,7 +12,7 @@ import { indexRoute } from "./routes/index-route.tsx"; import { xIndexRedirect, xIndexRoute } from "./routes/x-index-route.tsx"; import { xPackageRedirect, xPackageRoute } from "./routes/x-package-route.tsx"; -import { initConfig, useConfig } from "./context/config.ts"; +import { useConfig } from "./context/config.ts"; import { initFetch } from "./context/fetch.ts"; import { initJSRClient } from "./context/jsr.ts"; import { initWorktrees } from "./lib/worktrees.ts"; @@ -25,6 +24,7 @@ import { redirectIndexRoute } from "./routes/redirect-index-route.tsx"; import { searchRoute } from "./routes/search-route.tsx"; import { initClones } from "./lib/clones.ts"; import { initOctokitContext } from "./lib/octokit.ts"; +import { currentRequestPlugin } from "./plugins/current-request.ts"; // Learn more at https://docs.deno.com/runtime/manual/examples/module_metadata#concepts if (import.meta.main) { @@ -70,8 +70,8 @@ if (import.meta.main) { ], plugins: [ yield* tailwindPlugin({ input: "main.css", outdir: "tailwind" }), + currentRequestPlugin(), etagPlugin(), - rebasePlugin(), sitemapPlugin(), ], }); diff --git a/www/plugins/current-request.ts b/www/plugins/current-request.ts new file mode 100644 index 000000000..5a0e555f6 --- /dev/null +++ b/www/plugins/current-request.ts @@ -0,0 +1,50 @@ +import type { RevolutionPlugin } from "revolution"; +import { posixNormalize } from "_posixNormalize"; +import { type Operation } from "effection"; +import { CurrentRequest } from "../context/request.ts"; + +export function currentRequestPlugin(): RevolutionPlugin { + return { + *http(request, next) { + yield* CurrentRequest.set(request); + return yield* next(request); + } + } +} + +/** + * Convert a non fully qualified url into a fully qualified url, complete + * with protocol. + */ +export function* useAbsoluteUrl(path: string = "/"): Operation { + let absolute = yield* useAbsoluteUrlFactory(); + + return absolute(path); +} + +export function* useAbsoluteUrlFactory(): Operation<(path: string) => string> { + let request = yield* CurrentRequest.expect() + + return (path) => { + let normalizedPath = posixNormalize(path); + if (normalizedPath.startsWith("/")) { + let url = new URL(request.url); + url.pathname = posixNormalize(`${url.pathname}${normalizedPath}`); + return url.toString(); + } else { + return new URL(path, request.url).toString(); + } + }; +} + +/** + * Get the canonical url for the current path. + */ +export function* useCanonicalUrl(options: { base: string; }): Operation { + let request = yield* CurrentRequest.expect() + + let req = new URL(request.url); + let url = new URL(options.base); + url.pathname = `${url.pathname}${req.pathname}`; + return String(url); +} diff --git a/www/plugins/rebase.ts b/www/plugins/rebase.ts deleted file mode 100644 index 14e7c427f..000000000 --- a/www/plugins/rebase.ts +++ /dev/null @@ -1,94 +0,0 @@ -import type { RevolutionPlugin } from "revolution"; -import { createContext, type Operation } from "effection"; -import { posixNormalize } from "_posixNormalize"; -import { selectAll } from "hast-util-select"; -import { CurrentRequest } from "../context/request.ts"; - -const BaseUrl = createContext("baseUrl"); - -export function rebasePlugin(): RevolutionPlugin { - return { - *http(request, next) { - yield* CurrentRequest.set(request); - - let rebaseUrl = request.headers.get("X-Base-Url") ?? void 0; - if (rebaseUrl) { - yield* BaseUrl.set(new URL(rebaseUrl)); - } else { - let url = new URL(request.url); - url.pathname = "/"; - yield* BaseUrl.set(url); - } - - return yield* next(request); - }, - - /** - * Rebase an HTML document at a different URL. This replaces all `` and - * `` attributes that contain an absolute path. Any path that is - * relative or contains a fully qualitfied URL will be left alone. - * - * @param tree - the HTML tree to transform - * @param baseUrl - a string representing a fully qualified url, e.g. - * http://frontside.com/effection - */ - *html(request, next) { - let tree = yield* next(request); - - let baseUrl = yield* BaseUrl.expect(); - let base = new URL(baseUrl); - let elements = selectAll('[href^="/"],[src^="/"]', tree); - - for (let element of elements) { - let properties = element.properties!; - - if (properties.href) { - properties.href = posixNormalize( - `${base.pathname}${properties.href}`, - ); - } - if (properties.src) { - properties.src = posixNormalize(`${base.pathname}${properties.src}`); - } - } - return tree; - }, - }; -} - -/** - * Convert a non fully qualified url into a fully qualified url, complete - * with protocol. - */ -export function* useAbsoluteUrl(path: string): Operation { - let absolute = yield* useAbsoluteUrlFactory(); - return absolute(path); -} - -export function* useAbsoluteUrlFactory(): Operation<(path: string) => string> { - let base = yield* BaseUrl.expect(); - let request = yield* CurrentRequest.expect(); - - return (path) => { - let normalizedPath = posixNormalize(path); - if (normalizedPath.startsWith("/")) { - let url = new URL(base); - url.pathname = posixNormalize(`${base.pathname}${path}`); - return url.toString(); - } else { - return new URL(path, request.url).toString(); - } - }; -} - -/** - * Get the canonical url for the current path. - */ -export function* useCanonicalUrl(options: { base: string; }): Operation { - let request = yield* CurrentRequest.expect() - - let req = new URL(request.url); - let url = new URL(options.base); - url.pathname = `${url.pathname}${req.pathname}`; - return String(url); -} diff --git a/www/plugins/sitemap.ts b/www/plugins/sitemap.ts index 17ed9dc70..bfd348698 100644 --- a/www/plugins/sitemap.ts +++ b/www/plugins/sitemap.ts @@ -3,7 +3,7 @@ import { route as revolutionRoute, useRevolutionOptions } from "revolution"; import type { Operation } from "effection"; import { stringify } from "@libs/xml"; import { compile } from "path-to-regexp"; -import { useAbsoluteUrlFactory } from "./rebase.ts"; +import { useAbsoluteUrlFactory } from "./current-request.ts"; export function sitemapPlugin(): RevolutionPlugin { return { diff --git a/www/routes/app.html.tsx b/www/routes/app.html.tsx index 96bbe17b5..2e83f752a 100644 --- a/www/routes/app.html.tsx +++ b/www/routes/app.html.tsx @@ -3,7 +3,7 @@ import type { JSXChild } from "revolution"; import { Footer } from "../components/footer.tsx"; import { Header, type HeaderProps } from "../components/header.tsx"; -import { useAbsoluteUrl, useCanonicalUrl } from "../plugins/rebase.ts"; +import { useAbsoluteUrl, useCanonicalUrl } from "../plugins/current-request.ts"; import { JSXElement } from "revolution/jsx-runtime"; export type Options = { From 69be78c6d0388b9639ff6c8911ed9e82278ad77a Mon Sep 17 00:00:00 2001 From: Charles Lowell Date: Wed, 14 Jan 2026 17:12:24 -0600 Subject: [PATCH 4/5] Don't be fancy --- .github/workflows/www.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/www.yaml b/.github/workflows/www.yaml index 73583893a..d90df1cb4 100644 --- a/.github/workflows/www.yaml +++ b/.github/workflows/www.yaml @@ -12,8 +12,6 @@ jobs: www: runs-on: ubuntu-latest timeout-minutes: 15 - env: - DEPLOY_NAME: ${{ github.ref_name == 'v4' && '' || format('--{0}', github.ref_name) }} permissions: id-token: write # Needed for auth with Deno Deploy @@ -55,7 +53,7 @@ jobs: staticalize-linux \ --site=http://127.0.0.1:8000 \ --output=www/built \ - --base=https://effection${{ env.DEPLOY_NAME }}.deno.dev + --base=https://effection.deno.dev - run: npx pagefind --site built working-directory: ./www From 6c58458371b5744f1a990c8effeae7b48d08a539 Mon Sep 17 00:00:00 2001 From: Charles Lowell Date: Wed, 14 Jan 2026 21:31:37 -0600 Subject: [PATCH 5/5] fix broken sitemap --- www/plugins/current-request.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/www/plugins/current-request.ts b/www/plugins/current-request.ts index 5a0e555f6..bda8acea7 100644 --- a/www/plugins/current-request.ts +++ b/www/plugins/current-request.ts @@ -29,7 +29,8 @@ export function* useAbsoluteUrlFactory(): Operation<(path: string) => string> { let normalizedPath = posixNormalize(path); if (normalizedPath.startsWith("/")) { let url = new URL(request.url); - url.pathname = posixNormalize(`${url.pathname}${normalizedPath}`); + url.pathname = normalizedPath + url.search = ''; return url.toString(); } else { return new URL(path, request.url).toString();