Writing Toy Software Is A Joy
135 points by zesterer
135 points by zesterer
I will say, a lot of these programs are larger than what I’d consider a toy as such. Closer to an super intricate Lego set or an involved model plane?
This is a fair take I think. Most models or Lego kits assemble in far less time. What would you consider toy software?
For me, it’s about “is this small enough that I could still play with it easily if I wanted to?”
https://github.com/yumaikas/eye and https://github.com/yumaikas/dirx are both toy-size things
https://github.com/yumaikas/jagged-scraps/blob/main/jag.janet starts to creep above that size. The rest of the jagged-scraps repo is stuff I’d consider toy-size. https://contrast.junglecoder.com/ is another thing I’d consider a software toy.
For programming languages, a small RPN evaluator is something I’d consider toy size. In college, I once made a meme creating program using WinForms and some font-rendering code I borrowed off someone’s blog. A few years back, when I was doing the 1hgj, I made https://yumaikas.itch.io/escort-the-king, which I’d also consider to be toy-sized (it leans -really- heavily on Godot’s built-in features, like Tilemaps, raycasting collisions, tweens, positional audio, and PathFollow2D)
A lot of it doesn’t really handle edge cases or have good error messaging. It’s stuff that’s very situated. It assumes that you’re cooperating with it, and often, that you have the ability to read the source. Stuff where you can just, sorta, play. It’s not -for- anyone beyond yourself, so you get to decide how far you take the affordances.
Technically, many of these are also tools (I use eye, jag and proc on a regular basis, the discord contrast checker was made for a server I’m in), but I had a lot of fun putting them together, and they bring me joy. Most everything here I’ve linked was made in a handful of hours.
There’s an art to building small, scrappy, sloppy things, in learning how much you can leave out and still have a nice trinket at the end of the day, how much you can do if you embrace taking the shortcuts you wouldn’t, or couldn’t, take if you were standing something up to the internet (jag uses janet’s eval on CLI args, for example).
I love to write this kind of toy projects, although I think the author estimations are extremely optimistic. This one in particular:
Dynamic interpreter (difficulty = 4/10, time = 3 days) A tree-walking interpreter for a JavaScript-like language with basic flow control.
3 days? really? Perhaps if you have already a ton of experience writing languages, and you have written may compilers or interpreters before. But if you are new to the topic, I’m very skeptical that you can get a JS-like language in three days working on your free time.
It took me like 6 months (on my free time) to go through Crafting Interpreters and write my own interpreter for Lox. And that book tells you everything line by line. Some algorithms in this area are not very intuitive. Expression parsing via Pratt or precedence climbing is a bit mind blowing. Or the “upvalues” strategy to deal with closure captures is another example. It’s hard to come up with these things if you don’t have experience with the topic before. So there is a lot of study needed.
But of course this is a ton of fun! I recommend trying these projects, but expect much more time required. And enjoy the rabbit hole.
I think the author estimations are extremely optimistic.
Don’t you know this is a key part of toy projects? :P
Hahaha, what great point! :) Optimism is definitely a key ingredient for having joy while coding. Your comment made my day!
3 days? really?
Oh sure, 3 days to a buggy mvp that kinda sorta works for you. Then hacking on it on and off for the next ten years :P
so story time, i did a little script interpreter myself and it was indeed about three days of spare time to get it to a point that i felt pretty accomplished. You could do stuff like function x() { var a = 5; var b = a * 2 + 3; return b; } print(x());
and it’d say 13 and yeah, sweet, this thing works. Came back to it later and added all kinds of things, classes (as a syntax rewrite to prototypes), different kinds of loops, even some experimental things like macros, these went fairly quickly too. Wrapped my gui lib in it and i can create windows and widgets and it felt really fancy. Played with it for a bunch of things and yeah, by then it was more like 150 more hours sunk into it rather than the original 15 but still.
…but then later, believe it or not, years later, i tried 1 + 2 - 3 + 4
and it said -4 and i was like ummmm what? Turns out that parser I wrote in the original three days read that as 1 + 2 - (3 + 4)
since i did a parseAddend when i should have done a parseFactor… or something like that, the fix wasn’t too hard, but it indicated just how poorly I actually did that original 3 day implementation.
Maybe someday I’ll rewrite it and do it right this time. Should only take 3 days right??? lol
Parsing is the bug (edit: unintended typo that makes more sense than “big”) hurdle here. Actually doing the tree walk / interpreting is a couple hours if you have a good grasp on how these interpreters work. If you don’t, I’d urge you to understand the “metacircular interpreter” for Scheme. It’ll change your perspective quickly.
3 days? really?
The DSL-driven approach to lisp essentially makes a new language for the domain space, every time. Implementing the language is just a few days. Designing it (choosing primitives and the API surface) is much harder. The C world’s poor string handling and parsing makes it difficult, because compiler books spend most of their length overcoming the implementation language!
especially considering they ranked a hash map as a four! in c maybe, but in most languages a naive hash map is trivial
If you’ve been using LLMs for a while, this cold-turkey approach might even be painful at first, but persist. There is no joy without pain.
I think this is a good reminder in general. LLM tools are like gambling and can thus be rather addictive.
It’s better to learn these things yourself, for your own brains sake.
These ratings are estimates and assume that you’re already comfortable with at least one-general purpose programming language and that, like me, you tend to only have an hour or two per day free to write code. Also included are some suggested resources.
So a day is one or two hours? These estimates are brutally short. Not sure if the author is really this good, or flexing, or if they just call it quits once the project compiles and the happy path returns a plausible result.
Maybe I’ll do some adjusting. It’s difficult to calibrate estimates once you’ve got experience building something!
I’ve been consistently surprised by just how often some arcane nugget of knowledge I’ve acquired when working on a toy project has turned out to be immensely valuable in my day job
This is very true. It’s so surprising when it happens: “WTF. I just learning this weird thing and it’s useful for this $work thing?!”. I wrote about how that happened a few times with me
A note on learning and LLMs
[…]
The runner’s high doesn’t come to those that take the bus.
I really like the way this is put. And it tells me things about running that weren’t entirely obvious to me. Maybe I should consider getting into that…
These are super cool projects! Although I do have to agree with some other comments that either the author had a lot adjacent experience, or just that good – I know I would be that much slower.
But I definitely agree with the spirit, even a super simple toy application will give you a lot of understanding. I’ve built a basic Win32 app using C only, and that already is enough to give a mental model of Windows GUI application loop.
Thank you so much. I’ve been thinking very deeply about this. I’m surrounded by a younger generation of coders all using LLMs to solve their problems on their personal projects. But if one is a knowledge journey, then learn slow and without the LLM. This is a perfect post.
@zesterer In the GUI toolkit section, thank you for including the warning about shipping a toolkit without accessibility. I’m curious, how far did you get with your toy GUI toolkit, and what language did you do it in?
Yeah, GUI frameworks - along with perhaps cryptography - is one of the few areas that really doesn’t need a bunch of newcomers advertising their solutions as production-quality. But provided you’re painting a big ‘don’t use this unless you’re not going to throw it in front of the general public’ sign on it, it’s fine.
Not very far, but enough that I could make a calculator! My goal was to make a retained mode UI framework in Rust (Rust, infamously, is not well set up for the sort of self-interacting callback-oriented programming that retained mode requires, so most Rust UI libraries are immediate-mode). The design somewhat borrows from Haskell’s lens pattern and uses combinators to build up modular UI elements and handle events. If I had enough time I’d probably revisit it, but hey - the point of building toys is to quickly figure out what does and doesn’t work and then carry that knowledge forward. You can find it here.
Fortunately, the Rust GUI ecosystem is doing a good job of decomposing the big job of a production-quality GUI toolkit into smaller crates. I realize that promoting these here risks missing the point, like the other post about using a chess library. But it depends on what aspect(s) of the problem you want to solve for yourself in your own way, and what you’re fine with delegating.
Anyway, for text layout, you can use Parley. And for accessibility, you can use my own project, AccessKit, to implement the platform-specific accessibility APIs. Of course, it’s still up to you to expose the right hierarchy, roles, and properties in your framework. But at least this way you don’t have to deal with COM, Objective-C, D-Bus, Java interop for Android, etc.
Oh, you’re the AccessKit dev? Brilliant work! I’ve been meaning to find some time to integrate it into Veloren but have managed to scare myself away from it for the last 18 months. I think AccessKit is a great example of the value of providing low-barrier ecosystem tools and letting folks figure out how to plug it in.
Well, Arnold Loubriat (not on Lobsters) and I are the co-developers. I started the project, but his role has increased over the past few years. So I should give credit where it’s due and not just call it my project.
Writing toy software is wonderful because you can focus on the core (for whatever definition of core) and you can drop it when you have learn what you wanted to learn. The edge cases, the production features, having to deal with requests that is the boring part of software.
In 2025, the beauty and craft of writing software is being eroded. AI is threatening to replace us (or, at least, the most joyful aspects of our craft) and software development is being increasingly commodified, measured, packaged, and industrialised. Software development needs more simple joy, … “
Thanks for writing this. I feel this way a lot about AI. It’s nice to be reminded there is still pleasure in finding things out (another feyman reference).
The runner’s high doesn’t come to those that take the bus.”
Love that ending line!
[Orbital Mechanics Sim] Additional complexity comes with implementing more precise and faster integration methods, accounting for relativistic effects, and plugging in real numbers from NASA to predict the next high tide or full moon.
That sounds really cool! How many different celestial bodies did you have to simulate to get decent predictions?
Sun/Earth/Moon was sufficient for near-term things like tides and moon phases. I moved on from the project before getting much more adventurous than that (not least because I suspected relativistic effects would start to be relevant, and I didn’t much fancy opening that can of worms).
Excellent article. As others have said, the estimates seem very aggressive for some of the projects. But hey… those depend on free time availability :) I know I could pull off some crazy stuff 20 years ago while I was in university because of all of the free evenings I had – and these days it takes me days of heavily fragmented free time to accomplish anything. (Plus 20 years ago my expertise was also lower, so I’m sure I let many things go that I wouldn’t today.)
Anyhow, this made me think of https://handmade.network/ . The software in there isn’t quite the same as “toy software” but many of the projects that come out of there have the same vibe of “why not do this? and do it from scratch?”. Worth taking a look.
I would say Chess Engine development difficulty is much lower, there are bunch of libraries that you can start with to skip the niche parts, such as move generation and represenatation of the chess board. But the engine itself is a simple Alpha-Beta pruning search with a very basic evaluation algorithm. If you are looking for more challange, you can re-write each component one by one, make your engine stronger etc.
Also I recommend the following website for chess engine development: https://www.chessprogramming.org
The whole point of writing toy software is that you’re doing that yourself - if you’re just using libraries then what really is the point?
Maybe you are interested in search but not move generation? Yes the point is to do it yourself, but that does not mean you should do everything yourself.
The post literally starts with “I would say Chess Engine development difficulty is much lower”, and then says the reason is that you don’t have to write a chess engine. That’s like saying writing a toy os is easy, as there are lots of libraries (minix,…) that can do parts of it for you.
I do agree that writing certain things by yourself is very daunting, but honestly the board representation and the moves are relatively small things, definitely doable in a few days.
I would say if you build a cross-platform GUI, picking up Skia is more like that instead of trying to make your own rendering engine (unless that’s your goal).
I have recommended libraries to just get started. Also I don’t think it means you are not writing toy software. On contrary, if you want to write a serious chess engine, you can’t just use those ready libraries as they are not performant enough. I would call an engine that uses python-chess
much more of a toy than a one that writes their own movegen.
I think where I differ is that I don’t mind if there’s no pot of gold at the end of the rainbow. The journey is the goal, and I feel happy for having done it. That it happens to be a great training exercise for ‘real’ software development is just a happy accident. I’m sure not everybody feels way though.