npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

astro-mermaid-satteri

v0.3.3

Published

Astro integration for rendering Mermaid diagrams with Sätteri, auto dark/light theme switching, and View Transitions support.

Downloads

238

Readme

astro-mermaid-satteri

A TypeScript rewrite of astro-mermaid for Astro 7 and the Sätteri markdown processor. Renders Mermaid diagrams in Markdown, MDX, and .astro files. Theme switching, icon packs, View Transitions, and a Sätteri hast plugin under the hood. Works with standalone projects and Starlight.

Install

Option A — astro add (quick)

npx astro add astro-mermaid-satteri

This installs astro-mermaid-satteri, mermaid, and @astrojs/markdown-satteri (all peer dependencies). It also adds the integration to your astro.config.* automatically — but note that astro add imports it as mermaidSatteri (derived from the package name), not mermaid:

// Generated by astro add — valid, but the name is mermaidSatteri
import mermaidSatteri from 'astro-mermaid-satteri';

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

You still need to add the Sätteri processor to your markdown config manually — astro add can't do this for you:

import { defineConfig } from 'astro/config';
import { satteri } from '@astrojs/markdown-satteri';
import mermaidSatteri from 'astro-mermaid-satteri';

export default defineConfig({
  markdown: {
    processor: satteri(),
  },
  integrations: [
    mermaidSatteri(),
  ],
});

You can rename mermaidSatteri to mermaid in the import if you prefer:

import mermaid from 'astro-mermaid-satteri';  // rename the default import

Known issue: Running astro add astro-mermaid-satteri on a project that already imports the integration (under a different name like mermaid) produces invalid import syntax. This is an Astro bug — the addIntegration function doesn't detect existing imports from the same package. If this happens, use Option B instead.

Option B — manual install (recommended)

npm install astro-mermaid-satteri mermaid @astrojs/markdown-satteri

astro, mermaid, and @astrojs/markdown-satteri are peer dependencies. Astro 7 ships with Sätteri as its default markdown processor, so most projects already have what they need.

Then add the integration and the Sätteri processor to your config:

// astro.config.mjs
import { defineConfig } from 'astro/config';
import { satteri } from '@astrojs/markdown-satteri';
import mermaid from 'astro-mermaid-satteri';

export default defineConfig({
  markdown: {
    processor: satteri(),
  },
  integrations: [
    mermaid({
      theme: 'forest',
      autoTheme: true,
    }),
  ],
});

Quick Start

See Install for the full config setup. Once configured, write a fenced code block in any .md or .mdx file:

```mermaid
graph TD
    A[Start] --> B[Process]
    B --> C[End]
```

In .astro files, write the diagram source directly in a <pre> tag. The client script picks up any pre.mermaid element on the page:

<pre class="mermaid">graph LR
    A --> B --> C
</pre>

Diagram Dimensions

Specify a fixed width and/or height (in pixels) with w-NNN and h-NNN in the info string:

```mermaid w-200 h-200
graph TD
    A[Start] --> B[End]
```

Both are optional and can appear in any order. The diagram scales to the given size while preserving the SVG's aspect ratio. When no dimensions are specified, diagrams remain responsive (max-width: 100%, height: auto).

Captions

Add a caption with title="..." in the info string. The diagram is wrapped in a <figure> with a <figcaption>:

```mermaid title="System Architecture"
graph TD
    A[Frontend] --> B[API] --> C[Database]
```

Single quotes also work: title='My Diagram'.

Alignment

Control horizontal alignment with align=left, align=right, or align=center (default):

```mermaid w-300 align=left
graph LR
    A --> B
```

Combining Options

All info-string options can be mixed in any order:

```mermaid w-400 h-200 title="Deployment Overview" align=left
graph TD
    A[Start] --> B[Deploy] --> C[Done]
```

Copy Button

Each rendered diagram has a copy button in the top-right corner (visible on hover) that copies the Mermaid source to the clipboard.

Lazy Loading

