Jekyll From Zero to Production (Minima‑first)

Layers 1–4: Core mechanics → structure → navigation → production hardening
DataInsideData.com build notes (project-ready, workshop-friendly)

Intent: This document captures the exact, repeatable process used to build DataInsideData.com on Minima, with safe overrides and production hygiene, while staying teachable and migration-friendly for a future move to Minimal Mistakes.


Executive summary (what you get by following this)

By the end of Layer 4 you’ll have:

  • A clean local dev loop that matches production styling
  • Clear information architecture (header nav + footer utilities)
  • Safe, minimal theme overrides (footer/head + custom CSS)
  • SEO + discovery endpoints: /sitemap.xml, /feed.xml, /robots.txt
  • Pagination that scales (and won’t surprise you later)
  • A branch/PR workflow that integrates with your private→public deploy pipeline (If you chose to go in that direction.)

Layer 1 — Core Jekyll mechanics

What Jekyll is

Jekyll is a static site generator. It compiles content into static assets:

  • HTML
  • CSS
  • JavaScript
  • XML (feed/sitemap)

There is no runtime database or request-time backend. Hosting becomes simple: serve static files.

The local build loop

bundle install           # only when Gemfile changes
bundle exec jekyll serve # execute build

What jekyll serve does:

  • Builds the site into _site/
  • Starts a local server (typically http://localhost:4000)
  • Watches for file changes and rebuilds automatically

Important: changing _config.yml requires a restart. That’s expected.

Front matter (why it exists)

Front matter connects content to structure. Without it, Jekyll may treat a file as a raw asset and skip layout/Liquid processing.

Example listing page:

---
layout: home
title: Posts
permalink: /blog/
---

Layer 2 — Structure, layouts, defaults, and “theme resolution”

Rendering hierarchy (critical concept)

Jekyll resolves files in this order:

  1. Your repo (site source)
  2. Theme gem (Minima)
  3. Fallback behavior

If you create a file in your repo with the same path + filename as a theme file, your version wins automatically.

Why _includes, _layouts, _sass may be “missing”

When using a gem theme, those directories live inside the theme gem. You only create them when you need an override.

This keeps your repo:

  • smaller
  • cleaner
  • upgrade-safe

Defaults in _config.yml (remove repetition)

Use defaults to prevent repeated front matter across many files:

defaults:
  - scope:
      path: ""
      type: posts
    values:
      layout: post

  - scope:
      path: ""
      type: pages
    values:
      layout: page

Benefit: less copy/paste, fewer mistakes, easier scaling.


Layer 3 — Pages, home vs blog, navigation

One canonical homepage

Your homepage is defined by index.md / index.markdown at /.

Example:

---
layout: home
title: ""
permalink: /
---

Rule:

One homepage. Avoid creating multiple pages that compete for /.

Blog index page

Create a dedicated post listing page at /blog/:

---
layout: home
title: Posts
list_title: Recent & relevant
permalink: /blog/
---

Header navigation is controlled explicitly with header_pages:

header_pages:
  - start-here.markdown
  - blog.markdown
  - projects/projects.markdown
  - about.markdown
  - contact/contact.markdown

Notes:

  • In Minima, the site title links to / (so a separate “Home” item is optional).
  • Keep the header lean and move “utility links” into the footer.

First override introduced:

_includes/footer.html

Why footer is a safe first override:

  • low coupling
  • easy to test visually
  • minimal risk during upgrades

Rule of thumb:

Override edges (footer/meta) before the spine (header/layouts).


Layer 4 — Business + production hardening (Minima → future‑proof)

4.0 Goals

Layer 4 makes the site:

  • business-friendly (clear nav + legal links)
  • production-friendly (SEO, sitemap, robots)
  • maintainable (minimal overrides)
  • upgrade-friendly (future Minimal Mistakes)

4.1 Information architecture

Header nav (primary actions)

Keep header nav lean:

  • Posts
  • Projects
  • About
  • Contact

Move these to footer:

  • Archive
  • Sitemap
  • RSS
  • Privacy Policy
  • Terms of Use

Why:

  • archive/sitemap/RSS are secondary
  • legal links belong in the footer on most professional sites

4.2 Plugins (SEO + discovery)

Enable:

plugins:
  - jekyll-feed
  - jekyll-seo-tag
  - jekyll-sitemap

What they do:

  • jekyll-feed/feed.xml
  • jekyll-seo-tag → consistent SEO/meta via % seo %
  • jekyll-sitemap/sitemap.xml

4.3 Excerpts + listing pages

Show excerpts on listing pages:

minima:
  show_excerpts: true

Then add per-post front matter excerpts:

excerpt: "One sentence that sells the post."

Rule of thumb (DID style):

  • 1 sentence
  • clear value
  • ~120–180 characters

4.4 Pagination (scales when content grows)

Config:

paginate: 5
paginate_path: "/blog/page:num/"

Pagination typically requires jekyll-paginate.

Gemfile

gem "jekyll-paginate"

_config.ym

plugins:
  - jekyll-paginate

4.5 Safe head + custom CSS strategy

Override:

_includes/head.html

and load custom CSS after Minima’s main.css:

<link rel="stylesheet" href="/assets/main.css">
<link rel="stylesheet" href="/assets/css/custom.css">

Custom CSS file:

assets/css/custom.css

Principle:

Don’t fork the theme. Layer over it.

4.6 robots.txt + verifications

Add robots.txt at repo root:

User-agent: *
Allow: /

Sitemap: https://datainsidedata.com/sitemap.xml

Verify locally:

  • /sitemap.xml
  • /feed.xml
  • /robots.txt

4.7 URL stability: renames + redirects

If you rename a post after it’s been generated or shared, use redirect_from:

redirect_from:
  - /blog/2026/01/11/old-slug.html
  - /2026/01/11/old-slug.html

Optional: add jekyll-redirect-from for safer refactors:

plugins:
  - jekyll-redirect-from

To make all post URLs consistently live under /blog/, add:

permalink: /blog/:year/:month/:day/:title:output_ext

This reduces accidental 404s and keeps URLs predictable.


Repo “Flex” plan: branch/PR workflow with deploy confidence

What you’re protecting

  • Private repo: source of truth (Jekyll source)
  • Public repo: compiled output only
  • GitHub Actions builds private → pushes into public → Pages serves from gh-pages

Safe PR workflow

  1. Create a branch: feat/* or chore/*
  2. Commit small, logical changes
  3. Open PR (describe what/why + local test notes)
  4. Merge to main
  5. CI builds + deploys automatically

Pre-merge checklist

  • bundle exec jekyll clean && bundle exec jekyll serve
  • verify:
    • / home works
    • /blog/ and /blog/page2/ (if applicable)
    • /archive/
    • /sitemap.xml, /feed.xml, /robots.txt

Diagrams you can paste into draw.io

Diagram A — Build + deploy flow (copy/paste text diagram)

Paste into a draw.io text box and convert into shapes manually:

[Private Repo: datainsidedata-website]
   |  (PR merge to main)
   v
[GitHub Actions: build Jekyll]
   |
   v
[Build Artifact: _site/]
   |
   v
[Public Repo: did-site-public (gh-pages branch)]
   |
   v
[GitHub Pages + CNAME: datainsidedata.com]

Diagram B — Theme override resolution (copy/paste)

Request for: _includes/footer.html
   |
   v
Check your repo first:
  if exists: use YOUR file
  else: use THEME file (minima gem)

Diagram C — Mermaid (use as a reference for draw.io)

flowchart LR
  A[Private Repo: datainsidedata-website] --> B[GitHub Actions Build]
  B --> C[_site/ build artifact]
  C --> D[Public Repo: did-site-public (gh-pages)]
  D --> E[GitHub Pages + CNAME]
  E --> F[datainsidedata.com]

  subgraph RES["Theme resolution rule"]
    R1[Your repo files] --> R2[Theme gem files] --> R3[Fallback]
  end

Reusable project template (for future projects)

Create one file per project under _projects/.

---
layout: page
title: "Project Name"
status: "Active | Paused | Archived"
tags: [architecture, devops, security]
---

## Overview

What this is and why it exists.

## Architecture

Key components and data flow.

## Security + privacy

Threat model, secrets handling, least privilege.

## CI/CD

Branching strategy, automation, deploy pipeline.

## Lessons learned

What broke, what you fixed, what you’d do differently.