Create UML Diagrams using Mermaid

Documentation without diagrams is like trying to explain architecture with just words. Sure, you can do it, but why torture yourself and your readers?

I’ve been wrestling with this exact problem while working on technical blog posts. You know that moment when you’re describing a complex system flow and realize you need three paragraphs just to explain what a simple diagram could show in seconds? That’s when I discovered Mermaid.

Quick Authentication Example

100%
sequenceDiagram participant User participant System User->>System: Login Request System-->>User: Authentication Token

Simple, clean, and gets the point across immediately.

Why Mermaid beats drawing tools every time

Here’s the thing about traditional diagramming tools – they’re a pain to maintain. Change one thing in your system, and you’re back in Visio or Lucidchart, moving boxes around like you’re rearranging furniture.

Mermaid flips this whole approach. You describe your diagrams with code, version control them with your project, and update them as easily as editing text. Plus, they live right in your documentation where people actually need them.

🔄 Version Control Win

I can git diff my diagrams now. That alone sold me on this approach. No more 'diagram-final-FINAL-v3.png' nonsense.

Setting up the UML component

Let’s build something reusable. Create a file called UMLDiagram.astro in your components folder:

---
interface Props {
  code?: string;
  title?: string;
  caption?: string;
}

const {
  code = `
    classDiagram
    class Example {
      +String data
      +update() void
    }
  `,
  title = "",
  caption = ""
} = Astro.props;

---

<div class="w-full max-w-4xl mx-auto p-4">
  {title && (
    <h3 class="text-xl font-semibold mb-4 text-gray-800">
      {title}
    </h3>
  )}
  
  <div class="relative bg-white rounded-lg shadow-md overflow-hidden">
    <div class="mermaid p-6 bg-gray-50">
      {code.trim()}
    </div>
  </div>

  {caption && (
    <p class="mt-2 text-sm text-gray-600 italic">
      {caption}
    </p>
  )}
</div>

<!-- Load mermaid from CDN -->
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>
  declare const mermaid: any;
  
  // Initialize mermaid
  mermaid.initialize({
    startOnLoad: true,
    theme: 'default',
    securityLevel: 'loose',
    htmlLabels: true,
    flowchart: {
      useMaxWidth: true,
      htmlLabels: true,
      curve: 'basis'
    }
  });
</script>

This component does exactly what you’d expect – takes some Mermaid code, wraps it in a nice container, and handles all the initialization nonsense for you.

📦 CDN vs NPM

I'm using the CDN approach here because it's simpler for most use cases. If you're already bundling Mermaid in your project, you can skip the script tag and import it properly.

First, install Mermaid

If you want to go the proper npm route (which I recommend for production sites):

npm install mermaid

Or if you’re Team Yarn:

yarn add mermaid

But honestly? The CDN version works perfectly fine for most blogs and documentation sites.

Breaking down the component logic

Let’s talk about what makes this component actually useful:

The props are dead simple – code for your diagram, optional title and caption. I set a default diagram because there’s nothing worse than a broken component when you forget to pass props.

interface Props {
  code?: string;
  title?: string;
  caption?: string;
}

The layout uses Tailwind classes to create a card-like appearance. Nothing fancy, but it looks professional and doesn’t clash with most existing designs.

🎨 Tailwind Dependency

This component assumes you're using Tailwind. If you're not, just replace the classes with your own CSS. The structure is what matters here.

The Mermaid initialization bit

This is where the magic happens:

mermaid.initialize({
  startOnLoad: true,
  theme: 'default',
  securityLevel: 'loose',
  htmlLabels: true,
  flowchart: {
    useMaxWidth: true,
    htmlLabels: true,
    curve: 'basis'
  }
});

Most of these settings are sensible defaults, but securityLevel: 'loose' is important if you want to use HTML in your diagrams. The default security level is more restrictive.

Building something actually useful

Let’s create a realistic example – an e-commerce system flow that actually demonstrates the power of sequence diagrams:

