/ astro-integrations / How to Use Netlify with Astro: Complete Guide
astro-integrations 9 min read

How to Use Netlify with Astro: Complete Guide

Step-by-step guide to integrating Netlify with your Astro website.

How to Use Netlify with Astro: Complete Guide

Netlify is one of the most popular platforms for deploying Astro sites, and for good reason. You get continuous deployment from Git, serverless functions, edge computing, and a generous free tier. Astro has an official Netlify adapter, which means you can deploy both static and server-rendered Astro sites with minimal configuration.

I use Netlify for several Astro projects, and the deploy process is about as smooth as it gets. Push to Git, site builds automatically, preview deploys for pull requests. The whole workflow just works.

Prerequisites

  • Node.js 22.12.0 or newer. Astro 6 dropped support for Node 18 and 20, so the engine field on astro@6.4.2 now requires node >=22.12.0.
  • An Astro project (npm create astro@latest)
  • A Netlify account (free tier available)
  • A Git repository (GitHub, GitLab, Bitbucket, or Azure DevOps)

Verified package versions as of this writing (checked on 2026-05-29 against registry.npmjs.org):

Package Latest Notes
astro 6.4.2 requires node >=22.12.0
@astrojs/netlify 7.0.11 peer dependency astro ^6.0.0 (v7 is the Astro 6 line)
@netlify/functions 5.3.0 types and helpers for standalone Netlify Functions
netlify-cli 26.0.2 optional, for CLI based deploys

Installation

For static Astro sites you do not need any adapter at all. Astro's default output is a fully static site, and Netlify serves the dist/ folder directly.

For on-demand rendering (server-rendered pages, API routes, middleware) install the official adapter:

npx astro add netlify

This installs @astrojs/netlify and edits your astro.config.mjs for you in one step. For a manual install:

npm install @astrojs/netlify

If you are upgrading an existing project to Astro 6, run npx @astrojs/upgrade, which bumps Astro and every official integration (including the Netlify adapter) together to compatible versions.

Configuration

For a static site your astro.config.mjs needs no changes. Astro's default output mode is "static", which Netlify handles natively.

Important version note. The old output: "hybrid" mode was removed in Astro 5 and does not exist in Astro 6. There are now only two output values, "static" (the default) and "server". The behavior the old hybrid mode provided is now built into "static". Any route or endpoint can opt into on-demand rendering by exporting export const prerender = false;, and Astro switches that route to server rendering while the rest of the site stays static. If you copied an older config that still sets output: "hybrid", delete that line.

For full server-side rendering of every page, use output: "server":

// astro.config.mjs
import { defineConfig } from "astro/config";
import netlify from "@astrojs/netlify";

export default defineConfig({
  output: "server",
  adapter: netlify(),
});

To keep most of the site static and only server-render specific routes, leave the output at its default and opt individual pages in:

// astro.config.mjs
import { defineConfig } from "astro/config";
import netlify from "@astrojs/netlify";

export default defineConfig({
  // output defaults to "static"; no output key needed
  adapter: netlify(),
});
---
// src/pages/dynamic.astro
export const prerender = false; // this single page renders on demand
---

The adapter accepts several options. The most commonly used ones:

adapter: netlify({
  edgeMiddleware: true,        // run Astro middleware as a Netlify Edge Function
  imageCDN: true,              // default true; serves images through Netlify Image CDN
  cacheOnDemandPages: true,    // cache server-rendered pages on Netlify's CDN
  includeFiles: ["./my-data.json"], // bundle extra files with the function
}),

Create a netlify.toml in your project root for build settings:

[build]
  command = "npm run build"
  publish = "dist"

[build.environment]
  NODE_VERSION = "22.12.0"

You usually do not need to hand-write redirect rules in netlify.toml. If you define redirects in your Astro config, the adapter translates them into a dist/_redirects file at build time:

// astro.config.mjs
export default defineConfig({
  adapter: netlify(),
  redirects: {
    "/blog/old-post": "/blog/new-post",
  },
});

Basic Usage

Connect your Git repository to Netlify through the Netlify dashboard:

  1. Log in to Netlify and click "Add new site" > "Import an existing project"
  2. Select your Git provider and repository
  3. Set the build command to npm run build (or astro build)
  4. Set the publish directory to dist
  5. Add any environment variables your site needs
  6. Click "Deploy site"

That is it. Netlify detects Astro automatically and handles the rest. Every push to your main branch triggers a new deploy.

For environment variables, add them in Netlify's dashboard under Site settings > Environment variables:

