Skip to content

How to add a live demo to your GitHub README, with the exact Markdown

Add a live demo to a GitHub README with one line of Markdown: a GIF or video, GitHub Pages, deploy buttons, Codespaces, Binder, Colab or a Run on pyrovue badge.

By the pyrovue team · · 10 min read

To add a live demo to a GitHub README, put one line of Markdown near the top that links to a running copy of your project: a hosted demo site, a deploy button, or a badge that opens the repository in a cloud environment. Every one of them is the same shape, a linked image:

[![Alt text that says what happens](https://example.com/badge.svg)](https://example.com/demo-link)

If you want visitors to see the project working without clicking anything, embed a GIF or a video instead, or as well. GitHub plays .mp4, .mov and .webm files you upload: up to 10MB in repositories on a free plan and 100MB on a paid plan.

Which one fits depends on the project. A static frontend can live on GitHub Pages for free. A full-stack app, an API or a CLI needs a server, so the choice is between a deploy button (the visitor deploys a copy to their own hosting account) and a run badge (the visitor gets a temporary environment). Notebooks have their own badges. Below is the exact Markdown for each, what it costs you, what it needs in the repo and which projects it suits, checked against each vendor's docs in November 2026.

Show it without a click: GIF, video or terminal recording

A recording is the only demo that works for someone skimming. There is nothing to sign in to and nothing that can be down. It costs you nothing, because GitHub hosts the file, and it fits every kind of project. The catch is that it shows rather than lets people try, and it goes stale when the UI changes.

To put a video in a README:

  1. Record a short clip and export it as H.264 .mp4. GitHub's attaching files docs recommend H.264 because codec support varies between browsers.
  2. Drag the file into any comment box on GitHub, for example a new issue you never submit. GitHub uploads it straight away and inserts a user-attachments URL.
  3. Paste that URL on its own line in README.md. GitHub renders it as a player.
See it running:

https://github.com/user-attachments/assets/YOUR-ASSET-ID

Files uploaded to a public repository can be viewed without signing in. Uploaded images and GIFs are capped at 10MB. A GIF can also be committed to the repo and referenced by relative path, which keeps it versioned with the code:

![Searching the dashboard and opening a record](docs/demo.gif)

For a CLI, a terminal recording beats a screen capture. VHS, from Charm, renders a GIF from a script, so you can regenerate it in CI when the output changes:

vhs new demo.tape   # writes a starter script
vhs demo.tape       # renders the GIF named on its Output line

asciinema recordings can't play inside a README because GitHub strips scripts, so link the SVG preview to the recording page:

[![asciicast](https://asciinema.org/a/RECORDING_ID.svg)](https://asciinema.org/a/RECORDING_ID)

Host a live demo site with GitHub Pages

GitHub Pages serves HTML, CSS and JavaScript from your repository for free. The visitor gets a URL that opens instantly, with no account. The limits, from GitHub's Pages limits page: a published site can be up to 1GB, bandwidth has a soft limit of 100GB a month, deployments time out after 10 minutes, and GitHub says not to use Pages for commercial SaaS or for anything that sends passwords.

Pages is static only. It fits frontends that call public APIs, documentation sites, and JavaScript or WebAssembly libraries with a playground page. It can't run a Node, Python or Ruby server, so a full-stack app needs one of the options further down.

To set it up, build the site to static files in a GitHub Actions workflow and choose Settings → Pages → Source: GitHub Actions. Project sites are served from a subpath, https://OWNER.github.io/REPO/, so tell your bundler: in Vite that is base: '/REPO/' in vite.config.js. Then link it at the top of the README, and also put the URL in the repository's About → Website field so it shows in the sidebar:

**[Try the live demo](https://OWNER.github.io/REPO/)**

Add a deploy button: Vercel, Netlify, Render and Railway

A deploy button doesn't show your demo. It gives the visitor their own deployment, in their own hosting account. That costs you nothing, and it's the right tool for templates and starters that people are meant to deploy. It's the wrong tool for "let me see it work": the visitor needs an account, often a Git account the repo gets copied into, and a build that takes a few minutes.

Vercel

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FOWNER%2FREPO&env=DATABASE_URL)

repository-url is required and must be URL-encoded. Vercel clones the repo into the visitor's GitHub, GitLab or Bitbucket account and creates a project. env lists the names of variables the visitor must fill in; values can't go in the URL, because it ends up in browser history. envDefaults pre-fills non-secret values. The Deploy Button source docs list the other parameters, such as project-name and repository-name.

Netlify

[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/OWNER/REPO)

The repo must be public on GitHub.com or GitLab.com, and Netlify clones it into the visitor's account. A netlify.toml is optional; its [template.environment] section prompts for variables. base= points at a folder in a monorepo and branch= deploys another branch. Netlify's deploy docs cover the rest.

Render

[![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/OWNER/REPO)

Render needs a render.yaml Blueprint at the repo root describing the services. Unlike Vercel and Netlify, the visitor's services deploy from your repository, so Render's button docs strongly advise turning off auto-deploy. Otherwise every push you make redeploys every copy:

services:
  - type: web
    runtime: node
    name: my-app
    plan: free
    buildCommand: npm ci && npm run build
    startCommand: npm start
    autoDeployTrigger: 'off'
    envVars:
      - key: API_KEY
        sync: false   # the visitor is asked for a value

Railway

[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/new/template/TEMPLATE_CODE?utm_medium=integration&utm_source=button&utm_campaign=generic)

Railway's button points at a template, not a repo. You create and publish a template first (it can include databases), then use its code in the link. Railway's docs suggest replacing generic with your template's name, and authors of published templates are eligible for kickbacks when other people deploy them.

Add an "Open in GitHub Codespaces", StackBlitz or CodeSandbox badge

These badges open the repository in an editor in the browser. The visitor gets the code and a terminal, which suits contributors better than people who only want to see the result.

GitHub Codespaces

[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/OWNER/REPO)

The visitor gets VS Code in the browser on a cloud VM with the repo checked out. Usage is billed to the visitor's personal account; a free account includes 120 core-hours a month (60 hours on a 2-core machine) and 15GB-month of storage. Without configuration they get a generic image and install everything themselves. A .devcontainer/devcontainer.json makes it start ready:

{
  "image": "mcr.microsoft.com/devcontainers/javascript-node:22",
  "postCreateCommand": "npm ci",
  "postAttachCommand": "npm run dev",
  "forwardPorts": [3000]
}

Add /tree/BRANCH for a branch, or ?quickstart=1 to offer a recent codespace before a new one. GitHub's guide to Codespaces links and badges has the full list.

StackBlitz

[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/OWNER/REPO)

StackBlitz runs the project inside the visitor's browser tab with WebContainers, so there is no server to pay for and it starts quickly. It runs the dev script in package.json, or start if there is no dev; ?startScript=build picks another. WebContainers target Node.js, with full support in Chrome and beta support in Firefox and Safari 16.4 and later. A Python or Go backend or a database server won't run in it, so it fits JavaScript frontends and libraries. Use stackblitz.com/fork/github/... to give each visitor their own copy.

CodeSandbox

[![Edit in CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/OWNER/REPO)

CodeSandbox, owned by Together AI since December 2024, imports the repo into a cloud VM. The visitor needs an account; the free Build plan includes 40 VM-hours a month. Click the badge once after you add it to check that the import works for your repo.

Binder and Colab badges for notebooks

For a repository of Jupyter notebooks, these two are the standard choice.

Binder

[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/OWNER/REPO/HEAD?urlpath=lab/tree/demo.ipynb)

Binder is free and needs no account. It builds an image from requirements.txt, environment.yml or the other files repo2docker reads, at the root or in a binder/ folder, then opens JupyterLab. ?urlpath=rstudio opens RStudio instead. The first launch after a push has to build the image, so it is slow; later launches reuse it. Binder's user guidelines give 1GB of RAM guaranteed, 2GB at most, and shut sessions down after 10 minutes without activity.

Google Colab

[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/OWNER/REPO/blob/main/demo.ipynb)

Colab opens one notebook, not the repository, in a Google-hosted runtime with optional GPUs. The visitor needs a Google account and gets an editable copy that can't overwrite your file. Nothing from the repo is installed for them, so the first cell has to fetch it:

!git clone https://github.com/OWNER/REPO.git
%cd REPO
!pip install -r requirements.txt

The shortcut: a Run on pyrovue badge

If the project has a server, such as a full-stack app, an API or a Django or Rails site, the options above make the visitor either deploy it or install it. A Run on pyrovue badge gives them the running app instead:

[![Run on pyrovue](https://pyrovue.com/badge.svg)](https://pyrovue.com/github.com/OWNER/REPO?ref=badge)

For a gitlab.com project:

[![Run on pyrovue](https://pyrovue.com/badge.svg)](https://pyrovue.com/gitlab.com/GROUP/PROJECT?ref=badge)

The visitor sees the repo, signs in and gets their own box: a Linux container in pyrovue's cloud where the project is installed and started, with a live preview, a terminal, the files, the setup log, a Code Map and a guided tour. Nothing starts without a click. Most repos are running in about a minute. The box runs on the visitor's plan, not yours; the free Hobby plan includes 20 box-hours a month.

Most repos need no configuration: pyrovue reads lockfiles, the README, Dockerfiles, Compose files, dev containers and hosting configs to work out the install and start commands, and the first setup that works is replayed for the next visitor on the same commit. To pin the commands, add a pyrovue.json at the root:

{
  "setup": ["pnpm install", "pnpm db:migrate"],
  "start": "pnpm dev",
  "port": 3000,
  "env": { "DATABASE_URL": "file:./dev.db" }
}

It doesn't fit projects that need Docker inside the environment, a GPU, or MongoDB or Elasticsearch from a Compose file, and notebook-only repos are better on Binder. The badge generator writes the Markdown, HTML and reStructuredText for your repo or a branch, and pyrovue for open-source demos explains what visitors see.

Which README demo fits which project

OptionWhat the visitor getsWhat it costs youWhat the repo needsBest for
GIF or videoA recording, no clickNothingA recording under the size limitEvery project, especially UIs and CLIs
GitHub PagesA live URL, no accountNothing, within Pages limitsA static build and a Pages workflowStatic frontends, docs, JS or WASM libraries
Vercel or Netlify buttonTheir own deploymentNothingNothing extra; optional env promptsFrontend templates and starters
Render or Railway buttonTheir own deployment with servicesNothingrender.yaml, or a published Railway templateFull-stack templates with a database
Codespaces badgeVS Code in a cloud VMNothing (billed to the visitor)devcontainer.json recommendedContributors, any stack
StackBlitz badgeThe app running in their browserNothingA dev or start scriptNode.js frontends and libraries
CodeSandbox badgeThe repo in a cloud VMNothing (visitor's plan)Nothing requiredFrontends
Binder badgeJupyterLab, no accountNothingrequirements.txt or environment.ymlNotebooks, Python and R
Colab badgeOne notebook, optional GPUNothingAn install cell in the notebookSingle notebooks, ML demos
Run on pyrovue badgeThe running app, terminal and code tourNothing (visitor's plan)Nothing for most repos; pyrovue.json to pinFull-stack apps, APIs, CLIs

By project type:

  • Static frontend: GitHub Pages plus a GIF.
  • Full-stack app or API: a run badge for trying it, a deploy button if people are meant to host it.
  • CLI: a VHS or asciinema recording, plus a badge that opens a terminal (Codespaces or pyrovue).
  • Notebook: Binder for the whole repo, Colab for a single notebook.
  • Library: StackBlitz for JavaScript, Binder or Colab for Python, or an examples folder that a run badge can start.

Make the demo easy to find and safe to try

  • Put it above the fold. GitHub shows the README under the file list, so the first screen of it is all most visitors read. Put the demo link or badge directly under the title and one-sentence description, before the install steps.
  • Lead with one. Pick the badge that best shows the project and put it first. Six badges in a row read as noise.
  • Write real alt text. Screen readers read it, and it's what shows if the image fails to load. Say the action ("Open in GitHub Codespaces", "Run on pyrovue"), not "badge". For a GIF, describe what happens in it.
  • Keep demo data safe. Never commit a real API key to make a demo work. Ship a .env.example with placeholders, use seed data, and let deploy buttons ask for secrets (Vercel's env, Netlify's [template.environment], Render's sync: false). A public demo that accepts writes needs a scheduled reset.
  • Give pull requests a run link too. The workflow on the button page comments a pyrovue link on each new pull request, so reviewers can open the change running. It triggers on pull_request_target, which GitHub runs from your default branch with a write token, so it only posts a comment and never checks out the pull request's code:
on:
  pull_request_target:
    types: [opened, reopened]
permissions:
  pull-requests: write

Whoever opens the link runs the pull request in a box on their own plan. Pull request previews compares this with preview deployments on Vercel or Netlify.

Run the repo you bookmarked and never tried.

Hobby is free and needs no card. Paste a link and your first box is up in about a minute.