This commit is contained in:
parent
4b73564dac
commit
a4f9dadd8b
10 changed files with 58 additions and 17 deletions
2
Gemfile
2
Gemfile
|
@ -12,3 +12,5 @@ gem "front_matter_parser", "~> 1.0"
|
|||
gem 'phlex-markdown', git: 'https://github.com/phlex-ruby/phlex-markdown'
|
||||
|
||||
gem "tailwindcss-phlexite", "~> 0.1.0"
|
||||
|
||||
gem "kramdown", "~> 2.5"
|
||||
|
|
|
@ -10,10 +10,13 @@ GEM
|
|||
remote: https://rubygems.org/
|
||||
specs:
|
||||
front_matter_parser (1.0.1)
|
||||
kramdown (2.5.1)
|
||||
rexml (>= 3.3.9)
|
||||
markly (0.12.1)
|
||||
phlex (2.3.1)
|
||||
zeitwerk (~> 2.7)
|
||||
phlexite (0.1.3)
|
||||
rexml (3.4.1)
|
||||
tailwindcss-phlexite (0.1.0)
|
||||
tailwindcss-ruby (~> 4.1)
|
||||
tailwindcss-ruby (4.1.8)
|
||||
|
@ -30,6 +33,7 @@ PLATFORMS
|
|||
|
||||
DEPENDENCIES
|
||||
front_matter_parser (~> 1.0)
|
||||
kramdown (~> 2.5)
|
||||
phlex (~> 2.3)
|
||||
phlex-markdown!
|
||||
phlexite (~> 0.1.3)
|
||||
|
|
BIN
assets/blog-banners/cheetahmontage.png
Normal file
BIN
assets/blog-banners/cheetahmontage.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 163 KiB |
2
build.rb
2
build.rb
|
@ -1,5 +1,5 @@
|
|||
require "phlex"
|
||||
require "phlex/markdown"
|
||||
require "kramdown"
|
||||
require "phlexite"
|
||||
require "tailwindcss/phlexite"
|
||||
require "front_matter_parser"
|
||||
|
|
2
dev
Executable file
2
dev
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
watchman-make -p '**/*.rb' '**/*.md' --run 'bundle exec ruby build.rb'
|
|
@ -2,14 +2,17 @@ module Pages
|
|||
class Layout < ::Phlex::HTML
|
||||
def pages = {
|
||||
home: {
|
||||
as: :home,
|
||||
title: "Home",
|
||||
url: "/"
|
||||
},
|
||||
blog: {
|
||||
as: :blog,
|
||||
title: "Blog",
|
||||
url: "/blog"
|
||||
},
|
||||
about: {
|
||||
as: :about,
|
||||
title: "About",
|
||||
url: "/about"
|
||||
}
|
||||
|
@ -46,7 +49,7 @@ module Pages
|
|||
header(class: "#{@banner ? 'fixed' : 'sticky'} top-0 w-screen bg-transparent pointer-events-none flex p-3 items-center justify-center") {
|
||||
nav(class: 'flex gap-2 p-2 rounded-full border border-gray-300 bg-white/50 backdrop-blur-md pointer-events-auto') {
|
||||
pages.each { |key, page|
|
||||
a(href: page[:url], class: "block rounded-full px-3 py-1 #{key == @page ? 'bg-gray-100/50' : ''}") { page[:title] }
|
||||
a(href: page[:url], class: "block rounded-full px-3 py-1 #{key == @page_info[:as] ? 'bg-gray-100/50' : ''}") { page[:title] }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ class Pages::Post < ::Phlex::HTML
|
|||
end
|
||||
def view_template
|
||||
meta = @post[:data].front_matter
|
||||
render ::Pages::Layout.new({title: meta['title']}) {
|
||||
render ::Pages::Layout.new({ as: :blog, title: meta['title'] }, banner: meta['banner'], meta: {title: meta['title']}) {
|
||||
article(class: 'prose prose-lg m-auto') {
|
||||
h1 { meta['title'] }
|
||||
if meta['published_on']
|
||||
|
@ -19,7 +19,7 @@ class Pages::Post < ::Phlex::HTML
|
|||
|
||||
hr
|
||||
|
||||
render ::Phlex::Markdown.new(@post[:data].content)
|
||||
raw safe Kramdown::Document.new(@post[:data].content).to_html
|
||||
}
|
||||
}
|
||||
end
|
||||
|
|
|
@ -5,23 +5,23 @@ published_on: '2025-02-13'
|
|||
|
||||
*Updated 6/4/2025: Replaced the demo page.*
|
||||
|
||||
Go modules are great. URL-based imports, generally, are great. One of the things that makes them so great is that putting them on your own domain provides a good way of verifying ownership without going through a third party or a complicated review process. Plus, it looks cool.
|
||||
Go modules are great. URL-based imports, generally, are great. One of the things that makes them so great is that putting them on your own domain provides a good way of verifying ownership without going through a third party or a complicated review process. Plus, it looks cool.
|
||||
|
||||
So, how exactly does one accomplish such a thing? Well, it's [buried in the documentation](https://pkg.go.dev/cmd/go#hdr-Remote_import_paths), but it's really pretty simple. For each import path (e.g. `mysite.com/mypackage`), just put a page on your website with a `go-import` meta tag:
|
||||
|
||||
```html
|
||||
~~~ html
|
||||
<meta name="go-import" content="mysite.com/mypackage git https://ultragreatgithost.com/me/mypackage">
|
||||
```
|
||||
~~~
|
||||
|
||||
_(`git` can be replaced with `bzr`, `fossil`, `hg`, or `svn` for different VCSs — see the docs page linked above.)_
|
||||
|
||||
This website, for instance, builds these pages from a hash in [`build.rb`](https://git.sr.ht/~aleksrutins/farthergate.com/tree/main/item/build.rb#L14):
|
||||
|
||||
```ruby
|
||||
~~~ ruby
|
||||
def go_modules = {
|
||||
"farthergate.com/stack" => "https://git.farthergate.com/aleks/stack",
|
||||
# ...
|
||||
}
|
||||
```
|
||||
~~~
|
||||
|
||||
See [farthergate.com/terminated](/terminated) for an example of a generated page. Look in the web inspector for the `meta` tag!
|
||||
See [farthergate.com/terminated](/terminated) for an example of a generated page. Look in the web inspector for the `meta` tag!
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
---
|
||||
title: An ode to simplicity
|
||||
---
|
||||
|
||||
If there's one lesson that I take from developing — and, more importantly, later abandoning — [Cheetah](https://cheetah.farthergate.com), it's this: nothing can kill a good project, or even a middling-to-mediocre project, like scope creep.
|
||||
|
||||
The first big mistake I made was to do everything myself. Now, this was an incredible learning experience, of course: I learned how to write functioning Rust code, for one (functioning, not clean; please mind your footing around the `Rc<RefCell<HashMap<String, Rc<RefCell<ElementRegistrar>>>>>`), but by everything, I mean _everything_. Starting with the template engine. And it wouldn't just be a normal, text-based template engine: this template engine (in [one file](https://github.com/aleksrutins/cheetah/blob/master/src/template.rs), for those who don't value their sanity) worked on the DOM.
|
37
posts/2025-06-10-an-ode-to-simplicity.md
Normal file
37
posts/2025-06-10-an-ode-to-simplicity.md
Normal file
|
@ -0,0 +1,37 @@
|
|||
---
|
||||
title: An ode to simplicity
|
||||
banner: /blog-banners/cheetahmontage.png
|
||||
published_on: '2025-06-10'
|
||||
---
|
||||
|
||||
If there's one lesson that I take from developing — and, more importantly, later abandoning — [Cheetah](https://cheetah.farthergate.com), it's this: nothing can kill a good project, or even a middling-to-mediocre project, like scope creep.
|
||||
|
||||
The first big mistake I made was to do everything myself. Now, this was an incredible learning experience, of course: I learned how to write functioning Rust code, for one (functioning, not clean; please mind your footing around the `Rc<RefCell<HashMap<String, Rc<RefCell<ElementRegistrar>>>>>`), but by everything, I mean _everything_. Starting with the template engine. And it wouldn't just be a normal, text-based template engine: this template engine (in [one file](https://github.com/aleksrutins/cheetah/blob/master/src/template.rs), for those who don't value their sanity) worked on the DOM.
|
||||
|
||||
The engine would have been complicated enough already with just that, but the cherry on top was a declarative-shadow-DOM-based hydrating component system that automatically extracted scripts from the page. And, of course, everything had to run _as fast as humanly possible 🚀_ (after all, this is Rust). Thus: pointers! Pointers everywhere! Except: this is Rust, so we wrap our pointers in seven layers of boxes, because we don't understand how they work and are more than a little scared of them.
|
||||
|
||||
Don't even ask about the Nix-based DSL for generating the HTML-based DSL for generating the site, or the Nix- and Caddy-based container builder, or any number of other quarter-finished micro-initiatives that all fed into the leviathan that that project was.
|
||||
|
||||
Suffice to say, it didn't work very well. Forcing everything to be in its own shadow DOM — as expected — broke styling. Sure, the generator itself was _blazingly fast 🚀_, but _blazingly fast 🚀_ isn't worth much when the recommended project template pulls the Rust-based project from Nix without a binary cache. Building the site took a nanosecond, but the full CI workflow ended up taking several minutes each time.
|
||||
|
||||
The final nail in the coffin, though, was dependency hell. Cheetah had more dependencies than any self-respecting programmer could chuck a rubber duck at.[^1] The most important of these was `kuchiki`, an HTML traversing library, which, after a couple of years, became unmaintained. I only noticed this when I tried to package an RPM — Fedora only packages the latest version of Rust crates, and the latest versions of `kuchiki`'s dependencies were incompatible. There was more, too, but I won't put you through it. In short, `cheetah` became unmaintainable. I had built a massive, hulking project, and being able to maintain it depended on everything not breaking all at once. A couple of years out, once versions started to misalign, everything broke. All at once.
|
||||
|
||||
---
|
||||
|
||||
Sometimes, discretion is the better part of valor. So, I rewrote it. It took a bit to settle, but I eventually settled on Ruby, and created [Phlexite](https://git.farthergate.com/asr/phlexite).
|
||||
|
||||
In all honesty, "static site generator" are three rather strong words to describe Phlexite. It's a glorified path generation library with a nice DSL. It happens to also be smart enough to call functions to make pages. It's meant to be used with Phlex, but it's not restricted to it — in fact, it has no dependencies at all. It's simple enough that I haven't needed to update it in several months. This site is running with the latest (at the time of writing) version of Phlex (a major version ahead of where Phlex was when I last updated Phlexite), and it works without a hitch. If Cheetah was overcomplicated, Phlexite is oversimplified. And, after using it for a few months, oversimplification is winning.
|
||||
|
||||
Writing Rust feels, at times, like a constant battle for my sanity and soul. It builds character,[^2] sure, but it's not always enjoyable. Ruby is _fun_. In Ruby, the answer to "Can I do this?" is almost always "Yes, easily". I can write code without worrying about performance, and it'll end up _fast enough_. Sure, Phlexite doesn't build sites as fast as Cheetah, but you don't have to wait for the optimizing compiler to build _it_ — and thus, CI ends up taking 20 seconds, rather than five minutes.
|
||||
|
||||
This site is built with Phlexite. It has Tailwind-based styling, a sensible build script, a tiny little dev script based on Watchman, draft post support — all things that the Cheetah version didn't have, because I was too busy fighting the tooling. When I want to add a new feature, I just... add it. It doesn't generally take that long. Instead of fighting tooling on my blog, I can get past that to actually _write_.[^3]
|
||||
|
||||
Parallels elsewhere: more recently, I've been using vanilla GNOME with VS Code and Zed on all of my devices, and I've been incredibly productive. WM configuration is _cool_, and bspwm and COSMIC are _blazingly fast 🚀_. But what use is _cool_ and _blazingly fast 🚀_ if I can't get anything done?
|
||||
|
||||
Tech should serve our productivity, not the other way around. That's why high-level, dynamically-typed languages were made in the first place — and why they're still just as relevant, no matter how interesting the latest statically-typed systems programming language may be.
|
||||
|
||||
---
|
||||
|
||||
[^1]: The great irony here, of course, is that I accrued all of these dependencies in the interest of doing everything myself.
|
||||
[^2]: <https://calvinandhobbes.fandom.com/wiki/Building_character>
|
||||
[^3]: My past self would have trouble believing that this is what a blog is for, but I'm pretty sure that this is what a blog is, actually for.
|
Loading…
Add table
Add a link
Reference in a new issue