ben.enterprises | RSS

Obligatory Meta First Post About Creating This Blog

Java Is All You Need

Published:

The first post on every blog is about the tech stack used to create said blog: this blog is no exception.

Java SSG

The site is generated via a handwritten Static Site Generator (SSG) in Java1 without any additional libraries. Every blog post is stored as a Java record: public static record BlogArticle ( String path, String title, String subtitle, Time publicationDate, Time lastEdited, String body, List<FootNote> footnotes ) { } public static record FootNote(String tag, String body) { } public record Time(int year, int month, int day) { /* Omitted */ } Instead of implementing some sort of file reading system, the blog posts themselves are Java code too! public class HelloBlog { public static BlogArticle ARTICLE = new BlogArticle( "hello-blog", "Obligatory Meta First Post About Creating This Blog", "Java Is All You Need", new Time(2024, 11, 23), new Time(2024, 11, 23), """ <p> Yap yap yap &FOOT[yap] </p> """, List.of( new FootNote( "yap", "Footnotes :)" ) ) } Every blog post is then turned into the final page you are currently seeing with some simple Java code to add header and footer, set up the footnotes, etc.

RSS

Like all blogs, there needed to be an RSS2 feed that nobody actually uses. Following the RSS 2.0 Spec to implement the RSS feed generation was fairly simple. The trickiest part was correctly generating the dates. RSS uses the date format from RFC822: Standard for ARPA Internet Text Messages with the additional modification that you can (and should) use a four-digit year if you are no longer living in the 90s. Looking at other blogs, I was worried I would need to specify a day of the week, luckily RFC 822 makes this optional. RFC 822 also requires a time of day and timezone, so I just use "00:00 +0000".

Gotta Go Fast

I chose bunny.net to host this site for its globally low latency and reasonable pricing. I am still playing around with image compression. I am currently testing jpegli for JPEG, libjxl for JPEG-XL, and libavif/libaom for AVIF. Picture elements are used to provide modern image formats to browsers that support them3 and srcset is used to provide low-res versions of images for slow connections. Inspired by Dan Luu, I went with very minimal styling for this blog. The handful of CSS rules are inlined directly in the HTML head and there is no JS or web fonts. Pages without hundreds or thousands of KiB of CSS, JS, web fonts, and other sources of bloat load faster, especially on slower connections and low-performance devices. The entire text of Pride and Prejudice when compressed with brotli is 214 KiB, yet many blogs spend more than just to make sure you have their favorite fonts.

Things Not Worth Their Own Paragraph

It could be possible to further debloat the blog by removing unneeded whitespace and CSS rules through some sort of processing step, however removing all CSS and whitespace so on an earlier version of this page only saved <200 bytes after brotli compression. It's unfortunate that HTML does not have a built-in footnote system. I'm unhappy with how the codeblocks look on mobile, but I can't find any solutions that don't wrap each line in its own HTML tag and don't require JS. I applied a 70em max-width to this blog on the advice of a page with no max-width. I tried to obfuscate my email with some display:none <p>'s in the middle, I hope it works. Running a test server with Java's built-in web server is easy: SimpleFileServer.createFileServer(new InetSocketAddress(1984), Main.GEN_DIR, OutputLevel.VERBOSE).start();

  1. ^ The greatest programming language of all time*. Also, footnotes work :)
  2. ^ I elected not to implement Atom support because I'm not aware of anything notable that can consume Atom feeds but can't consume RSS 2.0 feeds
  3. ^ Currently only Safari supports JPEG-XL at the time of writing. https://caniuse.com/jpegxl AVIF is supported in all major browsers. https://caniuse.com/avif