Skip to content
Astro as integrations 4 min read

Netlify Adapter

The @astrojs/netlify adapter lets you deploy a server-rendered Astro project to Netlify, where your on-demand routes run as Netlify Functions or, optionally, as Edge Functions at the network edge. Astro stays zero-JS-by-default and ships only the islands you opt into with client:*, while the adapter wires up the serverless runtime, request handling, and asset routing for you. This is the path you reach for when static output alone is not enough — you need API routes, server endpoints, on-demand rendering, or middleware running on Netlify’s platform.

Installing the adapter

The fastest way to add the adapter is astro add, which installs the package, updates your config, and sets a sensible output mode.

npx astro add netlify

If you prefer to do it manually, install the package and register it yourself.

npm install @astrojs/netlify

Then set the adapter in astro.config.mjs. The adapter implicitly enables on-demand rendering, so you only need output: 'server' if you want every route rendered on the server by default. Otherwise leave the default static output and mark individual routes with export const prerender = false.

import { defineConfig } from 'astro/config';
import netlify from '@astrojs/netlify';

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

Astro 5 uses output: 'static' by default and renders any route on demand when you set export const prerender = false in that page or endpoint. Use output: 'server' only when most of the site should be dynamic.

Netlify Functions vs Edge Functions

By default the adapter targets standard Netlify Functions — Node.js serverless functions with full access to the Node runtime, npm packages, and filesystem-style APIs. You can instead run rendering on Netlify Edge Functions, which execute on a Deno-based runtime distributed close to the user for lower latency, at the cost of a more constrained API surface.

Enable the edge runtime with the edgeMiddleware option for middleware, or build edge-rendered routes by configuring the adapter accordingly.

import { defineConfig } from 'astro/config';
import netlify from '@astrojs/netlify';

export default defineConfig({
  output: 'server',
  adapter: netlify({
    edgeMiddleware: true,
  }),
});
CapabilityNetlify FunctionsEdge Functions
RuntimeNode.jsDeno (edge)
LatencyRegionalGlobally distributed
Node/npm APIsFullLimited (Web APIs)
Best forHeavy logic, DB callsFast middleware, redirects
Cold startsPossibleMinimal

On-demand routes and endpoints

Pages and endpoints render on the server when prerendering is disabled. A server endpoint receives a standard APIContext and returns a Response.

// src/pages/api/time.ts
import type { APIRoute } from 'astro';

export const prerender = false;

export const GET: APIRoute = async () => {
  const now = new Date().toISOString();
  return new Response(JSON.stringify({ now }), {
    headers: { 'Content-Type': 'application/json' },
  });
};

Hitting the deployed endpoint returns live data on each request.

Output:

{"now":"2026-06-14T10:42:08.317Z"}

A dynamic page works the same way — disable prerendering and read request data inside the component script. Islands hydrate only where marked.

---
// src/pages/greeting.astro
export const prerender = false;

const name = Astro.url.searchParams.get('name') ?? 'world';
---
<html>
  <body>
    <h1>Hello, {name}!</h1>
  </body>
</html>

Accessing the Netlify context

Inside on-demand routes you can read Netlify-specific request context — such as geolocation and the incoming request — through standard Astro APIs and the platform headers Netlify injects.

// src/pages/api/where.ts
import type { APIRoute } from 'astro';

export const prerender = false;

export const GET: APIRoute = ({ request }) => {
  const country = request.headers.get('x-nf-geo')
    ? JSON.parse(request.headers.get('x-nf-geo')!).country?.code
    : 'unknown';
  return new Response(`You are in ${country}`);
};

Image optimization and caching

The adapter integrates with Netlify Image CDN so Astro’s <Image /> component can transform images on demand. You can also enable static asset caching and on-demand revalidation through the imageCDN and caching options.

import { defineConfig } from 'astro/config';
import netlify from '@astrojs/netlify';

export default defineConfig({
  output: 'server',
  adapter: netlify({
    imageCDN: true,
  }),
});

Disable imageCDN if you serve images from an external provider or do your own optimization, since routing them through Netlify’s CDN adds no benefit and may double-transform assets.

Deploying

Commit a netlify.toml (or configure the build in the Netlify dashboard) so Netlify knows the build command and publish directory. The adapter outputs functions automatically during the Astro build.

# netlify.toml
[build]
  command = "astro build"
  publish = "dist"

Then deploy via Git integration or the Netlify CLI.

npx netlify deploy --build --prod

Best practices

  • Keep most routes static and opt into on-demand rendering per route with export const prerender = false rather than flipping the whole site to output: 'server'.
  • Use Edge Functions for lightweight, latency-sensitive middleware (auth checks, redirects, A/B routing) and standard Functions for heavy logic or database access.
  • Read geolocation and request metadata from Netlify’s injected headers instead of bundling extra dependencies.
  • Enable imageCDN only when Netlify is actually serving your images, to avoid redundant transformation.
  • Pin the adapter version and align it with your Astro major version to avoid runtime mismatches.
  • Test functions locally with netlify dev before pushing to catch runtime-specific issues early.
Last updated June 14, 2026
Was this helpful?