
The New Foojay.io: Generated by Hugo, Maintained by Java
Publishing an article on Foojay used to mean creating an account, learning a web editor, and hoping your code blocks survived the formatting. Since this week it means opening a pull request. Foojay.io runs as a static site now, Hugo generates it from a public Git repository , and every article keeps the address it always had.
I wrote the full story on Foojay itself in Announcing The New Foojay . Here I want to highlight the part that fits this blog best, so the Java tooling that keeps the site running.
One evening that got out of hand
WordPress served Foojay for six years and more than 2000 articles. But the plugin updates, the page load times, and the effort for every small feature kept growing. One evening I got fed up with a recurring issue and started a small experiment to see how far Hugo could take the content. At 03:00 that night I knew it could work, including a full import of every article, a content cleanup, and a few features I had wanted for years.
What you notice as a visitor
- Pages load faster, because GitHub Pages serves plain HTML.
- Search runs in your browser against a static index.
- 100 podcast episodes carry a transcript on the page, roughly 824,000 words you can skim, search, or quote from.
- The JUG directory comes from the community-run World Wide JUGs repository, so a JUG lead corrects an entry at the source instead of asking us.
- The calendar reads the iCal feed each JUG publishes. 102 JUGs sit in the directory, and 70 of them publish a feed we can read.
- Comments live in GitHub Discussions, and the 580 comments from the old site stay with each article as an archive.
- A small Cloudflare Worker counts the reads. It stores a page key and a number, no cookie and no IP address. All 13.8 million existing reads moved along, so nobody’s article went back to zero.
- The site targets WCAG 2.2 AA, and the accessibility statement says where it actually stands.
Every legacy path still resolves, including the old /blog/ scheme and the slugs that changed years ago. All 2250 articles, 350 author profiles, 50 JVM terms
, the JUG directory, and the sponsors came across.
Your article is a folder
An article on the new Foojay is a folder with an index.md or index.adoc and the images next to the text. The folder name becomes the URL. The frontmatter asks for six things: title, date, description, author, hero image, and categories. Foojay derives the rest.
Open a pull request and a check reads your frontmatter and builds the whole site. A mistyped author slug or a forgotten image shows up in about a minute, from a robot, before a human spends time on it. The submit guide covers the three ways to get your article in, including a plain e-mail with a zip.
The Java part
Hugo generates the pages. Java does everything else. Each script is a single file that runs on JBang
, so no pom.xml and no build step:
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS org.jsoup:jsoup:1.17.2
//DEPS com.vladsch.flexmark:flexmark-html2md-converter:0.64.8
//JAVA 21+
Four groups of scripts do the work:
- The migration. jsoup parses the WordPress HTML, flexmark converts it to Markdown, and Jackson plus SnakeYAML handle the JSON and YAML. I ran the import again and again until the cutover, which kept the old site live during the whole rebuild.
- The daily syncs. One script pulls the JUG directory and the Java Champions list from the community repositories that own that data. A second one walks the iCal feeds. A third refreshes the read counts four times a day.
- The transcripts. YouTube already recognised the speech for every podcast episode, so a script fetches those captions and writes a
transcript.mdnext to the episode. That takes seconds per episode instead of hours of local compute. The page renders the transcript because the file exists, so no flag needs setting. - The checks. On every pull request, a script validates the frontmatter and builds all pages. On the built site, another one resolves every internal link against the files on disk, half a million of them in about five seconds. Around 40 browser checks then click through the finished site, because search, the two world maps, and the image lightbox all fail the same quiet way: the page returns 200, looks complete, and stops doing its job.
All of it sits in the scripts/ directory of the repository, so you can read what runs.
Why Hugo and not a Java generator
Foojay is the website for the Friends of OpenJDK, so a Java generator looked like the obvious choice. I had tried JBake before, and at the time it looked quiet, with no release between early 2023 and late 2025. Credit where it is due, it shipped 2.7.0 since. Someone on the Foojay Slack pointed me at Roq , the Quarkus-based generator that renders Markdown through Qute templates. It looks genuinely good, and if you want the generator itself in Java, start there.
I went with the tool I already know. Hugo runs this blog , pi4j.com , lottie4j.com , and melodymatrix.rocks . For a community project that has to stand in ten years, “I know this tool and it keeps getting maintained” beats “this is the most interesting choice”. And as the four script groups above show, the generator is the smallest part of the job.
The calendar makes the difference visible
The old Foojay calendar needed somebody to type every JUG into WordPress. September 2026 got 11 entries that way. The new calendar reads the JUG feeds once a day and shows 23 entries for the same month, none of them typed in. Both screenshots below show September 2026, taken on the first of the month.
A tour of the result
What it cost
Two numbers, because “a few weeks with a small budget” says nothing on its own. About 100 hours across two months, a lot of that outside working hours. And roughly $1000 of AI model usage at published token prices. I described what I needed, Claude wrote the scripts, and I reviewed and adjusted until the output matched the site I wanted. Three years ago this rebuild needed a big budget and a team.
Come and write
The barrier to publishing on Foojay is now a pull request, and that changes who can contribute. If you ever thought “someone should write that up”, copy a file from the template folder , fill it in, and open the pull request. A JVM flag that saved you a week counts. So does a conference report, or a library nobody knows about.
Spotted a typo in an article, in mine or in someone else’s? Every page carries an Edit this page on GitHub link that turns your fix into a pull request in three clicks. Something broken or missing goes in an issue .