Skip to main content
The preview() function starts a local server to preview your production build. This helps you test your site locally before deploying it.
The JavaScript API is experimental and may change in future releases.
The preview server is not designed for production use. Always use a proper hosting platform for production deployments.

Import

import { preview } from 'astro';

Signature

function preview(inlineConfig: AstroInlineConfig): Promise<PreviewServer>

Parameters

inlineConfig
AstroInlineConfig
required
Configuration object for your Astro project. Supports all options from astro.config.mjs.
inlineConfig.root
string
The root directory of your Astro project. Defaults to the current working directory.
inlineConfig.logLevel
'debug' | 'info' | 'warn' | 'error' | 'silent'
default:"'info'"
Controls the verbosity of logging output.
inlineConfig.outDir
string
default:"'./dist'"
The directory containing your build output to preview.
inlineConfig.server
object
Server configuration options.
inlineConfig.server.port
number
default:"4321"
The port the preview server listens on.
inlineConfig.server.host
string | boolean
default:"false"
Set which network IP addresses the server listens on. Set to true to listen on all addresses.

Return Value

Returns a Promise<PreviewServer> that resolves to a server object with the following properties:
host
string | undefined
The host the server is listening on.
port
number
The port the server is listening on.
stop
() => Promise<void>
Stops the preview server and cleans up resources.
closed
() => Promise<void>
Promise that resolves when the server is closed.

Examples

Basic Preview

import { build, preview } from 'astro';

// First, build your site
await build({
  root: './my-project',
});

// Then preview it
const server = await preview({
  root: './my-project',
});

console.log(`Preview server running at http://localhost:${server.port}`);

Custom Port

import { preview } from 'astro';

const server = await preview({
  root: './my-project',
  server: {
    port: 8080,
  },
});

Network Access

import { preview } from 'astro';

const server = await preview({
  root: './my-project',
  server: {
    host: true, // Listen on all network interfaces
    port: 4321,
  },
});

Preview with Custom Output Directory

import { preview } from 'astro';

const server = await preview({
  root: './my-project',
  outDir: './custom-dist',
});

Automated Testing

import { build, preview } from 'astro';
import fetch from 'node-fetch';

let server;

beforeAll(async () => {
  // Build the site
  await build({
    root: './test-site',
    logLevel: 'silent',
  });

  // Start preview server
  server = await preview({
    root: './test-site',
    logLevel: 'silent',
    server: { port: 4567 },
  });
});

afterAll(async () => {
  await server.stop();
});

test('homepage loads correctly', async () => {
  const response = await fetch(`http://localhost:${server.port}`);
  expect(response.status).toBe(200);
  const html = await response.text();
  expect(html).toContain('<!DOCTYPE html>');
});

Preview and Test Script

import { build, preview } from 'astro';
import fetch from 'node-fetch';

async function testProduction() {
  console.log('Building site...');
  await build({ root: '.' });

  console.log('Starting preview server...');
  const server = await preview({
    root: '.',
    server: { port: 4321 },
  });

  try {
    // Test critical pages
    const pages = ['/', '/about', '/blog'];

    for (const page of pages) {
      const response = await fetch(`http://localhost:${server.port}${page}`);
      console.log(`${page}: ${response.status}`);

      if (response.status !== 200) {
        throw new Error(`Page ${page} returned ${response.status}`);
      }
    }

    console.log('All tests passed!');
  } finally {
    await server.stop();
  }
}

testProduction().catch(console.error);

Temporary Preview

import { preview } from 'astro';

const server = await preview({
  root: './my-project',
});

// Preview for 5 minutes then shut down
setTimeout(async () => {
  console.log('Stopping preview server...');
  await server.stop();
  console.log('Preview server stopped');
}, 5 * 60 * 1000);

SSR Preview

import { build, preview } from 'astro';

// Build SSR site
await build({
  root: './my-ssr-project',
  output: 'server',
});

// Preview requires an adapter with preview support
const server = await preview({
  root: './my-ssr-project',
});

console.log(`SSR preview at http://localhost:${server.port}`);

Preview with Logging

import { preview } from 'astro';

const server = await preview({
  root: './my-project',
  logLevel: 'debug',
  server: {
    port: 4321,
  },
});

console.log('Preview server started');
console.log(`Host: ${server.host || 'localhost'}`);
console.log(`Port: ${server.port}`);

Error Handling

import { preview } from 'astro';
import { existsSync } from 'node:fs';

async function startPreview() {
  const outDir = './dist';

  // Check if build exists
  if (!existsSync(outDir)) {
    console.error('Build not found. Run build first.');
    process.exit(1);
  }

  try {
    const server = await preview({
      root: '.',
      outDir,
    });

    console.log(`Preview running at http://localhost:${server.port}`);

    // Handle shutdown
    process.on('SIGINT', async () => {
      await server.stop();
      process.exit(0);
    });
  } catch (error) {
    console.error('Preview failed:', error);
    process.exit(1);
  }
}

startPreview();
  • build() - Build for production
  • dev() - Start development server
  • sync() - Generate TypeScript types

Build docs developers (and LLMs) love