DEV Community

andrzejwp for flotiq

Posted on • Updated on • Originally published at

Adding a custom domain to Heroku apps for free

This has been originally posted as a Flotiq Deep Dive

How to add custom domains to free Heroku apps

Heroku is pretty great for hosting websites and their Deploy to Heroku buttons are so awesome, especially with how they can be integrated with static website generators, like Gatsby. Heroku's free account is also quite capable, you are allowed to deploy up to 5 applications, hosted in their * domain. But, as soon as you'd like to move this app to a custom domain - you have to pay. If you've already built and deployed your blog, for example using this tutorial your next step will probably be adding a custom domain for your blog.

Here's a quick tutorial how to get around this, with Cloudflare Workers.


  • Cloudflare account (free)
  • Cloudflare Workers enabled (free)
  • Flotiq account (free)

Cloudflare Workers

Cloudflare is a global CDN (Contend Delivery Network), which provides websites across the globe with features like anti-DDoS protection, global content distribution and the possibility to run serverless applications "on the edge".

Cloudflare provides a pretty handy CLI tool to work with your Workers code, you can read more about how to get started here. In this tutorial, however, we will use the Cloudflare GUI to build the solution.

Creating the worker

Once you login to your Cloudflare account go to Menu / Workers. From the Workers dashboard select Create Worker.

You will be redirected to the Worker editor tool, which will be filled out with a Hello World code for you, this is the part that we'll update next.

Proxying content inside the Worker code

The Worker code below is going to take care of rewriting the URLs from* to*.

// keep track of all our blog endpoints here
const myBlog = {
  hostname: "",
  targetSubdirectory: "/blog",
  assetsPathnames: ["/public/", "/assets/"]

async function handleRequest(request) {
  // returns an empty string or a path if one exists
  const formatPath = (url) => {
    const pruned = url.pathname.split("/").filter(part => part)
    return pruned && pruned.length > 1 ? `${pruned.join("/")}` : ""

  const parsedUrl = new URL(request.url)
  const requestMatches = match => new RegExp(match).test(parsedUrl.pathname)

  // if its blog html, get it
  if (requestMatches(myBlog.targetSubdirectory)) {
    console.log("this is a request for a blog document", parsedUrl.pathname)
    const targetPath = formatPath(parsedUrl).substr(myBlog.targetSubdirectory.length)
    return fetch(`https://${myBlog.hostname}/${targetPath}`)

  // if its blog assets, get them
  if ([myBlog.assetsPathnames].some(requestMatches)) {
    console.log("this is a request for blog assets", parsedUrl.pathname)
    const assetUrl = request.url.replace(parsedUrl.hostname, myBlog.hostname);

    return fetch(assetUrl)

  console.log("this is a request to my root domain",, parsedUrl.pathname);
  // if its not a request blog related stuff, do nothing
  return fetch(request)

addEventListener("fetch", event => {

which is adapted from this Cloudflare article.

Simply paste this code in the Worker editor, replacing the original Hello World code. Don't forget to update your Heroku APP URL. Next - click Save and Deploy.

That's it! Cloudflare has deployed your worker to an automatically generated endpoint, you can start using it right away, the URL will be presented to you in the confirmation dialog.

Add routing

In order to publish your blog under a subfolder of your domain - in your domain dashboard click Workers.

Next, click the Add Route button.

And finally - define the route, where you'd like to display the Heroku-hosted content.


You can use a free Cloudflare Workers account to add custom domains to your free Heroku Apps account.

Top comments (3)

andrzejwp profile image

Hey Guys, let me know if this is useful, or if there's anything you'd like me to amend in the article. Also - the documentation page linked at the top contains more step-by-step screenshots from Cloudflare, so go over there if you'd like to verify.

rafeqm profile image
Muhammad Rafiqi • Edited

I think this is helpful! But can you make more comprehensive step for these (e.g. explain what each block of code does?)? Because I have django app on heroku (which is free) that's not a blog and I can't find a way to understand your instructions because my app is not a blog. Thanks in advance!!

andrzejwp profile image

On a similar topic - you can also use Cloudflare to secure your API access.

Pretty important for JAMstack apps.