<UMLDiagram
  title="E-commerce Purchase Flow"
  code={`sequenceDiagram
    participant Customer
    participant API Gateway
    participant Auth Service
    participant Order Service
    participant Payment Service
    participant Inventory
    participant Notification
    
    rect rgb(240, 248, 255)
        Note over Customer,Notification: Purchase Flow
        Customer->>+API Gateway: Add to Cart
        API Gateway->>+Auth Service: Validate Session
        Auth Service-->>-API Gateway: Session Valid
        API Gateway->>+Inventory: Check Stock
        Inventory-->>-API Gateway: In Stock
        API Gateway-->>Customer: Item Added
    end

    rect rgb(255, 245, 238)
        Note over Customer,Notification: Checkout Process
        Customer->>+API Gateway: Checkout
        API Gateway->>+Order Service: Create Order
        Order Service->>+Payment Service: Process Payment
        
        par Parallel Processes
            Payment Service->>Payment Service: Validate Card
            Payment Service->>Payment Service: Security Checks
        end
        
        Payment Service-->>-Order Service: Payment Success
        Order Service->>Inventory: Update Stock
        Order Service-->>-API Gateway: Order Confirmed
        API Gateway->>+Notification: Send Confirmation
        Notification->>Notification: Generate Email
        Notification->>Customer: Order Details
        Note over Customer: Happy Customer! 🎉
    end`}
  caption="This shows how microservices interact during a typical e-commerce purchase. Notice the parallel processing and error handling flows."
/>

E-commerce Purchase Flow

100%
sequenceDiagram participant Customer participant API Gateway participant Auth Service participant Order Service participant Payment Service participant Inventory participant Notification rect rgb(240, 248, 255) Note over Customer,Notification: Purchase Flow Customer->>+API Gateway: Add to Cart API Gateway->>+Auth Service: Validate Session Auth Service-->>-API Gateway: Session Valid API Gateway->>+Inventory: Check Stock Inventory-->>-API Gateway: In Stock API Gateway-->>Customer: Item Added end rect rgb(255, 245, 238) Note over Customer,Notification: Checkout Process Customer->>+API Gateway: Checkout API Gateway->>+Order Service: Create Order Order Service->>+Payment Service: Process Payment par Parallel Processes Payment Service->>Payment Service: Validate Card Payment Service->>Payment Service: Security Checks end Payment Service-->>-Order Service: Payment Success Order Service->>Inventory: Update Stock Order Service-->>-API Gateway: Order Confirmed API Gateway->>+Notification: Send Confirmation Notification->>Notification: Generate Email Notification->>Customer: Order Details Note over Customer: Happy Customer! 🎉 end

This shows how microservices interact during a typical e-commerce purchase. Notice the parallel processing and error handling flows.

Now that’s a diagram worth having! Try explaining that system architecture with just text – you’d need half a page, and people would still be confused.

🎨 Color Coding Tip

Those colored rectangles (rect rgb(...)) are fantastic for grouping related operations. It makes complex diagrams much easier to follow.

Beyond just UML

The beautiful thing about Mermaid is it’s not just UML. You can create flowcharts, Gantt charts, git graphs, pie charts – basically any diagram you need for technical documentation.

Want a quick class diagram? Easy:

classDiagram
  class User {
    +String email
    +String password
    +login() boolean
    +logout() void
  }
  
  class Order {
    +String id
    +Date created
    +calculate_total() float
  }
  
  User ||--o{ Order : places

Need a flowchart? Done:

flowchart TD
  A[Start] --> B{Is user logged in?}
  B -->|Yes| C[Show dashboard]
  B -->|No| D[Redirect to login]
  D --> E[Login form]
  E --> F{Valid credentials?}
  F -->|Yes| C
  F -->|No| G[Show error]
  G --> E

What I wish I’d known earlier

The Mermaid syntax can be finicky. Extra spaces matter, indentation matters, and sometimes the error messages are about as helpful as a chocolate teapot.

My advice? Start simple, test frequently, and keep the Mermaid documentation open in another tab. Their live editor is fantastic for prototyping diagrams before embedding them.

🐛 Debug Mode

If your diagram isn't rendering, check the browser console. Mermaid usually gives decent error messages there, even if they don't show up visually.

Also, remember that these diagrams are interactive by default. Users can zoom and pan on complex diagrams, which is surprisingly useful for detailed sequence diagrams.


Adding visual diagrams to your technical content isn’t just nice-to-have anymore – it’s essential. Your readers will thank you, your documentation will be clearer, and you’ll actually enjoy maintaining diagrams when they’re just code.

The best part? Once you have this component set up, adding diagrams to your posts becomes as easy as writing a few lines of text. No more screenshot-crop-upload dance every time you need to update a diagram.

Now go forth and diagram everything!

Stay up to date

Get notified when I publish something new, and unsubscribe at any time.

Join 44 other subscribers.

Contact Pavlin Gunov at contact@pavlinbg.com

Phone: +1234567890

Address: Sofia, Bulgaria

© 2025 Pavlin

Instagram GitHub