til / rewrite using the BETH stack
About a year and a half ago, I rewrote this site using Remix and I was happy with the code. But, recently, I’ve been intrigued by htmx and wanted a project to test it on. A couple of weeks ago a video popped up in my recommendations on YouTube, The BETH Stack by Ethan Niser, which piqued my interest and I started doing some rewrite tests during my vacation.
The stack is very much on the bleeding edge:
But, I haven’t had any big issues, even if they are bleeding edge. The main issues have been with Elysia and the lack of documentation, but functionality wise it’s been great once I understood how to use it.
I had zero issues with Bun and they will release it’s 1.0 on September 7, so I’ll consider it stable enough for use.
That part that I was most excited to try was htmx and I haven’t been disappointed. I can’t tell how it will work for a larger scale app (but others have used it with good results), but for the scale of a simple blog it’s a great match.
This is a code example from my admin interface where I can write blog posts and get a rendered preview while writing.
/admin/previewwhich returns rendered Markdown
hx-targettells htmx which element, using a CSS selector, to update with the response
hx-triggersays that the
GETshould be triggered on keyup, if the value has changed, and after a 500ms delay.
1<textarea 2 hx-get="/admin/preview" 3 hx-target="#preview" 4 hx-trigger="keyup changed delay:500ms" 5> 6 Text here 7</textarea> 8<div id="preview"></div>
Keyboard shortcuts #
Keyboard shortcuts are simple to add (hint: use
ctrl + n /
ctrl + p to navigate between blog posts, or test
cmd + k to open a simple command menu).
href– A regular link, but I’m boosting which makes all anchors and forms perform AJAX requests instead. This makes the site faster, since it doesn’t have to process scripts or styles on navigation and instead only replaces the content of
bodywith the response.
hx-trigger– Trigger on clicks and (comma-separated events) on keyup when the control key and the n-key are pressed.
from:bodytakes advantage of event bubbling and captures the event on
body. Without it,
ctrl + nwould only work on the anchor itself.
1<a 2 href="/posts/:next-slug" 3 hx-trigger="click, keyup[ctrlKey && key == 'n'] from:body" 4> 5 Next title 6</a>
Database and ORM update #
Prisma has been my go-to ORM the last couple of years. The BETH Stack used Drizzle and I decided that I wanted to test that as well, since I was also going to migrate to Turso. I have to say that I’m very very happy with the change. It feels more like writing raw SQL and a big positive is that it supports real joins (which Prisma doesn’t). Drizzle will likely be my ORM of choice in the future.
Edit: I did switch to Turso. It worked perfectly and was fast, but their pricing is based on row reads/writes and some of my queries incur a lot of reads, especially the ones on the stats page. Loading the stats page meant over 200 000 row reads. This could just be me writing inefficient queries and/or lacking good indexes, but it prompted me to switch back to my Postgres DB which I still had for other projects. The free tier has a generous 1 billion row reads / month, but it can add up quickly if your queries affect lots of rows. ↩︎