AstroEco is Contributing…
Display your GitHub pull requests using astro-loader-github-prs

Changes
- Dynamic endpoint routes with a file extension (e.g.
[...slug].png.ts) no longer fail withNoMatchingStaticPathFoundduringastro buildwhentrailingSlash: "always"is set.stringifyParams()now mirrors thetrailingSlashForPath()logic already used in route pattern generation: when a route is an endpoint with a file extension, trailing slash is forced to'never', so generated paths (e.g./og/foo.png) match the route pattern (e.g./^\/og\/(.*?)\.png$/). The mismatch affected both ASCII and non-ASCII params.
Closes #17306
Testing
- Added three unit tests in
packages/astro/test/units/routing/get-params.test.tscovering:- Spread file-extension endpoint with non-ASCII params +
trailingSlash: 'always'— path must not get a trailing slash and must match the route pattern. - Single dynamic file-extension endpoint (
[name].json) with the same config. - Endpoint without a file extension still gets a trailing slash, confirming the fix is scoped correctly.
- Spread file-extension endpoint with non-ASCII params +
Docs
- No docs update needed — this is a bug fix for existing static build behavior with no API surface change.

Changes
- Fixes CSS module class names not matching between the element and the injected
<style>tag inastro devwhen usingvite.css.transformer: 'lightningcss'with content collections. Production builds were unaffected. - Root cause:
getStylesForURL()re-imports CSS modules with?inlineappended to get the raw CSS string. Lightning CSS uses the full module ID (including?inline) as the filename for scoped-name hashing, producing a different hash than the original import. The fix shares the dev-css plugin's existingcssContentCache(which holds already-processed CSS with correct hashes) with the content asset propagation plugin, so?inlinere-imports are avoided when the cache has the result.
Testing
- Adds
packages/astro/test/lightningcss-css-modules-content.test.ts— regression test that starts a dev server withlightningcssenabled, renders a content collection page, and asserts the scoped class name on the element appears in the injected<style>tag.
Docs
- No docs update needed — this is a bug fix with no API or configuration changes.
Closes #17312

Changes
This PR fixes a memory leak in the dev server. The listener was never cleaned at the end of the request.
Testing
Manually tested. I tried an integration test, but it was ugly and weird.
Docs
N/A

Fixes #17265
Changes
- Prevents Astro from inlining script chunks when module metadata reports dynamic imports, including external dynamic imports omitted from Rolldown chunk metadata.
- Extracts the script inlining decision into testable helpers.
Testing
- Adds unit coverage for external dynamic imports reported through module info while
chunk.dynamicImportsis empty.
Docs
- No docs update needed; this restores expected build output behavior.

