If you’ve accidentally deployed some bad code to Heroku, you may be familiar with Heroku’s application error page. Or maybe you’ve needed to put your application into maintenance mode and you’ve seen Heroku's maintenance mode page.
Both of these pages are customizable via config vars. All you need are publicly accessible, static HTML pages living somewhere outside of your application. Heroku recommends hosting them on Amazon S3, but it can be easy to upload pages there, forget about them, and have them fall out of sync with the rest of your application.
One way to avoid losing track of custom error and maintenance pages is to have them continuously deployed from your application’s repository. Here’s one way to do that.
This could be a new directory in your repository or one that already exists. Be aware that for whichever directory you pick, all of its files will be publicly accessible.
My application, Monday Miles, is a Rails application, which means that the
/public directory is already publicly accessible. Serving a mirror of it didn’t seem like a big deal in my case, so I chose to store my error and maintenance pages in
/public. Other options include a separate
/pages directory or perhaps a directory named after the domain from which you plan to serve these pages.
The pages should be static HTML pages. While you won’t be able to access assets from elsewhere in your application (like from the Asset Pipeline for Rails), you can upload images and CSS into the same directory and reference them with relative paths.
Netlify is an awesome service for hosting static sites. It can do some fancy stuff if you’re using a static site generator like Jekyll or Middleman, but it’s also great for hosting plain old directories of static HTML files. My favorite advantage of Netlify over GitHub Pages is that it provides free, one-click HTTPS for custom domains via Let’s Encrypt.
Once you’re signed up, click “New site from Git.” Choose your Git provider (as of writing, GitHub, GitLab, and Bitbucket are supported), select your repository, and choose the branch to deploy from (probably
master). To ensure that you’re only exposing the desired directory, you can either enter that directory in to the “Publish directory” field or add a super simple netlify.toml configuration file to the root of your repository (here's mine for Monday Miles). Since you’re not using a static site generator, you don’t need to set a build command. Click “Deploy site,” and verify that your pages are live at the provided *.netlify.com domain.
Heroku will serve your error and maintenance pages within an iFrame, so it’s unlikely that your users will notice if the pages are served from *.netlify.com. However, Netlify makes it so easy to get started with a custom domain that I think it’s worth the couple extra minutes.
On the Overview page for your new Netlify app, click “Set up a custom domain” and follow the instructions to add a custom domain (I chose public.mondaymiles.com). If your domain lives with a provider that provides a CDN like Cloudflare, be sure to set the new CNAME record for “DNS only,” since Netlify has its own CDN. Follow the instructions to provision a Let’s Encrypt certificate and enable HTTPS.
If you want any requests for non-existent files at your Netlify domain to redirect users to your main application, you’ll need to add a
_redirects file to your Netlify publish directory. Here's what mine looks like.
MAINTENANCE_PAGE_URL config vars to point at your error and maintenance pages on Netlify. You an do this through the Heroku CLI or through your application’s dashboard on the “Settings” page. Remember to do this for all of your applications if you’re using Heroku Pipelines. Follow Heroku’s instructions to test your error and maintenance pages.
And that’s it! Anytime you update those pages in your application’s repository, they’ll be updated on Netlify. Instead of seeing the generic Heroku error and maintenance mode pages, your users will see the custom pages you created (hopefully not too often!).