Bug
The admin shell's stylesheet (node_modules/emdash/src/astro/routes/admin.astro) is imported as:
import adminStylesUrl from "@emdash-cms/admin/styles.css?url";
and rendered as <link rel="stylesheet" href={adminStylesUrl} />.
Under astro dev with the @astrojs/cloudflare adapter, the browser's subsequent request for that stylesheet 500s with:
Transform failed with 1 error:
[PARSE_ERROR] Unexpected token
- in node_modules/@emdash-cms/admin/dist/styles.css?direct at 73..83
Plugin: vite:oxc
This breaks every /_emdash/admin/* route in local dev — the HTML shell itself returns 200, but it's completely unstyled since the stylesheet request fails.
Versions
astro 7.2.1
@astrojs/cloudflare 14.2.1
emdash 0.33.0
@emdash-cms/cloudflare 0.33.0
vite 8.2.1 (hoisted by astro/@astrojs/cloudflare)
- Node v24.12.0
Reproduce
npm install --legacy-peer-deps
npm run dev
Then, in another terminal, request the stylesheet the way a browser <link> does (Accept: text/css):
curl -s -w "HTTP %{http_code}\n" \
-H "Accept: text/css,*/*;q=0.1" \
"http://127.0.0.1:4321/node_modules/@emdash-cms/admin/dist/styles.css"
Expect HTTP 500 with the [PARSE_ERROR] ... vite:oxc body above. Visiting /_emdash/admin/login in a real browser shows the same thing — the HTML loads, but the linked stylesheet 500s.
A minimal reproduction repo is available at: https://github.com/bvjebin/emdash-cf-css-issue
Root cause (as far as we've traced it)
Vite's ?url CSS import resolves in dev to the file's bare path. When the browser later requests that path as a <link> (Accept: text/css), Vite's dev middleware appends a ?direct query to mean "give me raw CSS, not a JS module" (isDirectCSSRequest/directRequestRE in vite/dist/node/chunks/node.js).
We traced this with DEBUG=vite:plugin-transform astro dev and found:
- The
?url-imported JS module itself (styles.css?url) transforms fine (it's real JS — export default "/path/to/styles.css").
- The
?direct raw-CSS request is what fails, and only under @astrojs/cloudflare's bundled/workerd Vite environment.
vite:css / vite:css-post (which explicitly return null for direct CSS requests, expecting the raw CSS to pass through untouched) run first without error, but the raw CSS text then ends up handed to a JS-oriented transform (reported as vite:oxc), which fails to parse @layer properties{@supports (...)} — valid CSS, invalid JS.
- A project-level
postcss.config.cjs had no effect on this — ruled out as a contributing factor.
This looks like an interaction between @cloudflare/vite-plugin's bundled/workerd dev environment (which substitutes a different, rolldown-based JS transform plugin for the normal one) and Vite's ?direct CSS-serving mechanism, which isn't being correctly excluded from that substitution. We haven't root-caused this inside @cloudflare/vite-plugin/Vite itself.
Workaround
Importing the stylesheet with ?raw instead of ?url, and rendering it as an inline <style set:html={...}> instead of a <link>, sidesteps the browser's follow-up ?direct request entirely:
-import adminStylesUrl from "@emdash-cms/admin/styles.css?url";
+import adminStylesRaw from "@emdash-cms/admin/styles.css?raw";
...
-<link rel="stylesheet" href={adminStylesUrl} />
+<style set:html={adminStylesRaw}></style>
Happy to open a PR with this change (guarded to keep the original ?url/<link> behavior for setups not on @astrojs/cloudflare, if that's preferred) — let me know if that approach is acceptable.
Bug
The admin shell's stylesheet (
node_modules/emdash/src/astro/routes/admin.astro) is imported as:and rendered as
<link rel="stylesheet" href={adminStylesUrl} />.Under
astro devwith the@astrojs/cloudflareadapter, the browser's subsequent request for that stylesheet 500s with:This breaks every
/_emdash/admin/*route in local dev — the HTML shell itself returns 200, but it's completely unstyled since the stylesheet request fails.Versions
astro7.2.1@astrojs/cloudflare14.2.1emdash0.33.0@emdash-cms/cloudflare0.33.0vite8.2.1 (hoisted by astro/@astrojs/cloudflare)Reproduce
Then, in another terminal, request the stylesheet the way a browser
<link>does (Accept: text/css):Expect
HTTP 500with the[PARSE_ERROR] ... vite:oxcbody above. Visiting/_emdash/admin/loginin a real browser shows the same thing — the HTML loads, but the linked stylesheet 500s.A minimal reproduction repo is available at: https://github.com/bvjebin/emdash-cf-css-issue
Root cause (as far as we've traced it)
Vite's
?urlCSS import resolves in dev to the file's bare path. When the browser later requests that path as a<link>(Accept: text/css), Vite's dev middleware appends a?directquery to mean "give me raw CSS, not a JS module" (isDirectCSSRequest/directRequestREinvite/dist/node/chunks/node.js).We traced this with
DEBUG=vite:plugin-transform astro devand found:?url-imported JS module itself (styles.css?url) transforms fine (it's real JS —export default "/path/to/styles.css").?directraw-CSS request is what fails, and only under@astrojs/cloudflare's bundled/workerd Vite environment.vite:css/vite:css-post(which explicitlyreturn nullfor direct CSS requests, expecting the raw CSS to pass through untouched) run first without error, but the raw CSS text then ends up handed to a JS-oriented transform (reported asvite:oxc), which fails to parse@layer properties{@supports (...)}— valid CSS, invalid JS.postcss.config.cjshad no effect on this — ruled out as a contributing factor.This looks like an interaction between
@cloudflare/vite-plugin's bundled/workerd dev environment (which substitutes a different, rolldown-based JS transform plugin for the normal one) and Vite's?directCSS-serving mechanism, which isn't being correctly excluded from that substitution. We haven't root-caused this inside@cloudflare/vite-plugin/Vite itself.Workaround
Importing the stylesheet with
?rawinstead of?url, and rendering it as an inline<style set:html={...}>instead of a<link>, sidesteps the browser's follow-up?directrequest entirely:Happy to open a PR with this change (guarded to keep the original
?url/<link>behavior for setups not on@astrojs/cloudflare, if that's preferred) — let me know if that approach is acceptable.