From 30282fb01eaef983564dbf91c80888fa951b43ba Mon Sep 17 00:00:00 2001 From: okcodes <80954089+okcodes@users.noreply.github.com> Date: Thu, 10 Sep 2026 02:47:50 -0600 Subject: [PATCH 1/9] feat: give the website its own release line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The binary and the landing page ship on different schedules. Deploying a copy fix should not require cutting a vump release, which would tell everyone pinning the binary that something changed when nothing did. vump.toml now declares two projects, told apart by the shape of their tag: `main` tracks Cargo.toml and Cargo.lock and tags `v1.2.3`, `website` tracks website/package.json and tags `website-v1.2.3`. Each shape triggers one workflow, and `vump check` infers the project from the tag, so neither has to name --project. The shapes cannot collide: a website tag does not start with `v`. website/package.json gets its version back. It was dropped when the site had no release line, on the grounds that a number nobody maintains is exactly the kind of lie this repository exists to prevent — but vump now keeps it in step with the tag, which is what makes it true rather than decorative. Co-Authored-By: Claude Opus 5 --- CONTRIBUTING.md | 21 +++++++++++++++++++-- vump.toml | 38 ++++++++++++++++++++++++++------------ website/package.json | 10 +++++++--- 3 files changed, 52 insertions(+), 17 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9b8c380..213bf17 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -41,12 +41,29 @@ platform differences, not ordinary mistakes. ## Releases -vump versions itself with vump. +vump versions itself with vump, as two projects that ship independently. ```bash -vump patch --through push # or: alpha, beta, rc, release +vump patch --project main --through push # or: alpha, beta, rc, release ``` +| Project | Tracks | Tagged | Ships | +| --- | --- | --- | --- | +| `main` | `Cargo.toml`, `Cargo.lock` | `v1.2.3` | The binary: build matrix, signing, checksums, attestation, release | +| `website` | `website/package.json` | `website-v1.2.3` | [`website/`](website) to GitHub Pages | + +The tag shape decides which workflow runs, and `vump check` infers the project +from it, so neither has to be told `--project`. A copy fix on the landing page +therefore ships without a vump version — cutting one to deploy the site would +tell everyone pinning the binary that something changed when nothing did. The +same separation costs the reverse: a binary release does not redeploy the site, +so the version the page states lags until the site is released too. See +[`website/README.md`](website/README.md). + +The rest of this section is about the `main` project. The website's number +answers a narrower question — which build of the page is deployed — and needs +none of the reasoning below, since nothing resolves it. + ### Choosing the number, while the major is 0 **Until 1.0, the minor is the breaking slot.** This is not a formality: Cargo diff --git a/vump.toml b/vump.toml index 7757e58..e9098b3 100644 --- a/vump.toml +++ b/vump.toml @@ -1,20 +1,17 @@ -# vump's own configuration. +# Two independently-versioned projects, told apart by the shape of their tag. # -# Cargo.toml is the single source of truth for this project's version: the -# binary reads it at compile time via CARGO_PKG_VERSION, and CI verifies that -# every released tag matches it before building or publishing anything. -# -# Cargo.lock records that version too, and release builds run --locked, so it -# moves in the same commit rather than being left for a follow-up. - -files = ["Cargo.toml", "Cargo.lock"] +# The binary and the website ship on their own schedules: a copy fix on the +# landing page has nothing in it for someone running vump, and cutting a +# release to deploy one would tell every consumer a new version exists when +# none does. Each tag shape triggers its own workflow, and a single +# `vump check ${{ github.ref_name }}` in CI infers which project a pushed tag +# describes without being told --project. [git] # Stops short of pushing: the commit and tag are local and undoable, whereas a -# pushed tag starts the release workflow. `--through push` when that is wanted. +# pushed tag starts a release. `--through push` when that is wanted. through = "tag" -commit_message = "chore: bump version to v{new_version}" -tag_pattern = "v{new_version}" +commit_message = "chore: bump {project} to v{new_version}" # Stable releases come from main, which is where every one of them has been cut. # The accident this prevents: merging a pull request, staying on its now-deleted @@ -24,3 +21,20 @@ release_branches = ["main"] # prerelease_branches is deliberately unset. Alphas here are cut from the branch # doing the work — that is how every one so far has been made — and constraining # them would mean merging before they could be shared. + +# Cargo.toml is the single source of truth for the binary's version: it is read +# at compile time via CARGO_PKG_VERSION, and CI verifies that every released tag +# matches it before building or publishing anything. Cargo.lock records that +# version too, and release builds run --locked, so it moves in the same commit +# rather than being left for a follow-up. +[[project]] +name = "main" +files = ["Cargo.toml", "Cargo.lock"] +tag_pattern = "v{new_version}" + +# The website's version is what its deployed build reports in the corner, and +# what `vump check` verifies a website-v* tag against before Pages is touched. +[[project]] +name = "website" +files = ["website/package.json"] +tag_pattern = "website-v{new_version}" diff --git a/website/package.json b/website/package.json index ee0806e..45511c0 100644 --- a/website/package.json +++ b/website/package.json @@ -1,10 +1,12 @@ { "name": "vump-website", "private": true, + "version": "0.1.0", + "packageManager": "pnpm@11.25.0", "type": "module", "scripts": { "dev": "vite", - "build": "tsc -b && vite build", + "build": "tsc -b && vite build && vite build --config vite.ssr.config.ts --ssr src/entry-server.tsx --outDir dist-ssr && node scripts/prerender.mjs", "preview": "vite preview", "typecheck": "tsc -b", "lint": "oxlint --max-warnings=0", @@ -12,7 +14,9 @@ "format": "prettier --write .", "format:check": "prettier --check .", "check": "run-s typecheck lint format:check build", - "og": "node scripts/og.mjs" + "og": "node scripts/og.mjs", + "bump:vump": "node scripts/vump-version.mjs", + "clean": "rm -rf dist dist-ssr node_modules/.tmp" }, "dependencies": { "@fontsource-variable/instrument-sans": "^5.3.0", @@ -37,5 +41,5 @@ "vite": "^8.2.2", "wawoff2": "^2.0.1" }, - "description": "Marketing site for vump" + "description": "Landing page for vump" } From 8c1cc5c1bee6d96f9973d001dadaaa9efc2905e4 Mon Sep 17 00:00:00 2001 From: okcodes <80954089+okcodes@users.noreply.github.com> Date: Thu, 10 Sep 2026 02:48:00 -0600 Subject: [PATCH 2/9] feat: state the advertised release at build time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The masthead used to fetch the newest release from the GitHub API on every page load. Unauthenticated, that is sixty requests an hour per address, so the version would simply vanish for anyone behind a busy NAT — and a landing page that says different things to different people at different moments is not one anybody can quote. It is a declared input now: src/content/release.json, read at build time. Reading Cargo.toml instead is the obvious move and is wrong. Cargo.toml holds the version most recently bumped, which is not the version most recently published — right now it says 0.8.0-alpha.0 for a tag that was never pushed, while the newest release is 0.7.0. The page would advertise a download with no binaries behind it, which is the defect this tool exists to prevent, pointed at itself. Pre-releases are skipped for the same reason: the button beside the number hands over the newest stable, and stating an alpha next to it would be two answers to one question. `pnpm bump:vump` picks the newest stable from the repository's own tags, so pointing the site at a new release is one offline command rather than a lookup that can be rate-limited. Co-Authored-By: Claude Opus 5 --- website/scripts/vump-version.mjs | 62 +++++++++++++++++++++++ website/src/components/Nav.tsx | 22 ++++---- website/src/components/sections/Start.tsx | 11 ++-- website/src/content/links.ts | 13 +++-- website/src/content/release.json | 3 ++ website/src/lib/release.ts | 57 --------------------- website/tsconfig.app.json | 3 +- 7 files changed, 96 insertions(+), 75 deletions(-) create mode 100644 website/scripts/vump-version.mjs create mode 100644 website/src/content/release.json delete mode 100644 website/src/lib/release.ts diff --git a/website/scripts/vump-version.mjs b/website/scripts/vump-version.mjs new file mode 100644 index 0000000..794763c --- /dev/null +++ b/website/scripts/vump-version.mjs @@ -0,0 +1,62 @@ +/** + * Points the site at a different published vump release. + * + * The version the page states is a declared input, not something the build + * discovers: it is read from src/content/release.json at build time, so every + * deploy of the same commit says the same thing and no visitor's browser talks + * to an API to find out. This script only makes updating it one command instead + * of a lookup — it reads the repository's own tags, so it works offline and + * cannot be rate-limited. + * + * pnpm bump:vump # newest stable tag + * pnpm bump:vump 0.6.2 # a specific one + * + * Pre-releases are skipped deliberately. The page's audience is someone + * deciding whether to try vump, and the download button hands them the newest + * stable; stating an alpha beside it would be two answers to one question. + */ + +import { execFileSync } from 'node:child_process'; +import { readFileSync, writeFileSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; + +const target = fileURLToPath(new URL('../src/content/release.json', import.meta.url)); + +/** Parses a stable `vX.Y.Z` tag. Anything with a pre-release part is not one. */ +function stable(tag) { + const match = /^v(\d+)\.(\d+)\.(\d+)$/.exec(tag.trim()); + return match ? { tag, parts: [+match[1], +match[2], +match[3]] } : null; +} + +function newestStable() { + const tags = execFileSync('git', ['tag', '--list', 'v*'], { encoding: 'utf8' }).split('\n'); + const releases = tags.map(stable).filter(Boolean); + + if (releases.length === 0) { + throw new Error('no stable v* tags in this repository; pass a version explicitly'); + } + + releases.sort((a, b) => { + for (let i = 0; i < 3; i++) { + if (a.parts[i] !== b.parts[i]) return a.parts[i] - b.parts[i]; + } + return 0; + }); + + return releases.at(-1).tag.slice(1); +} + +const requested = process.argv[2]?.replace(/^v/, ''); +if (requested && !/^\d+\.\d+\.\d+$/.test(requested)) { + throw new Error(`not a stable version: ${requested}`); +} + +const version = requested ?? newestStable(); +const current = JSON.parse(readFileSync(target, 'utf8')).version; + +if (current === version) { + process.stdout.write(`already at ${version}\n`); +} else { + writeFileSync(target, `${JSON.stringify({ version }, null, 2)}\n`); + process.stdout.write(`${current} -> ${version}\n`); +} diff --git a/website/src/components/Nav.tsx b/website/src/components/Nav.tsx index 4b8bdff..34a2c4f 100644 --- a/website/src/components/Nav.tsx +++ b/website/src/components/Nav.tsx @@ -1,7 +1,6 @@ -import { links } from '../content/links.ts'; +import { links, VUMP_VERSION } from '../content/links.ts'; import { cn } from '../lib/cn.ts'; import { useScrolled } from '../lib/hooks.ts'; -import { useLatestRelease } from '../lib/release.ts'; import { GitHubIcon, Mark } from './ui/icons.tsx'; import { ThemeToggle } from './ui/ThemeToggle.tsx'; @@ -12,21 +11,24 @@ const SECTIONS = [ { href: '#start', label: 'Quick start' }, ]; +/** + * The release the site describes, resolved at build time. + * + * Asking GitHub for it from the visitor's browser would put an unauthenticated + * API call on every page load — rate-limited to 60 an hour per address, so the + * chip would simply vanish for anyone behind a busy NAT — and would make the + * page say different things at different moments. The version is a declared + * input instead: see scripts/vump-version.mjs. + */ function ReleaseChip() { - const release = useLatestRelease(); - if (!release) return null; - return ( - - {release.version} - {release.prerelease ? pre : null} + v{VUMP_VERSION} ); } diff --git a/website/src/components/sections/Start.tsx b/website/src/components/sections/Start.tsx index c2e75b3..0b671f7 100644 --- a/website/src/components/sections/Start.tsx +++ b/website/src/components/sections/Start.tsx @@ -1,4 +1,4 @@ -import { links } from '../../content/links.ts'; +import { links, VUMP_VERSION } from '../../content/links.ts'; import { initRun } from '../../content/runs.ts'; import { Button } from '../ui/Button.tsx'; import { Code } from '../ui/Code.tsx'; @@ -35,8 +35,13 @@ export function Start() {

