Skip to content

Move the frontend from pnpm and Node to Bun - #14

Merged
firsttris merged 2 commits into
mainfrom
bun-migration
Nov 4, 2026
Merged

firsttris merged 2 commits into
mainfrom
bun-migration

Conversation

@firsttris

Copy link
Copy Markdown
Owner

Moves the frontend in app/ from pnpm and Node to Bun as package manager, script runner and Playwright runner, following firsttris/workflows tech-stack.md ("Tooling") and the migrations of haul and windfenster.

Changes

  • app/package.json: packageManager: bun@1.4.4 (was pnpm@12.16.1); scripts chain bun run i18n; e2e is bun --bun playwright test (app/ already has "type": "module").
  • app/bun.lock converted from pnpm-lock.yaml by bun install: the same 378 package@version pairs (compared one by one). app/bunfig.toml: linker = "isolated" (pnpm's layout) and minimumReleaseAge = 86400 (pnpm 12's default). pnpm-lock.yaml removed (no other pnpm files or settings existed).
  • playwright.config.ts web server: bun --bun vite --mode mock.
  • tauri.conf.json: beforeDevCommand/beforeBuildCommand → bun run dev / bun run build.
  • justfile: setup, dev, dev-mock, lint, format, test-frontend, e2e, build call bun (bindings is cargo only).
  • scripts/screenshots.sh: bun run build, bun --bun vite preview, bun scripts/screenshots.mjs.
  • CI (ci.yml, release.yml): oven-sh/setup-bun@v2 with bun-version-file: app/package.json, bun install --frozen-lockfile; no setup-node, pnpm/action-setup or pnpm store cache. Releases build with bun run tauri build (the repo does not use tauri-action). Playwright image from app/bun.lock; in it the E2E job installs Bun with npm install --global "bun@$(node -p ...packageManager...)".
  • screenshots.yml: the shared workflow's install installs the same Bun the same way, lockfile: app/bun.lock.
  • Renovate: custom manager for packageManager in app/package.json, its own "Bun" group.
  • Docs (development.md, installation.md) and packaging/toolbox.sh: Bun instead of Node and pnpm.

Checks (locally)

pnpm/Node (main) Bun (this branch)
install --frozen-lockfile ok ok, 263 packages, lockfile unchanged
Biome 78 files, 1 warning 78 files, 1 warning (the same)
tsc -b ok ok
Vitest + coverage 13 files, 147 tests, 95.39 % lines stmts 13 files, 147 tests, same coverage
vite build ok ok
Playwright (mock backend, Chromium) 69 passed, 1 skipped (1 worker) 69 passed, 1 skipped (1 and 2 workers)
mkdocs build --strict ok
Renovate config validator ok

Also: bun scripts/screenshots.mjs against bun --bun vite preview took all 12 pictures (into a temp folder, nothing committed).

Not verified

  • Cargo fmt/clippy/test and the Tauri app build (bun run tauri dev/build) were not run (no WebKitGTK here); bun run tauri --version works.
  • just itself is not installed here; the recipes' commands were run directly.
  • WebKit project of Playwright (CI only) and the workflows themselves: CI on this PR will show.

Generated by Claude Code

Bun installs app/'s packages, runs its scripts and the Playwright runner, as
firsttris/workflows tech-stack.md ("Tooling") asks and as haul and windfenster
already do.

- app/package.json: packageManager bun@1.4.4; the scripts chain `bun run i18n`;
  e2e is `bun --bun playwright test` (app/ already is "type": "module"), and
  Playwright's web server `bun --bun vite --mode mock`.
- app/bun.lock converted from pnpm-lock.yaml by `bun install`: the same 378
  package versions. bunfig.toml keeps pnpm's isolated layout and pnpm 12's
  one-day minimum release age; pnpm-lock.yaml is gone.
