Integrations Overview
Purpose and Scope
Astro integrations are small packages that add behavior to a project without making every application reimplement the same setup. The official documentation describes them as a way to unlock UI renderers, enable server rendering through adapters, connect tools such as MDX or Partytown, generate features such as sitemaps, and hook custom code into development and build phases. In this repository, that idea appears at two levels: a reusable starter for authors who want to publish an integration, and maintained packages such as the Alpine integration that show the user-facing package pattern. Sources: examples/integration/README.md, packages/integrations/alpinejs/README.md
An integration should be understood as a boundary between project configuration and Astro’s internal lifecycle. A site author normally experiences an integration as a function placed in the project configuration. An integration author experiences it as an object with a package name and lifecycle hooks. The starter template is intentionally minimal so that the author can concentrate on the public contract first: export the integration from the package entry point, register the hooks that matter, and then test it inside a real Astro project before publishing. Sources: examples/integration/README.md, examples/integration/index.ts
Relevant Source Files
- examples/integration/README.md — describes the integration package starter, the expected package structure, the template creation command, and local publishing commands.
- examples/integration/index.ts — provides the minimal TypeScript implementation of an integration factory returning an AstroIntegration object with hook names.
- packages/astro/src/core/README.md — explains the core command lifecycle and the pipeline concepts that integrations participate in indirectly through build, dev, preview, and sync.
- packages/integrations/alpinejs/README.md — shows an official integration package README, including purpose, support links, documentation links, and maintenance expectations.
Core Primitives
The central primitive for integration authors is the integration factory: a function that returns an Astro integration object. In the starter, the default export is a function named createIntegration, and it imports the AstroIntegration type from the public astro package. The returned object includes a name and a hooks map. The example chooses three representative hook keys: astro:config:setup, astro:build:setup, and astro:build:done. Those names are useful orientation points because they show that integrations can act before configuration is finalized, during build setup, and after the build finishes. Sources: examples/integration/index.ts
The core README explains why those hook moments matter. Astro’s main logic for build, dev, preview, and sync lives in the core package, and the core entry point exports those commands as functions from the astro package. Internally, Astro maintains environment-specific pipelines for development, static build or prerendering, and production server deployments. Integrations do not need to own those internals, but they are designed to cooperate with the same lifecycle: configuration is established, a server or build pipeline is created, routes and render contexts use that configuration, and request-specific work proceeds through middleware, endpoints, and pages. Sources: packages/astro/src/core/README.md
Authoring Flow from the Starter
The integration starter is meant for code that will be reused across projects or published to npm. The README shows it can be created with the integration template, giving authors a package-shaped project instead of a site-shaped application. Its file tree is intentionally short: an entry point, a TypeScript configuration, and package metadata. That simplicity is important because the integration package itself should not hide its behavior behind many local conventions. Consumers will import the package, call its exported function, and expect Astro to run its hooks at the correct phase. Sources: examples/integration/README.md
npm create astro@latest -- --template integrationA useful local workflow is to treat the starter like any other npm package before publishing. The starter README calls out npm link for local registration, followed by linking the named integration inside an Astro project. That lets an author edit the integration package, install it into a test project, and verify the configuration behavior before distributing it. Publishing is a separate step, handled by npm publish after the package is ready and the author is logged in. This separation encourages integration authors to validate user experience locally rather than relying on published trial releases. Sources: examples/integration/README.md
npm link
# then, in an Astro project:
npm link my-integrationSystem-to-Code Mapping
The starter entry point maps directly onto the public Integration API described by the official docs. The returned name identifies the integration in logs and diagnostics, while the hooks map describes which lifecycle phases the package participates in. The example leaves the hook bodies empty and points authors toward established integrations such as React for configuration and build setup behavior, and Partytown for build completion behavior. That is a deliberate teaching pattern: the starter provides the shape, while production integrations provide concrete decisions about renderers, scripts, injected routes, generated files, or build artifacts. Sources: examples/integration/index.ts
The Alpine integration README shows the consumer side of the same contract. It presents the package as @astrojs/alpinejs and states that it adds Alpine.js so it can be used anywhere on the page. Instead of exposing internal hook code in the README, it sends users to the integration guide, support channels, and issue tracker. That reflects the difference between an integration package’s public promise and its implementation details. Users should be able to install the package and follow documentation; maintainers and contributors can use the repository and contribution links when they need to inspect or change behavior. Sources: packages/integrations/alpinejs/README.md
Using Official Integrations in Projects
For project authors, the common path is to install an official integration and add it to the Astro configuration. The official docs describe astro add as the automated setup command for official integrations and some community plugins. That command installs required dependencies and updates configuration for the selected package when supported. Alpine’s docs show both the automated path and the manual path: install @astrojs/alpinejs, install Alpine peer packages if the package manager does not do so, then add the integration function to the integrations array in the project configuration. Sources: packages/integrations/alpinejs/README.md
import { defineConfig } from 'astro/config';
import alpinejs from '@astrojs/alpinejs';
export default defineConfig({
integrations: [alpinejs()],
});This distinction between automatic and manual setup matters when documenting or testing an integration. Automatic setup is the best first instruction for users when the integration supports it, because it reduces configuration mistakes and dependency mismatches. Manual setup remains important for debugging, package managers with different peer dependency behavior, and custom project structures. When writing an integration README, follow the Alpine pattern: describe the feature in one sentence, link to the full docs, provide support routes, and make the contribution path clear for users who discover bugs or want to improve the package. Sources: packages/integrations/alpinejs/README.md
API Components and Reference
A compact integration object has two required ideas: identity and hooks. The identity is the name string returned by the factory. The hooks object is keyed by Astro lifecycle event names. The starter includes astro:config:setup for configuration-time changes, astro:build:setup for build preparation, and astro:build:done for work that runs after a build completes. The official Integration API reference expands that model with additional hook options and callback capabilities, but the starter’s minimal implementation is the safest baseline for new authors because it compiles against AstroIntegration before adding advanced behavior. Sources: examples/integration/index.ts
import type { AstroIntegration } from 'astro';
export default function createIntegration(): AstroIntegration {
return {
name: '@example/my-integration',
hooks: {
'astro:config:setup': () => {},
'astro:build:setup': () => {},
'astro:build:done': () => {},
},
};
}Implementation Details and Next Steps
When choosing where to add behavior, think in lifecycle terms rather than file terms. Configuration setup is appropriate for registering renderers, directives, middleware, routes, or other configuration-driven capabilities. Build setup is better for preparing work that depends on the resolved project and build environment. Build completion is appropriate for post-processing or reporting after output exists. The core README’s pipeline description reinforces that Astro has distinct development, build, and production server contexts, so integrations should avoid assuming that every hook runs with the same environment, routes, or request data available. Sources: examples/integration/index.ts, packages/astro/src/core/README.md
Next, read the framework integration pages when you need renderer behavior, the adapter deployment pages when your integration controls server output, and the API reference when you need the full hook signature. If you are creating a reusable package, start from the integration starter, keep the exported factory small, and test it through a linked Astro project before publishing. If you are simply using an integration, prefer astro add when the documentation supports it, then inspect the manual installation notes only when dependency or configuration problems appear. Sources: examples/integration/README.md, packages/integrations/alpinejs/README.md