This repository hosts the source code as well as the compiled webpage of the official Jekyll step by step tutorial.
This README.md file show all the necessary steps and commands to install Ruby, a Ruby package manager, a Ruby bundler gem, Jekyll and everything else that is needed to build a website with Jekyll.
Jekyll is a simple, blog-aware, static site generator perfect for personal, project, or organization sites. Think of it like a file-based CMS, without all the complexity. Jekyll takes your content, renders Markdown and Liquid templates, and spits out a complete, static website ready to be served by Apache, Nginx or another web server. Jekyll is the engine behind GitHub Pages, which you can use to host sites right from your GitHub repositories.
$ sudo apt install autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm5 libgdbm-dev
Not used if you always use rbenv to install gems.
$ echo '# Install Ruby Gems to ~/gems' >> ~/.bashrc
$ echo 'export GEM_HOME="$HOME/gems"' >> ~/.bashrc
$ echo 'export PATH="$HOME/gems/bin:$PATH"' >> ~/.bashrc
$ source ~/.bashrc
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
$ vim ~/.bashrc
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc $ echo 'eval "$(rbenv init -)"' >> ~/.bashrc
$ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
$ echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
$ rbenv install -l
$ rbenv install 2.6.0
$ rbenv global 2.6.0
$ rbenv versions
#output
system (ubuntu installation, sudo apt install )
* 2.6.0 (rbenv local installation, set with $ rbenv global, gem install, bundle install, ruby build)
$ rbenv local 2.1.0
#output
applyied to a folder adds file: .ruby-version with content: 2.1.0
$ ruby -version (if not in a folder containing file .ruby-version with content 2.1.0)
#output
2.6.0 (if set with $ rbenv global)
$ ruby -version
#output
2.1.0 (if in a folder set with $ rbenv local and containing file .ruby-version with content 2.1.0)
$ gem env
$ echo "gem: --no-document" > ~/.gemrc
(Bundler is a tool that manages gem dependencies for projects).
Reads file Gemfile, file Gemfile.lock-
$ gem install bundler (installed under enabled version, global or local)
rbenv works by creating a directory of shims, which point to the files used by the Ruby version which is enabled.
$ rbenv rehash
$ gem install jekyll bundler
If we have no Gemfile we start the server as shown below. This is equivalent to $ jekyll build
&& starting server at http://localhost:4000
.
$ jekyll serve
_site
https://jekyllrb.com/docs/variables/
site.xyz , page.xyz, paginator.xyz, content, layout
You can define own custom front matter (xyz) and use them as variables.
Objects (outputs a variable called page.title, page is the document).
{{ page.title }}
Tags (flow control logic, outputs sidebar if page.sidebar is true).
{% if page.show_sidebar %}
<div class="sidebar">
sidebar content
</div>
{% endif %}
- Puts string through a filter called capitalize and outputs Hi.
{{ "hi" | capitalize }}
- yaml snippet used to set variables in Markdown/html files
- set layout configuration in Markdown/html files
---
title: Home
---
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>{{ page.title }}</title>
</head>
<body>
<h1>{{ "Hello World!" | downcase }}</h1>
</body>
</html>
_layout
- to avoid duplicate code
- usually no front matter, and a content variable
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>{{ page.title }}</title>
</head>
<body>
{{ content }}
</body>
</html>
- index.html
---
layout: default
title: Home
---
<h1>{{ "Hello World!" | downcase }}</h1>
- about.md
---
layout: default
title: About
---
# About page
This page tells you a little bit about me.
with .html even though it is an .md file:
http://localhost:4000/about.html
_includes
- allows you to include content from another file
- navigation.html
<nav>
<a href="/">Home</a>
<a href="/about.html">About</a>
</nav>
- Layout.html
<body>
{% include navigation.html %}
{{ content }}
</body>
- navigation.html
<nav>
<a href="/" {% if page.url == "/" %}style="color: red;"{% endif %}>
Home
</a>
<a href="/about.html" {% if page.url == "/about.html" %}style="color: red;"{% endif %}>
About
</a>
</nav>
_data
- store an array of navigation items each with a name and link
- _data/navigation.yml
- name: Home
link: /
- name: About
link: /about.html
- navigation.html
<nav>
{% for item in site.data.navigation %}
<a href="{{ item.link }}" {% if page.url == item.link %}style="color: red;"{% endif %}>
{{ item.name }}
</a>
{% endfor %}
</nav>
assets/css, assets/images, assets/js
- CSS, JS, images
- and more, e.g. mp3
<nav>
{% for item in site.data.navigation %}
<a href="{{ item.link }}" {% if page.url == item.link %}
class="current"{% endif %}>{{ item.name }}
</a>
{% endfor %}
</nav>
- css/styles.scss
---
---
@import "main";
empty front matter at the top tells Jekyll it needs to process the file. @import "main" tells Sass to look for a file called main.scss in the sass directory (_sass/ by default)
- _sass/main.scss
.current {
color: green;
}
- layout/default.html
<link rel="stylesheet" href="/assets/css/styles.css">
_posts
- _posts/2018-08-20-bananas.md
---
layout: post
author: jill
---
A banana is an edible fruit – botanically a berry – produced by several kinds
of large herbaceous flowering plants in the genus Musa.
In some countries, bananas used for cooking may be called "plantains",
distinguishing them from dessert bananas. The fruit is variable in size, color,
and firmness, but is usually elongated and curved, with soft flesh rich in
starch covered with a rind, which may be green, yellow, red, purple, or brown
when ripe.
author is a custom variable, it’s not required and could have been named something like creator.
- _layouts/post.html
---
layout: default
---
<h1>{{ page.title }}</h1>
<p>{{ page.date | date_to_string }} - {{ page.author }}</p>
{{ content }}
This is an example of layout inheritance. The post layout outputs the title, date, author and content body which is wrapped by the default layout.
- /blog.html (in root directory)
---
layout: default
title: Blog
---
<h1>Latest Posts</h1>
<ul>
{% for post in site.posts %}
<li>
<h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
<p>{{ post.excerpt }}</p>
</li>
{% endfor %}
</ul>
Typically a blog has a page which lists all the posts.
- post.url is automatically set by Jekyll to the output path of the post
- post.title is pulled from the post filename and can be overridden by setting title in front matter
- post.excerpt is the first paragraph of content by default
- _data/navigation.yml
- name: Blog
link: /blog.html
Like posts but content doesn't habe to be grouped by date.
/_config.yml (in root directory)
collections:
authors:
output: true
defaults:
- scope:
path: ""
type: "authors"
values:
layout: "author"
- scope:
path: ""
type: "posts"
values:
layout: "post"
- scope:
path: ""
values:
layout: "default"
All posts to automatically have the post layout, authors to have author and everything else to use the default. Now you can remove layout from the front matter of all pages and posts (but not the layouts in
_layouts
). Note that any time you update _config.yml you’ll need to restart Jekyll for the changes to take affect.
_authors
- _authors/jill.md
---
short_name: jill
name: Jill Smith
position: Chief Editor
---
Jill is an avid fruit grower based in the south of France.
- _authors/ted.md
---
short_name: ted
name: Ted Doe
position: Writer
---
Ted has been eating fruit since he was baby.
- _layouts/staff.html
Iterate over site.authors
---
layout: default
title: Staff
---
<h1>Staff</h1>
<ul>
{% for author in site.authors %}
<li>
<h2><a href="{{ author.url }}">{{ author.name }}</a></h2>
<h3>{{ author.position }}</h3>
<p>{{ author.content | markdownify }}</p>
</li>
{% endfor %}
</ul>
Since the content is markdown, you need to run it through the markdownify filter. This happens automatically when outputting using {{ content }} in a layout.
- _data/navigation.yml
-name: Staff
link: /staff.html
- _layouts/author.html
---
layout: default
---
<h1>{{ page.name }}</h1>
<h2>{{ page.position }}</h2>
{{ content }}
<h2>Posts</h2>
<ul>
{% assign filtered_posts = site.posts | where: 'author', page.short_name %}
{% for post in filtered_posts %}
<li><a href="{{ post.url }}">{{ post.title }}</a></li>
{% endfor %}
</ul>
- _layouts/post.html
---
layout: default
---
<h1>{{ page.title }}</h1>
<p>
{{ page.date | date_to_string }}
{% assign author = site.authors | where: 'short_name', page.author | first %}
{% if author %}
- <a href="{{ author.url }}">{{ author.name }}</a>
{% endif %}
</p>
{{ content }}
Get the site ready for production.
Ensures the version of Jekyll and other gems remains consistent across different environments.
/Gemfile (at the root directory)
source 'https://rubygems.org'
gem 'jekyll'
$ bundle install
Installs the gems and creates Gemfile.lock which locks the current gem versions for a future bundle install.
$ bundle info jekyll
#output:
Installed at: /home/benzro/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0
If you ever want to update your gem versions you can run.
$ bundle update
When using a Gemfile, you’ll run commands like $ jekyll serve, with bundle exec prefixed. This restricts your Ruby environment to only use gems set in your Gemfile.
$ bundle exec jekyll serve
You probably get an error message, when you run $ jekyll build or $ jekyll serve with a Gemfile.
$ bundle exec jekyll build
Create custom generated content specific to your site. many plugins available or you can write your own.
- jekyll-sitemap - Creates a sitemap file to help search engines index content
- jekyll-feed - Creates an RSS feed for your posts
- jekyll-seo-tag - Adds meta tags to help with SEO
/Gemfile
group :jekyll_plugins do
gem 'jekyll-sitemap'
gem 'jekyll-feed'
gem 'jekyll-seo-tag'
end
$ bundle update
- jekyll-sitemap doesn’t need any setup, it will create your sitemap on build.
- jekyll-feed and jekyll-seo-tag you need to add tags to
_layouts/default.html
- _layouts/default.html
{% feed_meta %}
{% seo %}
- _site/sitemap.xml
- _site/feed.xml
- added one link for jekill-fee: file feed.xml
- added many lines for: jekyy-seo-tag
Output something in production but not in development.
By using the JEKYLL_ENV environment variable, default is "development".
Running a command like bundle with global variable "JEKYLL_ENV=production", e.g.
$ JEKYLL_ENV=production bundle exec jekyll build
- my-analytics-script.js
{% if jekyll.environment == "production" %}
<script src="my-analytics-script.js"></script>
{% endif %}
This code placed anywhere in your code, will only run, if you run build in production mode.
you would do the following:
{% if jekyll.environment == "development" %}
....
{% endif %}
To switch part of your config settings depending on the environment, use the build/serve command option, for example --config _config.yml,_config_development.yml
. Settings in later files override settings in earlier files.
$ [bundle exec] jekyll (build | serve) --config _config.yml,_config_development.yml
The most basic way to do this is to run a production build.
$ JEKYLL_ENV=production bundle exec jekyll build
A better way is to automate this process using a CI or 3rd party
https://jekyllrb.com/docs/deployment/automated/
https://learn.cloudcannon.com/jekyll-cheat-sheet/