# Example variables you might need
PUBLIC_SITE_URL=https://your-site.netlify.app
CONTENTFUL_API_TOKEN=your_token_here

One Astro 6 change to keep in mind. import.meta.env values are now always inlined at build time. If your server-side code reads an environment variable at runtime (for example a secret used inside an on-demand route), read it from process.env instead of import.meta.env, otherwise you will ship the build-time value rather than the runtime one.

To use standalone Netlify Functions alongside your Astro site, create a netlify/functions/ directory. Netlify detects it automatically, no extra config required:

// netlify/functions/hello.ts
import type { Handler } from "@netlify/functions";

export const handler: Handler = async (event) => {
  return {
    statusCode: 200,
    body: JSON.stringify({ message: "Hello from Netlify Functions" }),
  };
};

This function becomes available at /.netlify/functions/hello. Note this is separate from Astro's own on-demand rendering. Astro's prerender = false routes are compiled by the adapter into internal Netlify Functions for you, so for most app logic you can just write Astro API routes under src/pages/api/ rather than hand-rolling functions.

Production Tips

  1. Use deploy previews. Every pull request gets its own preview URL automatically. Share these with your team for review before merging. No extra configuration needed.

  2. Set up custom headers for performance. Add a _headers file in your public/ folder to control caching. For static assets, set long cache times: Cache-Control: public, max-age=31536000, immutable.

  • Enable Netlify Edge Functions for dynamic features. If you need middleware, A/B testing, or geolocation-based content, use edge functions. They run on Netlify's edge network, close to your users.

  • Configure redirects properly. Use the netlify.toml or a _redirects file for URL redirects and rewrites. This is important when migrating from another platform to preserve your SEO equity.

  • Monitor build times. Netlify changed how the free tier is metered. Accounts created before September 4, 2025 are on the legacy Free plan, which includes 300 build minutes per month. Newer accounts are on the credit-based model, where a Free plan gets 300 credits per month shared across deploys, functions, requests, and bandwidth rather than a flat build-minute allotment. Check Billing in your dashboard for your account's exact limits. Either way, for content-heavy sites with frequent updates, keep an eye on build usage. Use Astro's incremental builds or limit rebuilds to content-change webhooks.

  • Alternatives to Consider

    • Vercel if you want slightly faster builds and tighter integration with Next.js or other Vercel-optimized frameworks. Astro works well on both.
    • Cloudflare Pages if you want unlimited bandwidth on the free tier and a global edge network with zero egress fees.
    • Railway if your project needs a backend server alongside the frontend and you want everything on one platform.

    Common Errors and Fixes

    output: "hybrid" throws a config error. This mode was removed in Astro 5 and is gone in Astro 6. Delete the line. Use the default "static" output and add export const prerender = false; to the specific routes that need server rendering, or set output: "server" to render everything on demand.

    Adapter peer dependency warning on install. @astrojs/netlify@7 declares a peer dependency of astro ^6.0.0. If you are still on Astro 5 you need the @astrojs/netlify@6 line instead, and if you are on Astro 6 do not pin an older v6 adapter. Run npx @astrojs/upgrade to align Astro and the adapter to compatible versions in one pass.

    Build fails with a Node version error. Astro 6 dropped Node 18 and 20. Set NODE_VERSION = "22.12.0" (or newer) in netlify.toml, or commit a .nvmrc file, or set the NODE_VERSION environment variable in Netlify's site settings. Otherwise older Netlify build images may default to an unsupported Node.

    A secret reads as undefined or as the wrong value at runtime. In Astro 6 import.meta.env is inlined at build time, so it cannot see values that only exist when the function runs. Switch runtime reads in server code to process.env.

    A page that should be dynamic ships as static HTML. With the default "static" output, every page is prerendered unless it opts out. Add export const prerender = false; to that page or endpoint. Forgetting this is the most common reason an "SSR" page returns stale content.

    Astro redirects did not take effect. The adapter writes them to dist/_redirects only during astro build. Hand-editing netlify.toml redirects and also defining Astro redirects can conflict; prefer one source of truth. Confirm the generated dist/_redirects file exists after a build.

    Official Docs and Examples

    Wrapping Up

    Netlify and Astro is a battle-tested combination. The deployment process is effortless, the free tier is generous, and features like deploy previews and serverless functions cover most use cases without additional tooling. Whether you are running a static blog or a server-rendered application, Netlify handles Astro projects reliably.

    Sources

    All versions and facts below were checked on 2026-05-29.