Download Latest Version al-folio v1.1 source code.zip (51.6 MB)
Email in envelope

Get an email when there's a new version of al-folio

Home / v1.1
Name Modified Size InfoDownloads / Week
Parent folder
al-folio v1.1 source code.tar.gz 2026-07-30 51.5 MB
al-folio v1.1 source code.zip 2026-07-30 51.6 MB
README.md 2026-07-30 10.5 kB
Totals: 3 Items   103.1 MB 4

v1.1 is the first maintenance release on the v1 plugin architecture. It is mostly security and bug fixes, and it is the release where the plugin ecosystem actually started shipping: every gem with pending work is now published, and releases are automated rather than manual.

Most of the user-visible change is in the gems, not in this repo.

bundle update on its own will not upgrade you. The Gemfile pins every plugin to an exact version (= 1.0.x), and Bundler honours the pin already in your Gemfile β€” so a v1.0 site runs bundle update and stays on the vulnerable versions, with no error. You must edit the pins first β€” see the Upgrading section at the bottom.

The starter's Gemfile now pins:

gem v1.0 v1.1
al_folio_core 1.0.10 1.0.12
al_folio_cv 1.0.0 1.0.2
al_folio_distill 1.0.2 1.0.3
al_analytics 1.0.0 1.0.2
al_ext_posts 1.0.1 1.0.3
al_img_tools 1.0.2 1.0.3
al_search 1.0.2 1.0.3
al_math 1.0.1 1.0.2

πŸ”’ Security

Three real vulnerabilities, all of which affected every v1.0 site.

Swiper prototype pollution β€” CVSS 9.4 (al_img_tools 1.0.3) CVE-2026-27212 / GHSA-hmx5-qpq5-p643 affects Swiper >= 6.5.1, < 12.1.2; v1.0 shipped 11.0.5. Bumped to 12.1.2 with refreshed SRI hashes for the CSS, JS and source maps. The image slider uses the swiper-element Web Component bundle, whose <swiper-container> API is unchanged across the major bump, so no template changes are needed.

polyfill.io removed from the MathJax path (al_math 1.0.2) The polyfill.io CDN was taken over in a June 2024 supply-chain attack and had been serving malicious payloads. It was also unnecessary β€” MathJax 3 does not need it on any browser al-folio supports. The <script> tag is gone.

Distill runtime no longer loaded from a third-party origin without integrity (al_folio_distill 1.0.3) The vendored transforms.v2.js carried upstream's Polyfills transform, which removed the page's local template.v2.js tag and re-injected it from a hard-coded https://distill.pub/template.v2.js with no subresource integrity β€” silently discarding the hash-pinned copy the gem exists to ship, and granting arbitrary JS execution on every Distill page to whoever controls that origin. The runtime is now served from the vendored copy with integrity pinned to digests committed in provenance.json, and a build-time check reports drift instead of letting it fail SRI in visitors' browsers.

Remote loading is now explicit opt-in (al_folio.distill.allow_remote_loader, default false), and sync_distill.sh exits non-zero if a future re-sync reintroduces the remote loader.

Note for existing sites: if your _config.yml still has al_folio.distill.allow_remote_loader: true, set it to false. Under 1.0.2 that flag was inert; under 1.0.3 leaving it true opts you back out of the protection. bundle exec al-folio upgrade audit reports this as a blocking finding.

πŸ› Bug fixes

Repository cards were completely blank (al_folio_core 1.0.12) β€” two causes. The public github-readme-stats.vercel.app instance has been unreliable for a long time; the default is now the API-compatible, actively maintained github-stats-extended.vercel.app fork, so every existing query parameter keeps working. Separately, the service URL was interpolated straight from site.external_services.*, so a site generated from the template without that block emitted a relative /api/pin/?… URL and every card 404'd regardless of upstream health. It now resolves through a default: fallback and remains overridable for self-hosting. (al-org-dev/al-folio-core#26)