- tauri.conf.json, the justfile and scripts/screenshots.sh call bun.
- CI and release: setup-bun with bun-version-file app/package.json and
  `bun install --frozen-lockfile` instead of pnpm/action-setup and setup-node;
  in the Playwright image (E2E job, screenshots workflow) npm installs the Bun
  of packageManager, read with node (the image has no jq or unzip).
- Renovate: packageManager as a dependency of its own, in a "Bun" PR.
- Docs and the toolbox script: Bun instead of Node and pnpm.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y3rdfbWb1xDUdPRng7TX9Z
main's lock file maintenance (#13) only touched app/pnpm-lock.yaml, which this branch
replaces with app/bun.lock, so the file stays deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y3rdfbWb1xDUdPRng7TX9Z

Copy link
Copy Markdown
Owner Author

TDD review: no proven findings

I reviewed the migration and tried to prove every suspicion with a test or a run. None turned red, so there is nothing to fix in the PR itself.

Checked (all green):

  • Bump workflow: ran the Python step of firsttris/workflows bump-version.yml (version-file: Cargo.toml, extra-files: app/package.json, patch) on a copy of the branch. Result 0.1.8 → 0.1.9: Cargo.toml, Cargo.lock, app/package.json; the root package in bun.lock carries no version, so the lock stays as it is, and bun install --frozen-lockfile still passes afterwards.
  • Renovate regex: "packageManager": "bun@(?<currentValue>\d+\.\d+\.\d+)" matches app/package.json (currentValue: 1.4.4), and managerFilePatterns matches app/package.json.
  • Release on macOS: bun.lock contains the darwin arm64/x64 binaries of @tauri-apps/cli, rolldown, lightningcss, @tailwindcss/oxide, Biome and oxc-minify, so bun install --frozen-lockfile on macos-26 has what bun run tauri build --target universal-apple-darwin needs.
  • Without Node on PATH (the toolbox no longer installs nodejs): bun run tauri --version (tauri-cli 2.12.4), bun run build, bun run lint and bun run coverage (147 tests, thresholds met) all pass. Bun stands in for the node shebangs.
  • scripts/screenshots.sh with Playwright's Chromium: build, vite preview on 4317, the bun -e fetch probe (exit 1 without a server, 0 with one) and bun scripts/screenshots.mjs all ran through, and every picture was taken. kill $server also stops the vite child that bun --bun vite starts, so the trap leaves no server running.
  • Workflow snippets: the node -p "require('./package.json').packageManager.split('@')[1]" in ci.yml (cwd app) and the folded install input of screenshots.yml (from the repo root) both give 1.4.4; install and command are separate steps in the reusable workflow, so the cd app does not affect bash scripts/screenshots.sh.
  • bunx --package <pkg> <bin> (the validator hint in renovate.json5) is accepted by Bun 1.4.4.

Dropped (no failing test):

  • Renovate's npm manager already extracts packageManager: bun@… itself (extracts bun packageManager in renovate's lib/modules/manager/npm/extract/index.spec.ts), so the custom regex manager reports the same dependency a second time. Both land in the same "Bun" group and branch. I could not show a failure without a Renovate run, so this is only a note.
  • packaging/toolbox.sh and the Debian instructions install the newest Bun (curl … | bash), not the packageManager version. No failure could be shown.

Merge conflict: main's lock file maintenance (#13) changed app/pnpm-lock.yaml, which this branch deletes. I merged origin/main and kept the file deleted (376527c).

Checks on the merged branch (376527c): Biome, tsc -b, Vitest with coverage (147 passed, 96.68 % lines) and Playwright on the mock backend in Chromium (69 passed, 1 skipped) are green.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

TDD-Review abgeschlossen: keine belegten Findings; main ohne Force-Push eingemergt (376527c). CI grün: Frontend, Playwright E2E, Rust Linux/macOS, Coverage. Merge per Squash.


Generated by Claude Code

@firsttris
firsttris merged commit 9bcf9fb into main Nov 4, 2026
6 checks passed
@firsttris
firsttris deleted the bun-migration branch November 4, 2026 08:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants