
Beautiful Mermaid
- 1.7k installs
- 281 repo stars
- Updated April 25, 2026
- intellectronica/agent-skills
Skill that programmatically converts Mermaid diagram syntax to production-ready SVG and PNG assets with theme customization and multi-runtime support.
About
Beautiful Mermaid enables programmatic rendering of Mermaid diagrams to scalable SVG and high-resolution PNG formats. Supports flowcharts, sequence diagrams, state machines, class diagrams, and entity-relationship models with 13 customizable themes. Integrates with agent-browser for automated screenshot capture at 4K resolution. Includes syntax validation, edge label formatting, and special character handling. Outputs vector and raster assets to the current working directory with automatic cleanup of intermediary files.
- Renders 5 diagram types: flowchart, sequence, state, class, entity-relationship
- 13 customizable themes including Dracula, Tokyo Night, Nord, GitHub, Catppuccin
- Dual output: scalable SVG and 4K PNG via agent-browser integration
- Handles special characters, edge labels with pipe syntax, and node escaping
- Automated workflow with HTML wrapping, screenshot capture, and cleanup
Beautiful Mermaid by the numbers
- 1,714 all-time installs (skills.sh)
- +22 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #277 of 2,245 Frontend Development skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
beautiful-mermaid capabilities & compatibility
- Capabilities
- parse mermaid diagram syntax · render svg from mermaid code · apply 13 customizable themes · capture high resolution png via browser automati · generate html wrapper for screenshot capture · validate and fix diagram syntax
- Works with
- chrome
- Use cases
- documentation · web design · ui design · api development
npx skills add https://github.com/intellectronica/agent-skills --skill beautiful-mermaidAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.7k |
|---|---|
| repo stars | ★ 281 |
| Security audit | 2 / 3 scanners passed |
| Last updated | April 25, 2026 |
| Repository | intellectronica/agent-skills ↗ |
What it does
Render Mermaid diagrams as SVG and PNG for documentation, architecture visualization, and flowchart generation.
Who is it for?
Documentation generation, architecture visualization, CI/CD pipeline diagrams, database schema rendering, API flow documentation in automated agent workflows.
Skip if: Interactive diagram editing, real-time collaborative diagramming, manual UI design, unstructured diagram input.
When should I use this skill?
User requests diagram rendering, user provides Mermaid syntax, agent needs to visualize architecture or flow, documentation requires diagram assets.
What you get
Agent can generate high-quality diagram assets in both vector and raster formats with consistent theming, proper syntax handling, and automated browser capture.
- SVG vector diagram
- PNG raster image at 4K resolution
- HTML wrapper for screenshot capture
By the numbers
- 13 themes available
- 5 diagram types supported
- 4K viewport resolution (3840x2160)
Files
Beautiful Mermaid Diagram Rendering
Render Mermaid diagrams as SVG and PNG images using the Beautiful Mermaid library.
Dependencies
This skill requires the agent-browser skill for PNG rendering. Load it before proceeding with PNG capture.
Supported Diagram Types
- Flowchart - Process flows, decision trees, CI/CD pipelines
- Sequence - API calls, OAuth flows, database transactions
- State - State machines, connection lifecycles
- Class - UML class diagrams, design patterns
- Entity-Relationship - Database schemas, data models
Available Themes
Default, Dracula, Solarized, Zinc Dark, Tokyo Night, Tokyo Night Storm, Tokyo Night Light, Catppuccin Latte, Nord, Nord Light, GitHub Dark, GitHub Light, One Dark.
If no theme is specified, use default.
Common Syntax Patterns
Flowchart Edge Labels
Use pipe syntax for edge labels:
A -->|label| B
A ---|label| BAvoid space-dash syntax which can cause incomplete renders:
A -- label --> B # May cause issuesNode Labels with Special Characters
Wrap labels containing special characters in quotes:
A["Label with (parens)"]
B["Label with / slash"]Workflow
Step 1: Generate or Validate Mermaid Code
If the user provides a description rather than code, generate valid Mermaid syntax. Consult references/mermaid-syntax.md for full syntax details.
Step 2: Render SVG
Run the rendering script to produce an SVG file:
bun run scripts/render.ts --code "graph TD; A-->B" --output diagram --theme defaultOr from a file:
bun run scripts/render.ts --input diagram.mmd --output diagram --theme tokyo-nightAlternative runtimes:
npx tsx scripts/render.ts --code "..." --output diagram
deno run --allow-read --allow-write --allow-net scripts/render.ts --code "..." --output diagramThis produces <output>.svg in the current working directory.
Step 3: Create HTML Wrapper
Run the HTML wrapper script to prepare for screenshot:
bun run scripts/create-html.ts --svg diagram.svg --output diagram.htmlThis creates a minimal HTML file that displays the SVG with proper padding and background.
Step 4: Capture High-Resolution PNG with agent-browser
Use the agent-browser CLI to capture a high-quality screenshot. Refer to the agent-browser skill for full CLI documentation.
# Set 4K viewport for high-resolution capture
agent-browser set viewport 3840 2160
# Open the HTML wrapper
agent-browser open "file://$(pwd)/diagram.html"
# Wait for render to complete
agent-browser wait 1000
# Capture full-page screenshot
agent-browser screenshot --full diagram.png
# Close browser
agent-browser closeFor even higher resolution on complex diagrams, increase the viewport further or use the --padding option when creating the HTML wrapper to give the diagram more space.
Step 5: Clean Up Intermediary Files
After rendering, remove all intermediary files. Only the final .svg and .png should remain.
Files to clean up:
- The HTML wrapper file (e.g.,
diagram.html) - Any temporary
.mmdfiles created to hold diagram code - Any other files created during the rendering process
rm diagram.htmlIf a temporary .mmd file was created, remove it as well.
Output
Both outputs are always produced:
- SVG: Vector format, infinitely scalable, small file size
- PNG: High-resolution raster, captured at 4K (3840×2160) viewport with minimum 1200px diagram width
Files are saved to the current working directory unless the user explicitly specifies a different path.
Theme Selection Guide
| Theme | Background | Best For |
|---|---|---|
| default | Light grey | General use |
| dracula | Dark purple | Dark mode preference |
| tokyo-night | Dark blue | Modern dark aesthetic |
| tokyo-night-storm | Darker blue | Higher contrast |
| nord | Dark arctic | Muted, calm visuals |
| nord-light | Light arctic | Light mode with soft tones |
| github-dark | GitHub dark | Matches GitHub UI |
| github-light | GitHub light | Matches GitHub UI |
| catppuccin-latte | Warm light | Soft pastel aesthetic |
| solarized | Tan/cream | Solarized colour scheme |
| one-dark | Atom dark | Atom editor aesthetic |
| zinc-dark | Neutral dark | Minimal, no colour bias |
Troubleshooting
Theme not applied
Check the render script output for the bg and fg values, or inspect the SVG's opening tag for --bg and --fg CSS custom properties.
Diagram appears cut off or incomplete
- Check edge label syntax — use
-->|label|pipe notation, not-- label --> - Verify all node IDs are unique
- Check for unclosed brackets in node labels
Render produces empty or malformed SVG
- Validate Mermaid syntax at https://mermaid.live before rendering
- Check for special characters that need escaping (wrap in quotes)
- Ensure flowchart direction is specified (
graph TD,graph LR, etc.)
Mermaid Syntax Reference
Quick reference for generating valid Mermaid diagram code.
Flowchart
graph TD
A[Start] --> B{Decision}
B -->|Yes| C[Action 1]
B -->|No| D[Action 2]
C --> E[End]
D --> EDirection
TD/TB- Top to bottomBT- Bottom to topLR- Left to rightRL- Right to left
Node Shapes
A[Text]- RectangleA(Text)- Rounded rectangleA([Text])- Stadium/pillA[[Text]]- SubroutineA[(Text)]- Cylinder (database)A((Text))- CircleA>Text]- AsymmetricA{Text}- Diamond (decision)A{{Text}}- HexagonA[/Text/]- ParallelogramA[\Text\]- Parallelogram altA[/Text\]- TrapezoidA[\Text/]- Trapezoid alt
Edge Styles
A --> B- ArrowA --- B- LineA -.-> B- Dotted arrowA ==> B- Thick arrowA -->|text| B- Arrow with label (preferred)A ---|text| B- Line with label (preferred)
Important: Always use pipe syntax -->|label| for edge labels. The space-dash syntax -- label --> can cause incomplete renders.
Subgraphs
graph TD
subgraph Group1 [Label]
A --> B
end
subgraph Group2
C --> D
end
B --> CSequence Diagram
sequenceDiagram
participant A as Alice
participant B as Bob
A->>B: Hello
B-->>A: Hi there
A->>+B: Start process
B-->>-A: DoneArrow Types
->>- Solid arrow-->>- Dashed arrow-x- Solid with x--x- Dashed with x-)- Solid open arrow--)- Dashed open arrow
Activations
+after arrow activates participant-after arrow deactivates participant
Notes and Boxes
sequenceDiagram
Note over A,B: Shared note
Note right of A: Side note
rect rgb(200, 220, 255)
A->>B: In a box
endLoops and Conditionals
sequenceDiagram
loop Every minute
A->>B: Ping
end
alt Success
B-->>A: Pong
else Failure
B-->>A: Error
end
opt Optional
A->>B: Extra step
endState Diagram
stateDiagram-v2
[*] --> Idle
Idle --> Processing : start
Processing --> Done : complete
Processing --> Error : fail
Error --> Idle : reset
Done --> [*]Composite States
stateDiagram-v2
state Active {
[*] --> Running
Running --> Paused : pause
Paused --> Running : resume
}
Idle --> Active : activate
Active --> Idle : deactivateNotes
stateDiagram-v2
State1 : Description here
note right of State1
Additional info
end noteClass Diagram
classDiagram
class Animal {
+String name
+int age
+makeSound() void
}
class Dog {
+bark() void
}
Animal <|-- Dog : extendsRelationships
<|--- Inheritance*--- Compositiono--- Aggregation-->- Association--- Link (solid)..>- Dependency..|>- Realisation..- Link (dashed)
Cardinality
classDiagram
Customer "1" --> "*" Order
Order "1" --> "1..*" LineItemVisibility
+Public-Private#Protected~Package/Internal
Entity-Relationship Diagram
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
PRODUCT }|..|{ LINE-ITEM : "ordered in"Relationship Types
||- Exactly one|{- One or moreo{- Zero or moreo|- Zero or one
Identifying vs Non-identifying
--- Identifying (solid)..- Non-identifying (dashed)
Attributes
erDiagram
CUSTOMER {
string id PK
string name
string email UK
}
ORDER {
int id PK
string customer_id FK
date created_at
}Styling
CSS Classes
graph TD
A:::highlight --> B
classDef highlight fill:#f96,stroke:#333Inline Styles
graph TD
A --> B
style A fill:#bbf,stroke:#333Tips
1. Escape special characters: Use quotes for labels with special chars: A["Label with (parens)"] 2. Multi-line labels: Use <br/> for line breaks 3. Comments: Use %% for comments that won't render 4. IDs vs Labels: Node IDs should be simple, labels can be complex: node1["Complex Label Here"]
#!/usr/bin/env -S npx tsx
/**
* Create an HTML wrapper for an SVG to enable high-quality PNG capture
*
* Usage:
* bun run create-html.ts --svg diagram.svg --output diagram.html
* bun run create-html.ts --svg diagram.svg --output diagram.html --padding 40
*
* Runtimes:
* bun run create-html.ts ...
* npx tsx create-html.ts ...
* deno run --allow-read --allow-write create-html.ts ...
*/
import { readFileSync, writeFileSync, existsSync } from "node:fs";
import { resolve, basename } from "node:path";
interface Args {
svg: string;
output: string;
padding: number;
background?: string;
}
function parseArgs(): Args {
const args = process.argv.slice(2);
const result: Partial<Args> = { padding: 40 };
for (let i = 0; i < args.length; i++) {
const arg = args[i];
const next = args[i + 1];
switch (arg) {
case "--svg":
case "-s":
result.svg = next;
i++;
break;
case "--output":
case "-o":
result.output = next;
i++;
break;
case "--padding":
case "-p":
result.padding = parseInt(next, 10) || 40;
i++;
break;
case "--background":
case "-b":
result.background = next;
i++;
break;
case "--help":
case "-h":
printHelp();
process.exit(0);
}
}
if (!result.svg) {
console.error("Error: --svg is required");
printHelp();
process.exit(1);
}
if (!result.output) {
console.error("Error: --output is required");
printHelp();
process.exit(1);
}
return result as Args;
}
function printHelp(): void {
console.log(`
SVG to HTML Wrapper
Creates a minimal HTML file for screenshot capture of SVG diagrams.
Usage:
create-html.ts --svg <file.svg> --output <file.html> [options]
Options:
-s, --svg <file> Input SVG file
-o, --output <file> Output HTML file
-p, --padding <pixels> Padding around SVG (default: 40)
-b, --background <color> Background colour (auto-detected from SVG)
-h, --help Show this help
Examples:
create-html.ts --svg diagram.svg --output diagram.html
create-html.ts --svg diagram.svg --output diagram.html --padding 60
create-html.ts --svg diagram.svg --output diagram.html --background "#1a1b26"
`);
}
function extractBackgroundFromSvg(svgContent: string): string | null {
// Try to extract background from SVG style or rect
const bgMatch = svgContent.match(/background(?:-color)?:\s*([^;"\s]+)/i);
if (bgMatch) return bgMatch[1];
// Check for a background rect
const rectMatch = svgContent.match(
/<rect[^>]*fill="([^"]+)"[^>]*(?:width="100%"|height="100%")/i
);
if (rectMatch) return rectMatch[1];
// Check style attribute on svg element
const svgStyleMatch = svgContent.match(
/<svg[^>]*style="[^"]*background(?:-color)?:\s*([^;"\s]+)/i
);
if (svgStyleMatch) return svgStyleMatch[1];
return null;
}
function main(): void {
const args = parseArgs();
const svgPath = resolve(args.svg);
if (!existsSync(svgPath)) {
console.error(`SVG file not found: ${svgPath}`);
process.exit(1);
}
const svgContent = readFileSync(svgPath, "utf-8");
// Determine background colour
const background =
args.background ?? extractBackgroundFromSvg(svgContent) ?? "#ffffff";
// Create HTML wrapper optimised for high-resolution screenshot
// SVG renders at natural size with generous padding, no constraints
const html = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${basename(args.svg, ".svg")}</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
background: ${background};
}
.container {
padding: ${args.padding}px;
display: inline-block;
background: ${background};
}
.container svg {
display: block;
min-width: 1200px;
height: auto;
}
</style>
</head>
<body>
<div class="container">
${svgContent}
</div>
</body>
</html>`;
const outputPath = resolve(args.output);
writeFileSync(outputPath, html, "utf-8");
console.log(`HTML wrapper written to: ${outputPath}`);
console.log(`Background colour: ${background}`);
}
main();
#!/usr/bin/env -S npx tsx
/**
* Render a Mermaid diagram to SVG using Beautiful Mermaid
*
* Usage:
* bun run render.ts --input diagram.mmd --output diagram --theme tokyo-night
* bun run render.ts --code "graph TD; A-->B" --output diagram
*
* Runtimes:
* bun run render.ts ...
* npx tsx render.ts ...
* deno run --allow-read --allow-write --allow-net render.ts ...
*
* Output:
* Produces <output>.svg
*/
import { readFileSync, writeFileSync, existsSync } from "node:fs";
import { resolve } from "node:path";
const THEMES = [
"default",
"dracula",
"solarized",
"zinc-dark",
"tokyo-night",
"tokyo-night-storm",
"tokyo-night-light",
"catppuccin-latte",
"nord",
"nord-light",
"github-dark",
"github-light",
"one-dark",
] as const;
type Theme = (typeof THEMES)[number];
interface Args {
input?: string;
code?: string;
output: string;
theme: Theme;
}
function parseArgs(): Args {
const args = process.argv.slice(2);
const result: Partial<Args> = { theme: "default" };
for (let i = 0; i < args.length; i++) {
const arg = args[i];
const next = args[i + 1];
switch (arg) {
case "--input":
case "-i":
result.input = next;
i++;
break;
case "--code":
case "-c":
result.code = next;
i++;
break;
case "--output":
case "-o":
result.output = next;
i++;
break;
case "--theme":
case "-t":
if (next && THEMES.includes(next as Theme)) {
result.theme = next as Theme;
} else {
console.error(`Invalid theme: ${next}`);
console.error(`Available themes: ${THEMES.join(", ")}`);
process.exit(1);
}
i++;
break;
case "--help":
case "-h":
printHelp();
process.exit(0);
}
}
if (!result.input && !result.code) {
console.error("Error: Either --input or --code is required");
printHelp();
process.exit(1);
}
if (!result.output) {
console.error("Error: --output is required");
printHelp();
process.exit(1);
}
return result as Args;
}
function printHelp(): void {
console.log(`
Beautiful Mermaid Renderer
Renders Mermaid diagrams to SVG.
Usage:
render.ts --input <file.mmd> --output <basename> [--theme <theme>]
render.ts --code "<mermaid code>" --output <basename> [--theme <theme>]
Options:
-i, --input <file> Input Mermaid file (.mmd)
-c, --code <string> Mermaid code as string
-o, --output <name> Output base name (without extension)
-t, --theme <theme> Theme name (default: default)
-h, --help Show this help
Available themes:
${THEMES.join(", ")}
Output:
Produces <output>.svg
Examples:
render.ts -i diagram.mmd -o diagram -t tokyo-night
render.ts -c "graph TD; A-->B" -o simple
`);
}
function detectRuntime(): "bun" | "deno" | "node" {
if (typeof (globalThis as any).Bun !== "undefined") return "bun";
if (typeof (globalThis as any).Deno !== "undefined") return "deno";
return "node";
}
async function ensurePackage(name: string): Promise<any> {
const runtime = detectRuntime();
try {
if (runtime === "deno") {
return await import(`npm:${name}`);
}
return await import(name);
} catch {
console.error(`${name} not found. Installing...`);
const { execSync } = await import("node:child_process");
try {
if (runtime === "bun") {
execSync(`bun add ${name}`, { stdio: "inherit" });
} else if (runtime === "deno") {
return await import(`npm:${name}`);
} else {
execSync(`npm install ${name}`, { stdio: "inherit" });
}
return await import(name);
} catch (installError) {
console.error(`Failed to install ${name}:`, installError);
process.exit(1);
}
}
}
function getThemeConfig(themeName: Theme): { bg: string; fg: string } {
const themeConfigs: Record<Theme, { bg: string; fg: string }> = {
default: { bg: "#f5f5f5", fg: "#333333" },
dracula: { bg: "#282a36", fg: "#f8f8f2" },
solarized: { bg: "#fdf6e3", fg: "#657b83" },
"zinc-dark": { bg: "#18181b", fg: "#fafafa" },
"tokyo-night": { bg: "#1a1b26", fg: "#a9b1d6" },
"tokyo-night-storm": { bg: "#24283b", fg: "#a9b1d6" },
"tokyo-night-light": { bg: "#d5d6db", fg: "#343b58" },
"catppuccin-latte": { bg: "#eff1f5", fg: "#4c4f69" },
nord: { bg: "#2e3440", fg: "#eceff4" },
"nord-light": { bg: "#eceff4", fg: "#2e3440" },
"github-dark": { bg: "#0d1117", fg: "#c9d1d9" },
"github-light": { bg: "#ffffff", fg: "#24292f" },
"one-dark": { bg: "#282c34", fg: "#abb2bf" },
};
return themeConfigs[themeName];
}
async function main(): Promise<void> {
const args = parseArgs();
let mermaidCode: string;
if (args.input) {
const inputPath = resolve(args.input);
if (!existsSync(inputPath)) {
console.error(`Input file not found: ${inputPath}`);
process.exit(1);
}
mermaidCode = readFileSync(inputPath, "utf-8");
} else {
mermaidCode = args.code!;
}
console.log(`Rendering diagram with theme: ${args.theme}`);
const beautifulMermaid = await ensurePackage("beautiful-mermaid");
const renderMermaid = beautifulMermaid.renderMermaid;
const THEMES = beautifulMermaid.THEMES;
const themeConfig = THEMES?.[args.theme] ?? getThemeConfig(args.theme);
console.log(`Using theme: bg=${themeConfig.bg}, fg=${themeConfig.fg}`);
const svg = await renderMermaid(mermaidCode, themeConfig);
const svgPath = resolve(`${args.output}.svg`);
writeFileSync(svgPath, svg, "utf-8");
console.log(`SVG written to: ${svgPath}`);
}
main().catch((err) => {
console.error("Error:", err.message);
process.exit(1);
});
Related skills
Forks & variants (1)
Beautiful Mermaid has 1 known copy in the catalog totaling 263 installs. They canonicalize to this original listing.
- calesthio - 263 installs
FAQ
What diagram types are supported?
Flowchart, sequence, state, class, and entity-relationship diagrams. Flowcharts work for processes and decision trees; sequence for API flows; state for lifecycle models; class for UML patterns; ER for database schemas.
How do I render high-resolution PNG output?
Beautiful Mermaid uses agent-browser integration with 4K viewport (3840x2160) to capture screenshots. PNG files are automatically saved with minimum 1200px width. Use --padding option for additional spacing on complex diagrams.
What should I do if my diagram renders incomplete or cut off?
Check edge label syntax (use -->|label| pipe notation, not -- label -->), verify unique node IDs, ensure special characters are quoted, and validate syntax at mermaid.live before rendering.
Is Beautiful Mermaid safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.