From harness-claude
Build or consume Astro integrations to extend the build pipeline — add renderers, inject routes, modify Vite config, and hook into build lifecycle events.
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:astro-integration-patternThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Build or consume Astro integrations to extend the build pipeline — add renderers, inject routes, modify Vite config, and hook into build lifecycle events.
Build or consume Astro integrations to extend the build pipeline — add renderers, inject routes, modify Vite config, and hook into build lifecycle events.
@astrojs/react, @astrojs/tailwind, @astrojs/sitemap) to a projectastro.config.mjs using the integrations array. Call each integration as a function:// astro.config.mjs
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
import tailwind from '@astrojs/tailwind';
import sitemap from '@astrojs/sitemap';
export default defineConfig({
site: 'https://example.com',
integrations: [react(), tailwind({ applyBaseStyles: false }), sitemap()],
});
name and hooks:// my-integration.ts
import type { AstroIntegration } from 'astro';
export function myIntegration(options: { debug?: boolean } = {}): AstroIntegration {
return {
name: 'my-integration',
hooks: {
'astro:config:setup': ({ updateConfig, injectRoute, injectScript, addWatchFile, logger }) => {
// Modify Vite config
updateConfig({
vite: {
plugins: [myVitePlugin()],
define: { __DEBUG__: options.debug ?? false },
},
});
// Inject a virtual route
injectRoute({
pattern: '/my-integration-page',
entrypoint: './src/my-integration/page.astro',
});
// Inject a script on every page
injectScript('page', `console.log('Integration active');`);
logger.info('My integration configured');
},
'astro:build:done': ({ dir, routes, logger }) => {
logger.info(`Build complete. ${routes.length} routes generated.`);
},
},
};
}
| Hook | When it runs | Common uses |
|---|---|---|
astro:config:setup | Before build starts | updateConfig, injectRoute, injectScript, addRenderer |
astro:config:done | After all integrations have modified config | Read the final resolved config |
astro:server:setup | Dev server created | Add Vite dev server middleware |
astro:server:start | Dev server listening | Log the dev URL |
astro:build:start | Build starts | Initialize build-time resources |
astro:build:done | All pages/assets generated | Post-process output files, generate sitemaps |
addRenderer() inside astro:config:setup:'astro:config:setup': ({ addRenderer }) => {
addRenderer({
name: 'my-framework',
serverEntrypoint: 'my-framework/server.js',
clientEntrypoint: 'my-framework/client.js',
jsxImportSource: 'my-framework',
jsxTransformOptions: async () => ({
plugins: [['@babel/plugin-transform-react-jsx', { runtime: 'automatic' }]],
}),
});
}
addWatchFile() to trigger HMR when config files outside the project root change:'astro:config:setup': ({ addWatchFile, config }) => {
addWatchFile(new URL('./my-config.json', config.root));
}
astro:config:done — this is after all integrations have run and the config is finalized:'astro:config:done': ({ config }) => {
if (config.output === 'static') {
// perform SSG-specific setup
}
}
defineConfig in astro.config.mjs for colocation, or publish it as a separate npm package following the astro-* naming convention.Astro integrations are the official extensibility mechanism. They are synchronous or async functions that hook into well-defined lifecycle points in the Astro build pipeline. Unlike Vite plugins (which are lower-level), Astro integrations have access to Astro-specific primitives like injectRoute, addRenderer, and the Astro config object.
Integration execution order:
Integrations are executed in the order they appear in the integrations array. Hook calls within each lifecycle event are also ordered. This matters when integrations modify shared config (e.g., Vite plugins) — later integrations see the changes made by earlier ones.
updateConfig merging:
updateConfig() does a deep merge with the existing config. Call it multiple times if needed — each call merges on top of the previous state. Be careful with arrays (like vite.plugins) — they are concatenated, not replaced.
injectRoute and virtual modules:
injectRoute adds a route to the Astro router backed by an actual file. For truly virtual content (generated at build time), pair it with a Vite virtual module plugin to serve the file from memory.
Integration API stability:
The astro:config:setup and astro:build:done hooks are stable. Hooks prefixed with astro:server:* are available only in development. The full hooks API is documented in the Astro Integrations Reference.
Official integration patterns to study:
@astrojs/sitemap — minimal integration that generates files in astro:build:done@astrojs/tailwind — adds a Vite plugin via updateConfig@astrojs/react — uses addRenderer plus updateConfig for JSX transformPublishing guidelines:
Name your package astro-<feature>. Add astro and astro-component to keywords in package.json. Export the integration as the default export. Add "astro" to peerDependencies.
https://docs.astro.build/en/reference/integrations-reference
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeExpert Astro UI framework integrations — @astrojs/react, @astrojs/vue, @astrojs/svelte, @astrojs/solid-js, @astrojs/preact, @astrojs/alpinejs, @astrojs/lit, @qwikdev/astro, @analogjs/astro-angular. Setup, multi-framework config, usage patterns.
Comprehensive patterns for integrating React components, MDX content, and Tailwind CSS into Astro websites with type safety, performance optimization, and best practices.
Guides Astro rendering strategy decisions (SSG, SSR, hybrid), islands architecture with hydration directives, and content collections. Includes adapter configuration for Cloudflare and other platforms.