CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-astro

Astro is a modern site builder with web best practices, performance, and DX front-of-mind.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

integrations.mddocs/

Integrations and Adapters

Astro's integration system provides extensibility through hooks that allow integrations to modify configuration, inject routes, add renderers, and extend the build process.

Capabilities

Integration Interface

Defines an Astro integration.

interface AstroIntegration {
  /**
   * Integration name
   */
  name: string;

  /**
   * Integration hooks
   */
  hooks: {
    'astro:config:setup'?: (
      options: HookParameters<'astro:config:setup'>
    ) => void | Promise<void>;

    'astro:config:done'?: (
      options: HookParameters<'astro:config:done'>
    ) => void | Promise<void>;

    'astro:server:setup'?: (
      options: HookParameters<'astro:server:setup'>
    ) => void | Promise<void>;

    'astro:server:start'?: (
      options: HookParameters<'astro:server:start'>
    ) => void | Promise<void>;

    'astro:server:done'?: (
      options: HookParameters<'astro:server:done'>
    ) => void | Promise<void>;

    'astro:build:start'?: (
      options: HookParameters<'astro:build:start'>
    ) => void | Promise<void>;

    'astro:build:setup'?: (
      options: HookParameters<'astro:build:setup'>
    ) => void | Promise<void>;

    'astro:build:generated'?: (
      options: HookParameters<'astro:build:generated'>
    ) => void | Promise<void>;

    'astro:build:ssr'?: (
      options: HookParameters<'astro:build:ssr'>
    ) => void | Promise<void>;

    'astro:build:done'?: (
      options: HookParameters<'astro:build:done'>
    ) => void | Promise<void>;

    'astro:route:setup'?: (
      options: HookParameters<'astro:route:setup'>
    ) => void | Promise<void>;

    'astro:routes:resolved'?: (
      options: HookParameters<'astro:routes:resolved'>
    ) => void | Promise<void>;
  };
}

Integration Hooks

astro:config:setup

Runs during initial configuration setup. Most powerful hook for modifying configuration.

interface ConfigSetupHookParameters {
  /**
   * Current Astro configuration
   */
  config: AstroConfig;

  /**
   * Update Astro configuration
   * Returns the updated configuration
   */
  updateConfig: (newConfig: DeepPartial<AstroConfig>) => AstroConfig;

  /**
   * Add renderer for framework components
   */
  addRenderer: (renderer: AstroRenderer) => void;

  /**
   * Add client directive (e.g., client:visible)
   */
  addClientDirective: (directive: ClientDirectiveConfig) => void;

  /**
   * Add dev toolbar app
   */
  addDevToolbarApp: (entrypoint: string) => void;

  /**
   * Add middleware
   */
  addMiddleware: (middleware: AddMiddleware) => void;

  /**
   * Add watch files for dev server
   */
  addWatchFile: (file: URL | string) => void;

  /**
   * Inject route into the project
   */
  injectRoute: (route: InjectedRoute) => void;

  /**
   * Inject script into pages
   */
  injectScript: (stage: InjectedScriptStage, content: string) => void;

  /**
   * Create a directory for generated files
   * Returns URL to the created directory
   */
  createCodegenDir: () => URL;

  /**
   * Integration logger
   */
  logger: AstroIntegrationLogger;

  /**
   * Command being run
   */
  command: 'dev' | 'build' | 'preview' | 'sync';

  /**
   * Build mode
   */
  isRestart: boolean;
}
export default function myIntegration(): AstroIntegration {
  return {
    name: 'my-integration',
    hooks: {
      'astro:config:setup': ({
        config,
        updateConfig,
        addRenderer,
        injectRoute,
        logger,
      }) => {
        logger.info('Setting up integration');

        // Update configuration
        updateConfig({
          vite: {
            optimizeDeps: {
              include: ['my-package'],
            },
          },
        });

        // Add a renderer
        addRenderer({
          name: 'my-renderer',
          serverEntrypoint: 'my-renderer/server.js',
        });

        // Inject a route
        injectRoute({
          pattern: '/api/my-endpoint',
          entrypoint: './api/endpoint.ts',
        });
      },
    },
  };
}

astro:config:done

Runs after configuration is finalized. Read-only access to config.