Diagrams below the fold are deferred until they scroll near the viewport (via IntersectionObserver with a 300px root margin). This keeps pages with many diagrams fast on initial load. Diagrams already rendered (e.g. during theme switches) re-render immediately.

Integration Order

When pairing with Starlight or other markdown-processing integrations, put mermaid() first. It modifies the Sätteri processor at config setup, so it needs to run before anything else touches the pipeline.

import mermaid from 'astro-mermaid-satteri';
import starlight from '@astrojs/starlight';

export default defineConfig({
  integrations: [
    mermaid(),
    starlight({ title: 'My Docs' }),
  ],
});

Configuration

mermaid({
  // Default theme: 'default', 'dark', 'forest', 'neutral', 'base'
  theme: 'forest',

  // Auto-switch based on the data-theme attribute on <html> and <body>
  autoTheme: true,

  // Theme variables applied to all themes (see Theme Variables below)
  themeVariables: {
    fontSize: '16px',
  },

  // Per-mode overrides, merged on top of themeVariables
  lightThemeVariables: { lineColor: '#0066cc' },
  darkThemeVariables: { primaryColor: '#1a1a2e' },

  // Disable the built-in light-mode readability overrides (default: false)
  disableLightDefaults: false,

  // Suppress console.log in the browser (default: true).
  // Errors are always logged regardless.
  enableLog: false,

  // Anything here is merged into mermaid.initialize()
  mermaidConfig: {
    flowchart: { curve: 'basis' },
  },

  // Register icon packs for use in diagrams
  iconPacks: [
    { name: 'logos', url: 'https://unpkg.com/@iconify-json/logos@1/icons.json' },
    { name: 'iconoir', loader: () => fetch('https://unpkg.com/@iconify-json/iconoir@1/icons.json').then(res => res.json()) },
  ],
})

| Option | Type | Default | Description | | --- | --- | --- | --- | | theme | string | 'dark' | Mermaid theme: 'default', 'dark', 'forest', 'neutral', or 'base'. | | autoTheme | boolean | true | Switch between light and dark based on data-theme on <html> and <body>. | | themeVariables | Record<string, string> | {} | Theme variables applied to all themes, merged before per-theme overrides. | | lightThemeVariables | Record<string, string> | {} | Theme variables applied only in light/default mode, merged on top of themeVariables. | | darkThemeVariables | Record<string, string> | {} | Theme variables applied only in dark mode, merged on top of themeVariables. | | disableLightDefaults | boolean | false | Disable the built-in light-mode readability overrides. | | enableLog | boolean | true | Print diagnostic logs to the browser console. Errors always log. | | mermaidConfig | Record<string, unknown> | {} | Extra config passed to mermaid.initialize(). | | iconPacks | IconPackInput[] | [] | Icon packs to register. Accepts url, icons, or loader forms. |

Theme Switching

When autoTheme is on (the default), the integration reads data-theme from both <html> and <body>. data-theme="dark" maps to Mermaid's dark theme. data-theme="light" maps to default. If neither attribute is set, it falls back to prefers-color-scheme.

A MutationObserver watches for data-theme changes. When the attribute flips, the diagrams re-render after a 50ms debounce. That debounce matters: during View Transitions, the DOM swap can remove and re-add the attribute in the same tick, and without it you'd get a double render.

Theme Variables

Mermaid's default (light) theme uses washed-out fills (#ECECFF) and lightened actor borders that vanish against a light page background. The integration ships built-in light-mode overrides that darken lines, borders, and text for readability. These defaults apply automatically in light mode — no configuration needed.

You can customize theme variables at three levels. They merge in this order (later wins):

  1. Built-in light defaults — applied in light mode only (unless disabled). These are the readability overrides described above.
  2. themeVariables — applied to all themes. The base layer also sets background: 'transparent' so the SVG doesn't draw its own background (the container CSS handles that). Override it here if you need a different value.
  3. lightThemeVariables / darkThemeVariables — applied per mode, merged on top of themeVariables.
