💾 Archived View for ainent.xyz › devlog › smolver › 2022-01-12-smolver-development-log.gmi captured on 2024-05-12 at 15:26:26. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-07-10)
-=-=-=-=-=-=-
This is the first in a planning series of posts where I'll share my experience writing smolver, my Gemini server software, written in Swift.
The initial production version of smolver, before I made the code publicly available, is written using a small socketing framework that I have written for my game, with some slight modifications. For the game, it needs a constantly connected socket on which to notify the client of various server-side events and to receive data from the client. Refactoring this to work on Gemini's once-and-done connection style was trivial, and it felt nice to be able to reuse that code in way that I never intended nor envisioned (yay modularity!)
After refactoring, I was ready to start writing the basics of a Gemini server. Honestly, the hardest part of that was getting a domain, TLS and updating the OS this server runs on (not that that was hard, just offering that for comparison). After that, it only took ... let me check the exact number, because now I am curious ... 70 lines of code to get a working implementation. That number includes:
Bringing the totality of Gemini-specific code down to a whopping 44 lines of Swift code (this does not include the socketing framework mentioned above, which itself has a couple of 3rd party dependencies, but even then is still small). Granted, that 44 lines is quite ugly with some basic sanity checks, but it works enough for my needs: running a static server with a few internal backlinks. My simplistic requirements are not the point though! It's so simple it almost feels like I'm doing something wrong.
Next was to wrap my head around the entirety of the Gemini specification, so I just read it all. Then I read it again, this time taking notes, trying to simplify the already simple rules into a workable checklist. Then I broke those checklists down into even smaller chunks, so I could figure out the order in which things could most easily be implemented.
As much as I was bored in this agile planning phase, it for sure solved 2 problems for me:
I also decided to try something new on the project planning side, and just use basic markdown files with checklists, like so:
- [ ] Item 1 - [ ] Item 2 - [ ] Item 3
And then wrote a couple of small scripts to make it easy to track my progress:
`listRemainingTodos.sh`:
count() { grep -r "\[ \]" . } # I tried using variables instead, but that made the output one # ugly concatenated string (newlines were stripped out) echo "$(count | wc -l) TODOs left:" count
`listCompletedTodos.sh`:
count() { grep -r "\[x\]" } # I tried using variables instead, but that made the output one # ugly concatenated string (newlines were stripped out) echo "$(count | wc -l) TODOs completed:" count
Simple. Performant on low powered devices with slow hardware. Offline copy of backlog, as these markdown files and the scripts are checked into git alongside the code.
Tonight I started on alpha 2, and though I'm only into getting some basic data structures in place for Gemini responses, I'm still taken aback by the simplicity of the protocol. The other day I was almost wondering what I had gotten myself into with this project when I saw the TODO count from my script above, but as I get into it now, most of the requirements thus far have been trivial to implement in Swift. At this rate, a fully compliant server really should not take much development time nor many lines of code, especially relative to something analogous, like a web server.
All this work was done (minus the original work on the socketing framework, though I did use this approach to do the refactor I mentioned above) in `vi` on a PinePhone.
Compiling is slow on this device, but the codebase right now is small so it's bearable.
I'm also using `vi` on the PinePhone to write these posts.