{
  "created": "2026-10-10T12:41:55Z",
  "hierarchy": [
    {
      "name": "ROOT",
      "type": "folder",
      "uri": "/ROOT"
    },
    {
      "name": "Notes from Blog Engine Rewrite in Rust",
      "type": "article",
      "uri": "Notes_from_Blog_Engine_Rewrite_in_Rust"
    }
  ],
  "html": "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"/><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"/><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/><meta name=\"name\" content=\"Nikhil's Personal Wiki\"/><meta name=\"description\" content=\"Notes from Blog Engine Rewrite in Rust – Nikhil's Personal Wiki\"/><meta name=\"author\" content=\"Nikhil Anand\"/><meta name=\"theme-color\" content=\"#ffe9a00\"/><meta property=\"og:title\" content=\"Notes from Blog Engine Rewrite in Rust – Nikhil's Personal Wiki\"/><meta property=\"og:description\" content=\"Notes from Blog Engine Rewrite in Rust – Nikhil's Personal Wiki\"/><meta property=\"og:type\" content=\"website\"/><meta property=\"og:image\" content=\"/img/logo512.png\"/><meta property=\"og:site_name\" content=\"Nikhil's Personal Wiki\"/><link rel=\"og:image\" href=\"/img/logo512.png\"/><link rel=\"icon\" href=\"/img/favicon.png\"/><link rel=\"apple-touch-icon\" href=\"/img/logo192.png\"/><link rel=\"stylesheet\" href=\"/css/styles.css\"/><title>Notes from Blog Engine Rewrite in Rust – Nikhil's Personal Wiki</title><script defer data-domain=\"wiki.nikhil.io\" src=\"https://plausible.io/js/plausible.js\"></script></head><body><noscript>👉 A few things won't work if you have JavaScript disabled.</noscript><div class=\"container article\"><header><nav><ul><li><a href=\"/archive\" class title=\"Archive\"><span>Archive</span></a></li><li><a href=\"/Home\" class title=\"Home\"><span>Home</span></a></li><li><a href=\"/random\" class title=\"See a random article\"><span>Random</span></a></li><li><a href=\"/Notes_from_Blog_Engine_Rewrite_in_Rust/raw.txt\" title=\"View Source\"><span>Raw</span></a></li><li><a href=\"/Notes_from_Blog_Engine_Rewrite_in_Rust/revisions\" class title=\"View revisions\"><span>Revisions</span></a></li><li><a href=\"/Notes_from_Blog_Engine_Rewrite_in_Rust/index.json\" title=\"View JSON Object\"><span>JSON</span></a></li></ul></nav></header><main><article><article-hierarchy><ul><li><a data-entity-type=\"folder\" href=\"/ROOT\" title=\"ROOT\">Root</a></li><li><a data-entity-type=\"article\" href=\"/Notes_from_Blog_Engine_Rewrite_in_Rust\" title=\"Notes from Blog Engine Rewrite in Rust\">Notes from Blog Engine Rewrite in Rust</a></li></ul></article-hierarchy><header><h1>Notes from Blog Engine Rewrite in Rust</h1></header><article-content><!-- [[TOC]] -->\n<h2 id=\"motivation-and-problems\">Motivation and Problems</h2>\n<p>For the &ldquo;Love of the Game&rdquo;, the game being teaching myself enough Rust to have trenchant opinions on other languages. Things I&rsquo;d like it to do:</p>\n<ul>\n<li><strong>Markdown</strong>  Rendering.<br />\nThere&rsquo;s CommonMark and GFM. I have special markup that will require me to extend these. Not sure if I&rsquo;ll need <em>both</em> specs.</li>\n<li><strong>TSX</strong> for templating.<br />\nBecause I argue it&rsquo;s the best templating language ever.</li>\n<li><strong>SASS <em>and</em> Tailwind</strong> Rendering.<br />\nUse <code>grass</code> for the former.</li>\n<li><strong>Live-Reloading</strong><br />\nFor posts and all assets.</li>\n<li><strong>Asset Management</strong><br />\nThumbnails, optimized WebP generation, folder organization.</li>\n</ul>\n<h2 id=\"development-log-of-sorts\">Development Log (of sorts)</h2>\n<p>Ah the famous learning curve. But you can be very productive with Rust if you know what to focus on. For baby Rustaceans like me who&rsquo;re prototyping, the big things are:</p>\n<ul>\n<li>Not fighting the famed Borrow Checker</li>\n<li>Not using lifetimes as much as possible</li>\n<li>Just waving away any possible errors for now</li>\n<li>Knowing about and using popular libraries</li>\n</ul>\n<p>That&rsquo;s it. Concretely,</p>\n<ul>\n<li><code>clone</code> and <code>own</code> everything to avoid fighting the borrow checker and dealing with explicit lifetimes.</li>\n<li><code>unwrap</code> or <code>expect</code> to avoid handling the failure cases inside <code>Result</code> and <code>Option</code>.</li>\n</ul>\n<p>I&rsquo;ll add a few more:</p>\n<ul>\n<li>Use <code>String</code> instead of <code>&amp;str</code> (avoids borrowing/owning)</li>\n<li>Use <code>Vec&lt;T&gt;</code> to get owned collections (avoids borrowing/owning)</li>\n<li>Use <code>Arc&lt;T&gt;</code> to share <code>T</code> across threads (avoids lifetimes)</li>\n</ul>\n<p>So yeah, you&rsquo;re side-stepping what makes Rust &lsquo;great&rsquo; in the first place. But going back and dealing with these things is for the next iteration of your app. Super-easy to do so: <code>grep</code> for these things and work at them.</p>\n<h3 id=\"other-prototyping-shortcuts\">Other Prototyping Shortcuts</h3>\n<ul>\n<li>Use <code>dbg!</code> a lot.</li>\n<li>TODO: Complete this.</li>\n</ul>\n<h3 id=\"datetime\">Datetime</h3>\n<p>Rust&rsquo;s STDLIB is as shit as Python&rsquo;s with datetime manipulation (which is rather disappointing). Here&rsquo;s things it can and cannot do:</p>\n<table-wrapper>\n<table>\n<thead>\n<tr>\n<th>Action</th>\n<th>Can it?</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Current timestamp</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>Measure elapsed time</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>Add seconds to timestamp</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>Get year/month/day</td>\n<td>No</td>\n</tr>\n<tr>\n<td>Format as 2026-10-09</td>\n<td>No</td>\n</tr>\n<tr>\n<td>Parse ISO 8601 dates</td>\n<td>No</td>\n</tr>\n<tr>\n<td>Time zones</td>\n<td>No</td>\n</tr>\n<tr>\n<td>Calendar arithmetic</td>\n<td>No</td>\n</tr>\n</tbody>\n</table>\n</table-wrapper>\n<p>Like Python you are expected to use richer libraries: <code>chrono</code> or <code>jiff</code> (I like the latter.)</p>\n<h2 id=\"strings\">Strings</h2>\n<h3 id=\"concatenation\">Concatenation</h3>\n<p>Just use <code>format!()</code>. Rust&rsquo;s version of Python f-strings.</p>\n<p>Also, <code>.display()</code> returns <code>&amp;str</code> and <code>.to_str()</code> returns <code>Option&lt;&amp;str&gt;</code>. So you used:</p>\n<pre tabindex=\"0\" class=\"chroma\"><code><span class=\"line\"><span class=\"cl\"><span class=\"kd\">let</span><span class=\"w\"> </span><span class=\"n\">pattern</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"fm\">format!</span><span class=\"p\">(</span><span class=\"s\">&#34;{}/**/*.md&#34;</span><span class=\"p\">,</span><span class=\"w\"> </span><span class=\"n\">content_dir</span><span class=\"p\">.</span><span class=\"n\">display</span><span class=\"p\">());</span><span class=\"w\">\n</span></span></span></code></pre><p>Here&rsquo;s some concatenation drama:</p>\n<pre tabindex=\"0\" class=\"chroma\"><code><span class=\"line\"><span class=\"cl\"><span class=\"kd\">let</span><span class=\"w\"> </span><span class=\"n\">a</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"nb\">String</span>::<span class=\"n\">from</span><span class=\"p\">(</span><span class=\"s\">&#34;foo&#34;</span><span class=\"p\">);</span><span class=\"w\">\n</span></span></span><span class=\"line\"><span class=\"cl\"><span class=\"w\"></span><span class=\"kd\">let</span><span class=\"w\"> </span><span class=\"n\">s</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"n\">a</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"s\">&#34;/bar&#34;</span><span class=\"p\">;</span><span class=\"w\">            </span><span class=\"c1\">// ok: String + &amp;str\n</span></span></span><span class=\"line\"><span class=\"cl\"><span class=\"c1\"></span><span class=\"kd\">let</span><span class=\"w\"> </span><span class=\"n\">s</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">&#34;foo&#34;</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"s\">&#34;bar&#34;</span><span class=\"p\">;</span><span class=\"w\">         </span><span class=\"c1\">// error: &amp;str + &amp;str\n</span></span></span><span class=\"line\"><span class=\"cl\"><span class=\"c1\"></span><span class=\"kd\">let</span><span class=\"w\"> </span><span class=\"n\">s</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">&#34;foo&#34;</span><span class=\"p\">.</span><span class=\"n\">to_owned</span><span class=\"p\">()</span><span class=\"w\"> </span><span class=\"o\">+</span><span class=\"w\"> </span><span class=\"s\">&#34;bar&#34;</span><span class=\"p\">;</span><span class=\"w\"> </span><span class=\"c1\">// ok\n</span></span></span></code></pre><h2 id=\"miscellaneous\">Miscellaneous</h2>\n<p>HAD TO ENABLE &ldquo;AUTO COMMENT BLOCKS&rdquo; PLUGIN FOR FUCKING COMMENT CONTINUATIONS (and that too with Shift+Enter)</p>\n<h2 id=\"references\">References</h2>\n<ul>\n<li><a href=\"https://www.youtube.com/watch?v=wXtngLBkK4Q\">Great explainer on Async Rust</a></li>\n<li><a href=\"https://github.com/r7kamura/fronma\">FrontMatter parser</a> (really a wrapper)</li>\n</ul>\n</article-content></article></main><footer><p></p><ul><li>3,139 bytes</li><li>Created on Saturday, 10 October 2026 at 12:41 UTC</li><li>Modified on Saturday, 10 October 2026 at 12:41 UTC</li><br/><li><a href=\"https://github.com/afreeorange/wiki.nikhil.io.articles/edit/master/Notes from Blog Engine Rewrite in Rust.md\" title=\"Edit this article\">Edit this article</a></li><li><a href=\"https://github.com/afreeorange/bock\" title=\"View the project that generates this wiki on Github\"><span>bock 6.3.0-alpha</span></a></li></ul></footer></div><script src=\"/js/table-sort.js\" defer></script><script type=\"text/javascript\">\n        document.body.addEventListener(\n          \"keypress\", (e) => e.key === \"f\"\n          ? window.location.assign(\"/archive\")\n          : null);\n      </script></body></html>",
  "id": "31f81311-abf9-58e8-8990-56bf9faa1b32",
  "modified": "2026-10-10T12:41:55Z",
  "revisions": [
    {
      "authorEmail": "anand.nikhil@gmail.com",
      "authorName": "afreeorange",
      "date": "2026-10-10T12:41:55Z",
      "id": "57fafb6fc2f430d74d08c50f0905ac62b7058229",
      "shortId": "57fafb6f",
      "subject": "More notes\n",
      "content": "<!-- [[TOC]] -->\n\n## Motivation and Problems\n\nFor the \"Love of the Game\", the game being teaching myself enough Rust to have trenchant opinions on other languages. Things I'd like it to do:\n\n- **Markdown**  Rendering.\n  There's CommonMark and GFM. I have special markup that will require me to extend these. Not sure if I'll need _both_ specs.\n- **TSX** for templating.\n  Because I argue it's the best templating language ever.\n- **SASS _and_ Tailwind** Rendering.\n  Use `grass` for the former.\n- **Live-Reloading**\n  For posts and all assets.\n- **Asset Management**\n  Thumbnails, optimized WebP generation, folder organization.\n\n## Development Log (of sorts)\n\nAh the famous learning curve. But you can be very productive with Rust if you know what to focus on. For baby Rustaceans like me who're prototyping, the big things are:\n\n- Not fighting the famed Borrow Checker\n- Not using lifetimes as much as possible\n- Just waving away any possible errors for now\n- Knowing about and using popular libraries\n\nThat's it. Concretely,\n\n- `clone` and `own` everything to avoid fighting the borrow checker and dealing with explicit lifetimes.\n- `unwrap` or `expect` to avoid handling the failure cases inside `Result` and `Option`.\n\nI'll add a few more:\n\n- Use `String` instead of `&str` (avoids borrowing/owning)\n- Use `Vec<T>` to get owned collections (avoids borrowing/owning)\n- Use `Arc<T>` to share `T` across threads (avoids lifetimes)\n\nSo yeah, you're side-stepping what makes Rust 'great' in the first place. But going back and dealing with these things is for the next iteration of your app. Super-easy to do so: `grep` for these things and work at them.\n\n### Other Prototyping Shortcuts\n\n- Use `dbg!` a lot.\n- TODO: Complete this.\n\n### Datetime\n\nRust's STDLIB is as shit as Python's with datetime manipulation (which is rather disappointing). Here's things it can and cannot do:\n\n| Action                   | Can it? |\n| ------------------------ | ------- |\n| Current timestamp        | Yes     |\n| Measure elapsed time     | Yes     |\n| Add seconds to timestamp | Yes     |\n| Get year/month/day       | No      |\n| Format as 2026-10-09     | No      |\n| Parse ISO 8601 dates     | No      |\n| Time zones               | No      |\n| Calendar arithmetic      | No      |\n\nLike Python you are expected to use richer libraries: `chrono` or `jiff` (I like the latter.)\n\n## References\n\n- [Great explainer on Async Rust](https://www.youtube.com/watch?v=wXtngLBkK4Q)\n"
    }
  ],
  "sizeInBytes": 3139,
  "source": "<!-- [[TOC]] -->\n\n## Motivation and Problems\n\nFor the \"Love of the Game\", the game being teaching myself enough Rust to have trenchant opinions on other languages. Things I'd like it to do:\n\n- **Markdown**  Rendering.\n  There's CommonMark and GFM. I have special markup that will require me to extend these. Not sure if I'll need _both_ specs.\n- **TSX** for templating.\n  Because I argue it's the best templating language ever.\n- **SASS _and_ Tailwind** Rendering.\n  Use `grass` for the former.\n- **Live-Reloading**\n  For posts and all assets.\n- **Asset Management**\n  Thumbnails, optimized WebP generation, folder organization.\n\n## Development Log (of sorts)\n\nAh the famous learning curve. But you can be very productive with Rust if you know what to focus on. For baby Rustaceans like me who're prototyping, the big things are:\n\n- Not fighting the famed Borrow Checker\n- Not using lifetimes as much as possible\n- Just waving away any possible errors for now\n- Knowing about and using popular libraries\n\nThat's it. Concretely,\n\n- `clone` and `own` everything to avoid fighting the borrow checker and dealing with explicit lifetimes.\n- `unwrap` or `expect` to avoid handling the failure cases inside `Result` and `Option`.\n\nI'll add a few more:\n\n- Use `String` instead of `&str` (avoids borrowing/owning)\n- Use `Vec<T>` to get owned collections (avoids borrowing/owning)\n- Use `Arc<T>` to share `T` across threads (avoids lifetimes)\n\nSo yeah, you're side-stepping what makes Rust 'great' in the first place. But going back and dealing with these things is for the next iteration of your app. Super-easy to do so: `grep` for these things and work at them.\n\n### Other Prototyping Shortcuts\n\n- Use `dbg!` a lot.\n- TODO: Complete this.\n\n### Datetime\n\nRust's STDLIB is as shit as Python's with datetime manipulation (which is rather disappointing). Here's things it can and cannot do:\n\n| Action                   | Can it? |\n| ------------------------ | ------- |\n| Current timestamp        | Yes     |\n| Measure elapsed time     | Yes     |\n| Add seconds to timestamp | Yes     |\n| Get year/month/day       | No      |\n| Format as 2026-10-09     | No      |\n| Parse ISO 8601 dates     | No      |\n| Time zones               | No      |\n| Calendar arithmetic      | No      |\n\nLike Python you are expected to use richer libraries: `chrono` or `jiff` (I like the latter.)\n\n## Strings\n\n### Concatenation\n\nJust use `format!()`. Rust's version of Python f-strings.\n\nAlso, `.display()` returns `&str` and `.to_str()` returns `Option<&str>`. So you used:\n\n```rust\nlet pattern = format!(\"{}/**/*.md\", content_dir.display());\n```\n\nHere's some concatenation drama:\n\n```rust\nlet a = String::from(\"foo\");\nlet s = a + \"/bar\";            // ok: String + &str\nlet s = \"foo\" + \"bar\";         // error: &str + &str\nlet s = \"foo\".to_owned() + \"bar\"; // ok\n```\n\n## Miscellaneous\n\nHAD TO ENABLE \"AUTO COMMENT BLOCKS\" PLUGIN FOR FUCKING COMMENT CONTINUATIONS (and that too with Shift+Enter)\n\n## References\n\n- [Great explainer on Async Rust](https://www.youtube.com/watch?v=wXtngLBkK4Q)\n- [FrontMatter parser](https://github.com/r7kamura/fronma) (really a wrapper)\n",
  "title": "Notes from Blog Engine Rewrite in Rust",
  "untracked": false,
  "uri": "/Notes_from_Blog_Engine_Rewrite_in_Rust",
  "relativePath": "Notes from Blog Engine Rewrite in Rust.md"
}