mermaid({
  autoTheme: true,

  // Applied to all themes
  themeVariables: {
    fontSize: '16px',
    background: 'transparent',
  },

  // Applied only in light/default mode (overrides built-in defaults)
  lightThemeVariables: {
    lineColor: '#0066cc',
    mainBkg: '#f0f4ff',
  },

  // Applied only in dark mode
  darkThemeVariables: {
    primaryColor: '#1a1a2e',
  },
})

To disable the built-in light-mode overrides entirely (for full manual control):

mermaid({
  autoTheme: true,
  disableLightDefaults: true,
  // Now you control every light-mode value yourself
  lightThemeVariables: {
    lineColor: '#333333',
    textColor: '#333333',
    mainBkg: '#f5f5fa',
    // ... provide whatever you need
  },
})

themeVariables can also be set via mermaidConfig.themeVariables for backward compatibility, but the top-level option is preferred. A full list of available variables is in the Mermaid theme docs.

Icon Packs

Register icon packs to use custom icons in diagrams. Three forms work:

iconPacks: [
  // url: preferred. A JSON endpoint, fetched in the browser at runtime.
  { name: 'logos', url: 'https://unpkg.com/@iconify-json/logos@1/icons.json' },

  // icons: pass icon data directly, e.g. an imported JSON file.
  { name: 'my-icons', icons: myIcons },

  // loader: legacy. We inspect the function source for a fetch('...')
  // URL. Prefer url or icons instead.
  { name: 'iconoir', loader: () => fetch('https://unpkg.com/@iconify-json/iconoir@1/icons.json').then(res => res.json()) },
]

The integration never serializes function bodies to the client. A loader exists only to extract its fetch(...) URL. If no URL turns up, the pack is skipped with a warning. Use url or icons for reliable results.

Then reference icons in your diagrams:

```mermaid
architecture-beta
  group api(logos:aws-lambda)[API]

  service db(logos:postgresql)[Database] in api
  service disk1(logos:aws-s3)[Storage] in api
  service disk2(logos:cloudflare)[CDN] in api
  service server(logos:docker)[Server] in api

  db:L -- R:server
  disk1:T -- B:server
  disk2:T -- B:db
```

ELK Layout

To use the elk layout, install the @mermaid-js/layout-elk package and pass layout: 'elk' through mermaidConfig. Mermaid handles the dynamic import internally.

npm install @mermaid-js/layout-elk
mermaid({
  mermaidConfig: { layout: 'elk' },
});

Learn more about Mermaid layouts or The Eclipse Layout Kernel.

How It Works

At build time, a Sätteri hast plugin swaps <pre><code class="language-mermaid"> blocks for <pre class="mermaid"> elements containing the raw diagram text. It also excludes mermaid from syntax highlighting so Shiki doesn't transform the block before the plugin sees it.

On the client, the per-page script lazily imports Mermaid, loads any icon packs, and renders each pre.mermaid element. The script re-injects CSS on astro:page-load because View Transitions replace the <head>. While diagrams render, a spinner shows in place of the unprocessed block, and a min-height on the container keeps the page from jumping.

Privacy

Rendering happens 100% client-side. Diagram content never leaves the browser, and there are no calls to external services. The package works offline after the initial page load. Icon packs that use the url form do fetch from a URL you provide, but that's your choice, not a default behavior.

This makes the integration suitable for corporate environments with strict security policies, air-gapped networks, and applications that need data sovereignty.

Supported Diagrams

All Mermaid diagram types work: flowcharts, sequence diagrams, Gantt charts, class diagrams, state diagrams, entity relationship diagrams, user journey diagrams, git graphs, pie charts, requirement diagrams, C4 diagrams, mindmaps, timeline diagrams, quadrant charts, and anything else Mermaid supports.

Live Demo

A live demo of all 13 diagram types with theme switching, icon packs, and a responsive Tailwind UI is deployed on Cloudflare Pages: astro-mermaid-satteri-example.pages.dev

License

MIT