Running a Gatsby blog inside a Phoenix app
Mark
Posted on October 7, 2019
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...
See if you can write a simple plug that will read the path from
conn.request_path
and redirect/blog/
to/blog.index.html
. Or alternatively, you could look at a libraryplug_static_index_html
and see if you can use it to handle this for you.Try installing Absinthe GraphQL and serving your static Gatsby blog GraphQL from the Phoenix back-end. This is a fairly large endeavor, but it's a great learning experience!
Request a free email-based Elixir course from Alchemist.Camp
Posted on October 7, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.