Deploying a Two-Repo App to One Domain on Heroku
Tags: heroku, frontend, backend, web
Published: 2019-07-23 03:27:23

---
title: Deploying a Two-Repo App to One Domain on Heroku
published: true
description: A walkthrough for serving a front-end and back-end from Heroku on a single URL.
tags: Heroku, Frontend, Backend, Web
---

So!  You've followed good practices, and kept the frontend and backend of your new web app in separate Github repos.  (This is nice because it modularizes your project, and allows you to, say, swap out your backend without your frontend having to be redeployed.)  Now it's time to showcase your brand new invention.  However, you want to keep your backend exposed, and you want it to look professional, by hosting it on the same domain as your fronted.  How's that going to work?

The basic theory of this will apply to any hosting, but since Heroku's interface makes this dead simple, we'll use that as an example.

###Step 1: Initial Deployment

Deploy both repos to their own Heroku app.  Heroku has an excellent [guide](https://devcenter.heroku.com/articles/git) to deploying from Git from the command line, as well as one for deploying from Docker.  It doesn't matter what `.herokuapp` domains you choose for them at this point, since they'll only be visible to you.

###Step 2: Get thee a domain

Get a domain.  There are many registrar choices, and most of them are GoDaddy.  Namecheap and Domain.com also come up a lot as recommended.  YMMV, DYOR.  **Important:** make sure your choice supports adding custom DNS, specifically CNAME records.

###Step 3: Generate Custom DNS Pointers On Heroku

Now for the fun, and surprisingly easy, part.  Go to your backend's Heroku dashboard.  Open up the Settings tab, and scroll down to Domains and Certificates.  Click the big purple Add Domain button.  This opens the following dialog:

![](https://thepracticaldev.s3.amazonaws.com/i/bzosack7rbzcqjg123ey.png)

Here, type in a subdomain of the domain you own, for example  `backend.yourdomain.com`.  It's important that it's a subdomain and not the root: CNAME records can only point to subdomains.

Heroku auto-generates a unique DNS target; copy this to your clipboard.  After generating, your Domains section will look something like this:

![](https://thepracticaldev.s3.amazonaws.com/i/g1hb3ncl8iecynhmz7n1.png)

(I redacted my DNS targets, but that's where yours will be.)

###Step 4: Point your new domain's DNS to those records

Head to your domain's settings page, and look for a DNS area.  In my hosting, it looks like this:

![](https://thepracticaldev.s3.amazonaws.com/i/5jly4hhejtwra3yafzz2.png)

Once you're in the DNS panel of your domain, you should see an area to add custom DNS records.

![](https://thepracticaldev.s3.amazonaws.com/i/cboopqcm6nm5xqgu8fhv.png)

Here's how you should fill yours in:

![](https://thepracticaldev.s3.amazonaws.com/i/8hvfg961ffcecg5vcbsm.png)

Make sure the `Name` field matches the subdomain of the DNS record you generated on Heroku.  `Type` should be CNAME.  The `Value` is the one in your clipboard, the long auto-generated DNS pointer address.  Click Add Record and you'll be good to go!

If you're not curious about CNAMEs, you can skip the next section.  

### Intermission: A brief diversion on DNS and CNAME records

DNS exists to convert clumsy human things like letters and unicode into the lovely, clean numbers of true IP addresses.  These records exist on many servers around the world, and are cached by your ISP for quicker lookup time.

Unfortunately, CNAMEs are confusingly - perhaps even badly - named.  CNAME stands for `Canonical NAME`.  The implication is that you're changing the 'canonical name' of the record that points to your site's IP address.  *It's actually the opposite* - you're creating an *alias* to your site's Canonical NAME.  Oh well.  There are rumblings in the DNS community that indicate CNAMEs may eventually be replaced by ANAMEs, the *accurately named* `Alias NAME` record.  Besides being a properly constructed title, an ANAME is inherently faster than a CNAME: it serves the IP in one query, rather than a CNAME's two.  If only for the sake of naming conventions, I hope that this becomes the standard.  

Anyway, for now, you're almost certainly stuck with CNAMEs, as there is no formal ANAME standard and very few hosts offer it, and if they do it's going to be their own interpretation.  So it goes.  Intermission is over, let's get back to our program.

###Step 5: Now do it again

Repeat Steps 3 and 4 for your frontend.  Do not repeat step 5, as this would trigger an infinite loop.

###Step 6: Wait

If you read the DNS section above, you'll remember that DNS records exist in a ton of different places, and are cached under many different schemes.  This is frankly amazing and wonderful, but for you, it means giving DNS a second to catch up with your changes.  I found my CNAME changes happened pretty quickly - within a few minutes - but some changes can take hours, or even a day or two.  With any luck, your experience will be like mine.

###Step 7: The Final Touch

Let's say you want the visitor to experience only having to type in the root domain to get to your project.  That's pretty reasonable.  You're in luck!  Simply forward your root domain to your front-end subdomain.  In my hosting, that's simply called a 'redirect'.

![](https://thepracticaldev.s3.amazonaws.com/i/uulblavknhvzoi1d0v89.png)

This should also not take too long.

Congratulations!  You're now fully hosted and served under one domain.  Now someone can look at your site and have no hint of all the hard work you've done to get it to this point, which I guess was the idea all along.

You can see my implementation of this at [256hz.com](http://256hz.com), which is redirected to [portfolio.256hz.com](http://portfolio.256hz.com), which in turn gets its backend data from [pgdb.256hz.com](http://pgdb.256hz.com).

Thanks for reading!  If you have any trouble, leave a comment and I'll do what I can to help.