It was spring and I was inspired. It had been a long time since I’d felt inspired. Decades. But the creativity and joy I’d found on the personal web had roused some long-dormant impulse.
I got into all this computer stuff as a hobby and used to spend long nights doing hobby projects. I got into Linux and started building things: mail server, music server, DVR. All the classics of the early 2000s.
I loved the open-source community and wanted to contribute, but I didn’t think I was a good enough programmer. So I spent a lot of time answering questions in IRC and writing guides on forums. That gave me a way to give back to the community that had given me so much. It was gratifying to help someone who was struggling with something I had struggled with myself.
The more time I spent around people’s personal sites, the more I wanted a new hobby project. I spun up a couple servers (I particularly like mealie), but it wasn’t scratching the itch. I wanted to give something back, and this time I wanted it to be a software project.
All I needed was an idea, but that idea was elusive. Then one day, I was noodling around the 32-bit Café forum and an idea fell into my lap.
The idea came from a member named armaina. She wanted a self-hosted RSS feed generator along the lines of status.cafe so she could let her friends know about new art as she created it. It would be written in PHP and would store all its data in files on disk so it could just be copied to a new location if needed.
It was a good idea. Even better for me, it scratched all the itches I was feeling. It was a software project. It was a chance to learn. It was a way to give back.
I made a quick prototype and asked armaina if it looked like what she had in mind. It did! Knowing I was on the right path, I set to work for real. I called the project tkr. I’m unreasonably happy with that name. It’s a cheeky take on “ticker” that looks like a shell command. It’s one of my favorite things about the project.
I don’t have those long nights in me anymore, but I figured it would take me a few weeks to make something good enough and I’d have my first fun little project in the books.
It took me about 3 months.
As I sit down to start writing this, it’s been 4 days since I finished the initial release of tkr. That’s given me some time to reflect on the experience and left me with just enough time to share those reflections with you.
Writing in PHP is a lot of fun! It was clearly built for web development and it feels very natural to use it to build a web app. You can mix and match HTML and PHP, it has a lot of built-in functions for common things like setting headers and response codes, and it’s easy to make a change and see it in action in your browser. But I didn’t even realize my favorite thing about it until I started writing this paragraph. I didn’t need to install a bunch of PHP packages to build tkr. Everything I needed was just part of PHP. That immediately made it more accessible than something like python or node.js where anything you try to do seems to start with “install a bunch of packages.” Every day working with PHP was a joy. I’m already looking forward to building more things with it.
PHP also went and grew up since I last used it. I remember it being sort of a punching bag back in the mid-2000s. One of my first surprises upon discovering the personal web was discovering that it’s still widely used. But when I started to use it, I was more surprised to learn that it now has things like classes and types. It even supports functional programming! You don’t need any of those things to build a small web app, so it’s fine if that all sounds mysterious. But PHP managed to add them without losing its soul, which I think is really cool.
When I started tkr, I saved the posts in text files. I think I overengineered this. I set it up so there would be a single file for each day and folders for the month and year. So if you posted on August 21, 2025, the post would be at ticks/2025/08/21.txt. My thinking was that this would keep any single file from getting too big, but in retrospect I was being ridiculous. If any instance of tkr ever sees 1,000 posts, I’ll be shocked. I could have just put them all in a single file and called it a day.
That said, I still didn’t really like having the posts in text files. I kept having to write code to do things like fetch a group of posts, or find a specific post, or delete a post. These are all problems that SQL databases solved long ago. It’s possible that my background blinded me here, but I was much more comfortable using a database for storage than the filesystem. So I scrapped the file approach and started over.
A full-blown database would have made tkr way too hard to set up and manage, so I gave SQLite a try. I think that ended up being the best decision I made in the whole project. Yes, even better than the name. If you aren’t familiar with SQLite, it’s essentially a single-file SQL database. There’s no server to configure: no ports, no system accounts, none of that. It’s just a file on disk, but you use SQL to interact with it. The first time you try to access the database file, it’s automatically created. So I was able to give people a zero-configuration, single file database that let me use SQL to manage tkr’s data. Everybody wins!
If you’re interested in backend development with a database, I can’t recommend PHP and SQLite enthusiastically enough. You get a language that can do everything you need without having to worry about dependency management or bundlers or any of that. You get a database that lets you use SQL without having to set up a new service or worry about ports and accounts and backups. Just install PHP, maybe install the PHP SQLite extension if your OS doesn’t bundle it with PHP, and start writing. The database can even live right next to your application code, so when you want to install your app on a web server, you can just zip it up and upload it. I can’t imagine a much friendlier way to get started.
PHP and SQLite made building tkr much simpler than I expected, but there were a couple things that were harder than I thought they’d be. The RSS and Atom feeds were kind of a pain! I figured those would be straightforward since they’ve been around forever. Then I learned they’re XML and my heart sank a little. I spent a solid week messing with the formats until they loaded in Vivaldi’s feed reader. I was thrilled! Then armaina tried it in Feedbro and the RSS feed didn’t work. Turns out Vivaldi is forgiving of malformed RSS feeds. Feedbro isn’t. So I found an RSS validator and started testing with Feedbro. It took me another couple days, but I finally managed to get everything right. I hope I didn’t just jinx it.
But the installation was the worst. At first, I thought that was going to be one of the easier things. I’ve been working on fairly complex applications for a while. I was really looking forward to not having to worry about managing cloud infrastructure or dealing with message queues or setting up database replication or any of that “day-job” stuff. But what I forgot was that as annoying as all that stuff is, I at least controlled it. Now I had a simple app, but I had no idea what kind of systems it was going to be installed on. Sure enough, the first person to try it installed it on a Synology NAS and just got a blank screen.
It never crossed my mind that someone would install tkr on a NAS, but of course they would. I built it specifically to be self-hosted. I’m pretty sure the problem was that SQLite support was missing, but I had no way of checking that and the app sure wasn’t telling anyone. I never heard anything back from the person and I don’t blame them. Who wants to go to the trouble of trying something out and be rewarded for their effort with a screen full of nothing?
This shook my confidence. I’d been using tkr for a while. I’d installed it on my own server and upgraded it a bunch of times. I thought it was in pretty good shape, but now I wasn’t even sure I’d built something that people could install. So I decided I’d do two things. First, I’d add a prerequisite checker and a bunch of logging to the initial setup. That would give people a detailed report if anything went wrong. Second, I’d see if it was possible to add automated tests so I could verify that the app installs and basically works whenever I make a change.
This is where I think I really started overengineering things. I probably could have just gotten away with a note in the docs. But I didn’t want people to have a bad installation experience. I’ve spent my whole career digging through logs and trying to puzzle my way through weird behavior from sloppy, badly documented software. That’s fine when you’re being paid to do it. It’s not what most people are looking for from their hobbies.
But I was also feeling pressure to finish. That pressure was entirely self-imposed. When I decided I was going to build tkr, I started a topic about it on the 32-bit Café forum. I thought it would be fun to let people follow along as I built it. It was, and everyone was delightful, but one side effect was that I felt like I needed to post regular updates so people wouldn’t think I’d lost interest. I’d already had a couple public setbacks. Now I was about to take another big detour to build a bunch of stuff that most people should never see. I was a little worried that it was starting to look like I wasn’t ever going to finish. So I made the decision I would come to regret more than any other. I got help from an LLM.
I’m not going to turn this into an article about LLMs. Just about everything there is to say about them has been said and you don’t need me to rehash it here. Suffice it to say that the automated testing is where I reached the limit of what I could muddle through by “knowing enough to be dangerous.” I knew from my developer friends that there are things you had to think about to write testable code, but I didn’t really know what those were and I didn’t know how to search for them. I blundered around for a little while but wasn’t having much luck. A lot of my colleagues use Claude extensively, so I gave that a try and got the answers I needed.
(It turns out the term I was looking for was “dependency injection.” There are some decent search results for “PHP dependency injection,” so I’m putting the phrase here for anyone else who’d like to write tests for their PHP code without falling back on an LLM.)
I didn’t consider that there are people in the community who object strenuously enough to LLMs that the fact that I used one would mean that they wouldn’t want my project associated with their site. It seems obvious now, but I learned it just as I finished writing tkr, ironically enough from another topic on the 32-bit Café forum. I struggled with this for a day or two, then decided to put an LLM disclosure in the project README and in my tkr forum topic.
I’m sad that I set out to build something for the personal web community and then built it in a way that excludes a portion of it. But that’s life. You make decisions, deal with the consequences, learn from them, and make other decisions. I’ve decided to write guides for the things I used LLMs to help with. That way, maybe the next person who wants to do something similar can find my guide instead of going to an LLM. I’ve also decided to go back and replace the LLM-assisted code once I’ve had a little break and am ready to revisit tkr. I realized that if I do that, I can call it “tkr de-Claude.” That tickles me enough to almost make the initial blunder worth it.
But I’m also not going to let the fallout of that decision color the experience. I had a great time building tkr, I learned a lot from the process, and I’m proud of the result. If you have an idea for an application, I think you should try building it! If you do, these are my suggestions:
- Keep it simple. The fewer dependencies you have, the easier it will be for people to use it. Your instructions will be simpler, there will be less that can go wrong, and you won’t have to test as many things.
- If you’re just getting started with this kind of thing, try PHP.
- If you want a database, use SQLite.
- LLMs are polarizing. I wouldn’t let one just build the app, but I think it’s okay to use one as an aid. Not everyone agrees with me. If you use an LLM and are planning to make your project public, just let people know so they can decide whether they’re comfortable using it.
- If I had it to do over, I wouldn’t have developed tkr as publicly as I did. Some people find that energizing. If you’re one of those, then go for it! For me, it was more a source of pressure. In the future, I’m going to build things in private and wait until they’re done to share them publicly.
I hope you’ll try tkr. If you do, email me (greg@subcultureofone.org) or say hi on Mastodon and let me know how it goes.
But even more, I hope you’ll make something. This community is so creative. Whether it’s art or writing or software or music or crafts: whatever your passion is, I hope you’ll give it a home on the personal web and share it with the world. You never know who you might inspire.
Greg is a former hobbyist sysadmin who made the mistake of turning his hobby into a career. He's in the process of reverting it to a hobby at subcultureofone.org.
Member comments