interface ConfigDoneHookParameters {
  /**
   * Final Astro configuration (read-only)
   */
  config: AstroConfig;

  /**
   * Set adapter for SSR
   */
  setAdapter: (adapter: AstroAdapter) => void;

  /**
   * Inject TypeScript type definitions
   * Returns URL to the generated type file
   */
  injectTypes: (injectedType: InjectedType) => URL;

  /**
   * Build output mode
   */
  buildOutput: 'static' | 'server';

  /**
   * Integration logger
   */
  logger: AstroIntegrationLogger;
}

interface InjectedType {
  /**
   * Filename for the type definition file
   */
  filename: string;

  /**
   * TypeScript content to inject
   */
  content: string;
}

astro:server:setup

Runs when dev server is created.

interface ServerSetupHookParameters {
  /**
   * Vite dev server instance
   */
  server: ViteDevServer;

  /**
   * Integration logger
   */
  logger: AstroIntegrationLogger;

  /**
   * Toolbar tools
   */
  toolbar: ToolbarServerHelpers;

  /**
   * Refresh content collections (optional)
   */
  refreshContent?: (options: RefreshContentOptions) => Promise<void>;
}

interface RefreshContentOptions {
  /**
   * Loaders to refresh (optional)
   */
  loaders?: string[];

  /**
   * Context information (optional)
   */
  context?: Record<string, unknown>;
}

astro:server:start

Runs after dev server starts.

interface ServerStartHookParameters {
  /**
   * Server address
   */
  address: AddressInfo;

  /**
   * Integration logger
   */
  logger: AstroIntegrationLogger;
}

astro:build:start

Runs before build starts.

interface BuildStartHookParameters {
  /**
   * Integration logger
   */
  logger: AstroIntegrationLogger;
}

astro:build:setup

Runs during build setup.

interface BuildSetupHookParameters {
  /**
   * Vite build configuration
   */
  vite: ViteInlineConfig;

  /**
   * Pages to build
   */
  pages: Map<string, PageBuildData>;

  /**
   * Target output ('client' or 'server')
   */
  target: 'client' | 'server';

  /**
   * Update Vite configuration
   */
  updateConfig: (config: ViteInlineConfig) => void;

  /**
   * Integration logger
   */
  logger: AstroIntegrationLogger;
}

astro:build:generated

Runs after static build generates files.

interface BuildGeneratedHookParameters {
  /**
   * Build output directory
   */
  dir: URL;

  /**
   * Integration logger
   */
  logger: AstroIntegrationLogger;
}

astro:build:ssr

Runs after SSR build completes.

interface BuildSSRHookParameters {
  /**
   * SSR manifest
   */
  manifest: SSRManifest;

  /**
   * Entry points map
   */
  entryPoints: Map<RouteData, URL>;

  /**
   * Middleware entry point
   */
  middlewareEntryPoint: URL | undefined;

  /**
   * Integration logger
   */
  logger: AstroIntegrationLogger;
}

astro:build:done

Runs after entire build completes.

interface BuildDoneHookParameters {
  /**
   * Build output directory
   */
  dir: URL;

  /**
   * Generated routes
   * @deprecated Use the `assets` map and the new `astro:routes:resolved` hook
   */
  routes: IntegrationRouteData[];

  /**
   * Generated pages
   */
  pages: { pathname: string }[];

  /**
   * Assets map from routes to their generated asset URLs
   */
  assets: Map<string, URL[]>;

  /**
   * Integration logger
   */
  logger: AstroIntegrationLogger;
}

astro:route:setup

Runs when a route is being set up during the build process. This hook is called for each route being processed.

interface RouteSetupHookParameters {
  /**
   * Route options including component path and prerender settings
   */
  route: RouteOptions;

  /**
   * Integration logger
   */
  logger: AstroIntegrationLogger;
}

interface RouteOptions {
  /**
   * The path to this route relative to the project root. The slash is normalized as forward slash
   * across all OS.
   * @example "src/pages/blog/[...slug].astro"
   */
  readonly component: string;

  /**
   * Whether this route should be prerendered. If the route has an explicit `prerender` export,
   * the value will be passed here. Otherwise, it's undefined and will fallback to a prerender
   * default depending on the `output` option.
   */
  prerender?: boolean;
}

