This Astro routing cheatsheet maps every file name pattern in src/pages/ to the URL it produces, then lists the APIs for dynamic routes, pagination, endpoints, redirects and rewrites, and the order Astro uses when routes overlap. For explanations and worked examples, see the Astro routing guide.
Key Takeaways
- The file path under
src/pages/is the URL.index.astrois the folder’s root.[param]matches one segment;[...param]matches any depth, including none.- Static dynamic routes export
getStaticPaths(); on-demand routes readAstro.params._-prefixed files and folders are not routes.
File to URL
File in src/pages/ |
URL |
|---|---|
index.astro |
/ |
about.astro |
/about/ |
about/index.astro |
/about/ |
blog/[slug].astro |
/blog/anything/ |
[lang]/[slug].astro |
/en/pricing/ |
docs/[...path].astro |
/docs/, /docs/a/b/ |
blog/[page].astro |
/blog/1/, /blog/2/ |
blog/[...page].astro |
/blog/, /blog/2/ |
rss.xml.ts |
/rss.xml |
api/[id].json.ts |
/api/42.json |
404.astro |
Not-found page |
500.astro |
Server error page (on demand) |
_draft.astro |
No route |
Supported page types: .astro, .md, .mdx (with integration), .html; endpoints: .ts, .js.
Dynamic routes
---
// src/pages/blog/[slug].astro
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map((post) => ({ params: { slug: post.id }, props: { post } }));
}
const { slug } = Astro.params;
const { post } = Astro.props;
---
Rules: params values are strings (or undefined for rest params); every bracket needs a key; props carries data to the page.
On demand, skip getStaticPaths():
---
export const prerender = false;
const { slug } = Astro.params;
---
Pagination
export const getStaticPaths = (async ({ paginate }) => {
const posts = await getCollection('blog');
return paginate(posts, { pageSize: 10 });
}) satisfies GetStaticPaths;
page properties: data, currentPage, lastPage, total, size, start, end, url.prev, url.next, url.first, url.last, url.current.
Endpoints
// src/pages/data.json.ts
import type { APIRoute } from 'astro';
export const GET: APIRoute = () => Response.json({ ok: true });
export const POST: APIRoute = async ({ request }) => new Response(null, { status: 204 });
Static builds write GET output to a file. Other methods need prerender = false and an adapter.
Redirects
// astro.config.mjs
redirects: {
'/old/': '/new/',
'/blog/[slug]/': '/articles/[slug]/',
'/promo/': { status: 302, destination: '/pricing/' },
},
---
return Astro.redirect('/login/', 302); // on-demand pages
---
Static sites get meta-refresh pages; use public/_redirects on Netlify or Cloudflare Pages for real 301s. See redirects in Astro.
Rewrites
---
if (!product) return Astro.rewrite('/404/');
---
Serves another route’s content at the current URL. Middleware: context.rewrite().
Route priority (highest first)
- More path segments win.
- Static routes beat dynamic routes.
- Named params beat rest params.
- Prerendered routes beat on-demand routes.
- Endpoints beat pages.
- File-based routes beat redirects.
- Alphabetical order breaks ties.
URL config
| Option | Values | Default |
|---|---|---|
trailingSlash |
'always', 'never', 'ignore' |
'ignore' |
build.format |
'directory', 'file', 'preserve' |
'directory' |
base |
Path prefix | '/' |
See trailingSlash and build.format.
Useful values in a page
Astro.url.pathname // current path
Astro.params // dynamic segments
Astro.routePattern // e.g. "/blog/[slug]"
Astro.currentLocale // with i18n
import.meta.env.BASE_URL // the base path
Errors you’ll meet
| Message | Fix |
|---|---|
getStaticPaths() required |
Export it, or render on demand |
| No static path found | Check params and ids |
| Same path as another route | Remove the overlap |
The pages docs show how routing works in a Komal theme. Full API details are in the routing reference.
FAQ
How do I make page one of a paginated list live at /blog/?
Name the file [...page].astro.
Can I have a route with a file extension in the URL?
Yes, with an endpoint named like feed.json.ts, which serves /feed.json.