Mobile submenus rendered off-screen (al_folio_core 1.0.12) β€” inside the collapsed navbar the dropdown inherited position: absolute and right: 0 from the base Tailwind rule, anchoring it past the left edge of the viewport (measured at left: -85.7px on a 393px screen). Below the sm breakpoint the menu is now statically positioned, left-aligned, wraps long entries, and spans the full navbar width. Fixes [#3663] β€” thanks @bibliophilecoder.

Link previews shared without an image (al_folio_core 1.0.12) β€” og:image and twitter:image emitted relative asset paths, which external scrapers (Discord, LinkedIn, Mastodon, Slack) cannot resolve. Relative values are now prefixed with site.url + site.baseurl, matching how og:url is already built; already-absolute values are left untouched so a CDN URL is not double-prefixed. Fixes [#3666].

CV entries with a bare date rendered no date badge (al_folio_cv 1.0.2) β€” three of the five CV sections read only start_date/startDate, so a RenderCV entry carrying a single date: showed nothing. Because al_cv_sort_by_date already sorted on that key, such an entry was silently moved into chronological position while displaying nothing to explain why. Projects gained date rendering entirely. Fixes [#3339]. A second bug fell out of the same pass: {% capture %} retains surrounding whitespace, so the emptiness test in the awards and publications sections was never true and undated entries rendered an empty badge column.

CV entries rendered in source order (al_folio_cv 1.0.1) β€” volunteering was always appended after work history instead of being interleaved chronologically. Sorting is now handled by a new al_cv_sort_by_date filter that understands both RenderCV and JSONResume key names, partial dates (2020, 2020-06), YAML date objects, textual present end dates, and undated entries. Also fixed dangling date separators: an entry with no end date renders Present, an entry with no dates renders no badge, and an entry with no location no longer renders a lone map-pin row.

External posts published with empty titles (al_ext_posts 1.0.3) β€” when a fetch degraded (unreachable page, no <title>, blank RSS item) the post rendered as a blank but clickable row in the blog index and produced a stream of Empty `slug` generated warnings. A readable title is now derived from the URL's last meaningful path segment and a warning naming the URL is logged. Slugs and URLs are unchanged.

Unstyled popovers and tooltips (al_folio_core 1.0.11, pinned by [#3636]) β€” the vanilla fallback used when bootstrap-compat is disabled creates .af-popover / .af-tooltip elements in tooltips-setup.js, but they had no positioning or visual styling at all and appeared as unpositioned floating text.

Broken alt-text where a stat card failed (al_folio_core 1.0.11, pinned by [#3636]) β€” all repository stat-card images now carry an onerror handler, so when the external stat-card or trophy service is unavailable the card is hidden gracefully instead of showing broken alt-text.

✨ Improvements

  • Cloudflare Web Analytics support (al_analytics 1.0.2) β€” free, cookieless and unsampled. Set analytics.cloudflare to your beacon token. Fixes [#3351].
  • Simple Analytics support (al_analytics 1.0.1) β€” now documented, having shipped undiscoverable. Unlike every other provider it has no site ID to configure (it identifies a site by domain), so it is controlled by enable_simple_analytics alone.
  • Faster search-data generation (al_search 1.0.3) β€” the full site.pages scan used to find the home page title is replaced by a single filter chain, with regression coverage.
  • Self-hosted star history chart (#3684, [#3685]) β€” the README chart previously came from star-history.com, which was down. It is now generated in-repo by bin/generate_star_history.py (stdlib only, no dependencies), themed for light and dark, and refreshed automatically on every push to main plus weekly.

πŸ“š Documentation

A full pass for accuracy and agent-friendliness (#3681):

  • AGENTS.md is now the authoritative entry point for coding agents β€” change routing, the gem-ownership stop sign, the three silent failure modes, and the validated command set.
  • docs/ARCHITECTURE.md explains how the starter and gems fit together; docs/BOUNDARIES.md is the authoritative area-to-gem ownership table.
  • The showcase moved out of the README into docs/SHOWCASE.md.
  • Factual errors corrected throughout, and each fact now lives in exactly one place with links rather than restatements.

πŸ”§ Infrastructure

  • Release automation. No gem had ever been published from CI β€” which is why several sat unreleased on main while fixes shipped nowhere. All 16 plugin repos now have a tag-driven release.yml that verifies the tag matches the gemspec version, refuses to overwrite an already-published version, runs the test suite against the built artifact, and will not run from a fork.
  • Dependency bumps: nokogiri 1.19.3 β†’ 1.19.4 (#3653), concurrent-ruby 1.3.6 β†’ 1.3.7 (#3654), loofah 2.25.1 β†’ 2.25.2 (#3676), json 2.19.7 β†’ 2.19.9 (#3678).
  • Dead third_party_libraries.polyfill config entry removed now that nothing reads it.

⬆️ Upgrading

Because the pins are exact, upgrading is a two-step process. Running Bundler alone changes nothing.

1. Update the pins in your Gemfile to the v1.1 column in the table above. If you have not customised the file, copying the group :al_folio_plugins block from this release is the quickest way.

2. Update _config.yml:

:::yaml
al_folio:
  distill:
    allow_remote_loader: false # was true; leaving it true opts you out of the Distill hardening

You can also delete the now-unused third_party_libraries.polyfill entry β€” nothing reads it since al_math 1.0.2.

3. Then install and verify:

:::bash
bundle install
bundle exec al-folio upgrade audit

The audit reports a blocking finding while allow_remote_loader is still true, which is the backstop for step 2. To confirm the security fixes actually landed, check the resolved versions rather than assuming:

:::bash
bundle list | grep -E 'al_img_tools|al_math|al_folio_distill'

You want al_img_tools 1.0.3 or newer β€” that is the one carrying the CVSS 9.4 fix. Everything in this release is otherwise backwards compatible; no template, layout or content changes are required.


Full Changelog: https://github.com/alshedivat/al-folio/compare/v1.0...v1.1

Source: README.md, updated 2026-07-30