astro:routes:resolved

Runs after all routes have been resolved during the build process. This hook provides complete information about all routes in the project.

interface RoutesResolvedHookParameters {
  /**
   * Resolved routes with complete metadata
   */
  routes: IntegrationResolvedRoute[];

  /**
   * Integration logger
   */
  logger: AstroIntegrationLogger;
}

interface IntegrationResolvedRoute {
  /**
   * Route pattern (e.g., "/blog/[slug]")
   */
  pattern: string;

  /**
   * Regular expression for matching the route pattern
   */
  patternRegex: RegExp;

  /**
   * Path to the component file
   */
  entrypoint: string;

  /**
   * Whether this route is prerendered
   */
  isPrerendered: boolean;

  /**
   * Function to generate the route path from params
   */
  generate: (data?: any) => string;

  /**
   * Dynamic and spread route params
   */
  params: string[];

  /**
   * Output URL pathname (undefined for dynamic/spread routes)
   */
  pathname?: string;

  /**
   * Route segments
   */
  segments: RoutePart[][];

  /**
   * Route type
   */
  type: 'page' | 'endpoint' | 'redirect' | 'fallback';

  /**
   * Redirect configuration if this is a redirect route
   */
  redirect?: RedirectConfig;

  /**
   * Route origin (user-defined or internal)
   */
  origin?: 'user' | 'internal';

  /**
   * Redirect route information if this route redirects to another
   */
  redirectRoute?: IntegrationResolvedRoute;
}

interface RoutePart {
  /**
   * Segment content
   */
  content: string;

  /**
   * Whether this segment is dynamic (e.g., [id])
   */
  dynamic: boolean;

  /**
   * Whether this segment is a spread parameter (e.g., [...slug])
   */
  spread: boolean;
}

Renderer Interface

Defines a framework renderer (React, Vue, Svelte, etc.).

interface AstroRenderer {
  /**
   * Renderer name
   */
  name: string;

  /**
   * Server entrypoint for SSR
   */
  serverEntrypoint: string;

  /**
   * Client entrypoint for hydration
   */
  clientEntrypoint?: string;

  /**
   * JSX import source
   */
  jsxImportSource?: string;

  /**
   * JSX transformation plugin
   */
  jsxTransformOptions?: (options: {
    mode: string;
    ssr: boolean;
  }) => Promise<{ jsx: 'react' | 'preserve'; plugins?: any[] }>;
}

Example Renderer:

export default function reactIntegration(): AstroIntegration {
  return {
    name: '@astrojs/react',
    hooks: {
      'astro:config:setup': ({ addRenderer }) => {
        addRenderer({
          name: '@astrojs/react',
          serverEntrypoint: '@astrojs/react/server.js',
          clientEntrypoint: '@astrojs/react/client.js',
          jsxImportSource: 'react',
        });
      },
    },
  };
}

Client Directives

Custom client: directives for hydration strategies.

interface ClientDirectiveConfig {
  /**
   * Directive name (used as client:name)
   */
  name: string;

  /**
   * Entrypoint module
   */
  entrypoint: string;
}
export default function customHydration(): AstroIntegration {
  return {
    name: 'custom-hydration',
    hooks: {
      'astro:config:setup': ({ addClientDirective }) => {
        addClientDirective({
          name: 'custom',
          entrypoint: './client-directive.js',
        });
      },
    },
  };
}

Injected Routes

Add routes programmatically.

interface InjectedRoute {
  /**
   * Route pattern (e.g., '/api/data')
   */
  pattern: string;

  /**
   * Route entrypoint file
   */
  entrypoint: string;

  /**
   * Prerender the route
   * @default false
   */
  prerender?: boolean;
}
export default function apiRoutes(): AstroIntegration {
  return {
    name: 'api-routes',
    hooks: {
      'astro:config:setup': ({ injectRoute }) => {
        injectRoute({
          pattern: '/api/health',
          entrypoint: './src/api/health.ts',
        });

        injectRoute({
          pattern: '/sitemap.xml',
          entrypoint: './src/api/sitemap.ts',
          prerender: true,
        });
      },
    },
  };
}

Integration Logger

Logging utilities for integrations.

interface AstroIntegrationLogger {
  /**
   * Log info message
   */
  info(message: string): void;

