--- title: "Site Update: Rewrite in Rust" date: 2020-07-16 tags: - rust --- # Site Update: Rewrite in Rust Hello there! You are reading this post thanks to a lot of effort, research and consultation that has resulted in a complete from-scratch rewrite of this website in [Rust](https://rust-lang.org). The original implementation in Go is available [here](https://github.com/Xe/site/releases/tag/v1.5.0) should anyone want to reference that for any reason. If you find any issues with the [RSS feed](/blog.rss), [Atom feed](/blog.atom) or [JSONFeed](/blog.json), please let me know as soon as possible so I can fix them. This website stands on the shoulder of giants. Here are just a few of those and how they add up into this whole package. ## comrak All of my posts are written in [markdown](https://github.com/Xe/site/blob/master/blog/all-there-is-is-now-2019-05-25.markdown). [comrak](https://github.com/kivikakk/comrak) is a markdown parser written by a friend of mine that is as fast and as correct as possible. comrak does the job of turning all of that markdown (over 150 files at the time of writing this post) into the HTML that you are reading right now. It also supports a lot of common markdown extensions, which I use heavily in my posts. ## warp [warp](https://github.com/seanmonstar/warp) is the web framework I use for Rust. It gives users a set of filters that add up into entire web applications. For an example, see this example from its readme: ```rust use warp::Filter; #[tokio::main] async fn main() { // GET /hello/warp => 200 OK with body "Hello, warp!" let hello = warp::path!("hello" / String) .map(|name| format!("Hello, {}!", name)); warp::serve(hello) .run(([127, 0, 0, 1], 3030)) .await; } ``` This can then be built up into something like this: ```rust let site = index .or(contact.or(feeds).or(resume.or(signalboost)).or(patrons)) .or(blog_index.or(series.or(series_view).or(post_view))) .or(gallery_index.or(gallery_post_view)) .or(talk_index.or(talk_post_view)) .or(jsonfeed.or(atom).or(rss.or(sitemap))) .or(files.or(css).or(favicon).or(sw.or(robots))) .or(healthcheck.or(metrics_endpoint).or(go_vanity_jsonfeed)) // ... ``` which is the actual routing setup for this website! ## ructe In the previous version of this site, I used Go's [html/template](https://godoc.org/html/template). Rust does not have an equivalent of html/template in its standard library. After some research, I settled on [ructe](https://github.com/kaj/ructe) for the HTML templates. ructe works by preprocessing templates using a little domain-specific language that compiles down to Rust source code. This makes the templates become optimized with the rest of the program and enables my website to render most pages in less than 100 microseconds. Here is an example template (the one for [/patrons](/patrons)): ```html @use patreon::Users; @use super::{header_html, footer_html}; @(users: Users) @:header_html(Some("Patrons"), None)
These awesome people donate to me on Patreon. If you would like to show up in this list, please donate to me on Patreon. This is refreshed every time the site is deployed.