Skip to content

Instantly share code, notes, and snippets.

@thomasjwebb
Last active January 3, 2024 19:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thomasjwebb/f94c00484c91dbbd7d961eb244e7db7b to your computer and use it in GitHub Desktop.
Save thomasjwebb/f94c00484c91dbbd7d961eb244e7db7b to your computer and use it in GitHub Desktop.

Jekyll with Faircamp

This is not an ideal setup. What would be better is to add some faircamp features and templates to jekyll and/or add more jekyll sorts of features like arbitrary pages and blogging to faircamp. Preferrably both so that people can have options. I'd be willing to assist with either as I'm familiar with both ruby and rust. I also have a separate music social media thing I'm working on. Anyway, I digress! Here is the basic, crude way I made jekyll and faircamp sorta work together so that I can have extra pages but use faircamp's generated output as the main template in jekyll for other pages.

Firstly, faircamp's output uses relative paths. That's a simple, logical way to make the generated output work whether it's in a subdirectory or at the root, but it also means that the paths have to be different for different pages, meaning its generated output can't work as a template. So what I do is run faircamp first to generate its output, then I run this script to take that as an input and generate a default template:

require 'nokogiri'

input = File.open('faircamp_output/index.html').read
template = Nokogiri.HTML5(input)
template.at('title').content = '{{ page.title }}'

def doesnt_need_modification?(val)
    return /^(\w+:\/\/|#|\/)/.match? val
end

template.xpath('//@href|//@src').each do |n|
    if n.value == './'
        n.value = '/'
        next
    end
    next if doesnt_need_modification? n.value
    n.value = '/' + n.value
end

template.xpath('//@srcset').each do |n|
    n.value = n.value.split(',').map do |src|
        filen, size = src.split
        if doesnt_need_modification? filen
            filen
        else
            "/#{filen} #{size}"
        end
    end.join(',')
end

output = template.to_html
File.open('_layouts/default.html', 'w') do |file|
    file.write(output)
end

I also have a special rule in there because it tries to link to faircamp's subdirectory instead of root and I want it to link to index ("/"). Note that I'm rewriting assuming that faircamp is not in a subdirectory but sits alongside all jekyll-generated pages. This could be easily modified to accomodate that.

Note that I made the choice to use index to make the template so that links to the releases show up on every page. This script could easily be modified to make multiple templates from the different pages so that you have a choice for your jekyll pages.

I then copy faircamp's generated output into a directory, then copy jekyll's, allowing it to overwrite index.html and then serve from that generated directory for development or deploy from there. I don't have hot-reloading or anything like that, but it doesn't appear that works for faircamp either (at least for me, I usually have to ctrl+c and re-run faircamp --preview after I change files).

Make sure to add directories you don't want jekyll copying into its output to excludes in _config.yml. In my case, I put the catalog for faircamp in faircamp_catalog and its output into faircamp_output and use jekyll_output as jekyll's output and dist as where I put everything together. So that part of my _config.yml looks like this:

exclude:
  - dist
  - jekyll_output
  - faircamp_catalog
  - faircamp_output

Obviously those dirs should also be in your .gitignore. I also made sure to track the original .flac files and any other heavy files in the catalog with git-lfs.

I then make this as a script (./scripts/build.sh) that I run:

faircamp --catalog-dir faircamp_catalog --build-dir faircamp_output
bundle exec ruby ./scripts/doctor_template.rb
bundle exec jekyll build --destination jekyll_output
rm -rf dist && mkdir dist
cp -r faircamp_output/* dist/ && cp -r jekyll_output/* dist/

Also to easily do local testing, I made this script that serves from the dist directory:

require 'webrick'

port = 8000
root = File.expand_path './dist/'
server = WEBrick::HTTPServer.new :Port => port, :DocumentRoot => root

trap 'INT' do server.shutdown end

puts "Serving at http://localhost:#{port}"

server.start

Anyway, let's enhance jekyll and/or faircamp so that this whole gist becomes unnecessary! Or at least turn it into a jekyll plugin. If there's interest in that, I can polish this and turn it into a gem.

Example

I use this to generate my old band's website and will do this for at least one more website soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment