Devlog

Here’s the coding projects I’ve been working on in my spare time.

    Devlog: Trying OpenAI Codex to Produce Freelens Logo Creator

    Using OpenAI Codex to make a logo generator tool to allow customisation for different clusters in Freelens.

    Ah, MacOS’s locked-down nature strikes again! Was testing the CI/CD build for Dequoter and after downloading the artefact and attempting to open it, I got this warning message:

    Auto-generated description: A warning dialog box states that Dequoter is damaged and suggests moving it to the Bin, with options to cancel or proceed.

    Turn’s out it was being quarantined by MacOS, and these instructions resolved the issue.

    The binaries not notarised so I wasn’t expecting it to work out of the box. I was hoping that it would do that thing where the app will be listed in settings and I can allow it to launch from there, but I guess there’s something about where this file came from that was too much from MacOS. Ah well, I can live with this for the short term.

    Devlog: Dequoter — Something Different Today

    A new project called Dequoter was started to unquote a JSON string and filter it, utilizing Go for backend functionality and HTML for the frontend.

    Starting to work on the background tiles. This is what I have so far. I hope it’s not too busy or distracting.

    Auto-generated description: A pixelated video game scene features a character in knight armor navigating a stone brick environment with a wooden crate and a collectible item.

    Devlog: Godot Project — Bricks in Level 2-3 Laid

    Just a quick update today. I’ve finished all the brickwork in level 2-3. And it didn’t go too badly. Made one significant mistake which would’ve involved a lot of rework, that I patched up with some single tiles:

    Auto-generated description: Two sections of a pixelated game map featuring stone walls, an arched door, and orange blocks resembling platforms.
    Top: the mistake. Bottom: the fix.

    Doing the rest of it was pretty dreary work. Godot does have some tools to make this easier, but there was no getting around the level of care needed to place the bricks correctly. But it’s all pretty much done now. And just for comparison to the before screenshots I took when I started, here’s how how the level looks now:

    Auto-generated description: A pixelated video game scene shows a knight on a platform with lava below, stone blocks, and crates to the right. Auto-generated description: A pixelated video game scene shows a character in armor navigating a platform level with brick walls, crates, and spiked obstacles. Auto-generated description: A pixelated character in knight armor stands on a brick platform with a gray background, part of a retro-style video game.

    There’s still plenty of work. The background is not yet done, nor are any of the pickups placed. The HUD needs updating to show the key gems the player has, and I also need to repair some dodgy mechanics around moving platforms. But I guess that’s just a matter of plowing ahead.

    Devlog: Shutting Down Nano Journal

    With the move to Obsidian for my journalling needs, I shut down my bespoke journalling web-app. I deployed it on 26th August 2024, which makes it just over a year old. I did start using Obsidian on the 20th though, so it didn’t quite make it the entire year. Even so, not bad for something hand made and somewhat neglected. Most things I eventually abandon last way less than that.

    Anyway, here are some screenshots of the final version, just before I shut it down:

    You can compare this with some earlier screenshots documented in these posts:

    I guess you can describe the ascetics of this project as the “minimum amount to get working.” That was true of the backend too, which was somewhat rushed and difficult to maintain. That might be why I never really gave this a lot of love as other projects like Blogging Tools. But I added some features I that I thought were neat: such as attachments, and keeping a copy of a draft in the browser’s local storage before it was sent to the server.

    Anyway, I’m now in the middle of migrating the old posts over to Obsidian. One thing I’m glad I added was Git synchronisation. And given that entries were plain markdown files, migration was simply a matter of checking out the repository and moving the posts across. Easy enough work, although I am taking my time. There’s a bit of reliving involved with moving the posts over, and I’m approaching a period where some pretty sad things happened.

    Anyway, that was Nano Journal. Good at what it needed to do.

    Devlog: Godot Project — Level 2-3 Update

    Critical path for level 2-3 has been built.

    Devlog: UCL — Comparing UCL To Some Early Ideas

    Comparing UCL to an idea for a hypothetical command language for a now-defunct CLI project, which aimed to combine shell-like REPL functionality with scripting capabilities.

    Devlog: Blogging Tools — All About Images

    Some recent changes to Blogging Tools around images and image processing.

    Devlog: Godot Project — Level 4-2 And Level 2-3

    Progress has been made on level 4-2, and early development on level 2-3, alongside new game elements.

    Devlog: Blogging Tools — Category Fixer

    Adding an RSS feed parser and in-app notifications to build a feature to triage image posts that don’t have a category.

    Devlog: Godot Project — Some Feelings

    Progress on the Godot game has been fulfilling yet tinged with doubt about its value and purpose.

    Devlog: UCL — More About The Set Operator

    I made a decision around the set operator in UCL this morning.

    When I added the set operator, I made it such that when setting variables, you had to include the leading dollar sign:

    $a = 123
    

    The reason for this was that the set operator was also to be used for setting pseudo-variables, which had a different prefix character.

    @ans = "this"
    

    I needed the user to include the @ prefix to distinguish the two, and since one variable type required a prefix, it made sense to require it for the other.

    I’ve been trying this for a while, and I’ve deceided I didn’t like it. It felt strange to me. It shouldn’t, really, as it’s similar to how variable assignments work in Go’s templating language, which I consider an inspiration for UCL. On the other hand, TCL and Bash scripts, which are also inspirations, require the variable name to be written without the leading dollar sign in assignments. Heck, UCL itself still had constructs where referencing a name for a variable is done so without a leading dollar sign, such as block inputs. And I had no interest in changing that:

    proc foo { |x|
        echo $x
    }
    
    for [1 2 3] { |v| foo $v }
    

    So I made the decision to remove the need for the dollar sign prefix in the set operator. Now, when setting a variable, only the variable name can be used:

    msg = "Hello"
    echo $msg
    

    In fact, if one were to use the leading dollar sign, the program will fail with an error.

    This does have some tradeoffs. The first is that I still need to use the @ prefix for setting pseudo variables, and this change will violate the likeness of how the two look in assignments:

    @ans = 123
    bla = 234
    

    The second is that this breaks the likeness of how a sub-index looks when reading it, verses how it looks when it’s being modified:

    a = [1 2 3]
    a.(1) = 4
    $a
    --> [1 4 3]
    $a.(1)
    --> 4
    

    (One could argue that the dollar sign prefix makes sense here as the evaluator is dereferencing the list in order to modify the specific index. That’s a good argument, but it feels a little bit too esoteric to justify the confusion it would add).

    This sucks, but I think they’re tradeoffs worth making. UCL is more of a command language than a templating language, so when asked to imagine similar languages, I like to think one will respond with TCL or shell-scripts, rather than Go templates.

    And honestly, I think I just prefer it this way. I feel that I’m more likely to set regular variables rather than pseudo-variables and indicies. So why not go with the approach that seems nicer if you’re likely to encounter more often.

    Finally, I did try support both prefixed and non-prefixed variables in the set operator, but this just felt like I was shying away from making a decision. So it wasn’t long before I scrapped that.

    That Which Didn't Make the Cut: a Hugo CMS

    You’ve probably noticed1 that I’ve stopped posting links to Open Bookmarks, and have started posting them here again. The main reason for this is that I’ve abandoned work on the CMS I was working on that powered that bookmarking site. Yes, yes, I know: another one. Open Bookmarks was basically a static Hugo site, hosted on Netlify. But being someone that wanted to make it easy for me to post new links without having to do a Git checkout, or fiddle around YAML front-matter, I thought of building a simple web-service for this.

    I don’t want to say too much about it, other than I managed to get the post functionality working. Creating a new link post would involve fetching the page, and pre-populating the link and optional via link with the fetched page title. I’d just finish the post with some quotes or quips, then click Post. That’ll save the post in a local database, write it to a staged Hugo site, run Hugo to generate the static site, and upload it to Netlify. There was nothing special about link posts per se: they were just a specialisation of the regular posting feature — a template if you will — which would work the same way, just without the pre-fills.

    The other thing I added was support for adding arbitrary pages. This was a dramatic simplification to what is possible in Hugo, in that only one page bundle was supported. And it was pretty compromised: you had to set the page title to “Index” to modify the home page. But this was enough for that, plus some additional pages at the top level.

    One other feature was that you can “preview” the site if you didn’t have a Netlify site setup and you wanted to see the Hugo site within the app itself. I had an idea of adding support for staging posts prior to publishing them to Netlify, so that one could look at them. But this never got built.

    Finally there were some options for configuring the site properties. Uploads were never implemented.

    Here are some screenshots, which isn’t much other than evidence that I was prioritising the backend over the user experience:

    So, why was this killed? Well, apart from the fact that it seemed like remaking prior art — I’m sure there are plenty of Hugo CMSes out there — it seemed strange having two systems that relate to blogging. Recognising this, I decided to add this functionality to Blogging Tools:

    This can’t really be described as CMS. It’s more of a place to create posts from a template which can then be published via a Micropub endpoint. But it does the job I need, which is creating link posts with the links pre-filled.


    1. Or not. I mean, I’m not expecting you to notice. You’ve got lives of your own, after all. ↩︎

    Had a reason to write a journal entry today, which meant I had a reason to work on the journaling app. Biggest change was moving the entry list to a separate page and supersizing the text-area to allow for larger entries. Good thing too: today’s was going to need all the space it could get.

    Working on that Godot game again, mainly coming up with mechanics for a new level 2. This is what I’ve got so far: a mine tethered to a balloon. Their idle state is just bobbing up and down, but I am planning a variant which will drop their payload and fly away when the player is nearby.

    Auto-generated description: Three red balloons are tethered to spiked balls, hovering above a row of green and brown blocks.

    Devlog: Dynamo-Browse Now Scanning For UCL Extensions

    Significant milestone in integrating UCL with Dynamo-Browse, as UCL extensions are now being loaded on launch.

    All the recent changes to UCL is in service of unifying the scripting within Dynamo Browse. Right now there are two scripting languages: one for the commands entered after pressing :, and one for extensions. I want to replace both of them with UCL, which will power both interactive commands, and extensions.

    Most of the commands used within the in-app REPL loop has been implemented in UCL. I’m now in the process of building out the UCL extension support, start with functions for working with result sets, and pseudo-variables for modifying elements of the UI.

    Here’s a demo of what I’ve got so far. This shows the user’s ability to control the current result-set, and the selected item programatically. Even after these early changes, I’m already seeing much better support for doing such things than what was there before.

    Devlog: UCL — Assignment

    Some thoughts of changing how assignments work in UCL to support subscripts and pseudo-variables.

    Devlog: Blogging Tools — Finished Podcast Clips

    Well, it’s done. I’ve finally finished adding the podcast clip to Blogging Tools. And I won’t lie to you, it took longer than expected, even after enabling some of the AI features my IDE came with. Along with the complexity that came from implementing this feature, that touched on most of the key subsystems of Blogging Tools, the biggest complexity came from designing how the clip creation flow should work. Blogging Tools is at a disadvantage over clipping features in podcast players in that it:

    1. Doesn’t know what feeds you’ve subscribed to,
    2. Doesn’t know what episode you’re listening to, and
    3. Doesn’t know where in the episode you are.

    Blogging Tools needs to know this stuff for creating a clip, so there was no alternative to having the user input this when they’re creating the clip. I tried to streamline this in a few ways:

    • Feeds had to be predefined: While it’s possible to create a clip from an arbitrary feed, it’s a bit involved, and the path of least resistence is to set up the feeds you want to clip ahead of time. This works for me as I only have a handful of feeds I tend to make clips from.
    • Prioritise recent episodes: The clips I tend to make come from podcasts that touch on current events, so any episode listings should prioritise the more recent ones. The episode list is in the same order as the feed, which is not strictly the same, but fortunately the shows I subscribe to list episodes in reverse chronological order.
    • Easy course and fine positioning of clips: This means going straight to a particular point in the episode by entering the timestamp. This is mainly to keep the implementation simple, but I’ve always found trying to position the clip range on a visual representation of a waveform frustrating. It was always such a pain trying to make fine adjustments to where the clip should end. So I just made this simple and allow you to advance the start time and duration by single second increments by tapping a button.

    Rather than describe the whole flow in length, or prepare a set of screenshots, I’ve decided to record a video of how this all fits together.

    The rest was pretty straightforward: the videos are made using ffmpeg and publishing it on Micro.blog involved the Micropub API. There were some small frills added to the UI using both HTMX and Stimulus.JS so that job status updates could be pushed via web-sockets. They weren’t necessary, as it’s just me using this, but this project is becoming a bit of a testbed for stretching my skills a little, so I think small frills like this helped a bit.

    I haven’t made a clip for this yet or tested out how this will feel on a phone, but I’m guessing both will come in time. I also learnt some interesting tidbits, such that the source audio of an <audio> tag requires a HTTP response that supports range requests. Seeking won’t work otherwise: trying to change the time position will just seek the audio back to the start.

    Anyway, good to see this in prod and moving onto something else. I’ve getting excited thinking about the next thing I want to work on. No spoilers now, but it features both Dynamo Browse and UCL.

    Finally, I just want to make the point that this would not be possible without the open RSS podcasting ecosystem. If I was listening to podcasts in YouTube, forget it: I wouldn’t have been able to build something like this. I know for myself that I’ll continue to listen to RSS podcasts for as long as podcasters continue to publish them. Long may it be so.

Older Posts →