  /**
   * Log warning message
   */
  warn(message: string): void;

  /**
   * Log error message
   */
  error(message: string): void;

  /**
   * Log debug message
   */
  debug(message: string): void;

  /**
   * Create child logger with prefix
   */
  fork(label: string): AstroIntegrationLogger;
}

Example Integrations

Simple Integration

export default function simpleIntegration(): AstroIntegration {
  return {
    name: 'simple-integration',
    hooks: {
      'astro:config:setup': ({ logger }) => {
        logger.info('Setting up simple integration');
      },
      'astro:config:done': ({ config, logger }) => {
        logger.info(`Site: ${config.site}`);
      },
    },
  };
}

Vite Plugin Integration

export default function vitePluginIntegration(): AstroIntegration {
  return {
    name: 'vite-plugin-integration',
    hooks: {
      'astro:config:setup': ({ updateConfig }) => {
        updateConfig({
          vite: {
            plugins: [myVitePlugin()],
          },
        });
      },
    },
  };
}

Route Injection Integration

export default function routeInjection(): AstroIntegration {
  return {
    name: 'route-injection',
    hooks: {
      'astro:config:setup': ({ injectRoute, addWatchFile }) => {
        // Inject API routes
        injectRoute({
          pattern: '/api/posts',
          entrypoint: './src/api/posts.ts',
        });

        // Watch external file
        addWatchFile(new URL('./data/posts.json', import.meta.url));
      },
    },
  };
}

Build Post-Processing Integration

import fs from 'fs/promises';
import path from 'path';

export default function postProcess(): AstroIntegration {
  return {
    name: 'post-process',
    hooks: {
      'astro:build:done': async ({ dir, pages, logger }) => {
        logger.info(`Processing ${pages.length} pages`);

        for (const page of pages) {
          const filePath = path.join(dir.pathname, page.pathname, 'index.html');
          let content = await fs.readFile(filePath, 'utf-8');

          // Modify content
          content = content.replace('</body>', '<script>console.log("Injected")</script></body>');

          await fs.writeFile(filePath, content);
        }

        logger.info('Post-processing complete');
      },
    },
  };
}

Adapter Integration

export default function customAdapter(): AstroIntegration {
  return {
    name: 'custom-adapter',
    hooks: {
      'astro:config:setup': ({ updateConfig }) => {
        updateConfig({
          vite: {
            ssr: {
              noExternal: ['my-platform-package'],
            },
          },
        });
      },
      'astro:config:done': ({ setAdapter, config }) => {
        setAdapter({
          name: 'custom-adapter',
          serverEntrypoint: 'custom-adapter/server.js',
          supportedAstroFeatures: {
            staticOutput: 'stable',
            serverOutput: 'stable',
            hybridOutput: 'stable',
          },
        });
      },
      'astro:build:done': async ({ dir, logger }) => {
        logger.info('Preparing deployment package');
        // Copy files, create manifests, etc.
      },
    },
  };
}

Dev Toolbar Integration

export default function devToolbar(): AstroIntegration {
  return {
    name: 'dev-toolbar',
    hooks: {
      'astro:config:setup': ({ addDevToolbarApp }) => {
        addDevToolbarApp('./toolbar-app.ts');
      },
    },
  };
}

Integration Utilities

Add Middleware

interface AddMiddleware {
  /**
   * Middleware entrypoint
   */
  entrypoint: string;

  /**
   * Middleware order
   * - 'pre': Run before user middleware
   * - 'post': Run after user middleware
   * @default 'pre'
   */
  order?: 'pre' | 'post';
}

Inject Script

type InjectedScriptStage =
  | 'head-inline'
  | 'before-hydration'
  | 'page'
  | 'page-ssr';
'astro:config:setup': ({ injectScript }) => {
  // Inline script in <head>
  injectScript('head-inline', 'console.log("Init")');

  // Script before hydration
  injectScript('before-hydration', 'import "./setup.js"');
}

docs

assets.md

cli-and-build.md

configuration.md

container.md

content-collections.md

content-loaders.md

dev-toolbar.md

environment.md

i18n.md

index.md

integrations.md

middleware.md

server-actions.md

ssr-and-app.md

transitions.md

tile.json