These docs are for v1.0. Click to read the latest docs for v2.0.

Web-plugins examples

We've provided three short examples of what and how you can build using web-plugins.
They cover almost all SDK features.

📘

These examples use the ES6 JavaScript version. Ensure you execute them in browsers that support this version.

You can look at the example source code in app-examples repo.

Template Builder

This is a sample Roadmap Template Builder you can build on Miro Web SDK. It shows how to create and position multiple widgets of different types on the board and create custom interfaces in the library.

1384

Source code

Widget counter

You select several widgets, click the plugin button in the bottom bar, and the app shows the number of widgets grouped by type in the sidebar.

1150

Used web-plugin features:

  • Add button in bottom bar
  • Get current selected widgets
  • Subscribe to widgets selection updated event
  • Open custom view in sidebar

SourceCode

Custom icon set with drag-and-drop

Used web-plugin features:

  • Drag-and-drop images and shapes on the canvas
  • Render custom view
882

SourceCode

Stickies to shapes

You select several stickies, click the plugin button in the bottom bar, and the app replaces stickies with shapes.

772

Used web-plugin features:

  • Add button in bottom bar
  • Get current selected widgets
  • Remove widgets
  • Create widgets
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://miro.com/app/static/sdk.1.1.js"></script>
    <script src="main.js"></script>
  </head>
</html>
miro.onReady(() => {
  miro.initialize({
    extensionPoints: {
      bottomBar: {
        title: 'Sticker to shapes',
        svgIcon:
          '<circle cx="12" cy="12" r="9" fill="none" fill-rule="evenodd" stroke="currentColor" stroke-width="2"/>',
        positionPriority: 1,
        onClick: async () => {
          // Get selected widgets
          let selectedWidgets = await miro.board.selection.get()

          // Filter stickers from selected widgets
          let stickers = selectedWidgets.filter((widget) => widget.type === 'STICKER')

          // Delete selected stickers
          await miro.board.widgets.deleteById(stickers.map((sticker) => sticker.id))

          // Create shapes from selected stickers
          await miro.board.widgets.create(
            stickers.map((sticker) => ({
              type: 'shape',
              text: sticker.text,
              x: sticker.x,
              y: sticker.y,
              width: sticker.bounds.width,
              height: sticker.bounds.height,
            })),
          )

          // Show success message
          miro.showNotification('Stickers has been converted')
        },
      },
    },
  })
})

Looking glass

You can see the readable text of the widget in the sidebar without zooming in.

768

Used web-plugin features:

  • Subscribe on events
  • Open sidebar
  • Show custom view in sidebar
  • Add button in bottom bar
  • Get current selected widgets
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://miro.com/app/static/sdk.1.1.js"></script>
    <script src="main.js"></script>
  </head>
</html>
let icon = '<circle cx="12" cy="12" r="9" fill="none" fill-rule="evenodd" stroke="currentColor" stroke-width="2"></circle>'

miro.onReady(() => {
  miro.initialize({
    extensionPoints: {
      bottomBar: {
        title: 'Looking Glass',
        svgIcon: icon,
        positionPriority: 1,
        onClick: () => {
          miro.board.ui.openLeftSidebar('sidebar.html')
        },
      },
    },
  })
})
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <script src="https://miro.com/app/static/sdk.1.1.js"></script>

    <style>
      .rtb-sidebar-caption {
        font-size: 14px;
        font-weight: bold;
        color: rgba(0, 0, 0, 0.8);
        padding: 24px 0 0 24px;
      }

      textarea {
        display: block;
        height: calc(100% - 110px);
        margin: 20px 0 0 20px;
        background-color: white;
        border-radius: 4px;
        border: 0;
        width: calc(100% - 40px);
        text-align: left;
        font-size: 22px;
      }

      .tip {
        color: #cccccc;
        margin: 20px 0 0 26px;
      }
    </style>
  </head>

  <body>
    <div class="rtb-sidebar-caption">Looking Glass</div>
    <div class="tip" id="tip">Select widget to see its text</div>
    <textarea id="widget-text" readonly></textarea>

    <script src="sidebar.js"></script>
  </body>
</html>
miro.onReady(() => {
  // Subscribe on user selected widgets
  miro.addListener(miro.enums.event.SELECTION_UPDATED, getWidget)
  getWidget()
})

// Get HTML elements for tip and text container
const tipElement = document.getElementById('tip')
const widgetTextElement = document.getElementById('widget-text')

async function getWidget() {
  // Get selected widgets
  let widgets = await miro.board.selection.get()

  // Get first widget from selected widgets
  let text = widgets[0].text

  // Check that the widget has text field
  if (typeof text === 'string') {
    // Hide tip and show text in sidebar
    tipElement.style.opacity = '0'
    widgetTextElement.value = text
  } else {
    // Show tip and clear text in sidebar
    tipElement.style.opacity = '1'
    widgetTextElement.value = ''
  }
}

Clear board

Delete all board content if user confirms the deletion.

772

Used web-plugin features:

  • Open confirm modal
  • Get all board objects
  • Remove objects
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://miro.com/app/static/sdk.1.1.js"></script>
    <script src="main.js"></script>
  </head>
</html>
const icon = '<circle cx="12" cy="12" r="9" fill="none" fill-rule="evenodd" stroke="currentColor" stroke-width="2"></circle>'

miro.onReady(() => {
  miro.initialize({
    extensionPoints: {
      bottomBar: {
        title: 'Board cleaner',
        svgIcon: icon,
        onClick: async () => {
          // Show modal and wait for user choice
          let needToClear = confirm('Do you want delete all content?')

          if (needToClear) {
            // Get all board objects
            let objects = await miro.board.widgets.get()

            // Delete all board objects
            await miro.board.widgets.deleteById(objects.map((object) => object.id))

            // Display success
            miro.showNotification('Content has been deleted')
          }
        },
      },
    },
  })
})

Spreadsheet sync

Sync data on the board with Google Sheets.

800

Source code