Conversation
Single static page deployed via Cloudflare Workers Static Assets.
Paper-zine + terminal hybrid: cream/ink/moss/tomato palette, monospace
throughout, one fake-terminal inset that mirrors actual `runner` and
`runner list` output (field widths and group labels match
src/cmd/{info,list}.rs).
Click-to-copy install commands (npm/cargo/curl), responsive grid of
supported package managers / task runners / sources, MIT footer.
No build step, no deps. `wrangler.jsonc` declares the Static Assets
binding and the `runner.kjanat.com` custom-domain route;
`workers_dev: false` keeps the *.workers.dev URL hidden. `_headers`
ships strict CSP, HSTS, and edge cache. README at repo root gains a
single Website: link.
site/wrangler.jsonc points $schema at ./node_modules/wrangler/ config-schema.json — make that real. Add a private package.json declaring wrangler ^4.87.0 as devDependency, plus dev/deploy/tail scripts. bun install populates node_modules; .gitignore keeps node_modules and .wrangler out of git.
Format with tabs and trailing commas via dprint (typescript + svg plugins added at the workspace root). Add site/biome.json: lint on, formatter off (dprint owns format). Drop the local wrangler devDep in favour of `bunx wrangler` via npm scripts; bun.lock removed. README updated to use `bun --cwd=site dev|deploy`.
- prefers-color-scheme: dark — warm-graphite background, cream ink, brighter moss + tomato. Terminal block stays dark in both modes. color-scheme: light dark hints form controls + scrollbars. - Wordmark cursor: 11s loop — solid ~10s, quick double-blink, repeat. Stops being wallpaper noise; reads as a tiny heartbeat instead. - Terminal cursor: 5 iterations then settles solid, like a real prompt awaiting input. - Cargo install command corrected: cargo install --git=https:// github.com/kjanat/runner/ runner (not the unpublished crate name).
- install grid is now single-column at every breakpoint. Previously the primary npm row spanned full-width while cargo + curl were forced into half-cells — the shortest command got the most space, the longer ones overflowed. Stacking flips that. - "cargo · from source" label clarifies it builds from the git tip, not a published crate. Visible cargo command is now full (no ellipsis) since the box has the room. - Demo-terminal title row "runner 0.6.0" is now real anchors, matching the CLI's OSC8 hyperlinks: runner → repo, 0.6.0 → release tag. Added background: transparent on .term .link[:hover] so the global a:hover moss-swap doesn't bleed into the terminal.
dprint expanded the `idle-double-blink` keyframes block and the cargo install button onto multiple lines — bringing both inline with the rest of the file's already-expanded style. No behaviour change. Trim "— task execution backends not wired up" from the nx/mise caveat. "detection-only" already says it; the longer form leaked implementation roadmap into a user-facing line.
Real fixes the linter caught:
- "use strict" pragma at top of inline script
- Drop unused `const r = document.createRange()` (leftover from a
fallback path that was never reached)
- Destructure `const { cmd } = btn.dataset`
- Annotate the empty execCommand catch (best-effort fallback)
- Extract setTimeout's 1400ms into TOAST_MS
Disabled rules that fight the design (all nursery/style):
- noExcessiveLinesPerFile — single-file is the entire premise
- noHexColors — six-colour palette doesn't need oklch ceremony
- useBaseline — `::selection` is universal in target browsers
- noMagicNumbers — animation timings are local literals
Add `lint` script alias so `bun lint` works without typing `biome`.
Verified: html-validate exit 0, biome lint exit 0.
New section between the demo and the matrix that surfaces the binary's killer feature: dynamic, per-project tab completion. - Two copy-buttons: `eval "$(runner completions)"` (auto-detects $SHELL — covers bash/zsh/fish in one line) and the powershell pipeline equivalent. - Fake terminal showing `runner <TAB>` resolving to grouped candidates — package.json scripts, justfile recipes, justfile aliases, then built-in commands. Mirrors the real `_describe` group headers (`-- source --`). - One liner about path-typed flags delegating to the shell's own file completer (`--dir <TAB>` → `~/`, globs, cdpath). Single eval registers BOTH `runner` and `run` thanks to the sibling-binary detection in cmd/completions.rs.
17,429 → 14,572 bytes (-2,857, -16.4%). Now fits in the initial congestion window (10 × 1460 = 14,600) so a fresh visitor's first flight delivers the whole page — single round-trip, even uncompressed. Brotli compressed: 3,619 bytes. Cuts: - Drop inline SVG favicon (-344) → empty data: URI - Drop OG url + type metas (-180); shorten description copy (-100) - Drop view-source easter comments + verbose section comments (-280) - Trim font stack: drop "IBM Plex Mono" + "DejaVu Sans Mono" (-50) - Drop text-rendering, font-feature-settings, -webkit-text-size-adjust, -webkit-appearance — modern browsers don't need any of them (-200) - Drop .meta-tight / .meta-loose helper classes (consolidate to .meta) - Drop .term box-shadow (decorative, invisible against dark bg) - Drop text-decoration-thickness + from-font keywords on a (-90) - Inline single-use --term-bg/--term-link/--term-green vars (-130) - Shorten --term-dim/--term-bold to 3-digit hex (-15) - Refactor footer: drop .sep span structure for inline text (-200) - Drop the textarea fallback in the click-to-copy script. The site is https-only, modern clipboard API works in all secure contexts; catch fails silently (-450). Both validators clean: html-validate exit 0, biome lint exit 0.
- site/public/favicon.svg: serve the icon as a 241-byte file rather than inlining a data: URI. HTML now references it as `<link rel="icon" href="favicon.svg">` (31 bytes vs ~500 inline). - index.html: 14,505 bytes — 95 under IW10 (14,600). Trim font stack to ui-monospace/Menlo/Consolas/monospace so dprint keeps it on one line; trim meta description; drop og:description. - .dprint.json: bump markup printWidth to 160 so dprint stops splitting one-line meta tags into multi-line forms. - .zed/settings.json: associate .ico as SVG syntax for the editor. Both validators clean.
Rename favicon.svg → favicon.ico (same SVG bytes) and override the Content-Type via `_headers` to `image/svg+xml`. Browsers auto-request `/favicon.ico` regardless of the `<link>` tag; Cloudflare's extension-based MIME detection would otherwise serve it as `image/x-icon`, which the browser refuses to parse as SVG — especially with `X-Content-Type-Options: nosniff` set globally. Bumped `Cache-Control` on the icon to 1d/30d since favicons rarely change. Updated `<link rel="icon">` href to match.
`287659d` dropped the local `wrangler` devDep in favour of `bunx wrangler`, which left the `$schema` reference at `./node_modules/wrangler/config-schema.json` — a path that only resolves after a hypothetical install that no longer happens. Editors (Zed, VSCode) couldn't pick up schema completions/validation on a fresh clone. Switch to `https://www.unpkg.com/wrangler/config-schema.json` so the schema resolves without any local install. Tracks latest, same as `bunx wrangler` does at runtime.
Below 40rem (~640px) the install grid and terminal blocks were overflowing the viewport — `.copy .cmd` had `white-space: nowrap`, so the longer `cargo install --git=...` command pushed the box wider than the screen and forced horizontal scroll on the whole page. Tighten `main` padding (3rem → 2.5rem 1.1rem), shrink `.copy` and `.term` type, and let command text wrap with `overflow-wrap: anywhere` so URLs break cleanly. Pull `hr.rule` margin in too — the section gaps felt cavernous once the rest scaled down. No desktop change; rules are scoped to `(max-width: 40rem)`.
Add `public/404.html` and flip `not_found_handling` from `single-page-application` to `404-page` so wrangler serves the file on unmatched paths instead of rewriting to `/`. The page mirrors the main site's palette + mono stack and shows a fake `runner <requested-path>` error line so the 404 reads like the CLI itself rather than a generic browser page. Also flip `workers_dev` to `true` so the *.workers.dev preview URL stays reachable alongside the custom domain.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
runner-site | 1306ec3 | Commit Preview URL Branch Preview URL |
May 05 2026, 08:31 AM |
📝 Walkthroughfeat(site): add runner.kjanat.com landing page Add a single-file static landing site for runner, deployed via Cloudflare Workers Static Assets at runner.kjanat.com. Minimal payload (index.html ~3.6 KB brotli, 404.html ~1 KB brotli) sized to fit within TCP IW10 with headroom. Self-contained styles with light/dark support (prefers-color-scheme) and a mobile breakpoint at 40rem. Content & UX
Infrastructure & config
Developer tooling & docs
Testing & verification
Docs
Notes / feedback
WalkthroughAdds a new static site under ChangesWebsite Launch with Cloudflare Worker Infrastructure
sequenceDiagram
participant Dev as Developer
participant Bun as Bun CLI
participant Wr as Wrangler
participant CF as Cloudflare Worker
participant Browser as Browser
Dev->>Bun: run `bun --cwd=site deploy`
Bun->>Wr: invoke Wrangler deploy script
Wr->>CF: upload `site/public` assets and publish Worker (compatibility_date: 2026-05-05)
CF-->>Wr: confirm deployment
Browser->>CF: GET https://runner.kjanat.com/
CF-->>Browser: serve `index.html` or `404-page` from static assets
🚥 Pre-merge checks | ✅ 7 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (7 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
This comment was marked as resolved.
This comment was marked as resolved.
There was a problem hiding this comment.
♻️ Duplicate comments (1)
site/public/index.html (1)
407-414:⚠️ Potential issue | 🟠 Major | ⚡ Quick winStop shipping mutable refs in install/docs commands.
Line 407andLine 412copy commands from moving targets, andLines 419/557link tomaster. That weakens integrity and reproducibility. Also,Line 414displays a shortened command that doesn’t exactly match what gets copied. Pin to the release (v0.6.0) or a commit SHA and keep displayed/copy text identical.⚓ Suggested patch
- <button class="copy" type="button" data-cmd="cargo install --git=https://github.com/kjanat/runner/ runner"> + <button class="copy" type="button" data-cmd="cargo install --git=https://github.com/kjanat/runner --tag v0.6.0 runner"> <span class="label">cargo · from source</span> - <span class="cmd">cargo install --git=https://github.com/kjanat/runner/ runner</span> + <span class="cmd">cargo install --git=https://github.com/kjanat/runner --tag v0.6.0 runner</span> <span class="toast" aria-hidden="true">copied</span> </button> - <button class="copy" type="button" data-cmd="curl -fsSL https://raw.githubusercontent.com/kjanat/runner/master/install.sh | sh"> + <button class="copy" type="button" data-cmd="curl -fsSL https://raw.githubusercontent.com/kjanat/runner/v0.6.0/install.sh | sh"> <span class="label">linux installer</span> - <span class="cmd">curl -fsSL …/install.sh | sh</span> + <span class="cmd">curl -fsSL https://raw.githubusercontent.com/kjanat/runner/v0.6.0/install.sh | sh</span> <span class="toast" aria-hidden="true">copied</span> </button> @@ - The npm package is a façade — installs only the <a href="https://github.com/kjanat/runner/tree/master/npm">prebuilt binary</a> for your platform via + The npm package is a façade — installs only the <a href="https://github.com/kjanat/runner/tree/v0.6.0/npm">prebuilt binary</a> for your platform via <code>optionalDependencies</code>. No postinstall, no network at install time. @@ - href="https://github.com/kjanat/runner/blob/master/CHANGELOG.md" + href="https://github.com/kjanat/runner/blob/v0.6.0/CHANGELOG.md"Also applies to: 419-420, 557-558
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@site/public/index.html` around lines 407 - 414, Update the install command buttons to stop referencing moving targets: replace the git URL and raw URL in the data-cmd attributes on the copy buttons (the <button class="copy"> elements that contain the span.label and span.cmd) with a pinned release tag (e.g. v0.6.0) or a specific commit SHA, and ensure the visible span.cmd text exactly matches the data-cmd value (do this for the cargo install --git=… runner command and the curl …/install.sh | sh command and the other occurrences mentioned). Also update the links that currently point to master (the install.sh and repository links) to the same pinned tag/sha so displayed, copied, and linked targets are identical and reproducible.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In `@site/public/index.html`:
- Around line 407-414: Update the install command buttons to stop referencing
moving targets: replace the git URL and raw URL in the data-cmd attributes on
the copy buttons (the <button class="copy"> elements that contain the span.label
and span.cmd) with a pinned release tag (e.g. v0.6.0) or a specific commit SHA,
and ensure the visible span.cmd text exactly matches the data-cmd value (do this
for the cargo install --git=… runner command and the curl …/install.sh | sh
command and the other occurrences mentioned). Also update the links that
currently point to master (the install.sh and repository links) to the same
pinned tag/sha so displayed, copied, and linked targets are identical and
reproducible.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: a95f2bae-f95e-40c3-99d8-bf458a1694ff
📒 Files selected for processing (1)
site/public/index.html
📜 Review details
⏰ Context from checks skipped due to timeout of 18000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: verify
- GitHub Check: Workers Builds: runner-site
- GitHub Check: Analyze (rust)
- GitHub Check: Analyze (actions)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (2)
site/public/index.html (2)
353-359: Ahoy — mobile layout fix be solid.
Line 357now forces single-column matrix lists on small screens, andLines 363-369let long commands wrap instead of wrecking the viewport. Nice cleanup for handhelds.Also applies to: 363-369
385-385: Aye, this copy-status accessibility patch is properly shipshape.Live region +
aria-hiddentoast + reset-and-reannounce logic makes repeat copy feedback readable for assistive tech without breaking visual toast behavior.Also applies to: 564-578
CodeQL flagged the previous workflow_run + checkout-of-tag pattern as "untrusted code in a privileged context" (security/code-scanning #7-9): workflow_run runs with secrets, and `cargo publish` executes build.rs from the tag-controlled checkout, which would let a malicious tag exfiltrate CARGO_REGISTRY_TOKEN. Switch the trigger to `release: types: [published]`. release.yml still creates the release as a draft — a maintainer must review and click publish, which becomes the human gate. The `crates-io` environment's required reviewers are the second gate. workflow_dispatch is preserved for manual republishes.
- mobile: copy buttons no longer blow out viewport. min-width: 0 on .copy lets the grid item shrink below min-content; word-break and overflow-wrap on .cmd let long URLs wrap. html/body get overflow-x: hidden as a safety net. - copy: only mark "copied" when clipboard.writeText resolves; on failure, surface "Copy failed" via a polite live region so screen readers announce the result. - README: 404.html now listed in the layout tree.
The .toast spans say "copied" visually, but we already announce copy status via the polite live region. Marking them aria-hidden keeps screen readers from reading the toast text alongside the button name and the announcement.
.matrix ul forced two columns at every viewport. On phones that's a cramped newspaper split — package.json / turbo.json wrap awkwardly. Override to columns: 1 inside the existing 40rem media query.
ARIA live regions don't always re-announce identical text, so clicking the same copy button twice could go silent for screen readers. Clear the region and set the message on a microtask delay so each copy attempt is spoken.
Single-column 12-item list ate half the screen. Switch the matrix lists to flex-wrap with bullet separators on mobile, so they read as a compact inline group (npm · yarn · pnpm · …) and reflow naturally to the available width.
Replaces the bare "Website:" line with a small block linking the landing page (with a pointer to its source under site/) and the npm package. Adds two shields.io badges at the top: npm version of runner-run and MIT license.
There was a problem hiding this comment.
♻️ Duplicate comments (2)
site/public/index.html (2)
425-427:⚠️ Potential issue | 🟠 Major | ⚡ Quick winInstaller command is still pinned to mutable
master.Line 425 copies a
curl | shcommand from a moving branch tip. That weakens integrity guarantees and can silently change executed code. Pin to a release tag (or commit SHA), and keep visible command text in sync.Patch sketch
- <button class="copy" type="button" data-cmd="curl -fsSL https://raw.githubusercontent.com/kjanat/runner/master/install.sh | sh"> + <button class="copy" type="button" data-cmd="curl -fsSL https://raw.githubusercontent.com/kjanat/runner/v0.6.0/install.sh | sh"> <span class="label">linux installer</span> - <span class="cmd">curl -fsSL …/install.sh | sh</span> + <span class="cmd">curl -fsSL https://raw.githubusercontent.com/kjanat/runner/v0.6.0/install.sh | sh</span> <span class="toast" aria-hidden="true">copied</span> </button>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@site/public/index.html` around lines 425 - 427, The installer curl command in the copy button (button.copy with data-cmd attribute and the visible span.cmd text) points to the mutable branch "master"; update the data-cmd URL to a fixed release tag or commit SHA (e.g., replace /master/install.sh with /vX.Y.Z/install.sh or /<commit-sha>/install.sh) and update the visible span.cmd text to exactly match the pinned URL so the displayed command and the data-cmd stay in sync.
357-372:⚠️ Potential issue | 🟠 Major | ⚡ Quick winMobile matrix layout still degrades on narrow screens.
Line 357 through Line 372 keeps the wrapped inline flow; on tight widths, separators can appear at row starts and readability drops hard. That aligns with the “looks bad on mobile” report. Add a narrow-breakpoint stacked fallback.
Patch sketch
`@media` (max-width: 40rem) { .matrix ul { columns: auto; display: flex; flex-wrap: wrap; align-items: baseline; font-size: 0.9rem; } .matrix li + li::before { content: "·"; color: var(--dim); padding: 0 0.5rem; opacity: 0.7; } } +@media (max-width: 28rem) { + .matrix ul { + display: block; + columns: 1; + } + .matrix li { + padding: 0.05rem 0; + } + .matrix li + li::before { + content: none; + } +}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@site/public/index.html` around lines 357 - 372, The current .matrix ul/.matrix li layout uses flex-wrap and a middle-dot separator (.matrix li + li::before) which causes separators to wrap to line starts on narrow screens; add a narrow-screen fallback (media query) that switches .matrix ul to a stacked/block or column layout (e.g., display: block or flex-direction: column) and disable or hide the separator pseudo-element (.matrix li + li::before) at that breakpoint so list items stack cleanly on mobile while keeping the inline/multi-column layout for wider viewports.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In `@site/public/index.html`:
- Around line 425-427: The installer curl command in the copy button
(button.copy with data-cmd attribute and the visible span.cmd text) points to
the mutable branch "master"; update the data-cmd URL to a fixed release tag or
commit SHA (e.g., replace /master/install.sh with /vX.Y.Z/install.sh or
/<commit-sha>/install.sh) and update the visible span.cmd text to exactly match
the pinned URL so the displayed command and the data-cmd stay in sync.
- Around line 357-372: The current .matrix ul/.matrix li layout uses flex-wrap
and a middle-dot separator (.matrix li + li::before) which causes separators to
wrap to line starts on narrow screens; add a narrow-screen fallback (media
query) that switches .matrix ul to a stacked/block or column layout (e.g.,
display: block or flex-direction: column) and disable or hide the separator
pseudo-element (.matrix li + li::before) at that breakpoint so list items stack
cleanly on mobile while keeping the inline/multi-column layout for wider
viewports.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: ddb87bb4-a4fb-4f99-9bf2-d1a7e00ff5a1
📒 Files selected for processing (3)
README.mdsite/README.mdsite/public/index.html
📜 Review details
⏰ Context from checks skipped due to timeout of 18000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: verify
- GitHub Check: Analyze (rust)
- GitHub Check: Analyze (actions)
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: Workers Builds: runner-site
🔇 Additional comments (3)
README.md (1)
3-10: Solid docs touch-up.Badges and the new Site entry are clear, accurate, and make discovery easier. Nice, clean addition.
site/public/index.html (1)
398-399: Accessibility feedback wiring is in good shape now.The live region and status reset/update flow are implemented correctly; this is a clean fix.
Also applies to: 587-591
site/README.md (1)
29-37: Docs layout tree is accurate and useful.Including
public/404.htmland the worker config context makes ops/debug flow much clearer. Shipshape docs.
CodeQL flagged the previous workflow_run + checkout-of-tag pattern as "untrusted code in a privileged context" (security/code-scanning #7-9): workflow_run runs with secrets, and `cargo publish` executes build.rs from the tag-controlled checkout, which would let a malicious tag exfiltrate CARGO_REGISTRY_TOKEN. Switch the trigger to `release: types: [published]`. release.yml still creates the release as a draft — a maintainer must review and click publish, which becomes the human gate. The `crates-io` environment's required reviewers are the second gate. workflow_dispatch is preserved for manual republishes.
## Summary - Static landing page deployed to Cloudflare Workers Assets, served at `runner.kjanat.com`. - Single `index.html` (~3.6 KB brotli) + `404.html` (~1 KB brotli); whole first response fits inside TCP IW10 with headroom. - Self-contained styles, light/dark via `prefers-color-scheme`, mobile breakpoint at 40 rem. - Wrangler config: custom domain route, `workers_dev: true`, `not_found_handling: "404-page"`, observability on. - Auxiliary: `_headers`, `robots.txt`, SVG favicon served as `favicon.ico`, biome + dprint config.
Summary
runner.kjanat.com.index.html(~3.6 KB brotli) +404.html(~1 KB brotli); whole first response fits inside TCP IW10 with headroom.prefers-color-scheme, mobile breakpoint at 40 rem.workers_dev: true,not_found_handling: "404-page", observability on._headers,robots.txt, SVG favicon served asfavicon.ico, biome + dprint config.Test plan
Verified against deployed preview
https://b59e94b1-runner-site.kaj-kowalski.workers.dev/and prodhttps://runner.kjanat.com/.bun devinsite/starts wrangler dev on:8787/returns 200 +index.html/bogusreturns 404 + branded404.html(not soft-404 / not 200)/indexand/index.htmlredirect 307 →/prefers-color-scheme: darkbun checkandbun lintpass (1 advisory warning: emptycatch {}in copy-button clipboard fallback — intentional, can be addressed separately)runner.kjanat.comresolves to deployed Worker