Phoenix: Creating An Umbrella App With Your Site And Haskrocket’s Tilex

Brian Emory
Brian Emory | Web Developer
8 min readNov 27, 2017

Integrate Tilex with your site

Inspired by Hashrocket’s project Tilex, I wanted to add a Today I Learned section to my website. I tend to write myself little notes in my notebook or on a post-it as I pick up something new. As you can imagine, this does not make it very easy to reference something I have learned.

Originally, I was going to add a simple, blog-type of section for these short posts. I realized that Hashrocket has open-sourced Tilex and encourages people to fork and use it. So that is exactly what I decided to do.

I had a few options for making use of Tilex.

  1. I could create a separate Heroku application to host it.
  2. I could merge it into my personal site.
  3. I could turn my site into an umbrella app.

I have yet to do anything with an umbrella app so I decided to take this opportunity to learn by doing. It also seemed like the more challenging of the options. Not so coincidentally, it also makes for a good blog post.

I have created a separate repo for my personal site and its integration with Tilex. It will allow you to see everything I did without being muddied by all the commits it took to get things working the first time around (mostly due to errors of my own doing). Each section will have a link to the GitHub commit(s) for the code used in the section.

Presumptions

My domain provider is Google Domains and my webhost is Heroku. Anything that relates to those may be different for your provider and webhost. Be aware that both of the apps I am using as an example are using Phoenix 1.3 and have pretty default structures. Keep that mind if you are using an older version of Phoenix or have modified your app’s structure.

In the gists, you will see your_app, YourApp, or YourAppWeb from time to time. Be sure to rename those to the name of your app. For me, that means using tbe_elixir, TbeElixir, or TbeElixirWeb. You will see reminders for this from time to time (mostly in places where I forgot to do it myself).

Create a Subdomain Plug (88367f2)

We are going to create a new plug that will route our application based on what subdomain it used. When visitors visit our til subdomain, they will be routed to the Tilex app. Be sure to rename YourAppWeb.Plug.Til to the name of your app.

your_app/lib/your_app_web/plugs/til.ex

Next, we will add this plug to our endpoint.ex. We want it above our plug YourAppWeb.Router so it is the first thing that is hit when loading our site.

your_app/lib/your_app_web/endpoint.ex

Depending on how your domain provider and web host work, you may need to add a CNAME record with your provider and setup the domain on your host. I had to create a CNAME record with Google that pointed to my Heroku DNS target. You can add your subdomain to Heroku using heroku domains:add til.yourdomain.com from your terminal.

Create the Umbrella (54ed755, d0bda32)

We need to first create an apps folder in our root directory. Inside the apps folder, we will create another folder and give it the same name as our app. This is important. If the folder name does not match the app name, the app will not be found when our app is run. If you have any doubts, you can look inside your mix.exs, and right at the top is a project function. You will see app: :your_app. Name your folder exactly as your_app is shown.

In your root directory, move all of the files in your application to the folder you just created. I left behind the README.md, the Procfile which is used for deploying my app to Heroku, and all of the hidden dotfiles such as .git and .env. I also left behind the .gitignore and copied it into my new project directory. Alternatively, you could modify your root .gitignore to include the correct subdirectories but copying it over helps us move along quicker.

Inside the apps folder, we will add Tilex. Fork it from hashrocket/tilex on GitHub, and clone your fork into your apps folder. Per the instructions, we will also need to run mix deps.get, mix ecto.setup, and npm install --prefix assets.

Since our fork of Tilex has its own repo, we will want to create a submodule to link it with our main app. This ensures that when we commit to our repo (and push our code to production), our Tilex fork is included.

To create the submodule, enter the below command in your terminal, at the root directory, replacing <url> with your Tilex fork git url. To avoid any complications, use the https version of the URL and make sure your Tilex fork is not a private repo.

Type this in your terminal

If you have already committed your code, you may get an error stating ‘apps/tilex’ already exists in the index. This happens because our repo already has a reference to apps/tilex. You can remove this reference with git rm --cached apps/tilex. If you run git submodule add <url> apps/tilex again, it will add your submodule.

This will create a .gitmodules file that links the two git repos. If you visit your git repo after the next time you commit your code and look inside the apps folder, you should see a directory name similar to tilex @4e6c8dc. That is your link from your main repo to your Tilex repo.

We need a mix.exs and a config/config.exs in our root directory so let’s add those. You can replace Umbrella with whatever name you would like it to have.

mix.exs
config/config.exs

Since this is an umbrella app, we need to have our main app and Tilex share the same build, config, and lock files. To do this, we will add the following four lines to apps/your_app/mix.exs and apps/tilex/mix.exs.

We will add it to the end of the project function at the top of the file. It will look like the below code once we have added it. Be sure to add it to the mix.exs for both your main app and Tilex.

apps/tilex/mix.exs

At this point, you will want to run mix deps.get which will fetch our dependencies and generate the mix.lock file. The mix.lock and deps directory in our root is a combination of all the dependencies from our main app and Tilex.

Since we will be running two apps at the same time, we need to ensure they are running on separate ports in development (the til.ex plug will handle things on the production side). Change the port for Tilex in its config/dev.exs file.

apps/tilex/config/dev.exs

