Skip to content

Latest commit

 

History

History
1568 lines (1123 loc) · 78.8 KB

File metadata and controls

1568 lines (1123 loc) · 78.8 KB

Customize

Here we will give you some tips on how to customize the website. One important thing to note is that ALL the changes you make should be done on the main branch of your repository. The gh-pages branch is automatically overwritten every time you make a change to the main branch.

Note for users without coding experience: You do not need to understand the technology stack or have any coding background to create and customize your own website with al-folio. This template was specifically designed to be accessible to academics and researchers from all backgrounds. You can create a fully functional website by simply editing configuration files and adding content in Markdown, no coding required.

Project structure

The project is structured as follows, focusing on the main components that you will need to modify:

.
├── 📂 assets/: contains the assets that are displayed in the website
│   └── 📂 json/
    │   └── 📄 resume.json: CV in JSON format (https://jsonresume.org/)
├── 📂 _bibliography/
│   └── 📄 papers.bib: bibliography in BibTeX format
├── 📂 _books/: contains the bookshelf pages
├── 📄 _config.yml: the configuration file of the template
├── 📂 _data/: contains some of the data used in the template
│   ├── 📄 cv.yml: CV in YAML format, used when assets/json/resume.json is not found
│   ├── 📄 repositories.yml: users and repositories info in YAML format
│   └── 📄 socials.yml: your social media and contact info in YAML format
├── 📂 _includes/: optional local override includes (default includes are gem-owned in `v1.x`)
├── 📂 _layouts/: optional local override layouts (default layouts are gem-owned in `v1.x`)
├── 📂 _news/: the news that will appear in the news section in the about page
├── 📂 _pages/: contains the pages of the website
|   └── 📄 404.md: 404 page (page not found)
├── 📂 _posts/: contains the blog posts
├── 📂 _projects/: contains the projects
└── 📂 test/: starter integration + visual regression checks

In v1.x, the starter is intentionally thin. Theme internals (layouts/includes/style pipeline/runtime assets) are owned by gems such as al_folio_core and al_folio_distill.

Where common files moved in v1.x

Most customizations still live in your site repo. The difference is that default implementations now come from gems, so local files with the same path act as overrides.

Pre-v1 path or feature v1 owner Customize locally when...
_layouts/default.liquid, _layouts/page.liquid, _includes/head.liquid, _includes/scripts.liquid al_folio_core you intentionally need site-specific shell/runtime changes
_includes/cv/**, CV layouts, RenderCV wiring al_folio_cv you need a one-site CV display override
Distill layouts and assets/js/distillpub/** al_folio_distill you maintain custom Distill article behavior
Search assets and search setup al_search you change the local search UI only for your site
Citation badges, Scholar/Inspire helpers, bibliography helpers al_citations and al_folio_core your publication layout needs a local display override
External posts al_ext_posts your site has custom external-source rendering
Comments al_comments your site needs custom comment markup
Analytics al_analytics your site needs a custom analytics provider
Math, TikZ, charts, diagrams al_math and al_charts your site has custom rendering snippets
Repository cards al_folio_core you need custom links, badges, or card markup

When migrating an older customized fork, remove old local copies of files that you did not intentionally customize. In the dfuchss/fuchss.org rehearsal, deleting old local _includes/head.liquid, _includes/scripts.liquid, citation helper plugins, external-post helper plugins, assets/js/distillpub/**, and assets/js/search/** turned the upgrade audit from 4 blocking findings to 0 blocking findings.

When you intentionally keep a local override of a plugin-owned file, run bundle exec al-folio upgrade overrides audit after dependency updates. Review stale overrides with bundle exec al-folio upgrade overrides diff PATH, then acknowledge reviewed files with bundle exec al-folio upgrade overrides accept PATH.

Configuration

The configuration file _config.yml contains the main configuration of the website. Most of the settings is self-explanatory and we also tried to add as much comments as possible. If you have any questions, please check if it was not already answered in the FAQ.

Note that the url and baseurl settings are used to generate the links of the website, as explained in the install instructions.

All changes made to this file are only visible after you rebuild the website. That means that you need to run bundle exec jekyll serve again if you are running the website locally or push your changes to GitHub if you are using GitHub Pages. All other changes are visible immediately, you only need to refresh the page.

For v1.x starter sites, no local npm style build is required. Core CSS/runtime assets are shipped by the owning gems.

If changes don't appear after refreshing, try:

GitHub Copilot Customization Agent

This repository includes a specialized GitHub Copilot agent (.github/agents/customize.agent.md) designed to help you customize your al-folio website. The agent acts as an expert assistant that can:

  • Guide you through common customization tasks step-by-step
  • Modify configuration files, add content, and update your website
  • Explain technical concepts in plain language (especially helpful if you're not familiar with Jekyll or web development)
  • Apply changes directly to your repository files
  • Answer questions about how to customize specific features

What the Agent Can Help With

The customization agent can assist with tasks such as:

  • Changing basic site information (title, author name, contact details)
  • Updating your CV or resume
  • Adding and managing publications from BibTeX files
  • Creating blog posts, projects, and news items
  • Customizing theme colors and styling
  • Managing social media links
  • Enabling or disabling features in _config.yml
  • Adding profile pictures and other assets
  • Troubleshooting configuration issues

How to Use the Agent

To use the customization agent:

  1. Ensure you have a GitHub Copilot subscription
  2. Open your repository in an editor with GitHub Copilot support (such as VS Code with the GitHub Copilot extension)
  3. Interact with GitHub Copilot and ask questions or request changes. For more information, check Using custom agents in your IDE
  4. The agent will guide you through the customization process and can make changes directly to your files

For example, you can ask:

  • "How do I change my website's theme color to blue?"
  • "Help me add a new blog post about my research"
  • "Update my profile information with my new university email"
  • "How do I add a publication to my website?"

The agent is designed to be patient and helpful, explaining each step clearly so you understand what's being changed and why.

Important: Verify Agent Output

The customization agent can make mistakes or produce incorrect information. Always review and verify the agent's suggestions and changes before applying them to your repository:

  • Review all changes – Before applying any modifications, carefully read what the agent suggests and ensure it makes sense for your needs
  • Test locally first – Before pushing changes to GitHub, test them locally using Docker or native setup (see the Installation instructions)
  • Check syntax – Make sure any YAML, Markdown, or BibTeX files have correct syntax. Incorrect syntax can break your website
  • Verify configuration – If the agent modifies _config.yml or other configuration files, check that the changes align with your intentions
  • Preview on your site – Run your site locally and navigate through it to ensure everything displays correctly and works as expected
  • Don't blindly apply changes – Understand what's being changed and why before committing to your repository

Example scenarios where verification is important:

  • If the agent suggests a BibTeX entry, verify the syntax matches existing entries in your _bibliography/papers.bib file
  • If the agent modifies your _config.yml, check that indentation is correct (YAML is very sensitive to spacing)
  • If the agent creates a new blog post or page, verify the frontmatter (the metadata at the top) is correct
  • If the agent suggests changes to theme colors or styling, preview your site locally to ensure the changes look as intended

Note: The customization agent requires GitHub Copilot to be enabled. For more information about GitHub Copilot and its features, see the GitHub Copilot documentation.

Understanding the Codebase with Code Wiki and DeepWiki

If you're interested in learning more about how al-folio works under the hood, or want to understand specific aspects of the codebase for deeper customization, you can use Code Wiki and DeepWiki as supplementary resources.

What are these tools?

Code Wiki and DeepWiki are AI-powered tools that help you explore and understand GitHub repositories through interactive documentation:

  • Code Wiki (powered by Google Gemini) generates interactive documentation from the repository code. You can browse the project structure, search for specific functions or modules, view architecture diagrams, and understand how different components interact.

  • DeepWiki provides an AI chat interface where you can ask natural language questions about the codebase, similar to having an engineer available 24/7. You can ask how features work, search for code patterns, or get explanations of complex logic.

When to use them

Use Code Wiki and DeepWiki only after:

These tools are best used for:

  • Understanding the architecture and how different parts of the codebase work together
  • Finding where specific functionality is implemented
  • Learning about the Jekyll template structure and Liquid syntax used in the theme
  • Exploring how specific features are implemented (e.g., how publications are rendered, how search works, etc.)

Access these tools:

Technology Stack

Understanding al-folio's technology stack will help you better customize and extend the theme. This section provides an overview of the key technologies and frameworks used in the project.

Frontend

  • Markdown: Content is written in Markdown format for pages, blog posts, and collections. This makes it easy to create and maintain content without worrying about HTML.
  • Liquid templating: Liquid is used for dynamic template generation. In v1.x, canonical templates are gem-owned; local _layouts/ and _includes/ are overrides when you need project-specific customization.
  • HTML & CSS: The theme uses semantic HTML5 and modern CSS for styling and layout.
  • Tailwind CSS (v1.x core): al-folio v1.x is Tailwind-first. Core layout/styling is generated from Tailwind with a small set of theme primitives.
  • SCSS token bridge: Theme tokens and dark/light palettes remain in _sass/ and are bridged into Tailwind-based output.
  • Bootstrap compatibility mode (optional): Legacy Bootstrap-marked content can be supported temporarily through al_folio.compat.bootstrap.enabled.
  • JavaScript: Minimal JavaScript is used for interactive features like the dark mode toggle, search functionality, and dynamic content rendering.
  • MathJax: For rendering mathematical equations in LaTeX format on your pages and blog posts.
  • Mermaid: For creating diagrams (flowcharts, sequence diagrams, etc.) directly in Markdown.
  • Font Awesome, Academicons, and Scholar Icons: Icon libraries used throughout the theme for visual elements.

Backend

  • Jekyll 4.x: Jekyll is a static site generator written in Ruby that transforms your Markdown files and templates into a static website. Jekyll is used to:

    • Convert Markdown files to HTML
    • Process Liquid templates
    • Manage collections (posts, projects, news, books, etc.)
    • Generate archives and pagination
    • Minify CSS and JavaScript
  • Ruby Gems (Jekyll plugins): The project uses several Ruby plugins to extend Jekyll's functionality:

    • classifier-reborn: Used for categorizing and finding related blog posts
    • jekyll-archives-v2: Creates archive pages for posts and collections organized by category, tag, or date
    • jekyll-feed: Generates an Atom (RSS-like) feed for your content
    • jekyll-jupyter-notebook: Integrates Jupyter notebooks into your site
    • jekyll-minifier: Minifies HTML, CSS, and JavaScript for better performance
    • jekyll-paginate-v2: Handles pagination for blog posts and archives
    • jekyll-scholar: Manages bibliography files (BibTeX) and generates publication pages with citations
    • jekyll-tabs: Adds tabbed content support
    • jekyll-toc: Automatically generates table of contents for pages with headers
    • jemoji: Converts emoji shortcodes to emoji images
    • Other utilities: jekyll-link-attributes, jekyll-imagemagick, jekyll-twitter-plugin, jekyll-get-json, and more
  • Python: Used for utility scripts like citation updates via Google Scholar (located in bin/)

Build and Deployment

  • GitHub Actions: Automated workflows for building, testing, and deploying your site. Workflows are defined in .github/workflows/:

    • Deploy: Automatically builds and deploys your site to GitHub Pages when you push changes to the main branch
    • Link checking: Validates that all links in your site are not broken
    • Code formatting: Ensures code follows the Prettier code style
    • Accessibility testing: Checks for accessibility issues using Axe
    • Lighthouse: Measures site performance and best practices
    • Citation updates: Automatically fetches citation counts from Google Scholar
  • GitHub Pages: Free hosting for your static website built by Jekyll

  • Docker: Optional containerization for local development (provides a consistent environment across different machines)

  • Prettier: Code formatter for Markdown, YAML, and Liquid files to maintain consistent formatting

Key Integration Points

Understanding how these technologies work together will help you customize al-folio effectively:

  1. Content Creation: Write content in Markdown
  2. Template Processing: Jekyll processes Markdown through Liquid templates
  3. Styling: Tailwind generates core styles, while SCSS variables/tokens provide stable theme configuration
  4. Bibliography: BibTeX files are processed by jekyll-scholar to generate publication pages
  5. Static Site Generation: Jekyll builds all files into static HTML
  6. Deployment: GitHub Actions automatically deploys the built site to GitHub Pages

Modifying the CV information

Your CV can be created using one of two formats. Choose the format that works best for you, or use both simultaneously by switching between them:

RenderCV Format (Recommended)

_data/cv.yml uses the RenderCV YAML format, which is human-readable and designed specifically for generating professional resumes. This format also enables optional automatic PDF generation via GitHub Actions.

If you choose this format:

  1. Edit your CV data in _data/cv.yml
  2. Optionally customize how the PDF is styled by editing:
  3. To display only this format, delete assets/json/resume.json (optional)

JSONResume Format

assets/json/resume.json uses the JSONResume standard format, which is compatible with other tools and services.

If you choose this format:

  1. Edit your CV data in assets/json/resume.json
  2. To display only this format, delete _data/cv.yml (optional)

Using Both Formats Simultaneously

You can keep both _data/cv.yml and assets/json/resume.json in your repository and switch between them on your website by setting the cv_format frontmatter variable in _pages/cv.md:

---
layout: cv
cv_format: rendercv # options: rendercv or jsonresume
---

Change rendercv to jsonresume to display the JSONResume format instead.

Automatic PDF Generation (RenderCV only)

If you use the RenderCV format, a GitHub Actions workflow can automatically generate a PDF version of your CV whenever you push changes to _data/cv.yml. The PDF is saved to assets/rendercv/rendercv_output/.

To link the auto-generated PDF to your CV page:

Set the cv_pdf variable in the frontmatter of _pages/cv.md to point to the generated PDF:

---
layout: cv
cv_pdf: /assets/rendercv/rendercv_output/CV.pdf
cv_format: rendercv
---

This will add a download button on your CV page that links to the PDF. (The exact filename depends on your RenderCV settings—check the output directory after the first workflow run to see the generated PDF name.)

To disable automatic PDF generation:

Delete or comment out the .github/workflows/render-cv.yml workflow file.

Modifying the user and repository information

The user and repository information is defined in _data/repositories.yml. You can add as many users and repositories as you want. Both informations are used in the repositories section.

Configuring external service URLs

The repository page uses external services to display GitHub statistics and trophies. By default, these are:

  • github-stats-extended.vercel.app for user stats and repository cards
  • github-profile-trophy.vercel.app for GitHub profile trophies

Important: These default services are hosted by third parties and may not be available 100% of the time. For better reliability, privacy, and customization, you can self-host these services and configure your website to use your own instances.

To use your own instances of these services, configure the URLs in _config.yml:

external_services:
  github_readme_stats_url: https://github-stats-extended.vercel.app
  github_profile_trophy_url: https://github-profile-trophy.vercel.app

To self-host these services, follow the deployment instructions in their respective repositories:

Once deployed, update the URLs above to point to your custom deployment.

Migrating from github-readme-stats

Earlier versions of al-folio defaulted to github-readme-stats.vercel.app. That public instance is no longer reliably available, which is why repository cards render blank on some sites. The default is now github-stats-extended, an actively maintained, API-compatible successor.

If your site was created before this change, your _config.yml still pins the old host. Update it by hand:

external_services:
  github_readme_stats_url: https://github-stats-extended.vercel.app

Only the domain changes — the endpoints and every query parameter al-folio sends (theme, locale, show_owner, description_lines_count, show_icons) are unchanged, so your cards keep the same appearance and your repo_theme_light / repo_theme_dark settings continue to work.

Creating new pages

You can create new pages by adding new Markdown files in the _pages directory. The easiest way to do this is to copy an existing page and modify it. You can choose the layout of the page by changing the layout attribute in the frontmatter of the Markdown file, and also the path to access it by changing the permalink attribute.

In v1.x, default layout implementations are gem-owned (primarily al_folio_core and feature gems). If you need custom layout behavior, create a local override file in your site (for example, create _layouts/<name>.liquid in your starter repo). If you want to improve shared runtime behavior for everyone, open a PR in the owning gem repo.

For a one-site customization, prefer a local override over a plugin fork. Fork or Git-pin a plugin only when the change belongs to that plugin's reusable behavior. For example:

gem "al_folio_core", git: "https://github.com/YOUR-USER/al-folio-core.git", branch: "my-fix"
gem "al_folio_core", path: "../al-folio-core"

Creating new blog posts

To create a new blog post, you can add a new Markdown file in the _posts directory, which is the default location for posts in Jekyll. The name of the file must follow the format YYYY-MM-DD-title.md. The easiest way to do this is to copy an existing blog post and modify it. Note that some blog posts have optional fields in the frontmatter that are used to enable specific behaviors or functions.

If you want to create blog posts that are not ready to be published, but you want to track it with git, you can create a _drafts directory and store them there.

Note that posts is also a collection, but it is a default collection created automatically by Jekyll. To access the posts, you can use the site.posts variable in your templates.

Creating new projects

You can create new projects by adding new Markdown files in the _projects directory. The easiest way to do this is to copy an existing project and modify it.

Adding some news

You can add news in the about page by adding new Markdown files in the _news directory. There are currently two types of news: inline news and news with a link. News with a link take you to a new page while inline news are displayed directly in the about page. The easiest way to create yours is to copy an existing news and modify it.

Adding Collections

al-folio uses Jekyll collections to let you break up your work into categories. The starter comes with four default collections, all declared under collections: in _config.yml: news, projects, books, and teachings. Items from the news collection are automatically displayed on the home page, items from the projects collection are displayed on a responsive grid on the projects page, items from the books collection are displayed on its own bookshelf page inside submenus, and items from the teachings collection are displayed as course pages (see Creating a teachings collection below).

You can easily create your own collections for any type of content—teaching materials, courses, apps, short stories, or whatever suits your needs.

Creating a new collection

To create a new collection, follow these steps. We will create a courses collection, but you can replace courses with any name you prefer:

  1. Add the collection to _config.yml

    Open the collections section in _config.yml and add your new collection:

    collections:
      news:
        defaults:
          layout: post
        output: true
      projects:
        output: true
      courses:
        output: true
        permalink: /courses/:path/
    • output: true makes the collection items accessible as separate pages
    • permalink defines the URL path for each collection item (:path is replaced with the filename)
      • Note: You can customize the permalink structure as needed. If not set, it uses /COLLECTION_NAME/:name/.
  2. Create a folder for your collection items

    Create a new folder in the root directory with an underscore prefix, matching your collection name. For a courses collection, create _courses/:

    _courses/
    ├── course_1.md
    ├── course_2.md
    └── course_3.md
    
  3. Create a landing page for your collection

    Add a Markdown file in _pages/ (e.g., courses.md) that will serve as the main page for your collection. You can use _pages/projects.md or _pages/books.md as a template and adapt it for your needs.

    In your landing page, access your collection using the site.COLLECTION_NAME variable:

    {% assign course_items = site.courses | sort: 'date' | reverse %}
    
    {% for item in course_items %}
      <h3>{{ item.title }}</h3>
      <p>{{ item.content }}</p>
    {% endfor %}
  4. Add a navigation link to your collection page

    Update _pages/dropdown.md or the navigation configuration of your page. In the frontmatter of your collection landing page (e.g., _pages/courses.md), add:

    nav: true
    nav_order: 5
    • nav: true makes the page appear in the navigation menu
    • nav_order sets the position in the menu (1 = first, 2 = second, etc.)
  5. Create collection items

    Add Markdown files in your new collection folder (e.g., _courses/) with appropriate frontmatter and content.

For more information regarding collections, check Jekyll official documentation and step-by-step guide.

Using frontmatter fields in your collection

When creating items in your collection, you can define custom frontmatter fields and use them in your landing page. For example:

---
layout: page
title: Introduction to Research Methods
importance: 1
category: methods
---

Course description and content here...

Then in your landing page template:

{% if item.category == 'methods' %}
  <span class="badge">{{ item.category }}</span>
{% endif %}

Creating a teachings collection

The al-folio theme includes a pre-configured _teachings/ collection for course pages. Each course is represented by a markdown file with frontmatter metadata. Here's how to add or modify courses:

Course file format

Create markdown files in _teachings/ with the following structure:

---
layout: course
title: Course Title
description: Course description
instructor: Your Name
year: 2023
term: Fall
location: Room 101
time: MWF 10:00-11:00
course_id: course-id # This should be unique
schedule:
  - week: 1
    date: Jan 10
    topic: Introduction
    description: Overview of course content and objectives
    materials:
      - name: Slides
        url: /assets/pdf/example_pdf.pdf
      - name: Reading
        url: https://example.com/reading
  - week: 2
    date: Jan 17
    topic: Topic 2
    description: Description of this week's content
---
Additional course content, information, or resources can be added here as markdown.

Important course collection notes

  1. Each course file must have a unique course_id in the frontmatter
  2. Course files will be grouped by year on the teaching page
  3. Within each year, courses are sorted by term
  4. The content below the frontmatter (written in markdown) will appear on the individual course page
  5. The schedule section will be automatically formatted into a table

Required fields

  • layout: course — Must be set to use the course layout
  • title — The course title
  • year — The year the course was/will be taught (used for sorting)
  • course_id — A unique identifier for the course

Optional fields

  • description — A brief description of the course
  • instructor — The course instructor's name
  • term — The academic term (e.g., Fall, Spring, Summer)
  • location — The course location
  • time — The course meeting time
  • schedule — A list of course sessions with details

Collections with categories and tags

If you want to add category and tag support (like the blog posts have), you need to configure the jekyll-archives section in _config.yml. See how this is done with the books collection for reference. For more details, check the jekyll-archives-v2 documentation.

Creating custom metadata groups and archive pages

Beyond the built-in categories and tags fields, you can create custom metadata fields for your collections to organize content in new ways. For example, if you have a book review collection, you might want to organize books by their adaptations (movies, TV shows, video games, etc.).

Understanding Jekyll's special handling of fields

Jekyll has special built-in support for only two fields:

  • categories – Automatically splits space-separated values into arrays
  • tags – Automatically splits space-separated values into arrays

Custom fields (any field name you create) remain as strings and require explicit handling in your Liquid templates.

Example: Adding a custom "adaptations" field

  1. Add the field to your collection frontmatter

    In your collection item (e.g., _books/the_godfather.md):

    ---
    layout: book-review
    title: The Godfather
    author: Mario Puzo
    categories: classics crime historical-fiction
    adaptations: movie TV-series video-game novel-adaptation
    ---
  2. Handle the custom field in your layout template

    In your layout file (e.g., _layouts/book-review.liquid), custom fields must be split into arrays before you can loop over them:

    {% if page.adaptations %}
      {% assign page_adaptations = page.adaptations | split: ' ' %}
      {% for adaptation in page_adaptations %}
        <a href="{{ adaptation | slugify | prepend: '/books/adaptation/' | relative_url }}">
          <i class="fa-solid fa-film fa-sm"></i> {{ adaptation }}
        </a>
      {% endfor %}
    {% endif %}

    Why the split: ' ' filter? Because adaptations is a custom field, Jekyll doesn't automatically convert it to an array like it does for categories and tags. The split: ' ' filter breaks the space-separated string into individual items.

  3. Enable archive pages for your custom field

    Add your custom field to the jekyll-archives configuration in _config.yml:

    jekyll-archives:
      posts:
        enabled:
          - year
          - tags
          - categories
      books:
        enabled:
          - year
          - tags
          - categories
          - adaptations # Add your custom field here
        permalinks:
          year: "/:collection/:year/"
          tags: "/:collection/:type/:name/"
          categories: "/:collection/:type/:name/"
          adaptations: "/:collection/:type/:name/" # Add permalink pattern here
  4. Test your archive pages

    After configuration, rebuild your site:

    docker compose down
    docker compose up

    Your archive pages will be generated at:

    • /books/adaptations/movie/
    • /books/adaptations/tv-series/ (slugified from TV-series)
    • /books/adaptations/video-game/ (slugified from video-game)

    Each page will automatically display all items with that adaptation value.

Field naming best practices

  • Use lowercase words separated by hyphens for multi-word values: live-action, video-game, TV-series
  • Choose meaningful names that describe the grouping: genres, adaptations, media-types, settings, etc.
  • Keep field values short and consistent across all items in your collection
  • Document custom fields in a README or comments for other contributors to understand

Complete example: Book reviews with custom adaptations field

File: _books/the_godfather.md

---
layout: book-review
title: The Godfather
author: Mario Puzo
categories: classics crime historical-fiction
tags: top-100
adaptations: movie TV-series video-game
---

File: _layouts/book-review.liquid (partial)

{% if page.adaptations %}
  <div class="adaptations">
    <strong>Adaptations:</strong>
    {% assign page_adaptations = page.adaptations | split: ' ' %}
    {% for adaptation in page_adaptations %}
      <a href="{{ adaptation | slugify | prepend: '/books/adaptation/' | relative_url }}">
        {{ adaptation }}
      </a>
      {% unless forloop.last %},{% endunless %}
    {% endfor %}
  </div>
{% endif %}

File: _config.yml (jekyll-archives section)

jekyll-archives:
  books:
    enabled:
      - year
      - categories
      - tags
      - adaptations
    permalinks:
      year: "/:collection/:year/"
      categories: "/:collection/:type/:name/"
      tags: "/:collection/:type/:name/"
      adaptations: "/:collection/:type/:name/"

After rebuilding, users can browse books by adaptation at /books/adaptations/movie/, etc.

Adding a new publication

To add publications create a new entry in the _bibliography/papers.bib file. You can find the BibTeX entry of a publication in Google Scholar by clicking on the quotation marks below the publication title, then clicking on "BibTeX", or also in the conference page itself. By default, the publications will be sorted by year and the most recent will be displayed first. You can change this behavior and more in the Jekyll Scholar section in _config.yml file.

You can add extra information to a publication, like a PDF file in the assets/pdf/ directory and add the path to the PDF file in the BibTeX entry with the pdf field. Some of the supported fields are: abstract, altmetric, annotation, arxiv, bibtex_show, blog, code, dimensions, doi, eprint, hal, html, isbn, pdf, pmid, poster, slides, supp, video, and website.

Author annotation

In publications, the author entry for yourself is identified by string array scholar:last_name and string array scholar:first_name in _config.yml. For example, if you have the following entry in your _config.yml:

scholar:
  last_name: [Einstein]
  first_name: [Albert, A.]

If the entry matches one form of the last names and the first names, it will be underlined. Keep meta-information about your co-authors in _data/coauthors.yml and Jekyll will insert links to their webpages automatically. The co-author data format is as follows, with the last names lower cased and without accents as the key:

"adams":
  - firstname: ["Edwin", "E.", "E. P.", "Edwin Plimpton"]
    url: https://en.wikipedia.org/wiki/Edwin_Plimpton_Adams

"podolsky":
  - firstname: ["Boris", "B.", "B. Y.", "Boris Yakovlevich"]
    url: https://en.wikipedia.org/wiki/Boris_Podolsky

"rosen":
  - firstname: ["Nathan", "N."]
    url: https://en.wikipedia.org/wiki/Nathan_Rosen

"bach":
  - firstname: ["Johann Sebastian", "J. S."]
    url: https://en.wikipedia.org/wiki/Johann_Sebastian_Bach

  - firstname: ["Carl Philipp Emanuel", "C. P. E."]
    url: https://en.wikipedia.org/wiki/Carl_Philipp_Emanuel_Bach

If the entry matches one of the combinations of the last names and the first names, it will be highlighted and linked to the url provided. Note that the keys MUST BE lower cased and MUST NOT contain accents. This is because the keys are used to match the last names in the BibTeX entries, considering possible variations (see related discussion).

Buttons (through custom bibtex keywords)

There are several custom bibtex keywords that you can use to affect how the entries are displayed on the webpage:

  • abbr: Adds an abbreviation to the left of the entry. You can add links to these by creating a venue.yaml-file in the _data folder and adding entries that match.
  • abstract: Adds an "Abs" button that expands a hidden text field when clicked to show the abstract text
  • altmetric: Adds an Altmetric badge (Note: if DOI is provided just use true, otherwise only add the altmetric identifier here - the link is generated automatically)
  • annotation: Adds a popover info message to the end of the author list that can potentially be used to clarify superscripts. HTML is allowed.
  • arxiv: Adds a link to the Arxiv website (Note: only add the arxiv identifier here - the link is generated automatically)
  • bibtex_show: Adds a "Bib" button that expands a hidden text field with the full bibliography entry
  • blog: Adds a "Blog" button redirecting to the specified link
  • code: Adds a "Code" button redirecting to the specified link
  • dimensions: Adds a Dimensions badge (Note: if DOI or PMID is provided just use true, otherwise only add the Dimensions' identifier here - the link is generated automatically)
  • hal: Adds a link to the HAL website (Note: only add the hal identifier (hal-xxx or tel-xxx) here - the link is generated automatically)
  • html: Inserts an "HTML" button redirecting to the user-specified link
  • pdf: Adds a "PDF" button redirecting to a specified file (if a full link is not specified, the file will be assumed to be placed in the /assets/pdf/ directory)
  • poster: Adds a "Poster" button redirecting to a specified file (if a full link is not specified, the file will be assumed to be placed in the /assets/pdf/ directory)
  • slides: Adds a "Slides" button redirecting to a specified file (if a full link is not specified, the file will be assumed to be placed in the /assets/pdf/ directory)
  • supp: Adds a "Supp" button to a specified file (if a full link is not specified, the file will be assumed to be placed in the /assets/pdf/ directory)
  • website: Adds a "Website" button redirecting to the specified link

In v1.x, bibliography buttons/layout runtime is gem-owned (al_citations + al_folio_core). For local customization, add a local override _layouts/bib.liquid in your site; for upstream/shared behavior changes, open a PR in the owning gem repo.

Changing theme color

A variety of beautiful theme colors have been selected for you to choose from. In v1.x, theme tokens are gem-owned by default. To customize colors locally, either use _config.yml theme settings (for light/dark scheme selection) or create local _sass/_themes.scss and _sass/_variables.scss override files in your starter repo (these override gem defaults).

Customizing layout and UI

You can customize the layout and user interface in _config.yml:

back_to_top: true
footer_fixed: true
max_width: 930px
navbar_fixed: true
  • back_to_top: Displays a "back to top" button in the footer. When clicked, it smoothly scrolls the page back to the top.
  • footer_fixed: When true, the footer remains fixed at the bottom of the viewport. When false, it appears at the end of the page content.
  • max_width: Controls the maximum width of the main content area in pixels. The default is 930px. You can adjust this to make your content wider or narrower.
  • navbar_fixed: When true, the navigation bar stays fixed at the top of the page when scrolling. When false, it scrolls with the page content.

Adding social media information

Social media information is managed through the jekyll-socials plugin. To add your social media links:

  1. Edit _data/socials.yml to add your social profiles
  2. The plugin will automatically display the social icons based on the order they are defined in the file (see the comments at the top of _data/socials.yml)

The template supports icons from:

In v1.x, icon runtime ownership is provided by the al_icons plugin. Icon files are loaded from pinned CDN URLs via third_party_libraries in _config.yml (not from starter-local assets/fonts or assets/webfonts copies).

Social media links will appear at the bottom of the About page and in the search results by default. You can customize this behavior in _config.yml:

  • enable_navbar_social: true – Display social links in the navigation bar
  • socials_in_search: false – Remove social links from search results

For more details, see the jekyll-socials documentation.

Adding a newsletter

You can add a newsletter subscription form by adding the specified information at the newsletter section in the _config.yml file. To set up a newsletter, you can use a service like Loops.so, which is the current supported solution. Once you have set up your newsletter, you can add the form endpoint to the endpoint field in the newsletter section of the _config.yml file.

Depending on your specified footer behavior, the sign up form either will appear at the bottom of the About page and at the bottom of blogposts if related_posts are enabled, or in the footer at the bottom of each page.

Configuring search features

The theme includes a powerful search functionality that can be customized in _config.yml:

bib_search: true
posts_in_search: true
search_enabled: true
socials_in_search: true
  • bib_search: Enables search within your publications/bibliography. When enabled, a search box appears on the publications page, allowing visitors to filter publications by title, author, venue, or year.
  • posts_in_search: Includes blog posts in the search index. Users can search for posts by title, content, or tags.
  • search_enabled: Enables the site-wide search feature. When enabled, a search box appears in the navigation bar, allowing users to search across your site content.
  • socials_in_search: Includes your social media links and contact information in search results. This makes it easier for visitors to find ways to connect with you.

All these search features work in real-time and do not require a page reload. Search runtime assets are owned by the al_search plugin.

The navbar search button and the Ctrl/Cmd + K shortcut both open the same search modal.

Sidebar table of contents (Tocbot)

Use front matter on pages/posts:

toc:
  sidebar: left # or right
  collapse: expanded # or auto
# optional explicit depth override:
# collapse_depth: 3

In v1.x, sidebar TOC rendering is powered by Tocbot (configured in _config.yml under third_party_libraries.tocbot). You can override displayed TOC labels per heading with data-toc-text:

## Customizing Your Table of Contents

{:data-toc-text="Customizing"}

toc.collapse behavior:

  • expanded (default): render the full nested TOC expanded.
  • auto: collapse nested branches and expand the active branch as you scroll.

If needed, toc.collapse_depth can be used for direct Tocbot-style depth control.

Pretty tables in Tailwind mode

Set pretty_table: true in front matter to enable interactive tables.

  • If al_folio.compat.bootstrap.enabled: true, Bootstrap Table runtime is used.
  • If al_folio.compat.bootstrap.enabled: false, the built-in Tailwind-first vanilla table engine is used.

The Tailwind table engine supports data-toggle="table" plus search, pagination, sortable columns, and click-to-select.

Lightbox images

Set in front matter:

images:
  lightbox2: true

v1.x uses the al_img_tools plugin lightbox adapter (vanilla JS, no jQuery requirement) while keeping existing data-lightbox markup.

Social media previews

al-folio supports Open Graph (OG) meta tags, which create rich preview objects when your pages are shared on social media platforms like Twitter, Facebook, LinkedIn, and others. These previews include your site's image, title, and description.

How to enable

To enable social media previews:

  1. Open _config.yml and set:

    serve_og_meta: true
  2. Rebuild your site:

    docker compose down && docker compose up
    # or
    bundle exec jekyll serve

Once enabled, all your site's pages will automatically include Open Graph meta tags in the HTML head element.

Configuring preview images

You can configure what image displays in social media previews on a per-page or site-wide basis.

Site-wide default image:

Add the following to _config.yml:

og_image: /assets/img/your-default-preview-image.png

Replace the path with your actual image location in assets/img/.

Per-page custom image:

To override the site-wide default for a specific page, add og_image to the page's frontmatter:

---
layout: page
title: My Page
og_image: /assets/img/custom-preview-image.png
---

Preview image best practices

  • Dimensions: Use 1200×630 pixels for optimal display on most social media platforms
  • Format: PNG or JPG formats work best
  • Size: Keep file size under 5MB
  • Content: Ensure the image clearly represents your page content

When a page is shared on social media, the platform will display your configured image along with the page title, description (from your site title or page description), and URL.


Related posts

The theme can automatically display related posts at the bottom of each blog post. These are selected by finding the most recent posts that share common tags with the current post.

How it works

  • By default, the most recent posts that share at least one tag with the current post are displayed
  • You can customize how many posts are shown and how many tags must match
  • You can disable related posts for individual posts or across your entire site

Configuration

To customize related posts behavior, edit the related_blog_posts section in _config.yml:

related_blog_posts:
  enabled: true
  max_related: 5
  • enabled: Set to true (default) to show related posts, or false to disable them site-wide
  • max_related: Maximum number of related posts to display (default: 5)

The theme also uses tags to find related content. Make sure your blog posts include relevant tags in their frontmatter:

---
layout: post
title: My Blog Post
tags: machine-learning python
---

Disable related posts for a specific post

To hide related posts on an individual blog post, add this to the post's frontmatter:

---
layout: post
title: My Blog Post
related_posts: false
---

Additional configuration in _config.yml

You can also customize related posts behavior with these settings:

related_blog_posts:
  enabled: true
  max_related: 5

These settings control:

  • Which posts are considered "related" (based on shared tags)
  • How many related posts to display
  • The algorithm used to calculate post similarity (uses the classifier-reborn gem)

Managing publication display

The theme offers several options for customizing how publications are displayed:

enable_publication_thumbnails: true
max_author_limit: 3
more_authors_animation_delay: 10
  • enable_publication_thumbnails: When true, displays preview images for publications (if specified in the BibTeX entry with the preview field). Set to false to disable thumbnails for all publications.
  • max_author_limit: Sets the maximum number of authors shown initially for each publication. If a publication has more authors, they are hidden behind a "more authors" link. Leave blank to always show all authors.
  • more_authors_animation_delay: Controls the animation speed (in milliseconds) when revealing additional authors. A smaller value means faster animation.

To add a thumbnail to a publication, include a preview field in your BibTeX entry:

@article{example2024,
  title={Example Paper},
  author={Author, First and Author, Second},
  journal={Example Journal},
  year={2024},
  preview={example_preview.png}
}

Place the image file in assets/img/publication_preview/.

Adding a Google Calendar

You can embed a Google Calendar on any page by using the calendar.liquid include.

Basic usage

Add the following to your page's Markdown file (for example, in _pages/teaching.md):

{% include calendar.liquid calendar_id='your-calendar-id@group.calendar.google.com' timezone='Your/Timezone' %}

Replace:

  • your-calendar-id@group.calendar.google.com with your actual Google Calendar ID (found in Google Calendar Settings → Integrate calendar → Calendar ID)
  • Your/Timezone with your timezone (e.g., UTC, Asia/Shanghai, America/New_York). The default is UTC.

Enable the calendar script for your page

To enable the calendar on your page, add calendar: true to the frontmatter:

---
layout: page
title: teaching
calendar: true
---

This setting prevents unnecessary script loading for pages that don't display a calendar.

Optional: Customize the calendar style

You can optionally customize the iframe styling using the style parameter:

{% include calendar.liquid calendar_id='your-calendar-id@group.calendar.google.com' timezone='UTC' style='border:0; width:100%; height:800px;' %}

The default style is border:0; width:100%; height:600px;.

Updating third-party libraries

The theme uses various third-party JavaScript and CSS libraries. You can manage these in the third_party_libraries section of _config.yml:

third_party_libraries:
  download: false
  bootstrap-table:
    version: "1.22.4"
    url:
      css: "https://cdn.jsdelivr.net/npm/bootstrap-table@{{version}}/dist/bootstrap-table.min.css"
      js: "https://cdn.jsdelivr.net/npm/bootstrap-table@{{version}}/dist/bootstrap-table.min.js"
    integrity:
      css: "sha256-..."
      js: "sha256-..."
  • download: When false (default), libraries are loaded from CDNs. When true, the specified library versions are downloaded during build and served from your site. This can improve performance but increases your repository size.
  • version: Specifies which version of each library to use. Update this to use a newer version.
  • url: Template URLs for loading the library. The {{version}} placeholder is replaced with the version number automatically.
  • integrity: Subresource Integrity (SRI) hashes ensure that the library hasn't been tampered with. When updating a library version, you should also update its integrity hash.
  • v1.x policy: use pinned CDN assets (with SRI where available) for standalone libraries; keep vendored release-time artifacts only in owning plugins when runtime/module graphs are complex (for example al_search, al_folio_distill).
  • v1.x policy: do not add install-time downloads in gem install / bundle install.
  • al_math uses CDN TikZJax assets configured in third_party_libraries.tikzjax.
  • toc.sidebar uses Tocbot assets configured in third_party_libraries.tocbot.

To update a library:

  1. Change the version number

  2. Obtain the new integrity hash for the updated library version and update the integrity field with the new hash. You can:

    • Check if the CDN provider (e.g., jsDelivr, cdnjs, unpkg) provides the SRI hash for the file. Many CDN sites display the SRI hash alongside the file URL.

    • Generate the SRI hash yourself using a tool such as SRI Hash Generator or by running the following command in your terminal:

      curl -sL [FILE_URL] | openssl dgst -sha384 -binary | openssl base64 -A

      Replace [FILE_URL] with the URL of the library file. Then, prefix the result with sha384- and use it in the integrity field. For icon-specific updates, see the FAQ:

Plugin ecosystem (v1.x)

al-folio is a thin starter in v1.x. Runtime ownership belongs to plugins/gems.

Naming convention

  • Theme-coupled plugins:
    • repo: al-folio-<feature>
    • gem/plugin id: al_folio_<feature>
  • Reusable plugins:
    • repo: al-<feature> or neutral name
    • gem/plugin id aligned with plugin namespace

Third-party non-al-* plugins are also valid and may be featured in the catalog.

Featured vs bundled plugins

  • Featured-only: shown in catalog/docs, not included in starter dependencies by default.
  • Bundled: included by default in starter wiring.

Starter wiring uses:

The starter currently has no gemspec; plugin integration docs should reference these two files.

Bootstrap compatibility mode (v1.x)

al-folio v1.0 and newer are Tailwind-first. If your site still contains Bootstrap-marked content from older versions, use:

al_folio:
  compat:
    bootstrap:
      enabled: true

Compatibility matrix

  • Supported through v1.2: common Bootstrap-marked layout/content patterns (for example: row, col-*, card, btn, and data-toggle attributes for collapse/dropdown/tooltip/popover)
  • Deprecated in v1.3: compatibility mode remains available but migration warnings become stricter
  • Removed in v2.0: compatibility mode is no longer part of the official runtime

For upgrades, run:

bundle exec al-folio upgrade audit
bundle exec al-folio upgrade apply --safe
bundle exec al-folio upgrade report

Removing content

Since this template has a lot of content, you may want to remove some of it. The easiest way to achieve this and avoid merge conflicts when updating your code (as pointed by CheariX ) is to add the unwanted files to the exclude section in your _config.yml file instead of actually deleting them, for example:

exclude:
  - _news/announcement_*.md
  - _pages/blog.md
  - _posts/
  - _projects/?_project.md
  - assets/jupyter/blog.ipynb

Here is a list of the main components that you may want to delete, and how to do it. Don't forget if you delete a page to update the nav_order of the remaining pages.

Removing the blog page

To remove the blog, you have to:

You can also:

  • disable latest_posts.enabled in _pages/about.md and disable related posts via front matter/config where needed
  • in v1.x there are no starter-local _includes/latest_posts.liquid, _includes/related_posts.liquid, or _layouts/archive.liquid files to delete (these are gem-owned)
  • remove al_ext_posts from the Gemfile and from the plugins section in _config.yml
  • remove the jekyll-archives-v2 gem from the Gemfile and the plugins section in _config.yml (unless you have a custom collection that uses it)
  • remove the classifier-reborn gem from the Gemfile

Removing the news section

To remove the news section, you can:

  • delete the _news directory
  • remove/disable the announcements block in _pages/about.md (news include runtime is gem-owned in v1.x)
  • remove the announcements part in _pages/about.md
  • remove the news part in the Collections section in the _config.yml file

Removing the projects page

To remove the projects, you can:

You can also:

  • in v1.x, projects include templates are gem-owned and not present as starter-local files to delete

Removing the publications page

To remove the publications, you can:

You can also:

  • in v1.x, bibliography layout/includes are gem-owned, so there are no starter-local _layouts/bib.liquid, _includes/bib_search.liquid, _includes/citation.liquid, or _includes/selected_papers.liquid files to delete
  • the old hide-custom-bibtex.rb helper is now provided by al_folio_core (there is no local file to delete)
  • remove al_citations from the Gemfile and from the plugins section in _config.yml
  • remove the jekyll-scholar gem from the Gemfile and the plugins section in _config.yml

Removing the repositories page

To remove the repositories, you can:

  • delete the repositories page _pages/repositories.md
  • in v1.x, repository rendering includes are gem-owned and not present as starter-local files to delete

You can also remove pages through commenting out front-matter blocks

For .md files in _pages directory, if you do not want to completely edit or delete them but save for later use, you can temporarily disable these variables. But be aware that Jekyll only recognizes front matter when it appears as uncommented. The layout, permalink, and other front-matter behavior are disabled for that file.

For example, books.md do:

<!-- ---
layout: book-shelf
title: bookshelf
permalink: /books/
nav: true
collection: books
--- -->

> What an astonishing thing a book is. It's a flat object made from a tree with flexible parts on which are imprinted lots of funny dark squiggles. But one glance at it and you're inside the mind of another person, maybe somebody dead for thousands of years. Across the millennia, an author is speaking clearly and silently inside your head, directly to you. Writing is perhaps the greatest of human inventions, binding together people who never knew each other, citizens of distant epochs. Books break the shackles of time. A book is proof that humans are capable of working magic.
>
> -- Carl Sagan, Cosmos, Part 11: The Persistence of Memory (1980)

## Books that I am reading, have read, or will read

Adding Token for Lighthouse Badger

To add secrets for lighthouse-badger, create a personal access token (PAT) and add it as a secret named LIGHTHOUSE_BADGER_TOKEN to your repository. The lighthouse-badger documentation specifies using an environment variable, but using it as a secret is more secure and appropriate for a PAT.

Also In case you face the error: "Input required and not supplied: token" in the Lighthouse Badger action, this solution resolves it.

Personal Access Token (fine-grained) Permissions for Lighthouse Badger:

  • contents: access: read and write
  • metadata: access: read-only

Due to the necessary permissions (PAT and others mentioned above), it is recommended to use it as a secret rather than an environment variable.

Customizing fonts, spacing, and more

In v1.x, base SCSS is gem-owned. For project-specific style customization, create local override files under _sass/ in your starter repo and define only the variables/rules you want to change.

Common override patterns:

  • Typography: add overrides for headings, inline code, tables, and blockquotes.
  • Navigation: override navbar/dropdown spacing, alignment, and interaction styles.
  • Colors and themes: override token variables such as --global-theme-color and related palette variables.
  • Components: override cards, projects, publications, and utility classes used by your content.

The easiest way to preview changes in advance is by using Chrome dev tools or Firefox dev tools. Inspect elements to see which styles apply and experiment with changes before editing the SCSS files. For more information on how to use these tools, check Chrome and Firefox how-tos, and this tutorial.

Scheduled Posts

al-folio contains a workflow which automatically publishes all posts scheduled at a specific day, at the end of the day (23:30). By default the action is disabled, and to enable it you need to go to .github/workflows/ and find the file called schedule-posts.txt. This is the workflow file. For GitHub to recognize it as one (or to enable the action), you need to rename it to schedule-posts.yml.

In order to use this you need to save all of your "Completed" blog posts which are scheduled to be uploaded on a specific date, in a folder named _scheduled/ in the root directory.

Incomplete posts should be saved in _drafts/

Name Format

In this folder you need to store your file in the same format as you would in _posts/

Example file name: 2024-08-26-This file will be uploaded on 26 August.md

Important Notes

  • The scheduler uploads posts everyday at 🕛 23:30 UTC
  • It will only upload posts at 23:30 UTC of their respective scheduled days, It's not uploaded in 23:59 in case there are a lot of files as the scheduler must finish before 00:00
  • It will only upload files which follow the pattern yyyy-mm-dd-title.md
    • This means that only markdown files will be posted
    • It means that any markdown which do not follow this pattern will not be posted
  • The scheduler works by moving posts from the _scheduled/ directory to _posts/, it will not post to folders like _projects/ or _news/
  • The date in the name of the file is the day that file will be uploaded on
    • 2024-08-27-file1.md will not be posted before or after 27-August-2024 (Scheduler only works for posts scheduled on the present day)
    • 2025-08-27-file2.md will be posted exactly on 27-August-2025
    • File3.md will not be posted at all
    • 2026-02-31-file4.md is supposed to be posted on 31-February-2026, but there is no 31st in February hence this file will never be posted either

GDPR Cookie Consent Dialog

al-folio supports a GDPR-compliant cookie consent dialog via the al_cookie plugin to help you respect visitor privacy and comply with privacy regulations (GDPR, CCPA, etc.). The feature is powered by Vanilla Cookie Consent and integrates with all analytics providers.

How it works

  • A consent dialog appears on the visitor's first visit to your site
  • Visitors can accept all, reject all, or customize preferences for analytics cookies
  • Analytics scripts (Google Analytics, Cronitor, Pirsch, Openpanel) are blocked by default and only run after explicit consent
  • Google Consent Mode ensures Google services operate in privacy mode before consent is granted
  • User preferences are saved in their browser and respected on subsequent visits
  • The dialog is mobile-responsive and supports multiple languages

When to use

  • Required if your site serves EU visitors and uses any analytics
  • ✅ Recommended for any website using analytics, tracking, or marketing tools
  • ❌ Not needed if your site doesn't use any analytics providers

How to enable

  1. Open _config.yml and locate the following line:

    enable_cookie_consent: false
  2. Change it to:

    enable_cookie_consent: true
  3. Ensure al_cookie is enabled in your plugin list:

    plugins:
      - al_cookie
  4. Rebuild your site:

    docker compose down && docker compose up
    # or
    bundle exec jekyll serve
  5. The consent dialog will automatically appear on your site's homepage on first visit

Customizing the consent dialog

The consent dialog configuration and messages are now owned by al_cookie (lib/templates/cookie_consent_setup.js.liquid in that gem). To customize behavior, override cookie consent scripts in your site templates or fork/pin al_cookie and adjust the template there.

  • Dialog titles and button labels
  • Cookie categories and descriptions
  • Contact information links (points to #contact by default)
  • Language translations

To modify the dialog, edit the language.translations.en section in the plugin template. For example, to change the consent dialog title:

consentModal: {
  title: 'Your custom title here',
  description: 'Your custom description...',
  // ... other options
}

Supported analytics providers

When cookie consent is enabled, these analytics providers are automatically blocked until the user consents:

  • Google Analytics (GA4) – Uses Google Consent Mode for privacy-first operation before consent
  • Cronitor RUM – Real User Monitoring for performance tracking
  • Pirsch Analytics – GDPR-compliant analytics alternative
  • Openpanel Analytics – Privacy-focused analytics platform

Each provider only collects data if:

  1. Its ID is set in _config.yml. The starter ships an analytics: block, and a provider becomes active as soon as you give it a non-empty ID:

    analytics:
      google: # Google Analytics measurement ID (format: G-XXXXXXXXXX)
      cronitor: # Cronitor RUM analytics site ID
      pirsch: # Pirsch analytics site ID (32 characters)
      openpanel: # Openpanel analytics client ID (UUID)

    The al_analytics plugin also accepts flat aliases (google_analytics, cronitor_analytics, pirsch_analytics, openpanel_analytics), which take precedence over the nested block. The matching enable_*_analytics flags are optional off-switches: leave them unset and the provider follows the ID, or set one to false to disable that provider while keeping its ID. Setting enable_google_analytics: true without an ID does nothing.

  2. The user has granted consent to the "analytics" category in the consent dialog

How it integrates with analytics

When enable_cookie_consent: true, the template automatically:

  1. Adds type="text/plain" data-category="analytics" to all analytics script tags
  2. This tells the cookie consent library to block these scripts until consent is granted
  3. Loads the consent library and initializes Google Consent Mode
  4. Updates consent preferences when the user changes them in the dialog

You don't need to modify any analytics configuration—it works automatically.

For developers

If you want to programmatically check consent status or react to consent changes, the library exposes the following:

// Check if user has granted analytics consent
window.CookieConsent.getCategories().analytics; // returns true or false

// Listen for consent changes
window.CookieConsent.onChange(function (consentData) {
  // Handle consent change
});

For more API details, see Vanilla Cookie Consent documentation.


Setting up a Personal Access Token (PAT) for Google Scholar Citation Updates

Tip

After setting up al-folio you may want to run python3 bin/update_scholar_citations.py to fill the _data/citations.yml file with your Google Scholar citation counts. The script needs the scholarly package from requirements.txt (python3 -m pip install scholarly).

This project includes an automated workflow to update the citation counts for your publications using Google Scholar. The workflow commits changes to _data/citations.yml directly to the main branch. By default, the GITHUB_TOKEN will be used to commit the changes. However, this token does not have permission to trigger subsequent workflows, such as the site rebuild workflow. In order to deploy the changes from main, you can manually trigger the deploy workflow.

Tip

To ensure that these commits can trigger further GitHub Actions workflows (such as site rebuilds), you can use a Personal Access Token (PAT) instead of the default GitHub Actions token. If you have set up a PAT, citation updates will trigger further workflows (such as site rebuilds) after committing changes. In order to run the action with a PAT, you need to uncomment the following lines from the workflow file (update-citations.yml):

with:
  token: ${{ secrets.PAT }}

Why is a PAT required?

GitHub restricts the default GITHUB_TOKEN from triggering other workflows when a commit is made from within a workflow. Using a PAT overcomes this limitation and allows for full automation.

How to set up the PAT

  1. Create a Personal Access Token

    • Go to GitHub Settings > Developer settings > Personal access tokens.
    • Click "Generate new token" (classic or fine-grained).
    • Grant at least the following permissions:
      • repo (for classic tokens if repo is private), public_repo (for classic tokens if repo is public) or contents: read/write (for fine-grained tokens)
    • Save the token somewhere safe.
  2. Add the PAT as a repository secret

    • Go to your repository on GitHub.
    • Navigate to Settings > Secrets and variables > Actions > New repository secret.
    • Name the secret PAT (must match the name used in the workflow).
    • Paste your PAT and save.
  3. Workflow usage The workflow .github/workflows/update-citations.yml uses this PAT to commit updates to _data/citations.yml.