## Changes
- Adds dependency crawling using `vitefu` in the `@astrojs/solid-js` integration to dynamically discover Solid packages and populate `noExternal` and `external` in the Vite configuration. This ensures that SolidJS package exports (e.g. packages declaring `"solid"` fields in their `exports`) are bundled/resolved correctly during SSR and client build.
- Casts `originalEmit` to `any` in `solid-component.test.ts` when forwarding calls from the monkey-patched `process.emit`. This bypasses TypeScript's overload resolution error where the union of all Node event names is not assignable to the specific `"worker"` signature.
## Testing
- Re-enabled and updated `describe('Solid component build')` test suite in [solid-component.test.ts](file:///packages/astro/test/solid-component.test.ts) (reverted `.skip`, removed `@ts-expect-error` annotations, and replaced outdated assertions).
- Verified that all 10 Solid component build tests successfully compile and pass.
- Verified that all doctype tests in [astro-doctype.test.ts](file:///packages/astro/test/astro-doctype.test.ts) pass successfully.
## Docs
- No documentation changes needed since these are internal dependency crawling improvements and test suite fixes.
Summary
- add an Astro-specific
SatteriFeaturestype that overrides the upstreamsmartPunctuationJSDoc - export the type so consumers see the corrected default in
satteri({ features })
Fixes #17305.
Testing
corepack pnpm --filter @astrojs/prism buildcorepack pnpm --filter @astrojs/internal-helpers buildcorepack pnpm --filter @astrojs/markdown-satteri buildcorepack pnpm --filter @astrojs/markdown-satteri testcorepack pnpm exec prettier packages/markdown/satteri/src/processor.ts packages/markdown/satteri/src/index.ts --checkgit diff --check
Notes
AI-assisted. I manually reviewed the final diff and verification output.

Changes
- Extracts the
loggertype fromAPIContextto an exportedAstroComponentLoggerinterface. - This allows developers to easily type their custom middleware or integration functions that use the logger.
- Added a minor changeset.
Testing
- The change is type-only and relies on TypeScript's compilation.
- Verified by running
pnpm run typecheckandpnpm run test:match "exports". - No runtime behavioral changes were made.
Docs
- Updated docs in PR withastro/docs#14203

Changes
- Removes the dev server socket close listener after request handling completes.
- Also removes the listener when the request signal aborts, preserving the disconnect behavior added in #17133 while avoiding listener buildup on reused sockets.
- Adds a regression test that sends repeated successful dev requests over one keep-alive dispatcher and asserts no MaxListenersExceededWarning is emitted for socket close listeners.
Testing
- pnpm --filter @astrojs/node... run build:ci
- pnpm --filter astro run build:ci
- pnpm --filter astro exec astro-scripts test test/request-signal.test.ts --strip-types
- pnpm exec prettier --check packages/astro/src/vite-plugin-app/app.ts packages/astro/test/request-signal.test.ts packages/astro/test/fixtures/request-signal/src/pages/dev-signal-test.ts .changeset/clean-dev-socket-listeners.md
Docs
No docs update needed. This is internal dev-server listener cleanup and does not change the public API.

Changes
Follow-up to #17187, which pre-bundled astro/virtual-modules/transitions.js in the Cloudflare adapter's server dev environment to stop a mid-request dep optimizer reload. The same class of bug (#17166 / #16853 / #16529) still fires for pages that use the astro:components virtual module (e.g. import { Code } from "astro:components").
- The adapter's server
optimizeDepsexcludesastro:*virtual modules, so the real module behind that virtual,astro/components, is never in the boot-time include list. - It is therefore discovered by the SSR dep optimizer only at first render. On the first request after a cold optimizer cache, that late discovery triggers
optimized dependencies changed. reloadingmid-render, which the workerd module runner does not survive cleanly: components resolvereactfromnode_moduleswhilereact-dom/servercomes from a freshly re-optimizeddeps_ssrchunk. Two copies of React in one render throwInvalid hook call/Cannot read properties of null (reading 'useState')in every island, and the page returns 200 with the islands empty. - Fix: add
astro/componentsto the server-environmentoptimizeDeps.includelist, right after the existingastro/virtual-modules/transitions.jsentry, so it is pre-bundled at boot and the mid-render reload never happens.
This is the same one-line shape as #17187, for a different late-discovered virtual-module target.
Testing
Reproduced on a real Astro 7 + @astrojs/cloudflare 14.1.1 + @astrojs/react site (React 19) that renders astro:components:
- Stock adapter (bug): cold
astro dev(rm -rf node_modules/.vite), then requesting routes across the reload window. The dev log showsdependency optimized: astro/components→optimized dependencies changed. reloading→ repeatedInvalid hook callandTypeError: Cannot read properties of null (reading 'useState'). Every route still returns 200 but React islands render empty. - Patched adapter (this PR): identical cold-cache procedure. Zero optimizer reloads after startup, zero hook errors, all islands render, and warm-cache reboots stay clean.
I verified this by packing the patched adapter and pinning it into the site via a pnpm override; the bug reproduces reliably without the patch and disappears with it.
Docs
No docs needed — this is an internal dev-server dependency-optimization detail with no user-facing API change.
Add Hostgrid help center site to the showcase.
Removed broken link to ecoping.earth. The domain appears to be expired/inactive, which poses a potential security risk for documentation users.
Changes
Adds HitKeep to the Starlight showcase with an 800x450 PNG thumbnail captured from a 1280x720 desktop viewport and resized per the contributing guide.
Validation
- pnpm --filter starlight-docs build
- pnpm exec prettier --check docs/src/components/showcase-sites.astro
- pnpm --filter starlight-docs typecheck

Changes
- Adds a
deferRender?: booleanoption to theglob()loader. Whentrue, renderable content entries (e.g. Markdown) skip eager rendering during content sync and instead use the same deferred-render path that.mdxfiles already use — rendering happens on demand at page build time via the Vite markdown plugin. - This resolves OOM crashes during
astro buildfor large Markdown collections that use heavy rehype plugins likerehype-katex, where rendered HTML can be 70× larger than source. Closes #17301. - Removes the
// todo: add an explicit way to opt in to deferred renderingcomment that tracked this gap since the Content Layer was introduced.
Testing
- Unit tests in
glob-loader.test.tscover eager rendering (default), deferred rendering whendeferRender: true, and that non-renderable data entries are unaffected. - Also verified by running
node --max-old-space-size=256 astro buildagainst a 200-file KaTeX-heavy fixture. The build previously OOM'd; withdeferRender: trueit succeeds. Confirmed working by the issue reporter (@integrable).
Docs
- Docs PR: withastro/docs#14208

Closes #17297
Changes
- A
.htmlor/index.htmlsuffixed request to a dynamic endpoint route (e.g.GET /api/items/123/status.htmlforsrc/pages/api/items/[id]/status.ts) no longer crashes dev withTypeError: Missing parameter: id. - The dev route matcher strips
.html//index.htmlwhen retrying unmatched requests, butgetParams()only stripped.htmlforroute.type === 'page'. For a matched endpoint, params came back{}andstringifyParamsthrew.getParamsnow applies the same fallback for non-page routes: if the pattern doesn't match the original pathname, retry with the suffix stripped. Endpoints that legitimately capture.htmlin a param (e.g.[path]matching/file.html) match on the original pathname and are unaffected. - Especially impactful under
netlify dev, which probes.html//index.htmlvariants on any 404 — firing the crash for every dynamic API endpoint.
Testing
- Added
getParamsunit tests covering.htmland/index.htmlrequests to a dynamic endpoint route, plus a guard asserting endpoints that capture.htmlin a param keep the suffix.
Docs
No docs update needed — this restores the routing behavior users already expect.

Changes
This PR adds a new experimental option called dataStore. It allows to split the data into multiple chunks.
I also did some refactor, so that we can prepare different data sources e.g. sqlite. For this reason, the functions of the interface are also async.
Chunks are created when:
- a chunk is bigger than 10Mb in weight
- every 1000 entries
Testing
Added various tests for:
- string chucking
- data store chunking
- integration
- e2e
Docs
/cc @withastro/maintainers-docs for feedback!

Changes
- CSS
url('data:image/...')data URIs no longer crashastro buildwithENAMETOOLONGwhentsconfig.jsonhascompilerOptions.baseUrlset. Thevite-plugin-config-aliasCSS transform now skips anyurl()reference that starts withdata:, since data URIs are inline content and never valid file paths to resolve. - The regression was introduced in v7 by the
cssUrlREmatching added to the CSS transform handler (commit4766f3716d). The baseUrl alias regex/^(?!\.*\/|\.*$|\w:)(.+)$/was designed to exclude Windows drive letters but\w:only matches a single character before the colon, sodata:(4 chars) slipped through and was passed tofs.statSync().
Closes #17293
Testing
- Adds
packages/astro/test/alias-css-url-data-uri.test.tswith a fixture that combinestsconfig.jsonbaseUrl: "."and a CSSurl()data URI — verifies the build completes without error and the data URI is preserved in output.
Docs
- No docs update needed; this restores previously working behavior from v6.

Closes #16119
Changes
- Fixes a v6 regression where scoped CSS from components nested inside a
client:onlyisland was silently dropped in production builds. In dev mode everything worked fine, making the bug particularly hard to spot. - Root cause: the CSS deduplication logic in
plugin-css.tscorrectly marks a child component's CSS for deletion (it was already bundled during SSR for another page), but theclient:onlypage never participated in SSR so it never received that CSS. ThegetParentClientOnlyswalk would add the CSS topagesToCss, but the deleted asset was already gone by the timeinlineStylesheetsPluginran. - Fix: when the
getParentClientOnlyswalk finds a CSS entry that was deleted, inline the CSS content directly intopageData.stylesfromdeletedCssAssets, bypassing the need for the asset to survive toinlineStylesheetsPlugin. Content-based deduplication prevents double-injecting styles that survived deletion normally.
Testing
- Added
packages/astro/test/client-only-child-styles.test.tswith a fixture covering two scenarios: a page usingclient:only(where the child's scoped styles must be recovered fromdeletedCssAssets) and a page usingclient:loaddirectly (to confirm no regression there).
Docs
- No docs update needed — this restores behavior that already worked in v5 and is expected to work per existing docs.

Changes
- Prevents prototype pollution in config merge by filtering proto/constructor/prototype keys
- Fixes XSS in <script> and <style> elements by escaping </script> and </style> sequences in raw string children before marking as HTML-safe
- Blocks cross-origin POST regardless of Content-Type to prevent CSRF bypass (defense-in-depth; CORS preflight already protects fetch)
Testing
- Updated 2 CSRF test assertions to expect 403 instead of 200 for cross-origin JSON/octet-stream POSTs
Docs
- No docs update needed; all changes are internal hardening with no user-facing API changes

Changes
Both "Advanced Routing" and "Blog" Example Template pages presented missing spaces between the HTML tags, the file locations are respectively examples/advanced-routing/src/pages/index.astro and examples/blog/src/pages/index.astro.
Image provided below for Before and After.
Testing
Testing was made by editing the files and opening the URL in both Firefox and Chromium-based browsers and seeing if:
- The problem was present and persistent between different Browser engines.
- The patch worked.
Both showed to be true.
Docs
Unneeded, very small text changes.
Images
"examples/blog/src/pages/index.astro":
| Before | After |
|---|---|
![]() |
![]() |
"examples/advanced-routing/src/pages/index.astro":
| Before | After |
|---|---|
![]() |
![]() |

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
astro@7.0.7
Patch Changes
-
#17317
437401eThanks @ematipico! - Fixes a dev server memory leak which caused Node.js to emit warnings in the console. -
#17299
1170b6dThanks @astrobot-houston! - Fixes a dev server crash when a.htmlor/index.htmlsuffixed request (such as thosenetlify devprobes as pretty-URL fallbacks) matched a dynamic endpoint route, causing aTypeError: Missing parametererror -
#17316
ed92e31Thanks @matthewp! - Fixes a build regression that could leave unresolved preload markers in inlined scripts with external dynamic imports -
Updated dependencies [
a77af9d,4aa78d8]:- @astrojs/telemetry@3.3.3
@astrojs/cloudflare@14.1.2
Patch Changes
-
#17285
6929e40Thanks @adamchal! - Fixes build-time image optimization ignoring a custom image service registered by an integrationPreviously, when using
imageService: 'compile'orimageService: 'custom', a custom image service was only respected if it was set directly in theimage.serviceoption ofastro.config. If an integration registered the service instead, images were silently optimized with the default Sharp service at build time. A custom image service now transforms your images at build time no matter how it was configured. -
#17303
464c46eThanks @jkomyno! - Prebundlesastro/componentsand the<ClientRouter />transition runtime modules in the dev server environment so pages using them no longer trigger a mid-session dep optimizer reload, which caused React "Invalid hook call" errors in islands on the first request after a cold cache -
#17275
6a99600Thanks @matthewp! - Fixes an issue wherevarsweren't available at build time. Now the adapter loadsvarsfrom the Wrangler config soastro:envpublic variables resolve at build time -
Updated dependencies []:
- @astrojs/underscore-redirects@1.0.3
@astrojs/telemetry@3.3.3
Patch Changes
-
#17311
a77af9dThanks @gameroman! - Refactors internal WSL detection by removing theis-wsldependency. -
#17304
4aa78d8Thanks @gameroman! - Replacedwhich-pm-runsdependency withpackage-manager-detector

Closes #17283
Changes
- The first browser to connect after
astro devstarts no longer receives an immediate, unprompted full-reload. Previously,invalidateDataStore()unconditionally sent afull-reloadHMR signal during thebuildStarthook — before any client connected — causing the signal to queue and fire the moment the first WebSocket client arrived. - Adds a
notifyClientoption toinvalidateDataStore()(defaulttrue). ThebuildStartcall now passes{ notifyClient: false }, preserving the module invalidation that prevents the content layer race condition (#12866) while skipping the client reload during startup.
Testing
- Added
packages/astro/test/units/content-layer/content-virtual-mod.test.ts— verifies thatbuildStartinvalidates the data store module but does not send afull-reloadto the client HMR channel.
Docs
- No docs update needed; this is a dev-server behavior fix with no API or config changes.

Changes
Follow-up to #17099: a custom image.service was only respected during build-time image generation (imageService: 'compile' and 'custom') when set directly in the user config. A service registered by an integration via updateConfig() was silently replaced with Sharp, because the adapter's astro:config:setup runs before all integrations. The service is now resolved against the final config in astro:config:done.
Testing
- New
integration-defined-image-service.test.tscovers both modes with the service registered by an integration. - Existing image service tests pass unchanged.
Docs
Not required. Existing docs assumes this works.

Changes
<Picture inferSize>with remote URLs no longer fails withFailedToFetchRemoteImageDimensionson rate-limiting servers (e.g. Wikimedia HTTP 429). ThePicturecomponent callsgetImage()once per output format, and each call was independently invokinginferRemoteSize()— firing 2–4 HTTP requests to the same URL in rapid succession.- Fix: resolve remote dimensions once in
Picture.astrobefore thegetImage()loop, then pass explicitwidth/height(droppinginferSize) to each call. No global caches — the result is scoped to the single component render, matching the approach recommended by @matthewp.
Closes #17263
Testing
- Covered by the existing
core-image-infersize.test.tssuite, which includes aPicture component workscase withinferSizein dev mode and passes without changes. - The specific failure mode (HTTP 429 from a rate-limiting server) is not easily reproducible in CI without a live server, and was verified manually by the reporter.
Docs
- No docs update needed —
inferSizebehavior on<Picture>is unchanged from the user's perspective; this fixes a reliability regression.

Changes
- Fixes
ImageandPicturecomponent layout styles being missing inastro devwhen JavaScript is disabled. The dev CSS pipeline was caching content by raw module ID (with\0prefix) in thetransformhook, but looking it up viacollected.id— thewrapId()-transformed version (/@id/__x00__...) — causing a cache miss for virtual CSS modules and producing empty<style>tags. Switching the lookup tocollected.idKey(the raw ID) aligns both sides of the cache.
Testing
- Adds
packages/astro/test/units/dev/dev-css-virtual-modules.test.tswith three unit tests covering:wrapId()transformation behavior for virtual module IDs, the no-op behavior for filesystem paths, and the cache key mismatch that the fix resolves.
Docs
- No docs update needed — this is a dev-mode bug fix with no API surface change.
Closes #17267
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
@astrojs/starlight@0.41.3
Patch Changes
- #3911
1686eccThanks @timothyjordan! - Keeps keyboard focus inside the mobile menu while it is open, preventing focus moving to hidden interactive elements in page content.

Fixes #16790
Changes
astro:envpublic variables defined undervarsin a Wrangler config (wrangler.toml/.json/.jsonc) now resolve when imported fromastro:env/clientandastro:env/server. Previously only.dev.varswas loaded into the environment, so public vars from the Wrangler config were inlined asundefinedat build time (onlygetSecretworked).- The adapter now resolves the effective env in
astro:config:donevia wrangler'sunstable_readConfig+unstable_getVarsForDev, which merges configvarswith.dev.vars/.dev.vars.<env>/.envoverrides exactly aswrangler devdoes (respectingCLOUDFLARE_ENV), and assigns the result toprocess.env. This replaces the previous hand-rolled.dev.varsreader, so there's a single source of truth that matches Wrangler's own precedence.
Testing
- Removed the manual
process.env.API_URL/process.env.PORToverrides from theastro-envSSR tests. Those overrides were masking the bug; the tests now rely on the adapter loadingvarsfrom the fixture'swrangler.jsonc, exercising the real code path for build and dev. The existingsecret/action secretcases continue to cover.dev.varsloading through the unified path.
Docs
- No docs update needed; this makes the adapter match the already-documented
astro:envbehavior.

Changes
- Adds a
render()overload forLiveDataEntry<LiveLoaderDataType<C>>topackages/astro/templates/content/types.d.ts. Previously, the only overload covered entries fromDataEntryMap(regular content collections). When a project only useslive.config.ts,DataEntryMapis empty, sokeyof DataEntryMapresolves toneverandrender()rejects any live entry with a TypeScript error. - The new overload mirrors the pattern already used by
getLiveEntryandgetLiveCollection. Projects with onlycontent.config.tsare unaffected —LiveContentConfigresolves toneverso the overload is inert.
Closes #16688
Testing
- No new test added — the bug is in a
.d.tstype template; integration-level verification (astro sync+astro check) is covered by the existing live loaders and content collection type test suites, all of which continue to pass.
Docs
- No docs update needed. This fixes a missing type overload to match already-documented runtime behavior.

Changes
- Island component paths (
client:component-path→metadata.componentUrl) now resolve extensionless relative imports (e.g.import { Counter } from '../components/Counter') to the real file on disk, probing Vite's default extension order and then directoryindexfiles. Previously the path stayed extensionless, so theinclude/excludeglobs of JSX renderer integrations (e.g.react({ include: ['**/react/*.tsx'] })) could never match it. - This is what fixes the "Invalid hook call" warning. Because the extensionless path never matched the
includeglob, the React renderer declined the component, and Astro asked the MDX renderer next — which tests a candidate by calling it as a plain function, so anyuseStateinside triggered React 19's warning. Now the glob matches, React claims the component, and MDX never probes it. (With multiple JSX frameworks configured, the same mismatch instead hard-failed with "Unable to render" — also fixed.) - Fixes #16767
Testing
- New
test/units/util/resolve-path.test.tscovering extension probing in Vite's order, directoryindexresolution, the existing.jsx→.tsxremap, and pass-through of extension-ful, bare, and#subpath specifiers (all fail without the fix) - New
multiple-jsx-renderersfixture page using an extensionless import matched by anincludeglob — the build hard-fails on it without the fix
Docs
- No docs update needed — this makes behavior match what the integration docs already show (
includeglobs written with file extensions).

Svelte 5 renamed its internal SSR prop from $$payload to $$renderer starting in a newer patch (tracked in fix(svelte): detect Svelte components with renamed renderer prop #14433, which updated the Svelte renderer). That PR correctly updated @astrojs/svelte, but the Solid renderer has its own copy of the same Svelte-exclusion check and was not updated at the same time.
Impact: users who have both @astrojs/solid-js and @astrojs/svelte installed, and whose Svelte version compiles components with $$renderer, will see those Svelte components rendered as empty strings by the Solid renderer instead of being handed off to the Svelte renderer.
Fix: mirror the same two-prop check already used in @astrojs/svelte:
if (componentStr.includes('$$payload') || componentStr.includes('$$renderer')) return false; 
Fixes #16078
Changes
- "Go To References" invoked from a
.tsfile now finds usages inside.astrofiles that are reached throughAstro.locals.*. Previously only.astrofiles with an explicit frontmatter import were discovered; a page usingAstro.locals.utils.toUpper()was silently missed. - The
@astrojs/ts-pluginnow injects the installed Astro package'senv.d.tsandastro-jsx.d.tsinto the TypeScript program, mirroring the language server'saddAstroTypes(). Without these theAstroglobal is undeclared, so the type chain throughAstro.localscan't resolve and references aren't found. (.astrofiles themselves already enter the program via Volar's external-files mechanism, so no file-discovery change is needed.) - Passes
includeScripts: false/includeStyles: falsetoconvertToTSX()(matching the language server) so<script>/<style>bodies are no longer wrapped in{() => { ... }}arrow functions, whereimportdeclarations are syntactically invalid and pollute the virtual file.
Known limitation
References to symbols imported inside <script> tags still won't appear via the ts-plugin. Making script content reference-searchable requires getExtraServiceScripts(), which Volar explicitly does not support in the TS-plugin path (decorateLanguageServiceHost.js logs getExtraServiceScripts() is not available in TS plugin.). The Astro language server handles that case; the ts-plugin cannot without upstream Volar changes.
Note on verification
This fix ships in @astrojs/ts-plugin, which the Astro VS Code extension bundles (astro-ts-plugin-bundle, registered via typescriptServerPlugins). When the extension is installed, tsserver loads the bundled plugin, so installing a preview of the npm package into a project's node_modules does not exercise the fix. End-to-end verification requires an extension build (or disabling the extension and relying solely on the tsconfig plugins entry with the workspace TypeScript).
Testing
- Adds
test/units/astro-types.test.mts: builds the.astro→.tsxoutput for a template that only usesAstro.locals.utils.toUpper(), then runsfindReferencesthrough the raw TypeScript language service. Asserts the reference is missed without type injection and found onceaddAstroTypesruns — a direct regression test for the reported behavior.
Docs
- No docs update needed; this is an editor-tooling bug fix with no user-facing API change.

Closes #17206
Changes
- The Container API no longer emits a false deprecation warning for
markdown.gfmandmarkdown.smartypantswhen neither option was set by the user. - Root cause:
AstroContainer.create()andcreateFromManifest()passedASTRO_CONFIG_DEFAULTSdirectly tovalidateConfig(). BecauseASTRO_CONFIG_DEFAULTSincludesgfm: trueandsmartypants: true, thewarnDeprecatedMarkdownOptionscheck saw them as user-specified values. Normal builds pass raw user config (without defaults pre-applied), so the warning never fires there. The fix strips those two keys from the markdown defaults before passing tovalidateConfig().
Testing
- Added
packages/astro/test/units/render/container-deprecation.test.ts: asserts thatAstroContainer.create()with default config does not log themarkdown.gfm/smartypantsdeprecation warning.
Docs
- No docs update needed — this is a false-positive warning fix with no API or behavior change for users.

Fixes #15627
Changes
- A
<script>inside a component rendered throughAstro.slots.render()now stays at its original position instead of being hoisted to the start of the slot output (sometimes escaping its parent element entirely). This regressed in #15147 and broke Starlight components (withastro/starlight#3712) as well as any CSS relying on:first-child/sibling selectors. SlotStringnow keeps its content as an orderedchunksstream with scripts inline, resolved and deduplicated lazily at stringify time — matching how the main render path already handles instructions.
Testing
- Adds "Scripts rendered via
Astro.slots.render()preserve their position", asserting the script renders inside its<li>/<ol>rather than before them. - Verified the existing #13847 test ("Scripts in Fragment slots are processed when another slot is unused") still passes alongside the new positional behavior.
Docs
- No docs update needed; this restores previously documented
<script>positioning behavior.

Changes
create-astronow respectsHTTP_PROXY/HTTPS_PROXYenvironment variables when downloading templates. When proxy env vars are set, the CLI re-execs itself with Node.js's--use-env-proxyflag so that nativefetch()(used by@bluwy/giget-core) routes requests through the configured proxy.- Requires no new dependencies. Degrades gracefully on Node.js < v22.21.0 — older versions get the same behavior as before. The flag is available in Node.js v22.21.0+ and v24.5.0+.
Closes #13684
Testing
- Added
packages/create-astro/test/units/proxy.test.tswith two cases: one verifying thatHTTPS_PROXYis respected (a non-existent proxy causes a connection error, proving the proxy was used), and one verifying normal operation is unaffected when no proxy env vars are set.
Docs
- No docs update needed; this restores previously expected behavior with no new APIs or config options.

Changes
- Adds a
formatoption toPaginateOptionsthat accepts a(url: string) => stringcallback. When provided, it is applied to all pagination URLs (current,next,prev,first,last) after they are constructed. - This is a non-breaking, opt-in addition — default behavior is completely unchanged. Users deploying to static file servers without URL rewrite rules can now use this to append
.html(or apply any other transformation) to pagination URLs generated bypaginate().
paginate(items, {
pageSize: 10,
format: (url) => `${url}.html`,
})Closes #13604
Testing
- Added 3 new
describeblocks (8 test cases) topackages/astro/test/units/render/paginate.test.tscovering:formatapplied to all URL properties,formatskipped forundefinedURLs,formatapplied after base path is prepended, and no regression whenformatis omitted.
Docs
- The new
formatoption is documented inline via JSDoc onPaginateOptions. A docs-site update to thepaginate()reference may be warranted to surface this option for users hitting 404s on static file servers.
@withastro/maintainers-docs for feedback

Closes #17135
Changes
getPackagenow imports packages using the absolute path returned byrequire.resolve()(converted to a file URL viapathToFileURL) instead of the bare package name. Previously,require.resolve()was correctly scoped to the project'scwd, but the subsequentawait import(packageName)resolved from astro's own install location — causingastro checkto fail when astro lives in a virtual store (e.g. pnpm) outside the project directory tree.- Affects both import sites in
getPackage: the initial load and the post-install load.
Testing
- Added
packages/astro/test/units/cli/install-package.test.ts: creates a temporary project directory with a fake package in itsnode_modules, then verifiesgetPackagecan find and load it when passed that directory ascwd.
Docs
- No docs update needed — this is an internal resolution fix with no user-facing API change.

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
astro@7.0.6
Patch Changes
-
#17261
79aa99cThanks @astrobot-houston! - Fixes a false deprecation warning formarkdown.gfmandmarkdown.smartypantswhen using the Container API -
#17247
f94280dThanks @chatman-media! - Fixes route generation throwing "Missing parameter" (or silently dropping the segment) when a dynamic param's value is0. The generator used truthy checks instead of checking forundefined, sopaginate(posts, { params: { categoryId: 0 } })would crash even though0is a perfectly valid param value. -
#17278
6f11739Thanks @astrobot-houston! - Fixes missing CSS for virtual style modules (e.g., responsive image layout styles) in dev mode when JavaScript is disabled -
#17250
0b30b35Thanks @matthewp! - Fixes thesecurity.checkOrigincheck so it is applied consistently to Astro Actions and on-demand endpoints, regardless of how the request pipeline is composed. Previously, the origin check could be skipped in the composableastro/honopipeline depending on the order of themiddleware()primitive (or when it was omitted). -
#17274
8c3579bThanks @astrobot-houston! - Fixes missingrender()type overload for live collection entries. Previously, callingrender()on aLiveDataEntryproduced a TypeScript error when using onlylive.config.tswithout acontent.config.ts. -
#17257
4208297Thanks @astrobot-houston! - Fixesastro checkfailing to find@astrojs/checkandtypescriptwhen astro is installed in a directory outside the project tree (e.g. pnpm virtual store) -
#17272
b428648Thanks @matthewp! - Fixes island component paths so that extensionless imports (e.g.import { Counter } from '../components/Counter') resolve to the real file on disk, matching Vite's extension order and directoryindexresolution. This makes theinclude/excludeoptions of JSX renderer integrations (React, Preact, Solid) match components imported without a file extension, and removes the spurious React 19 "Invalid hook call" warning logged on every request in dev whenincludewas set alongside another JSX renderer -
#17279
2aeaa44Thanks @astrobot-houston! - Fixes a bug where<Picture inferSize>with a remote image could fail withFailedToFetchRemoteImageDimensionswhen the image server rate-limits requests (e.g. HTTP 429). Remote dimensions are now resolved once per render instead of once per output format. -
#17251
5240e26Thanks @matthewp! - Hardens the handling of attribute rendering when using with custom elements. -
#17248
429bd62Thanks @astrobot-houston! - Fixes a crash when using Astro'sgetViteConfigwith Vitest browser mode (e.g., Storybook vitest runner). Astro now skips dev server setup inside Vitest, preventing errors. -
#17260
14524c0Thanks @matthewp! - Fixes a regression where a<script>inside a component rendered throughAstro.slots.render()was hoisted out of its original position instead of staying next to its component content -
Updated dependencies [
eb6f97e]:- @astrojs/internal-helpers@0.10.1
- @astrojs/markdown-remark@7.2.1
- @astrojs/markdown-satteri@0.3.3
create-astro@5.2.2
Patch Changes
- #17259
ed6bea5Thanks @astrobot-houston! - Fixes proxy support by respectingHTTP_PROXYandHTTPS_PROXYenvironment variables when downloading templates. On Node.js v22.21.0+ and v24.5.0+,create-astronow automatically enables the--use-env-proxyflag so that nativefetch()routes requests through the configured proxy.
@astrojs/cloudflare@14.1.1
Patch Changes
- Updated dependencies [
eb6f97e]:- @astrojs/internal-helpers@0.10.1
- @astrojs/underscore-redirects@1.0.3
@astrojs/markdoc@2.0.3
Patch Changes
- Updated dependencies [
eb6f97e]:- @astrojs/internal-helpers@0.10.1
@astrojs/mdx@7.0.2
Patch Changes
- Updated dependencies [
eb6f97e]:- @astrojs/internal-helpers@0.10.1
- @astrojs/markdown-remark@7.2.1
@astrojs/netlify@8.1.1
Patch Changes
- Updated dependencies [
eb6f97e]:- @astrojs/internal-helpers@0.10.1
- @astrojs/underscore-redirects@1.0.3
@astrojs/node@11.0.2
Patch Changes
-
#17252
eb6f97eThanks @matthewp! - Fixes trailing-slash handling for request paths that begin with a backslashWith
trailingSlash: 'always', the standalone Node server could append a trailing slash to a request path that begins with a backslash (for example/\example.com/foo) and echo that path back in theLocationheader of a301response. Because browsers resolve a leading\the same way as/, the resultingLocationcould point off-site.Such paths are now recognized as internal paths, matching the existing handling for paths that begin with
//, so they are no longer rewritten with a trailing slash. -
Updated dependencies [
eb6f97e]:- @astrojs/internal-helpers@0.10.1
@astrojs/preact@6.0.1
Patch Changes
- Updated dependencies [
eb6f97e]:- @astrojs/internal-helpers@0.10.1
@astrojs/react@6.0.1
Patch Changes
- Updated dependencies [
eb6f97e]:- @astrojs/internal-helpers@0.10.1
@astrojs/solid-js@7.0.1
Patch Changes
- #17270
0142964Thanks @FrancoKaddour! - Fix@astrojs/solid-jsincorrectly claiming Svelte 5 components compiled with the newer$$rendererprop (instead of the legacy$$payload). Projects mixing Solid and Svelte could see Svelte components silently rendered as empty strings by the Solid renderer.
@astrojs/vercel@11.0.2
Patch Changes
- Updated dependencies [
eb6f97e]:- @astrojs/internal-helpers@0.10.1
@astrojs/internal-helpers@0.10.1
Patch Changes
-
#17252
eb6f97eThanks @matthewp! - Fixes trailing-slash handling for request paths that begin with a backslashWith
trailingSlash: 'always', the standalone Node server could append a trailing slash to a request path that begins with a backslash (for example/\example.com/foo) and echo that path back in theLocationheader of a301response. Because browsers resolve a leading\the same way as/, the resultingLocationcould point off-site.Such paths are now recognized as internal paths, matching the existing handling for paths that begin with
//, so they are no longer rewritten with a trailing slash.
@astrojs/language-server@2.16.11
Patch Changes
- #17059
60cb289Thanks @dupontcyborg! - Update volar-service-* dependencies from 0.0.70 to 0.0.71 to pull in yaml-language-server 1.23.0 and yaml 2.8.3, resolving CVE-2026-33532 (GHSA-48c2-rrv3-qjmp), a denial-of-service vulnerability in yaml <2.8.3.
@astrojs/ts-plugin@1.10.10
Patch Changes
- #17269
c72d4f2Thanks @matthewp! - Fixes "Go To References" from.tsfiles missing usages inside.astrofiles that are reached throughAstro.locals. The plugin now injects Astro's ambient types so type chains likeAstro.locals.utils.toUpper()resolve, matching the language server.
@astrojs/markdown-remark@7.2.1
Patch Changes
- Updated dependencies [
eb6f97e]:- @astrojs/internal-helpers@0.10.1
@astrojs/markdown-satteri@0.3.3
Patch Changes
- Updated dependencies [
eb6f97e]:- @astrojs/internal-helpers@0.10.1

Changes
- Prefetch hover listeners now attach to links injected by
server:defercomponents. Previously,onPageLoad()scanned for<a>tags once on page load, but server islands resolve asynchronously after that scan completes — so their links were never registered. - Adds a
MutationObserverinsideonPageLoad()that watches for dynamically added DOM nodes. When a new anchor (or element containing one) is detected, the prefetch callback re-runs. The existinglistenedAnchorsWeakSet prevents duplicate listener attachment.
Closes #13297
Testing
- No automated tests added — the prefetch module is entirely client-side browser code (
document,MutationObserver, event listeners) with no existing test infrastructure in the repo. Fix was verified manually and confirmed by the reporter.
Docs
- No docs update needed; this is a bug fix restoring expected behavior for an existing feature combination.

Changes
- Fixes VS Code syntax highlighting breaking when
@property(or any CSS construct with angle brackets likesyntax: "<color>") is used inside a<style>block. Previously, the</style>closing tag and all subsequent<style>and<script>blocks would be incorrectly tokenized. - Updates all 7 style injection patterns in
astro.tmLanguage.src.yamlfrom a singlebegin/endapproach to the same two-patternbegin/end(single-line) +begin/while(multi-line) approach already used by script injection patterns since PR #15109. Thewhilepattern is evaluated at the start of each line before child patterns run, so</style>is always detected regardless of the embedded CSS grammar's internal state.
Testing
- Adds
packages/language-tools/vscode/test/grammar/fixtures/style/at-property.astro— a new grammar snapshot fixture verifying that all blocks are correctly scoped when@propertywith asyntax: "<color>"descriptor is present. - Updates the dummy CSS grammar (
css.tmLanguage-dummy.json) to include selector patterns that simulate VS Code's real CSS grammar behavior, making the existing snapshot tests more realistic. - Updates
expression.astro.snapandstyle.astro.snapsnapshots to reflect that leading whitespace before</style>is no longer scoped as CSS content (matches the existing script behavior).
Docs
No docs update needed — this is a VS Code extension grammar fix with no user-facing API changes.
Closes #16751

Summary
With trailingSlash: 'always', the standalone @astrojs/node server could append a trailing slash to a request path beginning with a backslash (e.g. /\example.com/foo) and echo it back in the Location header of a 301. Since browsers resolve a leading \ like /, that Location could point off-site.
isInternalPath now folds backslashes to forward slashes before comparing the prefix, so /\host is recognized as an internal path just like //host and is no longer rewritten with a trailing slash (it falls through to a 404). The core trailing-slash handlers already normalized this via URL parsing; this brings the raw-request path in the Node adapter in line.
Testing
- Unit tests for
isInternalPathcovering backslash prefixes. - Integration test in the Node adapter using a raw request line (a literal backslash, which URL parsers would otherwise normalize) asserting a
404with noLocationheader.

Changes
- Applies the existing attribute name validation to custom HTML element rendering during SSR. Attribute names containing characters invalid per the HTML spec (
" ' > / =or whitespace) are now dropped instead of interpolated raw, preventing unsafe HTML output.
Testing
- Adds
renderHTMLElement rejects invalid attribute keystest suite covering malicious keys (event handler injection, script tag injection) and valid keys (namespaced,data-*).
Docs
- No docs update needed — this is an internal hardening fix with no user-facing API change.

Changes
- Applies the
security.checkOrigincheck at the request dispatch points (Astro Actions and on-demand endpoints/pages), so it holds consistently regardless of how the composableastro/honopipeline is ordered. Previously the check only ran inside themiddleware()primitive, so it could be skipped depending on primitive order — or whenmiddleware()was omitted entirely. - Extracts the shared origin-check logic into
core/app/origin-check.ts(a predicate + response builder) consumed by the pipeline middleware, the actions dispatch, and thepages()endpoint dispatch. No behavior change to the classic pipeline: the check remains a no-op at the dispatch sinks when the middleware already ran, for prerendered/static routes, for safe methods, and whencheckOriginis disabled.
Testing
- Adds
action-origin-check.test.ts: composes a Hono app withactions()beforemiddleware()and asserts a cross-origin action request is rejected before the handler runs, while same-origin succeeds. - Adds
pages-origin-check.test.ts: composes a Hono app withpages()and nomiddleware()and asserts a cross-originPOSTto an on-demand endpoint is rejected before the handler runs, while same-origin succeeds.
Docs
- No docs update needed; existing
security.checkOriginbehavior is unchanged from the user's perspective.

Changes
Our packages still had the alpha versions in their peerDependencies fields. This PR fixes the problem by using the non-alpha packages.
Testing
Green CI.
Docs
N/A

Closes #16275
Changes
- When
process.env.VITESTis set,configureServerinvite-plugin-astro-servernow returns early instead of setting up Astro's dev server middleware. Vitest's browser mode (used by the Storybook vitest runner) boots its own Vite server, which triggers this hook — but its module evaluator doesn't implementwrapDynamicImport, causing aTypeErrorwhen Astro's SSR runner tries to loadcreateAstroServerAppvia dynamic imports. - The dev server middleware (SSR handler, prerender handler, trailing-slash redirects) is only meaningful for
astro dev, so skipping it in Vitest contexts is safe.
Testing
- Added
packages/astro/test/units/vite-plugin-astro-server/vitest-guard.test.tswith two cases: one confirming the early return whenVITESTis set (using a bare fake server with no environments), and one confirming normal execution proceeds whenVITESTis absent.
Docs
- No docs update needed — this is a bug fix with no user-facing API changes.
Last fetched: | Scheduled refresh: Every Saturday
See Customizing GitHub Activity Pages to configure your own
Inspired by prs.atinux.com



