Why Use Jekyll Collections for Documentation
Jekyll collections allow you to group content beyond standard posts and pages. They’re perfect for structured documentation because you can control order, metadata, and navigation more easily. Combining this with multilingual support creates an elegant and scalable system.
Core Benefits
- Organized content structure (e.g. tutorials, changelogs, API docs)
- Supports language segmentation
- Enables dynamic TOC, related items, and search
Step 1: Define the Collection
Edit your _config.yml
to define your multilingual documentation collections:
collections:
docs:
output: true
permalink: /:collection/:path/
defaults:
- scope:
path: ""
type: docs
values:
layout: doc
lang: en
Now create folders for each language under _docs
:
_docs/
├── en/
│ ├── getting-started.md
│ └── advanced-features.md
├── id/
│ ├── mulai.md
│ └── fitur-lanjutan.md
Each file includes front matter like:
---
title: "Getting Started"
lang: en
tags: [intro, basics]
order: 1
---
Step 2: Create Language-Aware Navigation
To render dynamic navigation, filter collections by language:
{% assign current_lang = page.lang %}
{% assign localized_docs = site.docs | where: "lang", current_lang | sort: "order" %}
<nav class="toc">
<ul>
{% for doc in localized_docs %}
<li><a href="{{ doc.url }}">{{ doc.title }}</a></li>
{% endfor %}
</ul>
</nav>
Step 3: Enable Multilingual Related Content
Just like in previous articles, filter by language and shared tags:
{% assign related_docs = site.docs | where: "lang", page.lang %}
{% assign shared_tags = page.tags %}
{% assign suggestions = related_docs | where_exp: "item", "item.url != page.url and item.tags | intersection: shared_tags | size > 0" %}
Limit to 3–5 suggestions:
{% for suggestion in suggestions limit:5 %}
<li><a href="{{ suggestion.url }}">{{ suggestion.title }}</a></li>
{% endfor %}
Step 4: Integrate Search for Documentation
As before, create a multilingual index for your docs collection:
---
layout: null
permalink: /search-docs-{{ page.lang }}.json
---
[
{% assign docs = site.docs | where: "lang", page.lang %}
{% for doc in docs %}
{
"title": "{{ doc.title | escape }}",
"url": "{{ doc.url }}",
"excerpt": "{{ doc.content | strip_html | truncate: 160 | escape }}",
"tags": "{{ doc.tags | join: ', ' }}"
} {% unless forloop.last %},{% endunless %}
{% endfor %}
]
Load this into Lunr/ElasticLunr just like previous examples, but point to /search-docs-id.json
or /search-docs-en.json
.
Step 5: Add Section Anchors and Dynamic TOC
You can use JavaScript to generate a table of contents from headings within each doc:
<div id="auto-toc"></div>
<script>
const headings = document.querySelectorAll('h2, h3')
const toc = document.getElementById('auto-toc')
headings.forEach(h => {
const id = h.id || h.textContent.trim().toLowerCase().replace(/\s+/g, '-')
h.id = id
const link = document.createElement('a')
link.href = '#' + id
link.textContent = h.textContent
toc.appendChild(link)
})
</script>
Optional: Language Switcher
If you name your files similarly (e.g. getting-started.md
and mulai.md
), you can map languages manually using a YAML data file like _data/doc_links.yml
:
getting-started:
en: /docs/getting-started/
id: /docs/mulai/
Then in layout:
{% assign doc_key = page.url | split: '/' | last %}
{% assign map = site.data.doc_links[doc_key] %}
{% if map %}
<a href="{{ map.id }}">Bahasa Indonesia</a>
{% endif %}
Real Use Case: Building a Knowledge Base
Let’s say you run a multilingual SaaS product with English and Indonesian docs. This setup allows you to:
- Link contextually between related topics in the same language
- Offer dynamic search per language
- Maintain a clean, SEO-optimized structure
- Deploy easily on GitHub Pages with zero backend
Next Step: Interactive Elements and Feedback Loops
Next, we’ll explore how to capture user behavior using JavaScript — like tracking clicks on search results and related posts — to improve relevance over time and better understand what users engage with.
Siap lanjut ke bagian pelacakan interaksi pengguna?