Repository navigation
Migrate xam.dk from Jekyll to Quarkus Roq - #227
Merged
Merged
Conversation
…ering - pom.xml/mvnw/.mvn + config/application.properties (Roq 2.1.9) - Qute layouts (default/home/page/post) + partials (head/navbar/footer/scripts/post-meta) - git mv _posts->content/posts, about/404/index into content/ - reuse _data via quarkus.roq.data.dir; site props in _data/siteConfig.yml - fix dup post (besog) and mixed asciidoc callouts - install Roq skill refs; plan in .specs roq generate: BUILD SUCCESS, 101 pages
- assets/ -> public/assets; compile _sass -> public/assets/main.css (build-css.sh) - static dirs (img images js qrcode userscripts) + files (avatar favicon etc) -> public/ - self-contained microsites (anabelle benjamin asylum tree) -> public/ as-is - asciidoc microsites (cape5 hibern8ide house surprise maxandersen) -> content/ directory pages - blog/wp-content -> public/blog/wp-content; split maxandersen .well-known -> public - drop obsolete pygments css link roq generate: BUILD SUCCESS, 109 pages, css+assets+microsites verified
- content/blog.html: paginated blog index (/blog/, /blog/pageN/) - content/rss.xml -> /blog/feed.atom (full content) - posts link /blog/:name/ (filename-based, matches old Jekyll :title URLs) - drop unused sitemap/tagging/aliases plugins (not in original site) - rewrite CI: jbang 'roq generate' + rsync to ssh.xam.dk:/www - move .htaccess -> public/; migrate draft with draft:true - remove Jekyll artifacts (Gemfile, _config*, _layouts, _includes, _plugins, Rakefile, _rake*, themes submodule, staticman.yml, etc.) roq generate: BUILD SUCCESS, 119 pages, all URLs verified
maxandersen
force-pushed
the
roq-migration
branch
2 times, most recently
from
October 3, 2026 21:47
7e6e20e to
f8eb19d
Compare
…ault + tests The old site was Jekyll + jekyll-asciidoc (AsciidoctorJ). Use 'quarkus-roq-plugin-asciidoc-jruby' so rendering matches by construction and we avoid per-gap workarounds for the default pure-Java engine (asciidoc-java): - single-line 'ifdef::env-github,...[:imagesdir: ..]' renders correctly (asciidoc-java silently dropped the whole body -> quarkiverse/quarkus-roq#1287); - 'video::[... width=640, height=480]' emits '<iframe width height>' like old; - content keeps original '= Title'/':page-*' headers (no block-form/YAML rewrites). AsciiDoc config (matches old behaviour): - quarkus.asciidoc.attributes.notitle=true (title once, in the masthead) - quarkus.asciidoc.attributes.icons=font (admonition <i class=fa icon-note>) - dropped redundant site.escaped-pages Also restored Jekyll's site-wide default masthead background as a root-layout frontmatter default (per-page backgrounds override). Testing: @RoqAndRoll generation test (8/8). Parity vs live: 0 URL drift (98/98 posts 200); per-page prose identical (the 2 flagged code-heavy posts differ only in code-highlighter markup, prose byte-identical). roq generate: BUILD SUCCESS.
maxandersen
force-pushed
the
roq-migration
branch
from
October 3, 2026 21:53
f8eb19d to
e73637c
Compare
New comments/webmentions can't be submitted anymore (staticman + jekyll-webmention_io are gone), but the old ones are preserved and displayed: - Consolidated _data/comments/<slug>/*.yml -> _data/comments.json and _data/webmentions/received.yml -> _data/mentions.json, both keyed by post URL path (the nested dirs registered as slash-named beans Qute can't navigate). 213 comments across 28 posts; 147 webmentions across 10 posts. - templates/partials/post-reactions.html renders them on each post (included in the post layout), with avatars/author/date and h-cite/h-card microformats. - Restored the webmention receiving endpoint (<link rel=webmention/pingback> -> webmention.io) in the head (was dropped in Phase A). - Styling in user.css; 3 new @RoqAndRoll tests (11/11 pass). e.g. /blog/the-black-swan-of-java/ shows 75 webmentions, /blog/new-job-at-jboss/ shows its comments.
Likes/reposts/mentions now render as a small avatar facepile with a one-line
count ('52 likes · 19 reposts · 1 mention') instead of a verbose row each, so
actual replies and comments stand out. Replies and comments keep full content.
- Regrouped _data/mentions.json by likes/reposts/links/replies (all keys always
present so Qute .size/iteration is null-safe).
- Rewrote post-reactions.html facepile + counts; facepile CSS in user.css.
Tests 11/11.
The webmention photos were all dead 'webmention.io/avatar/...' links (404; the proxy is gone), so broken <img>s were falling back to showing the author names. Replaced them with compact colored initials circles (computed into mentions.json, no external deps, always render). Comment avatars use the still-working disqus CDN and are kept as images. Tests 11/11.
Webmention photos now come from unavatar.io derived from each author's twitter handle (real current avatars; unavatar returns a default for dead accounts, never a broken link). Falls back to the colored initials circle via img onerror, and for the few non-twitter/no-url authors. New templates/partials/avatar.html. Tests 11/11.
Avatars were rendering at full source size. Fetch small images via unavatar '?size=96' and enforce explicit width/height on reaction avatars (facepile 32px, replies/comments 40px, object-fit: cover) so size is unambiguous even if an avatar source is large or CSS is stale. Tests 11/11.
- FetchAvatars.java (jbang, token-aware, idempotent): downloads unavatar.io photos once, resizes to 96px, caches in public/avatars/, rewrites _data/mentions.json to local /avatars/*.jpg (dead accounts -> initials). No runtime dependency / rate limits. 86 avatars cached (348K); 10 dead -> initials. - avatar.html partial: <img> local photo with initials-circle onerror fallback. - CSS: consolidated; classic circular avatars, smaller overlapping facepile (24px) with white ring, 36px comment/reply avatars. Tests 11/11.
Staticman comment submission is gone (staticman.yml removed in Phase C), so: - drop the dangling staticman endpoint + unused recaptcha keys from _data/config.yml - remove the dead contact-form block + unconditional recaptcha api.js from scripts.html (no contact page exists; form never rendered) Tests 11/11.
Only the referenced minified assets + webfonts are kept; dropped dev/source artifacts that were copied in from the Jekyll theme and never served: - bootstrap non-min css/js, bootstrap-grid/-reboot, bootstrap.js/bundle.js - font-awesome non-min css, FontAwesome.otf, less/ and scss/ sources - jquery.js (non-min), jqBootstrapValidation.js (contact form gone) - clean-blog scss/ sources, public/assets/main.scss (we compile _sass->main.css) - img/ theme samples (about-bg2, contact-bg, post-sample-image) public/assets 1.3M. Tests 11/11.
Jekyll relativize ensured links worked under any base path. Roq equivalent: site.url(path)/page.url emit host-relative paths that honor site.path-prefix. Converted all hardcoded /... links+assets (head, navbar, footer, scripts, home/page/post layouts, avatar partial, social links) to site.url(...). External/mailto URLs pass through unchanged. At root output is identical; setting site.path-prefix=/sub now relocates everything (verified -> /sub/...). Tests 11/11.
Restores Jekyll's relativize_url behavior so the site is portable under any base
path (and file://) with no config. UrlExtensions adds page.rel(target) (Qute
template extension) computing a path relative to the current page via
java.nio.file.Path.relativize; external/mailto/anchor pass through. All templates
now use {=page.rel(...)} for internal links/assets/backgrounds/avatars/social;
post/prev/next links relativized too; u-url uses page.url.absolute. Includes a
self-test (main) verifying relativize round-trips via URI.resolve.
Verified: 2868 generated local links resolve to existing files. Also fixed a
stray 'kk' typo in home.html masthead. Tests 11/11.
… .adoc link - image::images/… -> image::/images/… so they resolve (matches the /images/ convention used by all other posts); affected flamegraph.png and quoting-ios.png - jbang-everywhere: link:…unleashing….adoc[] -> link:/blog/unleasing-the-scripting-powers-of-java/[] Remaining unresolved links are all in the archived asylum/ microsite (dead index.php + Scripts/), left as-is. Tests 11/11.
Pure AsciiDoc (native = Title / :page-*: header, no YAML frontmatter) telling the migration story and calling out: no frontmatter needed, relativize via a Qute template extension (with the in-content caveat), restored read-only comments/ webmentions, and the cleanup.
The compiler-plugin runs now that there's a Java source (UrlExtensions); CI was on JDK 21 -> 'release version 25 not supported'. Bump setup-java to 25.
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.
Migrate xam.dk from Jekyll to Quarkus Roq
Converts the site from Jekyll 4.3 (clean-blog theme) to Quarkus Roq 2.1.9, preserving every URL and all content.
What changed
pom.xml, Maven wrapper,config/application.properties(Roq 2.1.9 / Quarkus 3.40.1 / Java 21+).default/home/page/post) + partials (head/navbar/footer/scripts/post-meta).content/viagit mv(history preserved). AsciiDoc posts keep their original= Title/:page-*headers._data/reused in place (quarkus.roq.data.dir=_data); site props in_data/siteConfig.yml.assets/→public/assets/; SCSS compiled once topublic/assets/main.css(build-css.sh). Static dirs/microsites moved topublic/(static) orcontent/(AsciiDoc pages)./blog/,/blog/pageN/), RSS at the original/blog/feed.atom, post URLs/blog/<name>/(match old Jekyll permalinks), site-wide default masthead background preserved via a root-layout frontmatter default..github/workflows/deploy.ymlnow builds via jbangroq generateand rsyncstarget/roq/to the samessh.xam.dk:/wwwtarget (unchanged excludes)._config*,_layouts,_includes,_plugins, Rakefile, theme submodule, …).AsciiDoc: use the jruby plugin (AsciidoctorJ)
The old site was Jekyll + jekyll-asciidoc = AsciidoctorJ. The default Roq plugin uses Yupiik
asciidoc-java(pure Java), which has rendering gaps vs AsciidoctorJ (single-lineifdefdrops the whole body — quarkus-roq#1287;video::dropswidth/height; admonition markup differs). To match the old site by construction and avoid per-gap hacks, this usesquarkus-roq-plugin-asciidoc-jruby:ifdefrenders correctly (content unchanged);video::[... width=640, height=480]emits<iframe width height>as before;quarkus.asciidoc.attributes.notitle=true(title once, in the masthead) andicons=font(admonition<i class="fa icon-note">), matching old behaviour;site.escaped-pages.Trade-off: bundles a JRuby runtime (heavier than pure Java), acceptable for a personal blog.
Historical comments + webmentions (read-only)
New comments/webmentions can't be submitted (staticman + jekyll-webmention_io are gone), but the old ones are preserved:
_data/comments/and_data/webmentions/received.ymlwere consolidated into_data/comments.json/_data/mentions.json(keyed by post URL) and rendered viatemplates/partials/post-reactions.html(213 comments, 147 webmentions). Likes/reposts/mentions show as a compact facepile with counts; replies and comments show full text. Author avatars are cached locally inpublic/avatars/(96px) by the one-off jbang scriptFetchAvatars.java(unavatar.io, token-aware, idempotent) — no runtime dependency; dead accounts fall back to initials circles. The webmention receiving<link rel="webmention">endpoint is kept in the head.Cleanup of unused code/assets
less//scss/sources,jqBootstrapValidation.js,public/assets/main.scss, and clean-blog theme sample images. Only referenced minified assets + webfonts remain (public/assets~1.3M).Testing
@RoqAndRollgeneration test (src/test/java/dk/xam/SiteGenerationTest.java) — 8/8 pass; guards body rendering, no duplicate title, default background, pagination, RSS, microsites.roq generate: BUILD SUCCESS, 119 pages.See
.specs/roq-migration.mdfor the full plan, testing method, known corner-cuts, and follow-ups (e.g. Font Awesomeicon-noteglyph CSS).