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
- Widget Counter
- Custom Icon Set with drag-and-drop
- Stickies to shapes
- Looking glass
- Clear board
- Spreadsheet sync
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.

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.

Used web-plugin features:
- Add button in bottom bar
- Get current selected widgets
- Subscribe to widgets selection updated event
- Open custom view in sidebar
Custom icon set with drag-and-drop
Used web-plugin features:
- Drag-and-drop images and shapes on the canvas
- Render custom view

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

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.

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.

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.

Updated over 1 year ago