How to: Generate Rails-Compatible html.erb with Hugo
Here’s how this site is currently generated:
This works really great but, thing is, I’ve been experimenting with Rails and I discovered a feature I gotta have: split, the hacker-friendly A/B framework. Flexible content experiments? Drop in your own algorithms?
I need it.
Except running an experiment in split requires embedding code in a page’s view, you know, dynamically, and all this Hugo output is static. What to do?
Turns out, we can teach Hugo to generate Rails compatible html.erb
templates. All we gotta do is define a custom output format for html.erb
and
Hugo will turn .md
files into that, too.
The new pipeline will be like this:
Configuring Hugo to generate html.erb
Here’s what my initial data looked like–
rps@neptune ~/s/rs.io-next> tree content
content
├── email
│ ├── credit-cards.md
│ ├── finding-info.md
│ ├── health-tip.md
│ ├── lies.md
│ ├── reboot.md
│ └── welcome.md
└── posts
├── about.md
├── book.md
├── cuda-r-keras-nixos.md
├── pepe-data.md
├── rails-static-hugo.md
├── rare-pepes.md
└── start-here.md
2 directories, 13 files
Here’s what I’ve added to my config.toml
:
uglyURLs = true
[mediaTypes]
[mediaTypes."text/x-html-erb"]
suffixes = ["html.erb"]
[outputFormats]
[outputFormats.HTML]
noUgly = true
[outputFormats.ERB]
mediaType = "text/x-html-erb"
isHTML = true
path = "hugo"
[outputs]
page = ["HTML", "ERB"]
The uglyURLs
code is necessary so that we don’t generate a bunch of
filename/index.html.erb
when what we want is filename.html.erb
to copy into
Rails.
The path = "hugo"
line sets it so that our erb files will be saved to public/hugo
and not mixed in with everything else.
Next you’ll need to create html.erb
versions of some of the templates in
your theme directory.
$ ls themes/hyde/layouts/_default/*html.erb
themes/hyde/layouts/_default/baseof.html.erb
themes/hyde/layouts/_default/list.html.erb
themes/hyde/layouts/_default/single.html.erb
These are what I needed; they’re exact copies of the .html
versions. Hugo will
use these templates to generate html.erb
files. Eventually you’ll probably
wish to modify them to not add Hugo’s header / footer / etc code, that way you
can have Rails manage that for you.
Now it should work. If yours isn’t, I found this tutorial on building a custom output format for Gopher useful in figuring out how they work.
It lives, it lives!
rps@neptune ~/s/rs.io-next> hugo
| EN
+------------------+-----+
Pages | 27
Paginator pages | 0
Non-page files | 0
Static files | 580
Processed images | 0
Aliases | 1
Sitemaps | 1
Cleaned | 0
Total in 99 ms
Here is what public/hugo
looks like now–
rps@neptune ~/s/rs.io-next> tree public/hugo
public/hugo
├── email
│ ├── credit-cards.html.erb
│ ├── finding-info.html.erb
│ ├── health-tip.html.erb
│ ├── lies.html.erb
│ ├── reboot.html.erb
│ └── welcome.html.erb
└── posts
├── book.html.erb
└── cuda-r-keras-nixos.html.erb
2 directories, 8 files
Look at all those sweet, sweet erb files!
Now, in your Rails app, create the folder app/views/pages
and cp -r public/hugo/*
to it, looking something like–
/home/rps/src/rs.io-rails/app/views/
├── layouts
│ ├── application.html.erb
│ ├── mailer.html.erb
│ └── mailer.text.erb
└── pages
├── email
│ ├── credit-cards.html.erb
│ ├── finding-info.html.erb
│ ├── health-tip.html.erb
│ ├── lies.html.erb
│ ├── reboot.html.erb
│ └── welcome.html.erb
└── posts
├── book.html.erb
└── cuda-r-keras-nixos.html.erb
4 directories, 11 files
Then, to your Gemfile add high_voltage
. It generates static pages and will
manage the copied html.erb
files for us. You’ll need to create the
initializer, too.
# config/initializers/high_voltage.rb
HighVoltage.configure do |config|
config.route_drawer = HighVoltage::RouteDrawers::Root
end
Without it, all the erb files imported from Hugo will be at
http://localhost:3000/pages/<filename>
. The above removes /pages/
from the
URL, otherwise your links will likely to be off in your Hugo-gen’d .erb
.
Rails should now be serving your Hugo imports. For example
app/views/pages/posts/cuda-r-keras-nixos.html.erb
will be at
http://localhost:3000/posts/cuda-r-keras-nixos
.
Tidying up
Once you’ve got it working, you’re going to want to go back and remove
public/hugo
and replace it with a symbolic link to app/views/pages
so that
Rails’ folder is automatically updated whenever you trigger a regen with Hugo,
i.e.
ln -s /home/rps/src/rs.io-rails/app/views/pages/ /home/rps/src/rs.io-next/public/hugo
You’ll also want to move and link the static assets from your $HUGO_APP/public
folder into
$RAILS_APP/public
.
$ mv $HUGO_APP/public/css $RAILS_APP/public/
$ ln -s $RAILS_APP/public/css $HUGO_APP/public/css
Rinse & repeat for the other static folders.