Jekyll Theme Setup and Customization

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.
Development and maintenance of all types of websites:
Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:
Development stages
Latest works
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    822
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    847
  • image_website-sbh_0.png
    Website development for SBH Partners
    999
  • image_website-_0.png
    Website development for Red Pear
    451

Jekyll Theme Setup and Customization

Jekyll themes are distributed in two ways: as gem packages (installed via Bundler) and as regular repositories (copied directly). The customization mechanism differs, but the override principle is the same: files in the project root override theme files.

Gem-based themes: how they work

When a theme is installed as a gem, its files are located in the Ruby gems directory, not in the project:

bundle info --path minima
# => /path/to/gems/minima-2.5.1

To view theme files:

bundle exec jekyll theme-files

To override: copy the needed file from the gem to the project root, preserving folder structure:

# Copy the theme layout to the project
cp $(bundle info --path minima)/_layouts/post.html _layouts/post.html

# Copy a partial
cp $(bundle info --path minima)/_includes/header.html _includes/header.html

After this, edit the copied file — Jekyll will automatically use it instead of the original.

Configuration through _config.yml

Most themes read parameters from the config. Example for the popular Minimal Mistakes theme:

# Theme
remote_theme: "mmistakes/[email protected]"

# Theme skin
minimal_mistakes_skin: "air" # "default", "air", "aqua", "contrast", "dark", "dirt", "neon", "mint", "plum", "sunrise"

# Site parameters
locale: "en-US"
title: "Site Title"
name: "Team"
description: "Description"
url: "https://example.com"

# Default author
author:
  name: "Name"
  avatar: "/assets/images/avatar.jpg"
  bio: "Brief description"
  links:
    - label: "Email"
      icon: "fas fa-fw fa-envelope-square"
      url: "mailto:[email protected]"
    - label: "LinkedIn"
      icon: "fab fa-fw fa-linkedin"
      url: "https://linkedin.com/in/username"

# Navigation
navigation:
  - title: "Home"
    url: /
  - title: "Blog"
    url: /blog/
  - title: "About"
    url: /about/

# Analytics
analytics:
  provider: "google-gtag"
  google:
    tracking_id: "G-XXXXXXXXXX"
    anonymize_ip: false

# Comments
comments:
  provider: "disqus"
  disqus:
    shortname: "mysite"

Style customization

Gem themes usually allow adding custom styles through a special file. For Minima:

/* assets/css/style.scss */
---
---
@import "minima";

/* Your overrides */
:root {
  --base-font-size: 16px;
  --base-line-height: 1.7;
  --brand-color: #2563eb;
  --brand-color-dark: #1e40af;
}

.site-header {
  border-top: 4px solid var(--brand-color);
  background: #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,0.08);
}

.post-title {
  font-size: 2.25rem;
  line-height: 1.2;
  letter-spacing: -0.02em;
}

For Minimal Mistakes — through _sass/minimal-mistakes/_variables.scss (need to copy from gem):

/* _sass/minimal-mistakes/_variables.scss */
$sans-serif: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif !default;
$monospace: "JetBrains Mono", "Fira Code", monospace !default;

$primary-color: #2563eb !default;
$success-color: #22c55e !default;
$warning-color: #f59e0b !default;
$danger-color: #ef4444 !default;

$border-radius: 6px !default;
$box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1) !default;

Liquid template overrides

Example: add a table of contents (TOC) to a post layout:

<!-- _layouts/post.html -->
---
layout: default
---
<article class="post h-entry">
  <header class="post-header">
    <h1 class="post-title p-name">{{ page.title | escape }}</h1>
    <p class="post-meta">
      <time class="dt-published" datetime="{{ page.date | date_to_xmlschema }}">
        {{ page.date | date: "%d %B %Y" }}
      </time>
      {% if page.author %}· {{ page.author }}{% endif %}
    </p>
  </header>

  {% if page.toc %}
  <aside class="toc">
    <h2>Contents</h2>
    {% include toc.html html=content %}
  </aside>
  {% endif %}

  <div class="post-content e-content">
    {{ content }}
  </div>

  {% if page.tags.size > 0 %}
  <div class="post-tags">
    {% for tag in page.tags %}
    <a href="/tags/{{ tag | slugify }}/" class="tag">#{{ tag }}</a>
    {% endfor %}
  </div>
  {% endif %}
</article>

Adding custom partials

If a theme doesn't provide a needed component, create it in _includes/:

<!-- _includes/cta-banner.html -->
{% assign bg = include.bg | default: "primary" %}
{% assign title = include.title %}
{% assign subtitle = include.subtitle %}
{% assign button_text = include.button_text | default: "Learn more" %}
{% assign button_url = include.button_url | default: "/contact/" %}

<section class="cta-banner cta-banner--{{ bg }}">
  <div class="container">
    <h2>{{ title }}</h2>
    {% if subtitle %}
    <p>{{ subtitle }}</p>
    {% endif %}
    <a href="{{ button_url }}" class="btn btn--primary">{{ button_text }}</a>
  </div>
</section>

Usage on a page or layout:

{% include cta-banner.html
  title="Ready to start a project?"
  subtitle="Let's discuss your goals and find a solution"
  button_text="Get in touch"
  button_url="/contact/"
  bg="dark"
%}

Navigation management

For complex menus — through _data/navigation.yml:

main:
  - title: "Services"
    url: /services/
    children:
      - title: "Web development"
        url: /services/web/
      - title: "Mobile apps"
        url: /services/mobile/
  - title: "Blog"
    url: /blog/
  - title: "Contact"
    url: /contact/
<!-- _includes/header.html -->
<nav>
  {% for item in site.data.navigation.main %}
  <div class="nav-item {% if item.children %}has-dropdown{% endif %}">
    <a href="{{ item.url | relative_url }}"
       {% if page.url == item.url %}aria-current="page"{% endif %}>
      {{ item.title }}
    </a>
    {% if item.children %}
    <ul class="dropdown">
      {% for child in item.children %}
      <li><a href="{{ child.url | relative_url }}">{{ child.title }}</a></li>
      {% endfor %}
    </ul>
    {% endif %}
  </div>
  {% endfor %}
</nav>

Timeline

Configuring a gem theme through config and custom CSS — 1–2 days. Overriding templates, adding custom partials and data — 3–5 days.