Skip to main content
Astro provides several official integrations beyond UI frameworks and adapters to enhance your site’s functionality.

Content Integrations

MDX

Use JSX components in Markdown files

Markdoc

Use Markdoc for content-driven sites

MDX

The MDX integration allows you to use JSX components and import statements in Markdown files.

Installation

npx astro add mdx
Or manually:
npm install @astrojs/mdx

Configuration

astro.config.mjs
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';

export default defineConfig({
  integrations: [mdx()],
});

Options

mdx({
  // Extend frontmatter with additional properties
  extendMarkdownConfig: true,
  
  // Remark plugins
  remarkPlugins: [],
  
  // Rehype plugins
  rehypePlugins: [],
  
  // Custom recma plugins
  recmaPlugins: [],
  
  // Optimize for production
  optimize: false,
})

Usage Example

Create an MDX page:
src/pages/blog/post.mdx
---
title: My First MDX Post
author: Astro Learner
---

import { Code } from 'astro:components';
import CustomComponent from '../../components/CustomComponent.astro';

# {frontmatter.title}

By {frontmatter.author}

Here's some content with a custom component:

<CustomComponent />

And here's some code:

<Code code={`const hello = 'world';`} lang="js" />

export const metadata = {
  published: new Date('2024-03-15'),
};

Using MDX with Components

You can import and use any framework component in MDX:
src/content/blog/interactive-post.mdx
---
title: Interactive Tutorial
---

import Counter from '../../components/Counter.tsx';
import Chart from '../../components/Chart.vue';

# Interactive Content

Try this counter:

<Counter client:load count={0} />

And here's a chart:

<Chart client:visible data={chartData} />

Frontmatter in MDX

Access frontmatter in your MDX:
---
layout: ../../layouts/BlogLayout.astro
title: Post Title
tags: ['astro', 'mdx']
---

# {frontmatter.title}

Tags: {frontmatter.tags.join(', ')}

Markdoc

Markdoc is a powerful, flexible content authoring format from Stripe.
The Markdoc integration is currently experimental.

Installation

npx astro add markdoc

Configuration

astro.config.mjs
import { defineConfig } from 'astro/config';
import markdoc from '@astrojs/markdoc';

export default defineConfig({
  integrations: [markdoc()],
});

Custom Tags and Nodes

Create custom Markdoc tags:
markdoc.config.mjs
import { defineMarkdocConfig, component } from '@astrojs/markdoc/config';

export default defineMarkdocConfig({
  tags: {
    callout: {
      render: component('./src/components/Callout.astro'),
      attributes: {
        type: { type: String, default: 'info' },
      },
    },
  },
});
Use in Markdoc:
{% callout type="warning" %}
This is a warning!
{% /callout %}

Utility Integrations

Sitemap

Automatically generate a sitemap.xml

Partytown

Relocate scripts to a web worker for better performance

Sitemap

The Sitemap integration automatically generates a sitemap.xml file for your site.

Installation

npx astro add sitemap

Configuration

astro.config.mjs
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';

export default defineConfig({
  site: 'https://example.com',
  integrations: [
    sitemap(),
  ],
});
You must set the site option in your Astro config for the sitemap to work.

Options

sitemap({
  // Filter pages to include
  filter: (page) => !page.includes('/admin/'),
  
  // Customize URLs
  customPages: [
    'https://example.com/custom-page',
  ],
  
  // Change priority and frequency
  changefreq: 'weekly',
  priority: 0.7,
  
  // i18n configuration
  i18n: {
    defaultLocale: 'en',
    locales: {
      en: 'en-US',
      es: 'es-ES',
    },
  },
  
  // Serialize each entry
  serialize: (item) => {
    if (item.url.includes('/blog/')) {
      item.changefreq = 'daily';
      item.priority = 0.9;
    }
    return item;
  },
})

Generated Output

The sitemap will be generated at /sitemap-index.xml and includes all static routes:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://example.com/</loc>
  </url>
  <url>
    <loc>https://example.com/about/</loc>
  </url>
  <url>
    <loc>https://example.com/blog/post-1/</loc>
    <changefreq>daily</changefreq>
    <priority>0.9</priority>
  </url>
</urlset>

Partytown

Partytown relocates resource-intensive scripts into a web worker, freeing up the main thread.

Installation

npx astro add partytown

Configuration

astro.config.mjs
import { defineConfig } from 'astro/config';
import partytown from '@astrojs/partytown';

export default defineConfig({
  integrations: [
    partytown({
      // Configure which scripts to move to web worker
      config: {
        forward: ['dataLayer.push'],
      },
    }),
  ],
});

Options

partytown({
  config: {
    // Forward specific methods to main thread
    forward: ['dataLayer.push', 'gtag'],
    
    // Debug mode
    debug: false,
    
    // Resolve URLs
    resolveUrl: (url) => {
      if (url.hostname === 'example.com') {
        const proxyUrl = new URL('https://my-proxy.com');
        proxyUrl.searchParams.append('url', url.href);
        return proxyUrl;
      }
      return url;
    },
  },
})

Usage Example

Add the type="text/partytown" attribute to scripts you want to run in a web worker:
src/pages/index.astro
---
// ...
---

<html>
  <head>
    <script type="text/partytown" src="https://www.googletagmanager.com/gtag/js"></script>
    <script type="text/partytown">
      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());
      gtag('config', 'GA_MEASUREMENT_ID');
    </script>
  </head>
  <body>
    <!-- Your content -->
  </body>
</html>

Common Use Cases

  • Google Analytics / Google Tag Manager
  • Facebook Pixel
  • Third-party analytics scripts
  • Heavy third-party libraries

DB (Database)

Astro DB provides a fully-managed SQL database designed for Astro.
Astro DB is available in Astro 4.5 and later.

Installation

npx astro add db

Define Your Schema

db/config.ts
import { defineDb, defineTable, column } from 'astro:db';

const Author = defineTable({
  columns: {
    id: column.number({ primaryKey: true }),
    name: column.text(),
    email: column.text({ unique: true }),
  },
});

const Post = defineTable({
  columns: {
    id: column.number({ primaryKey: true }),
    title: column.text(),
    body: column.text(),
    authorId: column.number({ references: () => Author.columns.id }),
    published: column.date(),
  },
});

export default defineDb({
  tables: { Author, Post },
});

Query Your Database

src/pages/blog.astro
---
import { db, Post, Author } from 'astro:db';

const posts = await db
  .select()
  .from(Post)
  .innerJoin(Author, eq(Post.authorId, Author.id));
---

<ul>
  {posts.map(post => (
    <li>
      <h2>{post.title}</h2>
      <p>By {post.Author.name}</p>
    </li>
  ))}
</ul>

Next Steps

UI Frameworks

Add React, Vue, Svelte, and other UI frameworks

SSR Adapters

Deploy with server-side rendering

Build docs developers (and LLMs) love