Embed
Embed quickstart
A live roadmap in one of your own pages, in three steps. Everything here is copy and paste, and none of it needs a build step or a server.
-
Get your embed key
Open the dashboard, choose your project, and go to Share & Embed. The embed key is the first thing on the page. Copy it, along with your project slug, which is the name in the address bar of your board.
The key is meant to be visible. It opens what your public board already shows and nothing more.
-
Add the script
Put these two lines wherever your page loads its scripts, then call
initonce with the two values you just copied.In your page<link rel="stylesheet" href="https://app.votefirst.app/embed/votefirst.css"> <script src="https://app.votefirst.app/embed/votefirst.js"></script> <script> VoteFirst.init({ project: 'your-project-slug', key: 'your-embed-key' }); </script>The stylesheet is optional. Leave it out and the widgets arrive with no styling at all, which is what you want if you would rather write every rule yourself.
The script tag can also carry the two values itself, which saves the
initcall entirely.The same thing, without a script of your own<script src="https://app.votefirst.app/embed/votefirst.js" data-project="your-project-slug" data-key="your-embed-key"></script> -
Mount a widget
Add an empty element where the board should appear, and name it in one call.
In your page<div id="votefirst-roadmap"></div> <script> VoteFirst.roadmap('#votefirst-roadmap'); </script>That is the whole integration. Load the page and your columns, cards and vote controls are there, reading live from your project.
The whole page
The three steps together, as one file you can save and open.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Our roadmap</title>
<link rel="stylesheet" href="https://app.votefirst.app/embed/votefirst.css">
</head>
<body>
<h1>Our roadmap</h1>
<div id="votefirst-roadmap"></div>
<script src="https://app.votefirst.app/embed/votefirst.js"></script>
<script>
VoteFirst.init({
project: 'your-project-slug',
key: 'your-embed-key'
});
VoteFirst.roadmap('#votefirst-roadmap');
</script>
</body>
</html>
Your embed key
The key identifies your project to the widgets. It is public by design the way any browser side key is: it has to reach every visitor's browser to be of any use, so nothing behind it can be secret.
An embed key is not an API key. An API key is the opposite kind of credential, a secret that opens every administrative route, and it must never appear in a page. The API sends no cross origin headers to a request carrying one, so a browser cannot complete that request anyway.
Restricting it to your own sites
Under Share & Embed you can list the origins allowed to use the key, one per line or separated by commas. Leave the list empty and any site may embed your board, which is often what a public roadmap wants.
| Entry | What it allows |
|---|---|
https://example.com | That origin alone. The scheme and the port have to match as well. |
example.com | The same thing. A bare host is read as https, because that is what somebody typing a domain into an allowlist means. |
https://*.example.com | Its subdomains, and not the bare domain. Add the bare domain as a second entry if you want both. |
http://localhost:3000 | Your own machine while you are building the page. A port is part of an origin, so this and http://localhost:5173 are two entries. |
* | Every origin, stated rather than implied. The same reach as an empty list. |
Each entry is reduced to the form a browser sends, a lowercase scheme and host with an optional port and nothing after it, and anything that could not be a host is dropped rather than stored. That is why the box shows you something other than what you typed after you save: it is showing you what was kept.
This restricts browsers only. A browser refused this way gets origin_not_allowed and a 403, and a request sent from a terminal carries whatever origin its author types, so the allowlist keeps your key from working on somebody else's site rather than making it a secret.
Rotating the key
Rotating stops every page still carrying the old key until its snippet is updated, so do it when a key has ended up somewhere it should not be. Votes, comments and suggestions already recorded are untouched.
What the key may spend
Per project, 3000 reads, 600 writes and 300 new voters a minute, and every page carrying your key draws from the same budget. Rendering a board is three reads, so those numbers are the size of an audience rather than the size of a person. Over any of them the request answers 429 and names the wait in Retry-After.
Pinning a version
The script address above is the stable channel. It is cached for five minutes, so fixes reach your page without you editing anything.
A version pinned address is also served, cached for a year, for anyone who would rather review an upgrade than receive one.
https://app.votefirst.app/embed/2.5.4/votefirst.js