Runing mix phx.server, you should see both apps successfully start.

Update the Compiled Assets (1db9b05)

You can visit http://localhost:4000 to see your main app, and http://localhost:4004 to see the Tilex app. However, if you visit http://til.localhost:4000 like you would in production, you will see that none of the assets have been loaded. Why is this happening? If we view the page source, we can see the cause by looking at the URL for app.css.

Main app CSS: localhost:4000/css/app.css
Tilex app CSS: localhost:4004/css/app.css (different URL)
til subdomain: til.localhost:4000/css/app.css (same CSS URL as the main app)

As you can see, we have a naming conflict. When we visit Tilex on the til subdomain, it is forced to use the main app’s CSS.

To get the correct assets for Tilex, we simply have to rename all occurrences of app.css and app.js to tilex.css and tilex.js. This will need to be done in Tilex’s brunch-config.js and in Tilex’s app.html.eex.

apps/tilex/assets/brunch-config.js
apps/tilex/lib/tilex_web/templates/layout/app.html.eex

You can also make similar changes to your main app if you would like. If you fire up the server again you will see everything looks and behaves as it should!

Environment Variables (a1de2a3)

If you already have an .env file, you will need to update it with the below information. Otherwise, create one in your root directory.

.env

You will need to set up your application with Google. If you have never done it before, there is a walkthrough with pictures in my Catcasts tutorial. For the redirect URIs, you will not be able to set one up for http://til.localhost:4004 per Google’s rules. You will want the following two redirect URIs.

You will use http://localhost:4004/admin in development to sign in. For production you will use https://til.yourdomain.com/admin.

After you have added your Google keys, run source .env in your terminal, start your server, and you should be able to visit http://localhost:4004/admin to sign in with Google. However, you will see an error telling you your email is not a valid email address.

Inside Tilex’s auth_controller, we will edit the authenticate function to remedy this. Line 5 of the gist is where we update the domain.

apps/tilex/lib/tilex_web/controllers/auth_controller.ex

If you try signing in again, it will be successful.

Get Ready to Deploy (546fc55)

This part may vary depending on your deployment strategy. I deploy to Heroku so steps you need to take may be different. First up, we need a phoenix_static_buildpack.config in our root directory.

Be sure to replace your_app with your main app’s name

Next, we need an elixir_buildpack.config which also goes in our root directory.

In the previous section, we set up our environment variables for our local machine. We also need to set them up for our deployed application. You can find the instructions for Heroku here. An example would be typingheroku config:set GOOGLE_CLIENT_ID=your_google_id in your terminal to set your GOOGLE_CLIENT_ID variable. Do this for each of your environment variables.

We now need to update the prod.exs for the Tilex app. This may vary for how you deploy. For Heroku, we will copy the config :your_app, YourAppWeb.Endpoint section from the top of our main app and use it in the Tilex app.

Copy this part from apps/your_app/config/prod.exs:

apps/your_app/config/prod.exs

And replace this part in apps/tilex/config/prod.exs:

apps/tilex/config/prod.exs

Be sure to change the two parts referencing your_app and YourApp. The first two will be replaced with tilex and Tilex respectively and the last with your Heroku URL. The first config :tilex, TilexWeb.Endpoint section from the Tilex prod.exs should now look like this:

apps/tilex/config/prod.exs

After pushing your code to Heroku, run heroku run “POOL_SIZE=2 mix ecto.migrate” in the command line to run Tilex’s migrations.

That is it we are done! We now have a working umbrella app deployed!

Run Our Tests (b922f2d)

The Tilex app has its own test suite. Now that we have successfully integrated Tilex, let’s run our tests to make sure everything is passing. We can run all of our tests for both apps from the root directory.

Here is our first error. You may not have this error depending on how Postgres is setup on your local machine. To fix it, we will go into Tilex’s test.exs and update the username.

apps/tilex/config/test.exs

The default username for Postgres is the same as your login name for your computer. For me, that means changing the above line to thebrianemory. Running our tests again we see two failing tests.

This should not come as a surprise to us. The tests are failing because they are unable to sign in with a hashrocket.com email address. This is a result of our earlier change to the domain in the auth_controller.

To fix this, we will need to edit tests in auth_controller_test to use our domain. Everywhere you see hashrocket.com, change it to your_domain.com. This is the same domain you used earlier and the one that matches your Google sign in email.

Running our tests again we see they are all passing!

Customize Tilex

There are several places in the code that reference Hashrocket as a URL, an email address, or Twitter handle. You can search for hashrocket.com and find all the references you may want to change.

You can also customize the CSS, Twitter cards, and anything else that strikes your fancy. The Twitter cards are located in apps/tilex/assets/static/assets. You can use Twitter’s Card Validator to validate the cards you create.

Hope this helps! Let me know if you have any trouble. Most likely any problem you come across I saw while trying to implement this myself. 😀

Follow me on Twitter @thebrianemory. Follow me here, click the hands below to show some appreciation, leave a comment, and get in touch!

--

--

Brian Emory
Brian Emory | Web Developer

Backend Software Engineer (Ruby/Elixir). Giraffe-like qualities. I enjoy video games, bad movies, hard ciders, and pizza.