Skip to content

Fix main on Nuxt 4: CSS minify error and CSP-blocked import map - #241

Merged
darkmastermindz merged 1 commit into
mainfrom
nuxt4-build
Oct 24, 2026
Merged

darkmastermindz merged 1 commit into
mainfrom
nuxt4-build

Conversation

@darkmastermindz

Copy link
Copy Markdown
Owner

Summary

Main is broken. Dependabot's security group update (#240) moved Nuxt from 3.x to 4.6.2, and every Netlify deploy since has failed: main's, and the previews for #230 and #231. There are two separate problems:

  1. The build fails. Nuxt 4 minifies CSS with Lightning CSS, which stops at tachyons' old Internet Explorer hacks (.cf{*zoom:1}):
    SyntaxError: [lightningcss minify] Unexpected end of input
  2. Once built, nothing runs. Nuxt 4 loads the app through an inline <script type="importmap"> that maps #entry to the entry chunk.
    • scripts/lib/csp.mjs only hashed classic and module inline scripts, so the enforced Content-Security-Policy blocked the import map.
    • Every page then threw Failed to resolve module specifier "#entry" and stayed static HTML: no coin, no cards, no navigation scripts.
    • The Android touch tests from Playwright: touch scrolling tests on every Android device (100 profiles) #238 caught this. All 105 tests failed with that error until the fix.

Related Issue

None. Found while checking #230's failed deploy preview, after #240 was merged.

Changes Made

  • nuxt.config.js: vite.css.lightningcss.errorRecovery: true, so the minifier drops the old IE hacks instead of failing. No modern browser reads them anyway.
  • scripts/lib/csp.mjs: inlineScriptHashes also hashes type="importmap". Browsers apply script-src to inline import maps.
  • tests/security/headers.test.mjs: a new test checks that inline import maps are hashed, whatever the case of the type attribute.

Testing

  • Before, on main at 450882e: npm run generate fails with the Lightning CSS error.
  • After:
    • npm test: 221 pass. npm run generate succeeds: Nuxt 4.6.2, Vite 8.3.5, 16 pages.
    • build-csp now allows 2 inline scripts by hash (the payload script and the import map).
  • Android touch tests (Playwright: touch scrolling tests on every Android device (100 profiles) #238): 93 passed, 12 skipped, 0 failed on Galaxy S9+, Pixel 7, Galaxy Tab S9 (landscape), Galaxy Z Fold 7 and Moto G4 (landscape). This PR's CI runs all 100 devices.
  • Nuxt 3 vs Nuxt 4 screenshots: I compared full-page screenshots of the Nuxt 3 build (640e4e1) and this branch, pixel by pixel.
    • Pages: /, /bio, /blog, /projects, /gear/outdoor and /terms, on desktop (1280px) and a Pixel 7.
    • Page heights are identical, and the app runs on both.
    • 11 of the 12 are pixel-identical. On the desktop home page, the About card opened on a different, randomly chosen tab.

Additional Information


Generated by Claude Code

Dependabot's #240 moved Nuxt from 3 to 4, and main broke twice:

- The build failed: Nuxt 4 minifies CSS with Lightning CSS, which stops
  at tachyons' old IE hacks (`*zoom: 1`). Error recovery drops them.
- Once built, no script ran: Nuxt 4 loads the app through an inline
  <script type="importmap">, and build-csp only hashed classic and
  module scripts, so the enforced CSP blocked the map ("Failed to
  resolve module specifier #entry") and every page stayed static.
  Import maps are now hashed too, with a test.

The Android touch suite caught the second one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nginuw5wmUjUSkmQB1J3pS
darkmastermindz pushed a commit that referenced this pull request Oct 24, 2026
…rt map)

Same change as #241, so this branch builds and runs on main's Nuxt 4
(from #240). It no-ops once #241 is merged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nginuw5wmUjUSkmQB1J3pS
@darkmastermindz
darkmastermindz merged commit 1bdcf3a into main Oct 24, 2026
12 checks passed
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