Astro: Routing, Rendering Modes & Content Collections
Static (SSG) vs Server (SSR) Rendering
// astro.config.mjs
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';
import react from '@astrojs/react';
import tailwind from '@astrojs/tailwind';
export default defineConfig({
output: 'server', // default is 'static' -- most content doesn't need per-request rendering
adapter: vercel(), // SSR requires a deployment adapter
integrations: [react(), tailwind()],
});---
// Per-route override: mix static and server-rendered pages in one project.
// A static marketing homepage alongside a personalized, server-rendered dashboard.
export const prerender = false; // this specific route renders per-request
const user = await getSessionUser(Astro.request);
---
<h1>Welcome back, {user.name}</h1>Dynamic Routes
---
// src/pages/blog/[slug].astro
// getStaticPaths declares, at build time, every concrete path to
// pre-render for this dynamic route -- one page per blog post
export async function getStaticPaths() {
const posts = await getAllPosts();
return posts.map((post) => ({
params: { slug: post.slug },
props: { post },
}));
}
const { post } = Astro.props;
---
<h1>{post.title}</h1>
<div set:html={post.contentHtml} />Content Collections
// src/content/config.ts -- type-safe schema for Markdown/MDX content
import { defineCollection, z } from 'astro:content';
const blog = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
publishDate: z.date(),
tags: z.array(z.string()).default([]),
draft: z.boolean().default(false),
}),
});
export const collections = { blog };
// A post's frontmatter is now validated at BUILD TIME -- a missing
// publishDate or a wrong type fails the build instead of shipping broken data
// src/pages/blog/[...slug].astro
---
import { getCollection } from 'astro:content';
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map((post) => ({
params: { slug: post.slug },
props: { post },
}));
}
const { post } = Astro.props;
const { Content } = await post.render();
---
<h1>{post.data.title}</h1>
<Content />Image Optimization
---
import { Image } from 'astro:assets';
import heroImage from '../assets/hero.jpg';
---
<!-- Auto-optimized at build time: resized, format-converted (e.g. WebP),
width/height set automatically to prevent layout shift -->
<Image src={heroImage} alt="Hero" width={800} height={400} />Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free