This full-stack example shows how to build an integration with GitHub that syncs data between GitHub issues and Miro app cards.
🚨 🚨 🚨 Only deprecated "Classic" GitHub projects work with this app. This means that you cannot connect this app to your own repo unless you have a deprecated "Classic" GitHub project. 🚨 🚨 🚨
This app is meant to show the basic concepts behind 2-way sync, but is in no way a working solution. This is intended for simple demo purposes to show a simple 2-way sync with free services like Netlify, Supabase, and Miro.
This app involves setting up different tools such as Netlify for deploying your app, Supabase for storing access tokens and GitHub for using GitHub actions to detech any changes in your projects. It takes 30-40 minutes to configure.
github-app-cards-demo.mov
- Included Features
- Tools and Technologies
- Prerequisites
- Associated Developer Tutorial
- Associated Video Tutorial
- Database Configuration
- Netlify Configuration
- Miro App Configuration
- Run the app locally
- Folder Structure
- Contributing
- License
- You have a Miro account.
- You're signed in to Miro.
- Your Miro account has a Developer team.
- Your development environment includes Node.js 14.13 or a later version.
- GitHub Account and access token.
- Supabase account and database.
- Netlify account.
To view a more in depth developer tutorial of this app (including code explanations) see the GitHub app cards 2-way sync tutorial on Miro's Developer documentation.
To view a more in depth developer tutorial in video format, you can watch the YouTube video below. This video explains how to build a 2-way data sync integrations with GitHub projects (classic) and Miro. It goes through demo videos, architecture diagrams, and code examples to teach you the fundamentals around building a 2-way data sync integration.
- Create a database in Supabase. First you may need to create an Org.
- Go into your dashboard and into your project and to the
table editor
. - Click on
Create a new table
- Name this table
auth
and add in the following columns, with the respectiveFormat
as shown in the screenshot below. Note that capitalization is important for the table name. This table will hold access_tokens to be able to call the Miro REST API to sync changes which happen in the GitHub project. Disable Row Level security.
This is the schema for the auth
table - make sure it is exactly the same to ensure this code works.
This is what the auth
table should look like once it's been updated.
- Click on
Create a new table
and name this tablecard-mapping
and add in the following columns, with the respectiveFormat
as shown in the screenshot below. This table will hold the app card ID from Miro and the GitHub issue ID along with the MiroUserId.
This is the schema for the card-mapping
table - make sure it is exactly the same to ensure this code works.
This is what the card-mapping
table should look like once it's been updated.
- Click on
Edit column
for themiroUserId
in thecard-mapping
table, and then add in the followingForeign Key Relation
as shown in the screenshot below.
- Once you save the
Foreign Key Relation
yourmiroUserId
from thecard-mapping
table should look something like the screenshot below. ClickSave
. We need this to be able to associate the miroUserId with a access_token so we can invoke the Miro REST API.
The code in this repo contains three different functions which are meant to be serverless functions:
- netlify/functions/authorize.js
- netlify/functions/issues.js
- netlify/functions/project-cards.js
authorize.js is going to run when you share your app with someone and then go through the OAuth flow.
issues.js is going to run when you update the title or description of an issue. We have a GitHub action which will do this, defined in .github/workflows/issues.yml
. You will need to update the GitHub Action URL to point to your deployed Netlify function. It should look something like https://miro-github.netlify.app/.netlify/functions/issues
.
project-cards.js is going to run when you move a card to a different column i.e. if you move a card from To Do
to Done
. We have a GitHub action which will do this, defined in .github/workflows/project-cards.yml
. You will need to update the GitHub Action URL to point to your deployed Netlify function. It should look something like https://miro-github.netlify.app/.netlify/functions/project-cards
.
Now we will show you step by step how to set this up for free with Netlify. When you deploy your site with Netlify, it will
automatically generate those functions since Netlify is looking for serverless functions in the netlify/functions
directory.
-
Go to your Netlify account and auth with your GitHub account.
-
Download the
github-appcards
repo by going to developers.miro.com and then scrolling down toCreate apps using samples
. Then find GitHub App Cards and click on theDownload source code as .zip
. Unzip the files. Rename the project togithub-appcards
. -
Create a new GitHub repo, and push up your
github-appcards
project which you just downloaded to it. You can use the following commands to do so:
cd github-appcards
git init
git add .
git commit -m "first commit"
git remote add origin https://github.com/<your-github-username>/<your-new-github-repo-which-will-hold-github-appcards-code>
git push -u origin main
-
At this point, you should have a personal repo which has the GitHub-appcards code in it. We will use this repo as a way to deploy this app with Netlify.
-
Go into Netlify, login, and from the
Team overview
section, click onAdd new site
->Import an existing project
->Deploy with GitHub
and then authenticate into GitHub and select this project which you just created which holds the GitHub app cards code. Select themain
branch andDeploy
-
Once the deploy is complete, you app should be deployed to
<site-name>.netlify.app
. For example, mine washttps://peaceful-fairy-c2e727.netlify.app
as shown in the screenshot below. I will use thehttps://peaceful-fairy-c2e727.netlify.app
as the example for how to connect your Miro app to the Netlify app but just understand that your URL will be different.
- Now, let's create a new Miro app on
developer.miro.com
. - Once you've created the app, from the app setting page, click on
edit in Manifest
and paste in the following:
appName: GitHub App Cards
sdkVersion: SDK_V2
sdkUri: https://peaceful-fairy-c2e727.netlify.app
boardPicker:
allowedDomains: []
redirectUris:
- https://peaceful-fairy-c2e727.netlify.app/.netlify/functions/authorize
redirectUriForSdk: https://peaceful-fairy-c2e727.netlify.app/.netlify/functions/authorize
scopes:
- boards:write
- boards:read
icons:
colored: ""
outline: ""
Make sure to change sdkUri
, redirectUris
, and redirectUriForSdk
with your site name.
- From the
Redirect URI for OAuth2.0
section in app settings, click onOptions
and make sureUse this URI for SDK authorization
is checked, as shown in the screenshot below.
- Rename the
.sample.env
file at the base of thegithub-appcards
repo to.env
and fill in the values as detailed in the comments. Note, yourredirectUriForSdk
on your app settings should be the same as theMIRO_REDIRECT_URI
in your env variables. Below, I have used thepeaceful-fairy
example to show how you should fill in this env file. Note that you must use your own deployed app base name and then it should end in.netlify/functions/authorize
for theMIRO_REDIRECT_URI
.
# Generate an access token in GitHub, and enter the value here.
# To generate the access token, go to https://github.com/settings/tokens
VITE_GH_ACCESS_TOKEN=
# In Supabase, you create a Postgres database, and you assign it a password.
# Enter the password of the created database in Supabase here.
# For more information, see:
# https://supabase.com/docs/guides/database/managing-passwords
VITE_SUPABASE_PASSWORD=
# Enter the URL of the Supabase database that the app uses for data persistence here.
# For more information, see:
# https://supabase.com/docs/guides/database
# Login to your account, then go down to Project Settings -> API -> URL.
# Your connection should look like `https://ahnvcdiskdadfgbljsdm.supabase.co
VITE_DATABASE_URL=
# Enter the API key of the Supabase project with the database that the app uses for data persistence here.
# For more information, see:
# Login to your account, then go down to Project Settings -> API -> Project API keys -> anon public.
VITE_DATABASE_PUBLIC_KEY=
# Enter the base URL of the hosting service your app runs on here.
# If you're developing locally, it can be 'localhost'.
# Netlify example: https://peaceful-fairy-c2e727.netlify.app/
VITE_BASE_URL=
# Enter the client secret of your app here.
# To retrieve the client secret, go to https://miro.com/app/settings/user-profile/
# Select 'Your apps', and then the app whose secret you want to retrieve.
# The app client secret is under 'App Credentials' > 'Client secret'.
MIRO_CLIENT_SECRET=
# Enter the OAuth code grant flow redirect URI for your app here.
# For more information, see:
# https://developers.miro.com/docs/getting-started-with-oauth
# Netlify example: https://peaceful-fairy-c2e727.netlify.app/.netlify/functions/authorize
MIRO_REDIRECT_URI=
-
Once you have filled this in, go back to your Netlify deploys and click on
Site configuration
-> then click onEnvironment variables
->Add a variable
->import from a .env file
and then just copy and paste the content and click onImport variables
. -
Trigger a new deploy.
Make sure your URLs have https:// at the beginning, otherwise the OAuth flow will not work.
Also make sure that your MIRO_REDIRECT_URI ends in .netlify/functions/authorize
.
- Lastly, you will need to change the URL in the GitHub action to point to your own deployed serverless functions. Point your GitHub action for
issues
to point to yourissues
endpoint from your serverless functions. The same should be done forproject-cards
. Go to .github/workflows/issues.yml and change the URL on line 11. Go to .github/workflows/project-cards.yml and change the URL on line 13.
- Go back to your app home page, and under the
Share app
section, click onCopy
and paste the URL in your browser. Install the app on a dev team.
⚠️ We recommend to install your app on a developer team while you are developing or testing apps.⚠️
- Go to your developer team, and open your boards.
- Click on the plus icon from the bottom section of your left sidebar. If you hover over it, it will say
More apps
. - Search for your app
GitHub App Cards
or whatever you chose to name it. Click on your app to use it, as shown in the video below. In the video we search for a different app, but the process is the same regardless of the app.
search-for-app.mov
.
├── .github
├── netlify
├── src
│ └── assets
│ └── style.css <-- CSS styles for the app.
| └── components <-- Folder of all UI components used in the app.
| └── utils
│ └── github.ts <-- Utility functions for interacting with the GitHub API.
│ miro.ts <-- Utility functions for interacting with the Miro Web SDK and REST API.
│ supabase.ts <-- Main entry for interacting with Supabase.
│ └── app.tsx <-- The main entry. Contains structure for the sidebar when launched.
│ appcard-modal.tsx <-- The main entry for the modal that appears when an app card is expanded.
│ constants.ts <-- A collection of static variables used throughout the app.
│ index.ts <-- Initializes app, and contains logic for opening the app from the sidebar and expanding an app card.
│ modal.tsx <-- The main entry for the modal that appears when selecting a GitHub issue to import.
├── app.html <-- The app itself. This is loaded on the board inside 'app.tsx'.
├── appcard-modal.html <-- The app card modal itself. This is loaded on the board inside the 'appcard-modal.tsx'.
├── index.html <-- The app entry point. This is the value you assign to 'sdkUri' in the app manifest file.
└── modal.html <-- The modal itself. This is loaded on the board inside the 'modal.tsx'.
If you want to contribute to this example, or any other Miro Open Source project, please review Miro's contributing guide.