# Astro's Internal Build Architecture and Asset Generation Process

> Uncover Astro's internal build architecture. Learn how Astro's Vite pipeline compiles components, extracts CSS, and generates hydration scripts for interactive islands into a structured dist directory.

- Repository: [Astro/astro](https://github.com/withastro/astro)
- Tags: internals
- Published: 2026-03-06

---

**Astro's build pipeline orchestrates a Vite-powered transformation sequence that compiles `.astro` components into static HTML or SSR bundles, extracts CSS, and generates hydration scripts for interactive islands, outputting everything to a structured `dist/` directory with a Vite manifest.**

The build system in the `withastro/astro` repository transforms declarative single-file components into optimized web applications through a tightly integrated seven-step compilation process. Understanding Astro's internal build architecture reveals how the framework achieves zero-JavaScript-by-default static output while selectively generating client-side hydration bundles.

## Build Initialization and Context Creation

The `astro build` command originates in [`packages/astro/cli.ts`](https://github.com/withastro/astro/blob/main/packages/astro/cli.ts), which parses CLI arguments and instantiates a **BuildContext** object. This context maintains global state—including Vite configuration, route mappings, and output directories—and immediately delegates control to the core builder in [`packages/astro/src/core/build.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/core/build.ts).

The build context acts as the central orchestrator, coordinating between the Astro compiler, Vite's bundler, and the file system throughout the pipeline.

## Vite Configuration and Plugin Injection

Astro constructs a custom Vite configuration through `createViteConfig` in [`packages/astro/src/vite-plugin-astro.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/vite-plugin-astro.ts). This function registers the **Astro Vite plugin**, which teaches Vite how to resolve `.astro` files, collect component metadata, and treat CSS and JavaScript as first-class assets.

The plugin configuration enables `manifest: true` to generate an asset mapping file and sets the foundation for the virtual module system used during component compilation.

## Route Discovery and Page Collection

The **Page Collector** (`collectPages` in [`packages/astro/src/core/pages.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/core/pages.ts)) walks the `src/pages/` directory to construct a route table. This phase determines which files require static generation versus server-side rendering by analyzing file paths and front-matter exports.

The collector identifies dynamic routes, prerendered pages, and SSR entries, creating a manifest of all URLs that must be processed in subsequent steps.

## Component Compilation and Virtual Modules

Each `.astro` file passes through the **Astro Compiler** (`compile` in [`packages/astro/src/compiler/compile.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/compiler/compile.ts)). The compiler performs three critical operations:

- **Front-matter parsing** extracts directives like `export const prerender = true` to determine rendering strategy
- **Virtual module generation** creates renderable JavaScript modules containing the component's HTML template and imported framework components
- **Hydration script creation** generates separate entry points for any component using `client:load`, `client:idle`, or other hydration directives

These virtual modules feed directly into Vite's rollup pipeline without intermediate file writes.

## Vite Build and Asset Processing

With virtual modules in place, Astro invokes `vite.build` using the custom configuration. Vite's rollup pipeline executes the heavy lifting:

- **JavaScript bundling** combines hydration scripts, framework code, and user scripts into optimized chunks (`*.js`)
- **CSS extraction** pulls imported stylesheets—including CSS-in-JS solutions—into separate files (`*.css`)
- **Asset handling** processes static files through Vite's asset loader, copying images, fonts, and other resources to the output directory while rewriting URLs in generated HTML and CSS

This phase handles all dependency resolution, tree-shaking, and code splitting automatically.

## HTML Generation and SSR Output

After Vite completes bundling, Astro iterates over the route table via `generatePages` in [`packages/astro/src/core/build.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/core/build.ts). For each route, the system either:

- **Prerenders static HTML** by executing the component's render function and writing the resulting string to `dist/`
- **Generates SSR entries** by creating a [`server.js`](https://github.com/withastro/astro/blob/main/server.js) entry point (when `output: server` is configured) that re-exports component functions for dynamic rendering

The generator injects `<script type="module">` tags pointing to the correct Vite-produced hydration chunks for interactive islands.

## Asset Emission and Manifest Creation

The final `dist/` directory contains a structured output:

- Static HTML files at their respective routes
- An `assets/` directory with compiled JavaScript, extracted CSS, and copied static files
- A `server/` directory containing SSR entry points for hybrid deployments
- A [`manifest.json`](https://github.com/withastro/astro/blob/main/manifest.json) file mapping original source files to hashed output assets

This manifest, generated by Vite when `manifest: true` is set, enables precise asset referencing and cache-busting strategies.

## Asset Generation Mechanisms

Different asset types follow distinct generation paths within the pipeline:

- **JS hydration scripts** — Created by the Astro compiler when detecting `client:*` directives, then bundled by Vite into discrete chunks
- **CSS stylesheets** — Extracted from component imports and `<style>` tags by Vite's CSS handling pipeline
- **Static files** — Processed as URL assets by Vite's loader, which copies them to `dist/assets` and rewrites references in the compiled output
- **SSR server bundles** — Built as separate entry points when the configuration specifies server output, located in [`packages/astro/src/core/build.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/core/build.ts) around the SSR branch logic

## Configuration and Usage Examples

```bash

# Execute the production build with default settings

npx astro build

```

```javascript
// astro.config.mjs - Customizing build output and enabling manifest
import { defineConfig } from 'astro';

export default defineConfig({
  outDir: 'dist',
  build: {
    format: 'server',
    manifest: true,
  },
});

```

```astro
---
// src/pages/index.astro
---
<html>
  <head>
    <title>My Astro Site</title>
  </head>
  <body>
    <MyReactComponent client:load />
    <!-- Triggers generation of a separate hydration chunk -->
  </body>
</html>

```

## Summary

- The build starts in [`packages/astro/cli.ts`](https://github.com/withastro/astro/blob/main/packages/astro/cli.ts) and maintains state through a **BuildContext** object in [`packages/astro/src/core/build.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/core/build.ts)
- **Vite integration** happens via [`packages/astro/src/vite-plugin-astro.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/vite-plugin-astro.ts), which configures the custom Astro plugin and enables manifest generation
- **Route discovery** in [`packages/astro/src/core/pages.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/core/pages.ts) creates a table distinguishing prerendered pages from SSR routes
- The **Astro Compiler** ([`packages/astro/src/compiler/compile.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/compiler/compile.ts)) transforms `.astro` files into virtual modules and hydration scripts
- **Vite's rollup pipeline** handles final bundling, CSS extraction, and static asset processing
- Output includes static HTML, an `assets/` directory, SSR entry points when configured, and a [`manifest.json`](https://github.com/withastro/astro/blob/main/manifest.json) file

## Frequently Asked Questions

### How does Astro decide between static prerendering and SSR?

Astro checks for `export const prerender = true` in a page's front-matter or examines the `output: server` configuration setting. The **Page Collector** in [`packages/astro/src/core/pages.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/core/pages.ts) categorizes routes accordingly, while the build logic in [`packages/astro/src/core/build.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/core/build.ts) branches to either render static HTML strings or emit a [`server.js`](https://github.com/withastro/astro/blob/main/server.js) SSR entry point.

### What generates the JavaScript chunks for interactive islands?

The **Astro Compiler** (`compile` function in [`packages/astro/src/compiler/compile.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/compiler/compile.ts)) detects `client:*` directives during component parsing and generates separate virtual entry points for hydration. Vite then bundles these into discrete JavaScript chunks during the rollup phase, which the HTML generator links via `<script type="module">` tags.

### Where are static assets like images and fonts stored after building?

Vite's internal asset loader processes these files during the build phase, copying them to `dist/assets/` with hashed filenames for cache busting. The original URL references in HTML and CSS are automatically rewritten to point to these processed assets, with the mapping recorded in [`manifest.json`](https://github.com/withastro/astro/blob/main/manifest.json).

### How can I inspect the relationship between source files and output assets?

Enable the Vite manifest by setting `build: { manifest: true }` in your `astro.config.mjs`. This generates a [`manifest.json`](https://github.com/withastro/astro/blob/main/manifest.json) file in the `dist/` directory containing a complete mapping of original source paths to their compiled output locations, including JavaScript chunks, CSS files, and static assets.