How to Add Custom or Branded Icons to Diagram‑Design: A Complete Guide

You can add custom or branded icons to diagram‑design by either registering an SVG symbol in the icon library (referenced as icon:name) or embedding a custom PNG/image directly as a node in your source diagram.

As of the latest release, diagram‑design supports two distinct pathways for incorporating non‑standard graphics: the icon reference system for scalable, theme‑aware symbols, and the image embed system for raster logos and photographs. This guide explains both approaches using actual source code locations from the cathrynlavery/diagram-design repository.


Understanding the Two Icon Systems

Before adding icons, choose the approach that matches your asset type:

Approach Best For Output Element Source File
Icon reference (icon:name) Brand logos, UI symbols, scalable graphics <use href="#icon‑{name}" /> icons.html symbol definitions
Custom image Photographs, complex raster logos, legacy assets <image href="..." /> Draw.io image style nodes

Both systems are handled by scripts/drawio_extract.py, which processes source diagrams and emits the appropriate SVG elements.


Method 1: Adding Custom Icons to the Icon Library

The icon library stores reusable SVG symbols that automatically inherit the diagram’s color scheme. This is the preferred method for branded icons you’ll use repeatedly.

Step 1: Define the SVG Symbol

Open skills/diagram-design/assets/icons.html and add a new <symbol> block:

<symbol id="icon‑mybrand" viewBox="0 0 24 24">
  <path d="M12 2L2 22h20L12 2z" fill="currentColor"/>
</symbol>

Follow these conventions from the primitive icon system:

  • Use viewBox="0 0 24 24" for consistency with built‑in icons.
  • Apply fill="currentColor" or stroke="currentColor" so the icon adapts to theme colors.
  • Keep paths optimized; the built‑in AWS icon uses this same pattern.

Step 2: Reference in Your Diagram

In Mermaid YAML or Draw.io metadata, use the icon field:

- { id: api-gateway, name: "API Gateway", icon: mybrand }

The renderer, per type‑it‑state.md, generates:

<use href="#icon‑mybrand" transform="translate(64 124)" style="color:#6366f1"/>

Step 3: Verify in drawio_extract.py

The parser at lines 268‑279 of scripts/drawio_extract.py detects shape.startswith("icon:") and routes to the symbol reference path:

if shape.startswith("icon:"):
    icon_name = shape[5:]  # strip 'icon:' prefix

    svg_element = f'<use href="#icon-{icon_name}" ... />'

Method 2: Embedding Custom PNGs and Raster Images

For logos or graphics that cannot be converted to SVG paths, embed them as image nodes.

In Draw.io Source Files

Set any shape’s style to image and provide a URL or data‑URI:

<mxCell style="shape=image;image=https://cdn.example.com/logo.png;..." ... />

Or use a base64‑encoded data‑URI for self‑contained diagrams:

shape=image;image=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34...

How the Importer Handles Images

Per import-drawio.md, the importer creates an image node type:

Property Value
type image
src Original image URL or data‑URI
preserveAspect true (default)

The export stage renders this as a standard SVG <image> element:

<image href="https://cdn.example.com/logo.png" x="120" y="80" width="48" height="48"/>

Important Limitations

  • Embedded images are not recolored — they render exactly as provided, ignoring the diagram’s theme.
  • Missing images fallback to a labeled rectangle; the tool never retains broken references.

Registering Icons in the Primitive Catalog

To make custom icons discoverable, document them in skills/diagram-design/references/primitive-icons.md. The built‑in catalog follows this format:

| Icon | ID | Source |
|------|----|--------|
| AWS | `aws` | Official brand kit |
| Azure | `azure` | Microsoft design resources |
| MyBrand | `mybrand` | Custom addition |

This reference file is not enforced at runtime but aids maintainability and collaboration.


Complete Workflow Example

Here’s an end‑to‑end example combining both methods:

1. Register a custom SVG icon:

<!-- skills/diagram-design/assets/icons.html -->
<symbol id="icon‑acmecorp" viewBox="0 0 24 24">
  <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none"/>
  <path d="M8 12l3 3 5-6" stroke="currentColor" stroke-width="2" fill="none"/>
</symbol>

2. Create a diagram YAML file:

diagram:
  title: "Acme Corp Infrastructure"
  nodes:
    - { id: frontend, name: "Web App", icon: acmecorp }
    - { id: legacy, name: "Legacy DB", icon: image, src: "assets/legacy-db.png" }
  edges:
    - { from: frontend, to: legacy }

3. Run the generator:

python -m diagram_design generate infrastructure.yaml --output out.svg

The resulting out.svg contains both the themed <use> reference and the embedded <image> tag.


Summary

  • Add SVG symbols to assets/icons.html for scalable, theme‑aware branded icons referenced as icon:name.
  • Use Draw.io image styles for PNGs and raster assets that must preserve original appearance.
  • drawio_extract.py (lines 268‑279) routes icon: prefixes to <use> elements; image types pass through as <image> tags.
  • import-drawio.md documents the image node type and its rendering behavior.
  • Prefer the icon library for consistency; reserve image embeds for unavoidable raster content.

Frequently Asked Questions

How do I ensure my custom icon matches the diagram color theme?

Define your SVG symbol with fill="currentColor" or stroke="currentColor" in assets/icons.html. The renderer applies the node’s assigned color via inline style="color: #hex" on the <use> element.

Can I use an external CDN URL for a custom icon?

Not directly through the icon: prefix — that requires a local symbol definition. For external images, use the image embed method with a full URL in the Draw.io image style property.

What happens if I reference an icon that doesn’t exist?

The generator logs a warning and renders a fallback shape — typically a rectangle with the node label. The drawio_extract.py parser does not halt on missing icon definitions.

Is there a size limit for embedded PNG images?

No hard limit is enforced in the source code, but large base64 data‑URIs increase file size and slow rendering. The primitive-icons.md documentation recommends optimizing raster assets to 48×48 or 96×96 display pixels.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →