Skip to content

File-based Routing

In Next.js App Router, every page.tsx inside app/ becomes a route. In Astro the same idea applies but the convention is simpler: any .astro file inside src/pages/ maps directly to a URL. The filename is the path segment.

Multi-page routing requires multiple files — open a full Astro project (npm create astro@latest) to run these examples locally.

The table below shows how file paths inside src/pages/ become URLs. This mirrors Next.js Pages Router conventions exactly — if you know /pages, you already know Astro routing.

File pathURL
src/pages/index.astro/
src/pages/about.astro/about
src/pages/blog/index.astro/blog
src/pages/blog/first-post.astro/blog/first-post
src/pages/contact.astro/contact
Next.js
// Next.js App Router
app/
page.tsx → /
about/
page.tsx → /about
blog/
page.tsx → /blog
first-post/
page.tsx → /blog/first-post
// Next.js Pages Router
pages/
index.tsx → /
about.tsx → /about
blog/
index.tsx → /blog
first-post.tsx → /blog/first-post
Astro
// Astro src/pages/
src/pages/
index.astro → /
about.astro → /about
blog/
index.astro → /blog
first-post.astro → /blog/first-post
// No page.tsx wrapper needed.
// The .astro file IS the page.

A page .astro file is just a regular .astro component. The difference is location — files in src/pages/ are treated as routes.

Next.js
// app/about/page.tsx (Next.js App Router)
export default function AboutPage() {
return (
<main>
<h1>About</h1>
<p>Welcome to the about page.</p>
</main>
);
}
Astro
---
// src/pages/about.astro
import Layout from '../layouts/Layout.astro';
---
<Layout title="About">
<main>
<h1>About</h1>
<p>Welcome to the about page.</p>
</main>
</Layout>

Here is what a typical Astro project looks like after adding a few routes:

flowchart TD
  src["src/"] --> layouts["layouts/"]
  src --> pages["pages/"]
  layouts --> layoutFile["Layout.astro (shared wrapper)"]
  pages --> indexFile["index.astro"]
  pages --> aboutFile["about.astro"]
  pages --> blog["blog/"]
  blog --> blogIndex["index.astro"]
  blog --> firstPost["first-post.astro"]
  indexFile --> indexURL["/"]
  aboutFile --> aboutURL["/about"]
  blogIndex --> blogURL["/blog"]
  firstPost --> firstPostURL["/blog/first-post"]
Astro project file tree mapped to URLs

Two routing features graduated from experimental in Astro 7 and map neatly onto things you know from Next.js:

  • Route caching (cache + routeRules in astro.config.mjs) is Astro’s answer to ISR / revalidate: server-rendered routes can be cached for a duration, with platform providers for Netlify, Vercel, and Cloudflare, plus an in-memory provider for Node.
astro.config.mjs
import { defineConfig, memoryCache } from 'astro/config';
export default defineConfig({
cache: { provider: memoryCache() },
routeRules: { '/blog/[...slug]': { maxAge: 3600 } }, // like revalidate: 3600
});
  • src/fetch.ts is a reserved entrypoint that receives every request before Astro’s router — the place for a standard fetch handler or Hono middleware (auth, redirects, A/B routing), the role middleware.ts plays in Next.js. If you already have a file with that name, rename it or set fetchFile: null in the config.
Where do you place a .astro file to make it a route in Astro?
What URL does `src/pages/blog/index.astro` map to?
Which Next.js router convention is most similar to Astro file-based routing?
Besides .astro files, which other file types can be placed in src/pages/ to create routes?