Trouble with link_to and relative links (for gh-pages)

Hello-

I’m trying to publish a middleman site to Github Pages (specifically, the pages branch of a project repo), but I’m having difficulty getting the site to build links relative to a subdirectory (gh-pages requires your path to include /repo-name/ at the beginning of all links).

This is my first time working with Middleman. I’m coming from the Jekyll world, so I’ll try to explain what I’m attempting in Jekyll terminology.

In Jekyll you can define a variable called baseurl in your config, which allows you to specify what path (if any) should come before your links when the site builds. As long as links in templates are written in the format of {{site.baseurl}}{{page.url}} things work fine. You’d set baseurl to your repo name for a standard GH-Pages workflow, but you could just change it to / if you were going to publish the site to the root folder of a server instead. Best of all, the development server would respect baseurl too, so you could view your site at localhost:4000/repo-name without things breaking.

I’m trying to essentially do the same things in Middleman, but I’m having trouble figuring out how to make this happen.

In my templates, I’m using link_to helpers and asset tags. In config.rb I have the following set globally:

activate :directory_indexes
set :relative_links, true

And for the :build environment, I have the following:

configure :build do
  # Relative assets needed to deploy to Github Pages
  activate :relative_assets
end

When I build the site, the asset tags for CSS and JS output relative links as expected. But my link_to links in the navigation are still coming out as absolute paths.

I’m expecting this in haml:

=link_to "Introduction", "/frontmatter/introduction"

to become something like:

<a href="../../../frontmatter/introduction">Introduction</a>

on an interior page. (I’m also using directory indexes if that makes any difference).

But instead the links I’ve created with link_to helpers all remain in this format:

<a href="/frontmatter/introduction">Introduction</a>

Am I doing something wrong? Alternatively, is there a way in Middleman to set something equivalent to a baseurl variable that I prepend my links with?

Thanks and apologies for the long post!

Update: I managed to get this working by using a method similar to what I would do in a Jekyll site.
The basic idea is to allow the environment to set the value of a :site_url variable.

Config.rb

Here are the relevant parts of my config.rb:

# Global site settings (not shown here)
set :site_url, ""
# ...

configure :build do
  # Relative assets needed to deploy to Github Pages
  activate :relative_assets
  set :site_url, "/repo-name"
end

So the variable always exists, but in dev mode the value is an empty string. If you are deploying to a GH-Pages project site, add repo name with a leading slash as shown. Or whatever else needs to prepend your URLs depending on where you are planning to publish.

Templates

I use the link_to helpers and varous asset tags in templates. But to get this working, pass the following arguments to them:

=link_to "Introduction", "#{site_url}/frontmatter/introduction"

In stylesheets, you can call image_path for the same effect:

background-image: url(#{image_path(object.cat)}.jpg)

So, this is the same trick as writing {{site.baseurl}}/{{post.url}} in a Jekyll site. There is probably some better way to do this, but that’s the best I’ve been able to come up with so far. Everything works when deploying to GH-Pages.

Hopefully this will help someone who runs into similar problems in the future.

1 Like

I actually worked few weeks ago on a Middleman (v4 - latest master) template and had the same issue.

Your friend is:

set :http_prefix, '/repo-name'

This should be set in the :build environment. Then, just use these path helpers like link_to and everything will work.

There is also a helper for your css:

.intro-heading {
  background: transparent url(image-path("header.jpg")) no-repeat scroll center center / cover;
}

Find the entire template here: https://github.com/beta-europe/meu-strasbourg/tree/master
Find the config.rb here: https://github.com/beta-europe/meu-strasbourg/blob/master/config.rb

Best,
Robert

1 Like

this is my config file

activate :autoprefixer

set :css_dir, "assets/css"
set :js_dir, "assets/js"
set :images_dir, "assets/images"
set :fonts_dir, "assets/fonts"
set :layout, "layouts/application"


page '/*.xml', layout: false
page '/*.json', layout: false
page '/*.txt', layout: false

configure :development do
   activate :livereload
end

configure :build do
  activate :relative_assets
  set :relative_links, true
  activate :minify_css
  activate :minify_javascript
end

but the relative links is not working there is no forward slash at the beginning of css and js links

<script src="assets/js/application.js"></script>

rather than

<script src="/assets/js/application.js"></script>

any ideas?