Devlog

Short updates on my development journey and projects.

2025

Some tech opinions as of recent:

With all my musings I always come back to the very often suggestion that ā€œthe best stack is the stack you know the bestā€, that is, just use what you’re most proficient in and ā€œjust buildā€. Of course, me being me, I decide not to stick to this. I probably have used Vue most in the last 3 months or so, and probably know it best. But I just don’t want to use it anymore. Reasons being is that it’s a heavy SPA framework and it’s heavily tied to VSCode. Recently I’ve been trying to move over to using Helix as much as possible, and Vue being a non-editor agnostic framework, has made it less appealing to me. Sure, setup for Vue in Helix is doable but it kind of goes against my initial reason for investing time into Helix, and that is that I barely touch the configuration. Vue’s LSP setup is super finicky and actually just awful to set up in anything other than VSCode. So I don’t want to use it anymore.

I’ve been trying to explore what other things there are out there. I don’t have much interest anymore in touching things like React, Svelte, Solid, Qwik, etc as they are just kind of the same to me. I am looking for things closer to vanilla JavaScript. Why not just vanilla JavaScript? Well, I do try to use it but often find myself struggling with the pain points that the above frameworks do solve. So ideally, something lightweight on top of JS, maybe JQuery? I’ve used it once before and to be frank was a very nice experience. I guess this comes down to what I’m building these days. Most of what I am building…I’m not sure if a framework is justifiable. I’m also progressively believing most of what’s built online really does not need to reach for a framework, in part thanks (or not thanks) to Alex Russel’s notes (hatred?) towards (JS) frameworks.

I briefly touched VanJS, a ā€œultraā€ lightweight JS library. It seems really good actually! And I like that it’s no build tool based. I’m starting to image a new stack of tools that I actually like and can continue building with.

That then brings me to OpenProps. It’s a CSS ā€œlibraryā€ that just basically provides tons of variables and a healthy CSS reset. The standard defaults it provides is like Tailwind, which you can just build off. I love this because while I kind of understand how nice Tailwind can be, I often find myself just absolutely hating the markup. It’s awful to read and the more complex CSS gets the more awkward it gets. Any type of custom animation ends up being written as normal CSS anyways, and I personally really, really dislike conditional class rendering with Tailwind. It’s hard for me to understand. Modern CSS is so powerful too nowadays, I wonder why we restrict ourselves to doing everything in strings. And on that note, one thing I like about modern CSS is nesting, which I think helps with readability of the styles tremendously.

I am exploring BiomeJS. I really wish for it to be the final solution to ā€œlintingā€ and formatting in JavaScript projects.

For some time I was trying to use just eslint, with some opinionated rules. I don’t have too many particular opinions on formatting, just that it’s easy to read, which I find most people’s to be, so that’s why I look to use other people’s. Unfortunately eslint formatting was not very good, and I often wished to go back to Prettier. So I guess I do have some opinions.

The reason I chose to not use Prettier, is because I disliked the idea of adding yet another dependency when eslint, which seemed to be doing the same thing, was enough.

So, here I am looking at BiomeJS. In particular, I am looking at setting it up with Zed. It looks to be okay, but now I have to see what I have done with the config. It has changed quite a bit since I last wrote about using eslint to format.

I guess that’s what I get for using ChatGPT. The script that would create an entry in my devlog from the Drafts app would just take the first line and make a slug from it. I ended up with huge slugs.

So I’m using this small script now to generate IDs for the slug, even though it’s not really needed. I do plan to allow to access these devlogs via a link, though.

function getSlug(_content) {
	// var slug = content.match(/^slug: (.*)$/m);
	// if (slug) return slug[1];
	// var firstLine = content.split("\n")[0].trim();
	// if (!firstLine) throw new Error("No valid title found");
	// return firstLine.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(
	// 	/^-|-$/g,
	// 	"",
	// );
	return "id" + Math.random().toString(16).slice(2);
}

I’m trying out InertiaJS, which I was introduced to from this blog post from this wonderful blog post https://dnlytras.com/blog/phoenix-react-inertia. Check it out to understand more, but basically, InertiaJS uses some tricks to allow you to utilize a SPA framework with your classic backend framework, without having to write an API for it as you typically would. This to me, sounds amazing. I don’t have much interest in learning NodeJS (or any of its derivatives) based backends like Hono, or Nest, and have been learning Phoenix for quite some time now. While I am enjoying Phoenix - I am not entirely sold on its frontend solution, LiveView (similarly to the author). So let’s see how InertiaJS goes.

Here’s a part of a script I found from Github, and had ChatGPT slightly edit it to fit my use case.

function main() {
  var content = draft.content;
  var slug = getSlug(content);
  var publishDate = new Date();
  content = createFrontMatter(content, publishDate) + content;

  var url = urlformat(
    BASE,
    OWNER,
    REPO,
    "contents",
    SOURCE,
    PATH,
    `${formatDate(publishDate)}-${slug}.md`,
  );

  var b64 = Base64.encode(content);
  var res = req("GET", url, null);

  if ((res.statusCode == 200) && (res.data.type != "file")) {
    throw "Target file exists, but is not a file: " + res.data.type;
  } else if (res.statusCode == 200) {
    res = req("PUT", url, {
      message: "Update via Drafts: " + slug,
      content: b64,
      sha: res.data.sha,
    });
  } else {
    res = req("PUT", url, { message: "New via Drafts: " + slug, content: b64 });
  }

  var result = urlformat(SITE, PATH, slug, "");
  app.setClipboard(result);
}

I’m curious how the markdown will render.

Okay, I was able to fix the rendering of devlog posts. It was all thanks to the following Stackoverflow link:

How to render multiple content entries

In particular, I was trying to run await render calls in a map in the frontmatter. It gets a bit confusing understanding what actually gets returned because if you see:

const { Content, headings } = await post.render();

// and then in the template
<Content />

I am pretty tired to know okay, what exactly is happening if it’s a component? Can I have a list of components that I just render?

The solution was easier, though:

<div class="space-y-8">
   {entriesByYear[year].map(async (entry) => {
      const { Content } = await entry.render()
         return (
            <article class="">
              <div class="mb-2 flex items-center justify-between">
                <span class="text-sm text-black/60 dark:text-white/60">
                  <FormattedDate date={entry.data.date} />
                </span>
              </div>
              <div class="prose prose-neutral dark:prose-invert">
                <Content />
              </div>
            </article>
    )})}
</div>

Testing my devlog script from Drafts!