Let's see what it takes to set up a Gatsby blog inside a Phoenix app!

Like Jekyll, VuePress and other popular static site generators, Gatsby is a easy way to create a snappy blog. Since it generates plain HTML, CSS and JS (aka "a static site"), all that's really needed is to drop the files in a directory that serves static contents.

By default, Phoenix includes a directory for serving static assets at /assets/static . Any files and subdirectories named in the only: key of Plug.Static inside your endpoint.ex file will be loaded from this static assets directory instead of being delegated to your router.

Initial Setup

Make sure you've installed Node, Elixir and Phoenix

Install the Gatsby CLI: npm install -g gatsby-cli

Create a new Phoenix app: mix phx.new my_app

Go into the newly created directory: cd my_app

Generate the DB: mix ecto.setup

Go into the assets directory (of your new app): cd assets

Create a Gatsby site inside assets : gatsby new gatsby https://github.com/gatsbyjs/gatsby-starter-hello-world

Verify the installations were successful

At this point, you should be able to start your Phoenix app by running mix phx.server from the base of your project, the my_app directory and opening localhost:4000 in your web browser.

The static site generated by Gatsby can be run in development mode by running gatsby develop from my_app/assets/gatsby and then opening localhost:8000 . It's just a "Hello world!" for now.

We named the site "gatsby" in the previous section so that it's clear, from the context of the enclosing Phoenix project, that this is a Gatsby site.

Generate the static site

In order to run the static site in production, we'll want to build a production bundle. The command to do it is gatsby build . By default this will build the site under a directory called "public", which in our case will be at my_app/assets/gatsby/public .

This isn't ideal.

We need to serve the output of the Gatsby build from our Phoenix static assets directory, but don't want to serve our Gatsby project's src or other directories publicly. There is an --output-dir flag that can be passed to the gatsby build command, but at the time of this writing, it's not possible to pass an output directory outside the Gatsby project, only the name of the directory is configurable.

Create a symlink

One way to get around this issue is to create a symlink from Gatsby's output directory to the static assets directory. First cd into the /my_app/assets/static directory, and then...

On Unix or Mac:

ln -s ../gatsby/public blog

On Windows:

mklink ..\gatsby\public blog

Now, the entire contents of whatever is generated in Gatsby's public output directory will be visible as a "blog" directory under the Phoenix static assets directory.

Enable the blog directory

The final step is to open up endpoint.ex and update the Plug.Static portion near the top to allow it to handle the newly created blog directory (which is a symbolic link of the Gatsby public directory). It should look like this:

defmodule MyAppWeb.Endpoint do use Phoenix.Endpoint, otp_app: :demo socket "/socket", MyAppWeb.UserSocket, websocket: true, longpoll: false plug Plug.Static.IndexHtml, at: "/blog" plug Plug.Static, at: "/", from: :demo, gzip: false, only: ~w(blog css fonts images js favicon.ico robots.txt) # The rest of the file

After saving these changes, and restarting the Phoenix app, the generated Gatsby site is served from within the Phoenix app at localhost:4000/blog/index.html .

Possible next steps

Now that everything is up and working, You could just build out the web app and static blog. For many apps and sites, no further integration is necessary.

Here are some ideas, though...