Skip to content

Deploy to Build Button

The Deploy to Build button lets anyone deploy a running copy of your app to Build with one click, with no dashboard setup. It’s a good fit for open-source projects, starter templates, and any README where visitors should be able to try the app rather than just read about it.

The button follows Heroku’s Button conventions. If your project already has a Heroku button, see Moving a Heroku button to Build.

  • A GitHub repository. Build deploys the repository’s default branch. Visitors need a Build account with GitHub connected, and their GitHub account must be able to read the repository, so for an open-source project the repository must be public.
  • An app.json at the repository root, with a buildpacks array. See Writing app.json.
  • A Procfile that declares how to run the app, plus a release process if the app needs database migrations. See Running migrations.

In Markdown:

[![Deploy to Build](https://build.io/deploy-to-build-button.svg)](https://app.build.io/deploy?template=https://github.com/your-username/your-repo)

In HTML:

<a href="https://app.build.io/deploy?template=https://github.com/your-username/your-repo">
<img src="https://build.io/deploy-to-build-button.svg" alt="Deploy to Build">
</a>

Replace your-username/your-repo with your repository. The button image is 128×32 px, so no width is needed.

Always include template. Without it, Build tries to detect the repository from the GitHub page the visitor came from, but that only works if they’re already signed in to Build.

The deploy endpoint, https://app.build.io/deploy, accepts these query parameters:

ParameterDescriptionExample
templateThe GitHub repository to deploy. Accepts a full URL, a github.com/... path, or owner/repo.template=https://github.com/myorg/myapp
app[name]Suggested app name. Build appends a short random suffix to keep names unique, so the app is named something like my-app-a1b2c3d4. Defaults to the repository name.app[name]=my-app
app[region]The region to deploy into.app[region]=us-east-1
env[NAME]Sets a config var on the new app. Repeat the parameter for each variable.env[GREETING]=Hello&env[LOG_LEVEL]=info
expresstrue skips the confirmation page and deploys immediately into the visitor’s personal team.express=true

A complete example:

https://app.build.io/deploy?template=https://github.com/myorg/myapp&app[name]=myapp&app[region]=us-east-1&env[NODE_ENV]=production

Build always deploys the default branch, even when the button is clicked on another branch’s page or template points at one. There’s currently no way to deploy a specific branch or tag.

Anything you put in the URL is visible to everyone who reads your README, so never put real secrets in env[...]. See Config vars and secrets.

Build reads app.json from the root of the default branch to set up the app. The file is required: a button deploy against a repository without one fails with a message asking you to add it.

A minimal app.json for a Rails app with a PostgreSQL database:

{
"name": "My Application",
"description": "A sample application",
"repository": "https://github.com/myorg/myapp",
"addons": [
"schema-to-go:basic"
],
"buildpacks": [
{ "url": "heroku/ruby" }
]
}

buildpacks is required. Unlike a normal deploy, the button doesn’t detect a buildpack automatically, so list every buildpack the app needs, each with a url. See Buildpacks.

Build follows Heroku’s app.json schema, with these differences:

FieldOn a button deploy
buildpacksRequired. Each entry needs a url.
formationApplied. size must be a dyno size, e.g. standard-1x.
stackApplied. Defaults to heroku-24.
name, description, keywords, website, repository, logoStored as app metadata. The app’s name comes from app[name] or the repository name, not from name.
success_urlStored but not used. After deploying, visitors land on the app’s new pipeline.
envNot applied. See Config vars and secrets.
scriptsStored but not executed, including postdeploy. See Running migrations.
environmentsNot used for the app the button deploys.

Any other field is ignored.

Build provisions an add-on only when both the service and the plan exist in Build’s catalog. Heroku add-on names such as heroku-postgresql aren’t in the catalog, and neither is a name without a plan, such as schema-to-go. Either one is skipped silently: the app deploys without the add-on and without an error.

Use the Build add-on for the service you need, with a plan from Add-on Services:

ServiceHeroku add-onBuild add-onSmallest plan
PostgreSQLheroku-postgresqlschema-to-goschema-to-go:basic
Redisheroku-rediscache-to-gocache-to-go:mini
MySQL / MariaDBjawsdb, cleardbave-to-goave-to-go:basic
Elasticsearch / OpenSearchbonsai, searchboxspandex-to-gospandex-to-go:dachs
Transactional emailmailgun, sendgridmailertogomailertogo:micro

Each entry in addons can be a "service:plan" string or an object with a plan key, e.g. { "plan": "schema-to-go:basic" }.

Once provisioned, an add-on sets its connection config vars on the app, e.g. DATABASE_URL for schema-to-go. After your first test deploy, check the app’s Resources tab to confirm every add-on was created.

The env block in app.json doesn’t reach the deployed app: the button replaces the app’s config vars after creating it from app.json. Only env[...] URL parameters and add-on config vars are set. Build also doesn’t prompt visitors for required values and doesn’t support Heroku’s "generator": "secret".

So:

  • Non-secret defaults: have the app fall back to a default when the variable is unset, or set them with env[...] on the button URL.

  • Secrets: don’t put them in the button URL. Generate a fallback at boot when the app can tolerate one, or tell visitors in your README to set the value after deploying:

    bld config:set SECRET_KEY_BASE=$(openssl rand -hex 64) -a <app-name>

You can keep an env block in app.json to document the variables your app reads, as long as nothing depends on Build applying it.

Build doesn’t run scripts.postdeploy. Run migrations in the release phase instead, by adding a release process to your Procfile:

release: bundle exec rails db:migrate
web: bundle exec puma -C config/puma.rb

The release command runs after every build, before the new version goes live, with the app’s config vars (including DATABASE_URL) available. If it fails, the deploy stops.

Heroku runs postdeploy once, but the release phase runs on every deploy. Anything you move over from postdeploy, such as seeding data, must be safe to run repeatedly.

  1. Change the button URL. Replace https://heroku.com/deploy with https://app.build.io/deploy and the button image with https://build.io/deploy-to-build-button.svg. The template, app[...], env[...], and express parameters carry over unchanged.
  2. Add buildpacks to app.json if it doesn’t have one.
  3. Rename add-ons to their Build names, with a plan. See Add-ons.
  4. Replace generator: "secret" and required config vars, since Build applies neither. See Config vars and secrets.
  5. Move scripts.postdeploy into a release process in your Procfile. See Running migrations.
  6. Test the button from your README and check the deployed app’s add-ons and config vars.

Before:

[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/myorg/myapp)

After:

[![Deploy to Build](https://build.io/deploy-to-build-button.svg)](https://app.build.io/deploy?template=https://github.com/myorg/myapp)

What happens when someone clicks the button

Section titled “What happens when someone clicks the button”
  1. The visitor must be signed in to Build with GitHub connected. If GitHub isn’t connected, Build sends them to the dashboard to connect it first.
  2. Unless express=true is set, a confirmation page lets the visitor change the app name, team, and region, and lists the config vars set by env[...].
  3. Build creates a new pipeline and app, named from app[name] plus a random suffix, and reads app.json from the latest commit on the default branch.
  4. Build provisions the add-ons, builds the app, runs the release phase, and starts the app.
  5. The visitor lands on the new pipeline, where they can follow the build and open the app.