Grab a binary for your platform, or build it from source.

- diff --git a/website/src/content/links.ts b/website/src/content/links.ts index f12237a..89a67f5 100644 --- a/website/src/content/links.ts +++ b/website/src/content/links.ts @@ -1,12 +1,17 @@ +import release from './release.json'; + const REPO = 'https://github.com/okcodes/vump'; +/** The published vump release this build of the site describes. */ +export const VUMP_VERSION: string = release.version; + export const links = { repo: REPO, readme: `${REPO}#readme`, releases: `${REPO}/releases`, - design: `${REPO}/blob/main/DESIGN.md`, - contributing: `${REPO}/blob/main/CONTRIBUTING.md`, - backlog: `${REPO}/blob/main/BACKLOG.md`, + /** The newest stable release, whatever it is when the visitor clicks. */ + latestRelease: `${REPO}/releases/latest`, + /** The exact release this build states. */ + release: `${REPO}/releases/tag/v${VUMP_VERSION}`, action: `${REPO}/tree/main/.github/actions/check`, - sandbox: `${REPO}/tree/main/sandbox`, } as const; diff --git a/website/src/content/release.json b/website/src/content/release.json new file mode 100644 index 0000000..767d070 --- /dev/null +++ b/website/src/content/release.json @@ -0,0 +1,3 @@ +{ + "version": "0.7.0" +} diff --git a/website/src/lib/release.ts b/website/src/lib/release.ts deleted file mode 100644 index 5152968..0000000 --- a/website/src/lib/release.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { useEffect, useState } from 'react'; - -export interface Release { - version: string; - url: string; - prerelease: boolean; -} - -interface ApiRelease { - tag_name: string; - html_url: string; - prerelease: boolean; - draft: boolean; -} - -/** - * The newest published release, read from GitHub when the page loads. - * - * This page deliberately keeps no copy of vump's version number. A number - * written into a marketing site is a number nobody bumps, and a version that - * disagrees with its source is the exact defect this tool exists to prevent. - * When the request fails, nothing is shown — an unverifiable version is worse - * than none. - */ -export function useLatestRelease(): Release | null { - const [release, setRelease] = useState(null); - - useEffect(() => { - const controller = new AbortController(); - - void (async () => { - try { - const response = await fetch( - 'https://api.github.com/repos/okcodes/vump/releases?per_page=5', - { signal: controller.signal, headers: { Accept: 'application/vnd.github+json' } }, - ); - if (!response.ok) return; - - const releases = (await response.json()) as ApiRelease[]; - const newest = releases.find((entry) => !entry.draft); - if (!newest) return; - - setRelease({ - version: newest.tag_name.replace(/^v/, ''), - url: newest.html_url, - prerelease: newest.prerelease, - }); - } catch { - // Offline, rate-limited, or blocked: the chip simply does not appear. - } - })(); - - return () => controller.abort(); - }, []); - - return release; -} diff --git a/website/tsconfig.app.json b/website/tsconfig.app.json index 289c5df..5050394 100644 --- a/website/tsconfig.app.json +++ b/website/tsconfig.app.json @@ -14,6 +14,7 @@ "verbatimModuleSyntax": true, "moduleDetection": "force", "noEmit": true, + "resolveJsonModule": true, "jsx": "react-jsx", /* Linting */ @@ -26,5 +27,5 @@ "erasableSyntaxOnly": true, "noFallthroughCasesInSwitch": true }, - "include": ["src"] + "include": ["src", "package.json"] } From fad30299256940f74fd83ac68534d17629b88813 Mon Sep 17 00:00:00 2001 From: okcodes <80954089+okcodes@users.noreply.github.com> Date: Thu, 10 Sep 2026 02:48:13 -0600 Subject: [PATCH 3/9] feat: prerender the page to static HTML MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The deployed page shipped an empty #root: correct in a browser, and nothing at all to a crawler, a link preview, or an agent fetching it. That is a strange thing for a page whose entire job is being read by someone deciding whether to try the tool. `vite build` still produces the client bundle; a second pass builds entry-server.tsx to dist-ssr/, prerender.mjs inlines that HTML into #root, and the intermediate is deleted rather than deployed. main.tsx hydrates when #root already has children and renders normally when it does not, which is what the dev server serves. Three things had to stop depending on the browser for this to render on the server, and none of them are workarounds: The theme now lives on the document element rather than in React state. The pre-paint script in index.html is what keeps the page from flashing the wrong theme, and mirroring that into state would have given the server-rendered HTML a theme it cannot know. Reading the attribute at the moment of the click cannot drift from what is on screen. The theme toggle renders both icons and hides one in CSS. Choosing between them in JavaScript would mean the prerendered HTML picks a theme the visitor may not be using, and hydration would swap it under them. The entrance animations are gated on a `js` class the pre-paint script adds. Without that, content held at opacity zero waiting for an observer would leave a scripting-disabled client staring at a blank page — the prerendered markup would be there, and invisible. The site's own address is settled while we are here: vump.codehacks.io, at the root, so the base-path environment variable and its .env are gone. Co-Authored-By: Claude Opus 5 --- website/.env | 7 ---- website/index.html | 37 +++++++++++-------- website/public/og.png | Bin 105497 -> 104591 bytes website/scripts/og.mjs | 2 +- website/scripts/prerender.mjs | 34 ++++++++++++++++++ website/src/components/ui/ThemeToggle.tsx | 16 +++++---- website/src/entry-server.tsx | 8 +++++ website/src/index.css | 13 ++++--- website/src/lib/hooks.ts | 8 ++++- website/src/lib/theme.ts | 42 +++++++++------------- website/src/main.tsx | 15 ++++++-- website/src/vite-env.d.ts | 10 ++++++ website/vite.config.ts | 31 ++++++++-------- website/vite.ssr.config.ts | 13 +++++++ 14 files changed, 157 insertions(+), 79 deletions(-) delete mode 100644 website/.env create mode 100644 website/scripts/prerender.mjs create mode 100644 website/src/entry-server.tsx create mode 100644 website/src/vite-env.d.ts create mode 100644 website/vite.ssr.config.ts diff --git a/website/.env b/website/.env deleted file mode 100644 index dca6dee..0000000 --- a/website/.env +++ /dev/null @@ -1,7 +0,0 @@ -# Where the site will be served from. Both values are read at build time. -# -# VITE_BASE_PATH is the path every asset URL is prefixed with: "/" for a custom -# domain at the root, "/vump/" for a GitHub project site at okcodes.github.io. -# VITE_SITE_URL is the absolute origin used for canonical and social-card URLs. -VITE_BASE_PATH=/ -VITE_SITE_URL=https://okcodes.github.io/vump diff --git a/website/index.html b/website/index.html index 072f3c9..c2604e2 100644 --- a/website/index.html +++ b/website/index.html @@ -9,10 +9,10 @@ name="description" content="vump writes your new version into package.json, Cargo.toml, pyproject.toml and their lock files at once — then commits, tags, and verifies the tag in CI." /> - + - - + + @@ -21,34 +21,41 @@ - - + + + + + - + @@ -61,7 +68,7 @@ "applicationCategory": "DeveloperApplication", "operatingSystem": "macOS, Linux, Windows", "description": "Keep semver version numbers in sync across the files of a repository, and verify in CI that a released tag matches what is recorded in source.", - "url": "https://github.com/okcodes/vump", + "url": "https://vump.codehacks.io/", "offers": { "@type": "Offer", "price": "0", "priceCurrency": "USD" } } diff --git a/website/public/og.png b/website/public/og.png index be162b7a2303cf190ed2fe111abe473f6dec7fd1..20f56758ca771a7478cc82051602aae151fd8626 100644 GIT binary patch delta 42923 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 M+*iF GITHUB.COM/OKCODES/VUMP + letter-spacing="1.4">VUMP.CODEHACKS.IO diff --git a/website/scripts/prerender.mjs b/website/scripts/prerender.mjs new file mode 100644 index 0000000..7963c34 --- /dev/null +++ b/website/scripts/prerender.mjs @@ -0,0 +1,34 @@ +/** + * Inlines the app's rendered HTML into dist/index.html. + * + * Runs after the client and SSR builds. Without it the deployed page ships an + * empty #root: correct in a browser, nothing at all to a crawler, a link + * preview, or an agent fetching the page — and this site's whole job is being + * read by someone deciding whether to try the tool. + * + * dist-ssr/ is a build-time intermediate and is deleted here rather than + * deployed. + */ + +import { readFileSync, rmSync, writeFileSync } from 'node:fs'; +import { join, dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const websiteDir = dirname(dirname(fileURLToPath(import.meta.url))); +const distDir = join(websiteDir, 'dist'); +const ssrDir = join(websiteDir, 'dist-ssr'); + +const { render } = await import(join(ssrDir, 'entry-server.js')); + +const indexPath = join(distDir, 'index.html'); +const template = readFileSync(indexPath, 'utf8'); +const rendered = template.replace('

', `
${render()}
`); + +if (rendered === template) { + throw new Error(`prerender: no '
' placeholder in ${indexPath}`); +} + +writeFileSync(indexPath, rendered); +rmSync(ssrDir, { recursive: true, force: true }); + +process.stdout.write('prerendered dist/index.html\n'); diff --git a/website/src/components/ui/ThemeToggle.tsx b/website/src/components/ui/ThemeToggle.tsx index 41b08de..58e87db 100644 --- a/website/src/components/ui/ThemeToggle.tsx +++ b/website/src/components/ui/ThemeToggle.tsx @@ -1,17 +1,21 @@ -import { useTheme } from '../../lib/theme.ts'; +import { toggleTheme } from '../../lib/theme.ts'; import { MoonIcon, SunIcon } from './icons.tsx'; +/** + * Both icons are rendered and one is hidden by the theme attribute in CSS. + * Choosing between them in JavaScript would mean the prerendered HTML picks a + * theme the visitor may not be using, and hydration would swap it under them. + */ export function ThemeToggle() { - const { theme, toggle } = useTheme(); - return ( ); } diff --git a/website/src/entry-server.tsx b/website/src/entry-server.tsx new file mode 100644 index 0000000..b4c12a3 --- /dev/null +++ b/website/src/entry-server.tsx @@ -0,0 +1,8 @@ +import { renderToString } from 'react-dom/server'; + +import { App } from './App.tsx'; + +/** Rendered at build time by scripts/prerender.mjs. */ +export function render(): string { + return renderToString(); +} diff --git a/website/src/index.css b/website/src/index.css index a9950b0..b67c233 100644 --- a/website/src/index.css +++ b/website/src/index.css @@ -188,8 +188,13 @@ border-color: var(--line); } - /* Content enters once, on first sight. Nothing moves on the way out. */ - .reveal { + /* + * Content enters once, on first sight; nothing moves on the way out. Gated on + * the .js class the pre-paint script adds, so the prerendered HTML a no-JS + * client or a crawler receives is visible as it stands rather than waiting + * for a reveal that will never be triggered. + */ + .js .reveal { opacity: 0; transform: translateY(14px); transition: @@ -197,13 +202,13 @@ transform 0.7s var(--ease-out-expo); } - .reveal[data-visible='true'] { + .js .reveal[data-visible='true'] { opacity: 1; transform: none; } @media (prefers-reduced-motion: reduce) { - .reveal { + .js .reveal { opacity: 1; transform: none; } diff --git a/website/src/lib/hooks.ts b/website/src/lib/hooks.ts index b93bd32..491bdf1 100644 --- a/website/src/lib/hooks.ts +++ b/website/src/lib/hooks.ts @@ -51,8 +51,14 @@ export function useInView(rootMargin = '0px 0px -10% 0px' /** Whether the visitor has asked for less motion. */ export function useReducedMotion() { + // Rendered on the server during the prerender step, where there is no + // matchMedia. Assuming motion is wanted matches what the client resolves for + // almost everyone, and the effect corrects it for the rest before anything + // has moved. const [reduced, setReduced] = useState( - () => window.matchMedia('(prefers-reduced-motion: reduce)').matches, + () => + typeof window !== 'undefined' && + window.matchMedia('(prefers-reduced-motion: reduce)').matches, ); useEffect(() => { diff --git a/website/src/lib/theme.ts b/website/src/lib/theme.ts index bd5a946..9d60969 100644 --- a/website/src/lib/theme.ts +++ b/website/src/lib/theme.ts @@ -1,31 +1,23 @@ -import { useCallback, useEffect, useState } from 'react'; - -export type Theme = 'dark' | 'light'; - -const KEY = 'vump-theme'; - -function current(): Theme { - return document.documentElement.dataset['theme'] === 'light' ? 'light' : 'dark'; -} - /** - * Reads the theme the pre-paint script in `index.html` already resolved, and - * writes any change back to it. The stored value is a deliberate choice, so it - * outranks the system preference from then on. + * The theme lives on the document element, not in React state. + * + * A script in index.html resolves it before first paint, which is what keeps + * the page from flashing the wrong one. Mirroring that into state would give + * the server-rendered HTML a theme it cannot know and make hydration disagree + * with what is already on screen; reading the attribute at the moment of the + * click cannot drift from it. */ -export function useTheme() { - const [theme, setTheme] = useState(current); - useEffect(() => { - document.documentElement.dataset['theme'] = theme; - try { - localStorage.setItem(KEY, theme); - } catch { - // A browser refusing storage is not a reason to refuse the theme. - } - }, [theme]); +const KEY = 'vump-theme'; - const toggle = useCallback(() => setTheme((t) => (t === 'dark' ? 'light' : 'dark')), []); +export function toggleTheme() { + const root = document.documentElement; + const next = root.dataset['theme'] === 'light' ? 'dark' : 'light'; + root.dataset['theme'] = next; - return { theme, toggle }; + try { + localStorage.setItem(KEY, next); + } catch { + // A browser refusing storage is not a reason to refuse the theme. + } } diff --git a/website/src/main.tsx b/website/src/main.tsx index 94f1b1b..a33e6ee 100644 --- a/website/src/main.tsx +++ b/website/src/main.tsx @@ -8,15 +8,24 @@ import '@fontsource/instrument-serif/latin-400-italic.css'; import './index.css'; import { StrictMode } from 'react'; -import { createRoot } from 'react-dom/client'; +import { createRoot, hydrateRoot } from 'react-dom/client'; import { App } from './App.tsx'; const root = document.getElementById('root'); if (!root) throw new Error('missing #root'); -createRoot(root).render( +const app = ( - , + ); + +// The build's prerender step fills #root with real markup, so a production load +// hydrates it instead of throwing it away. `vite dev` serves index.html +// unprerendered, where #root is empty and a plain render is what is wanted. +if (root.hasChildNodes()) { + hydrateRoot(root, app); +} else { + createRoot(root).render(app); +} diff --git a/website/src/vite-env.d.ts b/website/src/vite-env.d.ts new file mode 100644 index 0000000..2a185d6 --- /dev/null +++ b/website/src/vite-env.d.ts @@ -0,0 +1,10 @@ +/// + +interface ImportMetaEnv { + /** + * Short commit the site was built and deployed from, set by + * release-website.yml. Unset for local builds, where there is no deploy to + * point at. + */ + readonly VITE_WEBSITE_BUILD_SHA?: string; +} diff --git a/website/vite.config.ts b/website/vite.config.ts index f87568e..ef8bc85 100644 --- a/website/vite.config.ts +++ b/website/vite.config.ts @@ -1,21 +1,18 @@ import tailwindcss from '@tailwindcss/vite'; import react from '@vitejs/plugin-react'; -import { defineConfig, loadEnv } from 'vite'; +import { defineConfig } from 'vite'; -export default defineConfig(({ mode }) => { - // The site is destined for GitHub Pages. A project site is served from - // `//`, a custom domain from the root, and the difference is baked into - // every asset URL at build time — so it is an environment variable rather than - // a value edited in this file before each deploy. - const env = loadEnv(mode, process.cwd(), ''); - - return { - base: env.VITE_BASE_PATH || '/', - plugins: [react(), tailwindcss()], - build: { - // Every visitor loads the whole page, so splitting it into chunks buys - // nothing and costs a round trip. - assetsInlineLimit: 2048, - }, - }; +/** + * Served from vump.codehacks.io, at the root, so there is no base path to + * configure. A bare github.io project page would need one, at // — that + * is not this site's URL, and the custom domain is set in the repository's + * Pages settings rather than in a CNAME file, since the deploy is a workflow. + */ +export default defineConfig({ + plugins: [react(), tailwindcss()], + build: { + // Every visitor loads the whole page, so splitting it into chunks buys + // nothing and costs a round trip. + assetsInlineLimit: 2048, + }, }); diff --git a/website/vite.ssr.config.ts b/website/vite.ssr.config.ts new file mode 100644 index 0000000..ceda83a --- /dev/null +++ b/website/vite.ssr.config.ts @@ -0,0 +1,13 @@ +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vite'; + +/** + * Separate from vite.config.ts because this build's only output is the HTML + * string entry-server.tsx returns. It needs the JSX transform and nothing else: + * Tailwind's plugin compiles a stylesheet the client build has already emitted, + * and pointing an --ssr entry at a config carrying it produces a second copy + * nothing loads. See scripts/prerender.mjs. + */ +export default defineConfig({ + plugins: [react()], +}); From b5b55f490c05b58172ba3dd3a531fc4f471f7948 Mon Sep 17 00:00:00 2001 From: okcodes <80954089+okcodes@users.noreply.github.com> Date: Thu, 10 Sep 2026 02:48:26 -0600 Subject: [PATCH 4/9] feat: report which build of the site is deployed A bug report is a screenshot. The badge is fixed to the corner rather than placed in the footer so it appears in every one of them without the reporter scrolling to the bottom first, and it names the pair that identifies a build: the site's version and the commit it was built from. The version is read straight from package.json, which is the file vump keeps in step with the website-v* tag. A separately computed value could drift from that tag; this cannot. The commit arrives as a build-time variable the deploy workflow sets, and reads as "local" when there is no deploy to name. Co-Authored-By: Claude Opus 5 --- website/src/App.tsx | 2 ++ website/src/components/ui/VersionBadge.tsx | 31 ++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 website/src/components/ui/VersionBadge.tsx diff --git a/website/src/App.tsx b/website/src/App.tsx index 8a833bd..e22df6e 100644 --- a/website/src/App.tsx +++ b/website/src/App.tsx @@ -5,6 +5,7 @@ import { Features } from './components/sections/Features.tsx'; import { Files } from './components/sections/Files.tsx'; import { Hero } from './components/sections/Hero.tsx'; import { Start } from './components/sections/Start.tsx'; +import { VersionBadge } from './components/ui/VersionBadge.tsx'; export function App() { return ( @@ -24,6 +25,7 @@ export function App() {