Astro Info
Astro v6.1.8
Vite v7.3.2
Node v24.14.0
System macOS (arm64)
Package Manager npm
Output server
Adapter @astrojs/cloudflare (v13.1.10)
Integrations @astrojs/react (v5.0.3)
If this issue only occurs in one browser, which browser is a problem?
No response
Describe the Bug
Astro.routePattern returns the route pattern with all characters lowercased, even when the source filename uses camelCase for a dynamic param.
For a file at src/pages/blog/[postId].astro, accessing Astro.routePattern returns /blog/[postid] instead of /blog/[postId].
Interestingly, Astro.params keeps the original casing (Astro.params.postId works as expected). Only the pattern string is affected. RouteData.pathname for fully static routes also preserves casing — so the lowercase normalization is inconsistent within the same RouteData object.
I traced this to packages/astro/src/core/routing/parse-route.ts, in the joinSegments helper:
function joinSegments(segments: RoutePart[][]): string {
if (segments.length === 0) return '/';
const arr = segments.map((segment) => {
return segment.map((part) => (part.dynamic ? `[${part.content}]` : part.content)).join('');
});
return `/${arr.join('/')}`.toLowerCase(); // <-- entire path is lowercased
}
The return value is assigned to RouteData.route, and per #11867, Astro.routePattern exposes RouteData.route directly. So this internal normalization leaks all the way to the public API surface.
My guess is the .toLowerCase() was added to make internal route matching case-insensitive, but I couldn't find a code comment or doc explaining the intent — and the existing JSDoc for Astro.routePattern does not mention any normalization. I wanted to confirm with maintainers before proposing a fix, since the right resolution depends on whether this is intentional.
What's the expected result?
Astro.routePattern should preserve the casing used in the original filename. For src/pages/blog/[postId].astro, it should return /blog/[postId].
If the lowercase normalization is intentional for internal matching, I'd suggest either:
- Decouple the user-facing pattern from the internal normalized form (keep
RouteData.route casing-preserved, lowercase only at the matching step), or
- Document the normalization behavior on
Astro.routePattern so users aren't surprised.
Happy to open a PR once the intended direction is confirmed.
Link to Minimal Reproducible Example
https://stackblitz.com/edit/github-vsdaaq9e-y6hcp3rn
Participation
P.S. The https://astro.new/repro link in the bug report template currently fails with a TLS certificate mismatch (Netlify cert is *.netlify.app, missing astro.new SAN). I used a direct StackBlitz import instead.
Astro Info
If this issue only occurs in one browser, which browser is a problem?
No response
Describe the Bug
Astro.routePatternreturns the route pattern with all characters lowercased, even when the source filename uses camelCase for a dynamic param.For a file at
src/pages/blog/[postId].astro, accessingAstro.routePatternreturns/blog/[postid]instead of/blog/[postId].Interestingly,
Astro.paramskeeps the original casing (Astro.params.postIdworks as expected). Only the pattern string is affected.RouteData.pathnamefor fully static routes also preserves casing — so the lowercase normalization is inconsistent within the sameRouteDataobject.I traced this to
packages/astro/src/core/routing/parse-route.ts, in thejoinSegmentshelper:The return value is assigned to
RouteData.route, and per #11867,Astro.routePatternexposesRouteData.routedirectly. So this internal normalization leaks all the way to the public API surface.My guess is the
.toLowerCase()was added to make internal route matching case-insensitive, but I couldn't find a code comment or doc explaining the intent — and the existing JSDoc forAstro.routePatterndoes not mention any normalization. I wanted to confirm with maintainers before proposing a fix, since the right resolution depends on whether this is intentional.What's the expected result?
Astro.routePatternshould preserve the casing used in the original filename. Forsrc/pages/blog/[postId].astro, it should return/blog/[postId].If the lowercase normalization is intentional for internal matching, I'd suggest either:
RouteData.routecasing-preserved, lowercase only at the matching step), orAstro.routePatternso users aren't surprised.Happy to open a PR once the intended direction is confirmed.
Link to Minimal Reproducible Example
https://stackblitz.com/edit/github-vsdaaq9e-y6hcp3rn
Participation