Repository navigation
Convert the website from Jekyll to Hugo + Hextra - #273
Draft
garth-wells wants to merge 29 commits into
Draft
garth-wells wants to merge 29 commits into
garth-wells wants to merge 29 commits into
Conversation
The site is now built with Hugo using the Hextra theme, replacing the Jekyll setup. Every page keeps the address it had before. Content moves to content/, with Jekyll's `permalink` becoming Hugo's `url` and `image-zoom: fill` becoming `imageFit: cover`. Links between pages are now written as full addresses rather than relative paths to .md files. The Liquid includes become Hugo shortcodes (`paper`, `person`, `quote`, `image`, `buttons`/`button`), and the 250-branch country include becomes a data file read by the `person` shortcode. The page header (background image, title, subtitle) is a partial inserted below the navigation bar, so pages keep their hero images. Font Awesome (2114 files, 27MB) is dropped in favour of the icon set that ships with the theme. The hand-rolled photo gallery on the FEniCS 2026 page uses Hextra's `gallery` shortcode, and YouTube embeds use Hugo's `youtube` shortcode. Inline maths is now delimited by \( \) only, so that dollar amounts such as $500 are no longer parsed as maths. The build workflow uses Hugo, and a new deploy workflow publishes to GitHub Pages; this needs Settings -> Pages -> Source set to "GitHub Actions". The tests read hugo.yaml and Hugo front matter. test_links previously recursed into subdirectories using a path relative to the working directory rather than to the directory being walked, so it only ever checked the top-level pages; it now checks all of them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The maths section was wrong on two counts: the delimiters are written with a single backslash in the markdown source, and `math: true` is not needed, because Hextra's render hook loads KaTeX whenever a page actually contains maths. Drop the setting from the FEniCS 2026 page, where it was a no-op. Also document the three `imageFit` values rather than two, `aliases`, `headerLogo` and `hideHeader`, how pages are named and arranged in `content`, `data/flags.yaml`, `weight` in the navigation bar, how to update the theme, and how to run the tests. Fix three typos carried over from the previous README. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The build instructions only covered Ubuntu. Add the Homebrew packages for macOS, and say how to check that Hugo is the extended edition rather than naming the editions of particular packages. Split the section so that serving the website locally is its own step, with the address to open and a note that the first run downloads the theme. Pages link to each other by absolute address, so opening the built files directly does not work; say so, and give the command to serve the `public` folder instead. Use `python3` rather than `python` throughout, as macOS has no `python` on the path. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
jorgensd
reviewed
Oct 10, 2026
| steps: | ||
| - run: sudo apt-get install -y ruby-bundler | ||
| name: Install prerequisites | ||
| - uses: actions/checkout@v4 |
Member
There was a problem hiding this comment.
Since you are updating things, please update this to v7 (and maybe add a dependabot?
jorgensd
reviewed
Oct 10, 2026
| - run: bundle exec jekyll build | ||
|
|
||
| - uses: actions/setup-go@v5 | ||
| name: Install Go (needed to fetch the Hextra theme module) |
Put a blank line after every heading, wrap prose at 80 columns, give every fenced block a language, and use `1.` rather than `1)` for numbered steps. Break the list of shortcodes out of a long parenthetical sentence into a list, and wrap the example over two lines so that it fits; shortcodes may be written either way. No wording changes. markdownlint reports no issues. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The header used to float a 90%-opaque white panel over the background image. Against the FEniCS pattern that left the title washed out, and on the front page the logo all but disappeared into the field of the same artwork behind it. Instead, draw the image through a pseudo-element with a dark gradient scrim over it and set the title in white. The title is legible whatever the image behind it, the venue photographs read properly, and the header now looks the same in light and dark mode. The front page blurs its background so that the logo stands clear of the pattern. The header was also 540px tall, which pushed the content of every page below the fold; it is now 330px, or 260px where there is no subtitle. Elsewhere: - Cap the text measure at 52rem. Pages without a table of contents beside them were setting prose across the full 1000px column. - Make the front page's icon links look like the links they are: bordered cards with the icon in the brand blue and a hover state, laid out on a grid rather than as bare 80px glyphs. - Keep centred images to 30rem, so a sponsor logo no longer fills the column. - Centre a person's role and links under their centred name. Six pages opened with a `#` heading that repeated the page title and outranked the `##` sections beside it, so "Description" was set larger than the "Updates" above it and was missing from the contents list. Demote those to `##`. documentation/v0_9_0.md keeps its `#` headings, which genuinely outrank their children. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The reference site uses no web fonts: it is Hextra with the stock `ui-sans-serif, system-ui, …` stack, which is what this website already had. That resolves to SF Pro on macOS, but to Segoe UI on Windows and usually Cantarell or DejaVu on Linux, so most FEniCS users were not seeing the face it looks like in a Mac browser. Pin Inter instead, which is drawn along the same lines as SF Pro, so the result is close to the macOS rendering for everyone. The old Jekyll site set its headings in Lato; this replaces that, rather than leaving the fonts to the visitor's operating system. The font is served from static/assets/fonts rather than from Google Fonts, so that opening a page makes no third-party request. It is the variable font, covering every weight the website uses in one file, and it is split by unicode-range: the content currently has no Latin Extended characters, so browsers fetch only the 48KB Latin file, and the 85KB Latin Extended file is there for names that need it later. The Latin file is preloaded so that text is not first painted in the fallback face. Inter is used under the SIL Open Font License; the licence and the provenance of the files are in static/assets/fonts. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Follow the pattern golangci-lint.run uses: the note about the website stays on the left of the footer and the places the project can be found sit on the right, as icons. Below 640px the two stack and centre. The icons come from the theme's own set, so this adds no new assets, and they link to the same two addresses the front page already uses. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
They are in the footer of every page now, so the front page no longer needs a row of its own for them. That leaves one row of three for the things a visitor is most likely to want: Download, Documentation and the source code. Slack is still linked from the community page, and both are still linked from the footer. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The front page was 139 words with no code and no picture of a result,
which for a finite element library leaves out the whole argument. The
Stokes example and the two figures it used were already in the
repository but had been dropped from the page at some point and were
referenced by nothing.
Restore them, with the code brought up to the current API: the legacy
version used VectorElement, P2 * P1 and solve(), none of which exist in
DOLFINx. The snippet now follows the 0.11 Stokes demo, which it links
to, and the variational form above it matches the code sign for sign.
Sharing:
- No page had an og:image, so a link posted to Slack or LinkedIn showed
as a bare title. Add a share card, drawn the same way as the front
page header so that a shared link looks like the website, and point
site.Params.images at it; Hextra then fills in og:image, twitter:image
and upgrades the card to summary_large_image.
- No page set a description, so the meta description was an excerpt
starting mid-sentence ("Getting started The latest stable release
of..."). Write one for each of the main pages.
Also:
- The conference archive was a flat list of 23 entries where live links
and dead ones read alike. Lay the linked ones out as cards and keep
the rest as a short tail.
- Remove 3.3MB of images that nothing references, including the old
front page header, a superseded crop of the BAM photograph, and seven
portraits orphaned when the unused _developer include went. They
remain in the history if they are wanted again.
- dolfinxversion builds the URL of the DOLFINx documentation but, unlike
fenicsxversion, no test covered it, so it could have gone stale
silently. Check it against the released tags.
- The gallery photographs had alt text of "Photo 1", "Photo 12", which
tells a screen reader nothing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
"FEniCSx 0.11" sat under the title of those two pages. Both say which release is current in their first sentence, where it reads as a fact rather than as a label, so the header was repeating itself. The pages now use the shorter header, as the other pages without a subtitle do. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The figure shows three spheres, not two: the demo it came from placed s0, s1 and s2 in the channel, and brightening the image confirms the third behind the other two. Also spell 24,000 with a separator and rewrap the opening paragraph, which had a line left at 97 characters. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
At the foot of the front page the logo acknowledges NumFOCUS's support, so it was being drawn at the default 480px and dominating the section it sits under. Set it to 260px. The conference and GSoC pages are left alone: there the logo is one of a row of sponsors and should match the others. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- "Travel support applications opens" -> "open". - "We thank [Ridgway Scott Foundation]" -> "the Ridgway Scott Foundation", as the other conference pages and the foundation itself write it, and make "Best Presentation" singular to match the heading above it. - The registration fee was said to open and stay open; registration does. Recast those two lines. - Write the application address as a Markdown link, as the organising committee's addresses lower down already are. - Indent a list continuation line, and drop a stray blank line between the two sponsor blocks. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The page now reads in the order a reader needs it: what the conference is, how to take part, where it is, what is recognised, and then the administrative sections. Three moves: - Abstract submission now comes before Travel awards. A travel award application has to include "a tentative abstract ... which will also need to be formally submitted once abstract submission opens", so the reader was meeting that forward reference several sections before the one it points at. - "Getting there", which is still commented out, sat after Abstract submission. It belongs under Conference venue, which it continues, so that it is in the right place when it is written. - Code of conduct was wedged between Abstract submission and the awards. It is administrative, so it now sits with the other administrative sections near the end. No wording is changed: the text is the same word for word, only moved. Note that the previous order matched the FEniCS 2025 page almost exactly, so 2025 will now read differently; it would be worth making the same moves there if this order is preferred. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Front page: drop the "The FEniCS computing platform" heading, which repeated the title in the header above it. Download: remove the "FEniCSx vs legacy FEniCS" section, scope the complex number heading to Debian/Ubuntu, and rewrap the prose. FEniCS 2027: comment out the Updates section and the Description heading until there is news to carry, and move the link to previous conferences into a section of its own at the end.
The download page no longer points at them, and the project recommends FEniCSx to new users, so the page was unreachable except by an old link or bookmark. Redirect /download/archive/ to the download page rather than letting it 404, since the page has been at that address for years. The legacy library is still covered elsewhere: its citations, its documentation and what becomes of its packages. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The project posts conference talks there, and the FEniCS 2024 and 2026 pages already embed videos from it, so it belongs beside LinkedIn and Slack. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nothing on the website said that the next conference is in Berlin or that travel award applications close on 10 January 2027; the only sign of it was a navigation bar entry. Put it in Hextra's banner, which is a dismissible strip above the navigation bar on every page, and link it to the travel awards section. The key means a later message is shown again to anyone who closed this one, and deleting the block takes the banner down. The FEniCSx tutorial is the most useful thing to hand a newcomer, and it was reachable only through the documentation page. It now has a card of its own on the front page, second after Download, which is the order somebody new reads them in. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
garth-wells
force-pushed
the
hextra-conversion
branch
from
October 10, 2026 22:21
5aa88a2 to
5a2c8b9
Compare
Remove the "FEniCSx vs legacy FEniCS" section from the documentation page, fold the tutorial into the paragraph about the documentation, and take the Tutorial card off the front page again.
checkout, setup-go and upload-artifact move to v7, upload-pages-artifact to v5 and deploy-pages to v5; Go moves from 1.23 to 1.27. Hugo stays at 0.167.0, which is still the current release. upload-pages-artifact stopped including dotfiles at v4. The built site has none, so nothing is lost; if that changes, the action takes an include-hidden-files input from v5. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Output is unchanged: all 32 pages are byte-identical to the previous
build once the stylesheet fingerprint is normalised, and the only change
to the compiled CSS is the three dropped !important.
Templates:
- Delete layouts/baseof.html. It was a copy of Hextra's whole page
skeleton existing only to insert the page header after the navbar, and
the header sits in exactly the same place when it is the first thing
inside `define "main"`. One fewer theme file to keep in step.
- home.html, list.html and single.html were three byte-identical copies
of Hextra's article scaffolding. The body moves to
partials/page-body.html and each layout becomes two lines. (The three
files have to stay: Hugo's lookup prefers the theme's own home.html
and list.html over a project-wide template.)
- page-header.html: drop `hideHeader`, which no page used and which
indented the whole partial, and the `$fallbackSubtitle` variable that
existed only to carry the 404 subtitle forward. Subtitles now go
through RenderString, so `{{< param fenicsxversion >}}` works there as
it does in a page body, in place of a private {token} syntax that
understood two names.
- person.html: the website, GitHub, Twitter and LinkedIn blocks were the
same markup four times. One range over a slice of dicts, as
custom/footer.html already does.
Config: remove 15 keys from hugo.yaml that restate a Hugo or Hextra
default and so only pin behaviour that would otherwise follow the theme.
CSS: remove all three !important. Each fought a theme rule that does not
apply -- two are excluded by the theme's own :not(.not-prose) selector,
and the third is beaten on source order anyway, since custom.css is
concatenated after the theme's stylesheet.
JavaScript: 404-redirect.js had a branch for the bare prefix ("pub")
beside the general one, but substring gives the empty string there, so
the general branch already covered it.
Tests: extract the duplicated hugo.yaml and GitHub-client setup in
test_version_numbers.py into helpers. In test_links.py, stop re-reading
and re-parsing every page three times, and make the duplicate-URL check
one assertion that names the offending URL rather than one test per
page.
CI: the Hugo version was pinned in two workflows that would drift. Both
now use a composite action that holds it once. build.yml no longer
builds main, which deploy.yml already builds, so a merge runs one build
rather than two, and its artifact expires after a week.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The site rendered every page through copies of Hextra's own templates, taken so that the title could be replaced by a full-width header band. Those copies go silently stale whenever the theme changes its page scaffolding, which is the whole maintenance cost of forking a theme. Use the theme's templates and its documented hooks instead: - custom/page-begin.html puts the banner image above the title. - custom/content-begin.html puts the subtitle below it. - Hextra renders the title itself, so nothing has to suppress its <h1> and no CSS fights the theme. The band therefore sits inside the content column rather than spanning the window, and is styled as a rounded banner. The front page keeps its blurred background and logo. Section pages (the _index.md files) get `layout: single` in their front matter: without it Hextra lays them out as documentation index pages, with a left sidebar and a left-aligned title, which looked nothing like the rest of the site. layouts/404.html stays, and is the only file left that borrows theme markup. Hextra's 404 is a standalone document that goes through no hooks, so replacing it with the theme's would drop the site chrome and, more to the point, the script that redirects the legacy /pub/, /olddocs/ and /qa/ addresses. Its comment now says so. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Notes for coding agents working in this repository. README.md already explains page settings and how to build, so this covers what it does not: how to check a change, the rules that keep the theme unforked, and the handful of traps that otherwise cost an hour each -- the maths delimiter that Markdown steals, the bibliography tool that overwrites a curated file, the version tests that rate-limit against the GitHub API, and the footer that no headless screenshot can see. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The rule was there but read as a note about vendoring. State it as the first rule, covering Hugo as well as the theme, and list what the repository does own so that the boundary is unambiguous. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The leading underscore was Jekyll's marker for "do not publish this directory". Hugo has no such rule -- it publishes content/ and static/ and ignores everything else -- so the underscores had stopped meaning anything and only made the two directories look special. Nothing is published from either directory before or after, so no address on the website changes. The paths the scripts resolve are relative to their own file and the directories kept their depth, so those are untouched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Each reference was a single run of text between two blue bars, with the title buried mid-sentence and the DOI and arXiv links wrapped in square brackets. The right-hand bar also sat wherever the full-width box ended, which was rarely near the text. Give each one the shape a reader scans: title first, then the authors, then the venue and year, with the links as small labelled buttons. One accent bar on the left, and the :target highlight stays, so a link straight to a citation still shows which one it landed on. The shortcode takes exactly the same parameters, so no citation changes and tools/make_bibtex.py, which reads the markdown rather than the rendered page, is unaffected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rebuilds the site with Hugo and the
Hextra theme, replacing Jekyll.
Every page keeps the address it had before. All 34 URLs (pages and
assets) were checked against the running site, including the old
/conference/pages_2024/schedule.html, which now redirects.What moved where
_config.ymlhugo.yaml.mdfiles in the repo root and subfolderscontent/permalink:url:image-zoom: fillimageFit: cover_layouts/,_includes/layouts/_includes/_paper.htmletc.layouts/_shortcodes/_includes/_country.htmldata/flags.yaml_data/navbar.ymlmenu.maininhugo.yamlassets/(served as-is)static/assets/css/customsty.cssassets/css/custom.cssLinks between pages are now written as full addresses (
/download/)rather than relative paths to
.mdfiles.Look and feel
The page header (background image, title, subtitle) is a partial
inserted below the navigation bar, so pages keep their hero images and
the front page keeps the logo. Hextra adds site search, a dark-mode
toggle (light by default) and a per-page contents list.
The Liquid includes become shortcodes:
paper,person,quote,image, andbuttons/button._developer.htmlwas unused and hasbeen dropped. Each shortcode documents the settings it takes.
Judgement calls worth a look
of which the theme already ships.
\( \)only, not$ … $. The old MathJaxsettings treated
$as a delimiter, so($500)…($500)on theFEniCS 2026 page is currently being swallowed as maths on the live
site. Dollar amounts are now left alone; the one real formula on that
page became
\(\varphi\).load_page_listtestedos.path.isdir(f)against the working directory rather than thedirectory being walked, so it never recursed and only ever checked the
two top-level pages. It now checks all of them, and
href/srcattributes as well. Links inside HTML comments are skipped, since the
2027 page has a commented-out draft containing a placeholder URL.
galleryshortcode, and the YouTube embeds use Hugo'syoutubeshortcode.
_tools/make_bibtex.pyhas been pointed at the new paths but notrun: the committed
citations.bibis hand-curated (fuller authornames, a legacy section) and the tool would overwrite it with a
reduced version. That mismatch predates this change, but it may be
worth deciding whether the tool should still exist.
Before merging
GitHub Pages can no longer build this itself.
.github/workflows/deploy.ymlpublishes the site, but only once Settings → Pages → Source is
switched from "Deploy from a branch" to "GitHub Actions". Until that
is changed, pushes to
mainwill build but not publish.Checks
A clean clone builds with
hugo --minify --printPathWarnings --panicOnWarningwith no warnings, and_test/passes (103 tests,flake8 clean).
🤖 Generated with Claude Code