Full Width [alt+shift+f] Shortcuts [alt+shift+k]
Sign Up [alt+shift+s] Log In [alt+shift+l]
44
When I started wood carving, the only sharpening method I remembered was from seeing my mother use some kind of smooth broken stone that she passed over the length of the knife blade before sacrificing a chicken. I also remember seeing my father use a very coarse stone wheel placed on a motor shaft which threw many sparks when he sharpened some large axe for splitting wood. I had neither of those around anymore in my rented place in the city so I jumped headfirst in the mind numbing and sometimes esoteric art of getting a sharp blade. crude sharpening methods that my parents used Carving knives The first blade type I had to sharpen was for my BeaverCraft carving knives. They fortunately came with a strop, basically a plywood base in the form of a paddle, with leather stuck to it on both sides, and a green waxy bar. Unfortunately I had no idea what to do with it. BeaverCraft carving knive set Stropping is, at the most basic level, dragging the blade back and forth on a...
3 months ago

More from Copper • A blog about conductive layers

Woodworking as an escape from the absurdity of software

Some of you might remember the legendary comment of Eric Diven on a Docker CLI issue he opened years ago: @solvaholic: Sorry I missed your comment of many months ago. I no longer build software; I now make furniture out of wood. The hours are long, the pay sucks, and there’s always the opportunity to remove my finger with a table saw, but nobody asks me if I can add an RSS feed to a DBMS, so there’s that :-) I say legendary because it has over 9000 reactions and most are positive. There’s a reason why so many devs resonate with that comment. A lot of us said at some time things like “I’m gonna throw my laptop out the window and start a farm”. Even my last team leader sent me a message out of the blue saying “I think I’ll run a bar. I want to be a bartender and listen to other people’s stories, not figure out why protobuf doesn’t deserialize data that worked JUST FINE for the past three years”. You know the drill, sometimes the world of software development feels so absurd that you just want to buy a hundred alpaca and sell some wool socks and forget about solving conflicts in package.json for the rest of your life. I went through those stages too: when the Agile meetings got so absurd that we were being asked to estimate JIRA task time in T-shirt sizes, I quit my well paying job so I can spend that time creating macOS apps. Recently, when people started coming with so many unrealistic and absurd expectations and demands about my apps, I think I’ll soon quit software development altogether. It’s just not making sense anymore for me. A bit of history Most of my pre-college time was spent on things I didn’t want to do. I had a bit of childhood, but then I started going to school 6 hours per day, with 1-2 hours spent on commute after 5th grade. I only liked the 10-minute breaks between classes where I played basketball or practiced parkour. Every day after I came back from school, I had to work in agriculture, either out in the field with crazy winds and sun and UV radiation, or inside the greenhouse where it’s either a 50°C sauna or a muddy rainforest. I was very bad at every job I was given, but it’s what my parents did for a living and I had to help them, no questions asked. The few hours that remained, usually very late at night, tired both physically and mentally, I spent practicing acoustic guitar, doing bodybuilding exercises, writing poetry or drawing portraits. me, ages ago, playing a classical guitar on someone's old couch I almost never did homework or memorize whatever had to be memorized for the next day of school. I just couldn’t justify spending those few hours I had left on even more stuff I did not want to do. When I found my liberty in college, hundreds of kilometers away from my parents, it’s like something clicked. I suddenly became incapable of doing work that I found meaningless. Failing classes became acceptable, quitting jobs was something I did with little remorse if I felt I wasn’t helping anyone with the work I was assigned, and bureaucracy became a disease I had to avoid at all costs. I still washed the dishes though. Cleaning and other “chores” never felt meaningless for some reason. The first wood thing I did … was a chess board and piece set. With magnets inside them. Where the pieces look nothing like ordinary chess pieces. chess board, first iteration I was trying to get the pieces to snap into place in a satisfying way, and make sure the game stays that way when kids or dogs inevitably bump the table where the board sits. You know how Magnus Carlsen always adjusts his pieces so meticulously before a game? Well I have half of that obsession as well so I wanted to avoid doing that. Magnus Carlsen adjusting his pieces before a game pawn snapping into its square because of the magnet inside How it was done I started with a cheap but hefty pine board which I rounded with a lot of sandpaper. Then I asked my wife to help me colour in the darker squares because I’m pretty bad at colouring inside the edges (both literally and figuratively). We used some wood floor markers for that and the colour seems to be holding well. Most chess board builds you see on YouTube are done by gluing squares of different wood species with alternating colors, but I had neither the skill nor the tools to do that. Then I drilled holes for the super strong neodymium magnets from the underside of the board, having to get really close to the top side without passing through. I failed on two squares, but some wood putty took care of that. sculpting chess pieces with my dremel on the balcony I spent a few sunny days on the balcony sculpting the pieces with a badly sharpened knife and my Dremel. This was quite satisfying, there’s something really nice about seeing a non-descript rectangle take the shape of a little horse in your hands. I mean knight, but in Romanian that piece is called “horse”, and I really don’t see any knight there. chess board, start to finish Regarding the design, I got some inspiration after seeing these modernist chess sets, which not only looked beautiful in my eyes, but also had these geometric shapes that didn’t need that much sculpting to replicate. I found ready-to-buy spheres and cubes of wood at a craft shop around me (which took care of pawns and rooks), and the rest were carved out of rectangles and cones of wood. Modernist chess set designs Kaval Two Octobers ago, a Romanian music band called Subcarpați was holding a free “make a Kaval with your own hands” course, where a flute artisan taught the basics of his trade for a week. The Kaval or “caval” is a long flute with 5 holes and a distinct lower register where notes can sound melancholic and coming from far away, as opposed to the thin cheerful sound of the small shepherd flute. Kaval sample in G minor Ever since I bought my first Kaval, I always wanted to learn how to build one myself. It’s one of those trades where there’s very little info on the internet, so it feels almost mystical compared to what I’m used to in programming. I would also have the chance to walk home with the finished flute, so of course I went to the course. Making my own Kaval, in B minor I loved the fact that we worked in teams of two, and that everything had to be done by hand with no power tools. Even the long bore through the 70cm branch of elder tree had to be done with a hand drill, taking turns to rest our hands. The artisan had been a shepherd himself since childhood, and taught himself with a lot of trial and error about how to build good sounding flutes and how to make the holes so that the flute stays in tune. But he didn’t know why the holes should be at those specific distances or why the wood tube should be of that specific length for each scale. I wanted to know those things, because I had an idea of making a universal Kaval that can play in any scale. You see, if you want to play on top of songs in various scales, you need a Kaval made for each specific scale. So you’ll need an A minor flute, and a B minor one and a C minor one and so on, for a total of 12 different flute lengths. I eventually found info on how a flute works by thinking about it as an open or closed tube where the vibrating air creates nodes and antinodes that should coincide with the hole position. At the moment I’m still studying this and working towards my “universal flute” goal. The physical world has no undo button A few days ago I was walking with my dog around the university and I saw an elderberry tree with a really straight and already dead branch. I thought that might be great for trying to do another kaval, so I went back home to grab my folding saw to cut this branch. I brought it home, cut it to about 78cm for an A minor kaval, straightened it in the vise and started boring a hole through it. I used a 12mm drill first because elder branches have this spongious core that was exactly 12mm in my case. I was able to drill end to end in less than 10 minutes, first time I managed to do this successfully. Drilling a hole through an elder tree branch For such a large flute, you usually need a larger 16mm or 18mm hole to get enough volume, so I went ahead and used the 16mm drill to enlarge the hole. After about 10cm, things started squeaking loudly and smoking so I got the branch out of the vise to inspect it. Because the branch was not completely straight, the drill came out of the side and it was hitting the harder wood of the vise. Damn.. another wasted branch, there’s not a lot of straight material around me in the city. Man, how I wish I could hit undo and just experiment with the good 12mm hole. This reality hit me many times while working with wood in the past 6 months. I didn’t even realise that my mind got so used to having git and backups and Cmd-Z that those expectations transferred to the physical world as well. Move fast and break things is no longer a good mantra for me. I gave the broken branch to my dog, she loves chewing large sticks and got a real kick out of it. Her face definitely said BEST STICK EVER!! for about 5 minutes of pure bliss, so apparently nothing was wasted in the end. What does this have to do with software? For the past 10 years I lived in rented apartments, usually at the 3rd or 4th story with no access to a courtyard. I was never able to get used to that, given that all my childhood I lived and played in a 2000m² courtyard, on a road where there were more slow horse carriages than noisy cars. This year I moved into a rented house with a tiny but welcoming garden and a bit of paved court and only now I notice the effect this has had on my mind and behaviour. I develop macOS apps for a living, and there are some unhealthy things in this field that piled up over the years. I get a lot of messages in a demanding and negative tone, and because walking outside the apartment meant unbearable car noise, obnoxious smells and zero privacy, I always defaulted to simply acting on the feedback, putting up with it and working long hours into the night, instead of going for a walk to calm down. A few months ago, the most absurd demands started coming up for my apps: things like “why does your app not control the volume of my <weird sound device>? why don’t you just do it, people pay you for it” when the app in question is Lunar, an app for controlling monitor brightness, not sound devices. Or “why do you disable your apps from working on Windows?”, or “make Clop compress text and copy it to clipboard” (where Clop is my app that automatically compresses copied images, videos and PDFs, I have no idea what compressing text even means in that context). But this time, I was able to simply walk out the front door, grab a branch of beech wood, and, because I remembered my wife saying we forgot to package the french rolling pin when moving, I took out my pocket knife and started carving a simple rolling pin for her. It was so liberating to be able to just ignore those messages for a while and do something with my hands. the rolling pin is such a simple tool and to this day, my wife still tells me how much she likes it because it's exactly the right length and thickness for making her tasty egg noodles.. and best of all, it was free I understand that those people don’t know better, and they would have no idea that there’s no checkbox where you can choose whether an app works on macOS, Windows or Linux. I understand how if the app does something with audio volume or compression, some think that it should do everything related to those workloads, even if it’s completely outside the scope of the app. But the combination of the negative tone and getting message after message, some people being so persistent that they insist on sending me those messages through all possible mediums (email, Discord, Twitter, contact form, they’ll find me everywhere), makes it hard to just ignore them. There’s also this oily smell of AI and machine learning in the tech atmosphere, where I no longer feel relevant and I seem to have stopped caring about new tech when I noticed that 8 in 10 articles are about some new LLM or image generation model. I guess I like the smell of wood better. Side tangent on privileges of being a software dev I know I’m privileged to even be able to have the choice of what to do with my time. I got lucky when I chose a computer science university at the right time which allowed me to progress towards a huge semi-passive income in the last 10 years. that doesn’t mean I didn’t work my ass off, but luck plays a huge role too I got “lucky” to have my mind traumatised into some kind of OCD-like state where I hate leaving a thing unfinished. So I plow through exhaustion, skip meals, miss house chores and annoy dear people around me because I know “I just need to fix this little thing” and I’ll finish this app/feature/task I started. Even though I also know there’s no real deadline and I can leave it half-finished and the world won’t end. But even if it sounds annoying for a person like me to whine about how I don’t feel good or I feel burnt out, the privilege doesn’t negate the feelings. The regression to the norm will make everyone, rich or poor, get used to the status quo and complain about every thing that’s just a little worse than their current state. That’s happiness and sadness in a nutshell. I’m also vaguely aware that software dev as we know it is about to disappear soon, and I got tired of learning the newest thing just to have it replaced next year. I got tired of back pain and chronic finger pain from so many hours of sitting and typing, I’d rather have pain from work that also builds some muscle. And I got so tired of everything being online, immaterial, ephemeral and lonely, like indie development tends to be. Woodworking with cheap tools and free wood This house we rented is small and the owners had to fit the bedroom upstairs. I really don’t like climbing stairs up and down, especially when I have to let my dog out three times per night. So we gave up a room and started furnishing our own bedroom downstairs. I didn’t want to buy bedside tables for the price of the bed itself, so I thought I could maybe make by own. I’m not yet skilled enough to build my own bed though, so we had to buy that. Another day on a walk with my dog, I noticed that some trees were getting trimmed in the vicinity of our house and there were a lot of white birch branches on the side of the road. I said why not? ¯\_(ツ)_/¯, grabbed some branches and walked like a lunatic with white long sticks dangling up and down and a black frenetic dog zig-zagging left and right, all the way home. I had another small pine panel left from that chess project so I started thinking about the simplest way to turn what I have into a bedside table. pine board with birch branches I used low-grit sandpaper to give the board some nice round corners because I love squircles, swallowed about a spoonful of sawdust because I couldn’t find any breathing mask left, criss-crossed 4 branches in a way that would give a stable base, and screwed them to the underside of the board with long wood screws. The legs would wobble around though, so I drilled small 3mm holes into each branch where they met in the middle, and weaved a florist wire through them to keep the table steady. Bedside table, made out of pine with birch legs The laptop bed table After I’ve shown the bedside table to a friend of mine, he said he also needed a laptop table for those mornings when he’d rather not get out of bed. I wanted to say that’s not very healthy, but what got out instead was sure thing, I’ll do it!. Oh well.. I still had the large desk top I glued from smaller beech boards, on which I worked for the past 4 years. It stayed unused currently, so I cut part of it and built this cute thing: cute but heavy laptop table, made out of glued beech wood You’ll notice three defining features that every laptop table should have: a hole for a charging cable a carved coaster for the coffee cup a mildly surprised face? 😦 To tell the truth, all those are side effects of me drilling holes where there should be no hole, and dropping the board on the ground multiple times because my workbench was not large enough. All the things that could go wrong, went wrong with this table. I hid the defects by turning them into features. The whole truth actually is that the table looks nothing like what I planned. I bought these nice hidden brass cylindrical hinges to make the table foldable. That way, you could fold the sides flat inside and use it as some kind of armchair desk if you wanted. Brass hinges I wasn’t able to drill the correctly sized or positioned holes for the hinges because I still lack a lot of knowledge and skill in working with wood. So after losing my temper with the frickin’ hinges that still didn’t fit after a full day of drilling and chiseling, I glued the sides and inserted 2 trusty long wood screws per side, which I patched with a glue gun that made the screw holes look like eyes. After I also carved the handles, the table grew kind of a personality of its own, as you can see above. Why didn’t I do some wood joint, like a dovetail instead of ugly screws and glue? Because I had no idea they existed. Also, I wasn’t even able to fit a simple hinge, I would’ve probably never finished this table if I tried learning wood joinery on it. This reminds me of how whenever I did pair programming with a colleague, I noticed how they were doing some “nonoptimal” action and I would say: Why don’t you just use ripgrep instead of sifting through all these files? Because they don’t know it exists, stupid. Or because they just want to get this thing done and move on, they don’t grep files all day like you do. Learn from my mistakes, don’t think you know better or assume the other person needs your way of doing things. Maybe let them know after the fact, in a short message linking to the tool, and let them try it in their own time. But in my ignorance, I seem to have chosen a good enough joining method. As you can see in this wood joinery comparison, 5cm (2inch) screws can hold more than 50kg (110lbs) of force, and I used even longer screws so I think it’s going to hold a 3kg laptop just fine. Oh right, forgot about this little detail.. I also added a cork pocket for holding a notebook, tablet, phone etc. which I lined with a microfiber cloth on the inside for strength and sewn to the wood with that leftover alpaca wool for style. Cork pocket sewn to the table side The bookshelf without books Large bookshelf (200x120x40 cm), made out of pine boards While we were stuck in the apartment in the 2020 pandemic, me and my wife bought a lot of stuff that we thought would help us learn new things and start new hobbies. I thought I’m going to build smart LED lighting all my life and my wife would become a professional wool knitter. We were losing our minds, for sure. So now we were stuck with crates of stuff we haven’t used in years, and didn’t want to start unpacking them around the house. The clutter that followed after the pandemic, tired our minds just as much as the lockdown itself. We dumped the crates on an unused stairway spot, and I thought that a bookshelf as large as that spot would clear the clutter. Before: clutter | After: organized clutter But I could not find any bookshelf that large, certainly not for cheap. So I traced a few lines in Freeform, took some measurements, and ordered a bunch of large pine boards and a ton of long screws. I also ordered the cheapest portable workbench I could find ($30) that had a vise, so I can stop making sawdust inside. A few days later, I got to sawing the shelves to size with my cheap Japanese pull saw I bought from Lidl years ago. Hint: Hand sawing a long wood board with no skill will certainly end up with a crooked edge. Stacking up 5 boards one on top of the other will still end up crooked. Uhm, I guess the hint is, buy a track saw, or make sure the crooked edge isn’t visible. Hand sawing a straight long edge is not easy. making the bookshelf My wife helped a lot with measuring and figuring out where to drill holes and place the screws, while my dog inspected the work regularly to make sure the defects were hidden correctly. It took two days of screwing.. erm.. driving screws, I mean. But in the end we got the result we wanted! And I got sores in my right arm for days, driving those long screws is harder than I thought. The desk that became a workbench In the thumbnail of this post you can see the current “workbench” I use, which is basically that $30 vise workbench I bought for the bookshelf, with the top of my previous “coding desk” attached in the front. my current workbench In the image you can see (bottom-left to top, then right): the cheapest block plane I could find ($8) a red no-name plane I found in the shed of that 100-year old house that we never finished rebuilding because of legal reasons an axe I found rusted and partly broken in the same shed, on which I learnt how to sharpen and restore axes a folding japanese pull saw that I take everywhere with me some grip blocks on which I place boards for sanding a bottle of Osmo Polyx oil I use for finishing (this is the Rubio Monocoat for poor people) a set of carving knives from Beavercraft (really good and they were available at a nice discount) a combination square (tucked somewhere at the top of the bench) a branch of elder tree, which is prepared for drilling a hole through it for making a kaval I also own some no-name chisels that work well enough for now and some card scrapers that I still struggle sharpening. The only power tools I have are a Makita drill and a random orbit sander on which I did spend some money, an old circular saw I found in that same old shed (it was good enough to cut miters on that laptop table) and a Dremel I use rarely because I don’t like its power cord. I prefer battery powered tools. The window bench Our dog Cora loves sitting at the window, growling at old people and barking at children passing around. Yeah, she’s terrified of children for some reason. But the window sill is not wide enough and her leg kept falling with a “clang” on the radiator below. So I widened it by placing two glued up boards of pine on top of the radiator, that I planed and smoothed beforehand. Cora sitting at the window Cora at the window, with the widened sill This is when I learned that a hand plane is not some antique tool that nobody uses anymore, but a quite versatile piece that can easily smoothen grain where I would waste 5 sheets of sandpaper and choke on sawdust. I had to still let the heat radiate somehow, so I drilled large holes with a forstner bit, but I also blew the grain fibers on the underside because I had no idea of this possible problem. Turns out there is a simple solution to drilling large holes without ripping the fibers: Drill a small 3-6mm hole in the center with a normal wood drill, all the way to the other side (this will help you see where the forstner bit should be placed from both sides of the board) Place the forstner bit in the hole (this also helps with keeping the bit centered) and drill the large hole, stopping midway through the board Turn the board around and repeat step 2 until you meet the other end of the hole We also wanted to sit with Cora and there was not much space between the bed and the radiator for a regular chair, so I built a narrow bench. I used another two pine boards of the same size, but this time glued them on the side to create a wider board. For the legs, well the tree trimming continued throughout the spring, so one day I found some thick cherry branches which I brought home, scraped the bark from them, then attached them to the bench using screws from the top side. I was ok with a rustic look so I didn’t spend much on finishing, patching holes, or even proper wood drying. I did use the hand plane to chamfer the edges though, I love taking those thin continuous wood shavings from the edge. Window bench, in the morning sun The trunk coffee table Coffee table made out of a beech log We recently visited my parents, and loved how the grass finally started growing in some spots where their house and court renovation was finished and was no longer spewing cement dust. It was an abnormally sunny April and I wanted to chat with them at a coffee outside in the early morning before they started the field work, but there was nowhere to place the coffee outside. First world problems right? If you’ve read about The tail end, you might already understand why a trivial thing like coffee time with my parents feels so important to me. So one day, while walking on a gravel road near their house, I noticed one neighbour had these huge logs of beech that were recently cut. I thought that would be easy to turn into a small exterior coffee table, so I went to ask if I could buy one. Well I kind of had to yell “HELLO!” at their gate because I didn’t know their name, and did that a few times until a seemingly sleepy old man in pyjamas (it was 5 in the afternoon) appeared at the front door asking what I want. I asked how much he’d want for one of those logs, but he just said to get one, no money needed. Ok, there’s no point in insisting, I chose a wide enough but not too wide log, because these things are heavy and I wasn’t sure I could lift it, and rolled it slowly back home. I didn’t have my usual tools at my parents house, so I improvised. I found a battered cleaver which my dad used for chopping kindling for the barbecue. I sharpened it as well as I could, then used a hammer to roll a burr on the back of the cleaver that I could use for scraping. Scraping the bark off the beech log Beech wood has such a smooth hard wood under the bark that it didn’t even need sanding. I used my dad’s power planer to smooth out the top and make a quasi-flat surface then finished it with some walnut oil and it was (almost) ready! Because the wood was so green, it was certain that it will crack and roughen as it dried. So I cut a groove and wrapped a flat iron band around the top to keep it from moving too much. The bottom can expand as much as it wants, I’m actually quite curious to watch the table morph throughout the summer as we use it. The orchard bench Bench made from reclaimed wood, for my parents-in-law orchard Because we were born in villages that aren’t that far apart, me and my wife always visit both our parents in the same trip. This time when I got to my parents-in-law, I took a stroll through their little orchard. They added new trees this year! I can’t wait to taste the large apricots. What struck me as odd about the orchard was that there was no patch of grass to lay on. They like digging up the soil every year, and leaving it like that: an arid looking patch of land made of dry dirt boulders. I thought a bench would be a good solution and what do you know, there was an old broken door thrown in the firewood pile just outside the orchard, that had the perfect length and width for a bench. I forgot to take a photo of the door, but it looked kind of like this one, only worse and with a large rhomboid ◊ hole at the top. old broken wooden door I got to work immediately, dismantling the door piece by piece and pulling out nail after nail (they really liked their nails in those old times). I was left with two long and narrow wooden boards, a pile of rotten wood and two pocketfuls of rusted nails. I sawed the broken ends of the boards, then I used my father-in-law’s power planer (do all Romanian dads have a power planer or what?) to remove the old gray wood from the top, bottom and sides to get to the fresh wood below. There were a lot of holes and valleys so I had to scrape them by hand with sandpaper rolled around a screwdriver. This took a few more days than I expected, but I eventually got two cleanish boards of.. fir? pine? No idea. I used a velcro sandpaper attachment for the battery powered drill to sand out the rotten sides and give the boards a curvy and smooth live edge. Curvy edge on the bench, made by sanding out the rotten wood For the legs, I stole some more firewood from my in-laws pile, where I found some thick branches of unidentified species that were roughly the same length. Stripping the bark with an axe made them look good enough so I screwed them in at the four corners of the board. The bench was wobbly with just the legs, so I strengthened it sideways by adding shorter and thinner branches of more unidentified wood between the legs and the center of the board. I had to do something with the rhomboid ◊ hole, so I filled it with a square 4-by-4 salvaged from a recently dismantled shed, and now the bench has 5 legs. Instead of sawing the leg to size, I left it protruding above the bench and placed another thick salvaged board on top of it to serve as an arm rest, or coffee table, or a place for the bowl of cherries. For the finish, I burned the bench and the bottom of the legs to get a honey-brown aspect and to make it water resistant. I put a very thin layer of whatever wood lacquer I found in my in-laws shed, just for resistance because I don’t like glossy wood. Side photo of the bench for a better view of the legs Other small wood things Water glass shelf We don’t have much space on the current eating table, so I built a two-shelf stand where we can place the always present water filter jug and the glasses and free up some of the center space. It’s incredible how strong just a few screws can be. Table shelf for holding water filter and glasses Kaval stand I thought I should finally do something about the kavals always rolling around on some table or couch throughout the house, so I made a stand from long thin wood boards glued on the side, and finished it with sunflower oil to give it a golden/orange colour. This way I can always expand it by adding more boards to the side if I want to add more flutes. Stand for holding my kaval collection Sharpening block I need to sharpen blades almost daily, be it the pocket knife, axe, plane blade or chisels. So I made a custom sharpening block with the perfect tools for my sharpening technique. Sharpening block, diamond plate with leather strop on a beech base It has a $5 diamond plate with 600 grit on one side and a $5 leather strop (a piece of leather belt might work just as well) on the other side. I attached the leather with two small screws at the top so I can take it out easily if I need a flexible strop for my carving gouge for example. It is loaded with 0.25 micron diamond paste which can be found for cheap at gemstone cutting online stores (the knife-specific pastes are a lot more expensive and I’m not sure why). To be honest, a $0.5 green compound (chromium oxide) works just as well for stropping, that’s what I used before and still use for my detail carving knives. It gives a smoother edge than the diamond, the disadvantage being that it needs to be re-applied more often on the leather and that you need a bit more blade passes to get the same result. The diamonds seem be cutting faster, but really not much faster. A bit of a tangent on the sharpening topic I went through all the phases with sharpening tools. I’ve used water stones, natural stones, ceramic stones, pull-through carbide sharpeners (don’t use these), powered belt sharpeners, wheel sharpeners. Aside from the pull-through sharpeners and the steel rods, all the others work just as well with the right technique. I settled on the diamond plate because they’re cheap, portable, stay flat, need zero maintenance, and can cut through any type of metal. Paired with a leather strop, for me it’s the simplest way to sharpen. I recommend this OUTDOORS55 video for a no-bullshit sharpening tutorial and the Science of Sharp blog if you’re curious what the different sharpening techniques do to an edge under a microscope.

9 months ago 40 votes
Woodworking as an escape from the absurdity of software

Some of you might remember the legendary comment of Eric Diven on a Docker CLI issue he opened years ago: @solvaholic: Sorry I missed your comment of many months ago. I no longer build software; I now make furniture out of wood. The hours are long, the pay sucks, and there’s always the opportunity to remove my finger with a table saw, but nobody asks me if I can add an RSS feed to a DBMS, so there’s that :-) I say legendary because it has over 9000 reactions and most are positive. There’s a reason why so many devs resonate with that comment. A lot of us said at some time things like “I’m gonna throw my laptop out the window and start a farm”. Even my last team leader sent me a message out of the blue saying “I think I’ll run a bar. I want to be a bartender and listen to other people’s stories, not figure out why protobuf doesn’t deserialize data that worked JUST FINE for the past three years”. You know the drill, sometimes the world of software development feels so absurd that you just want to buy a hundred alpaca and sell some wool socks and forget about solving conflicts in package.json for the rest of your life. I went through those stages too: when the Agile meetings got so absurd that we were being asked to estimate JIRA task time in T-shirt sizes, I quit my well paying job so I can spend that time creating macOS apps. Recently, when people started coming with so many unrealistic and absurd expectations and demands about my apps, I think I’ll soon quit software development altogether. It’s just not making sense anymore for me. A bit of history Most of my pre-college time was spent on things I didn’t want to do. I had a bit of childhood, but then I started going to school 6 hours per day, with 1-2 hours spent on commute after 5th grade. I only liked the 10-minute breaks between classes where I played basketball or practiced parkour. Every day after I came back from school, I had to work in agriculture, either out in the field with crazy winds and sun and UV radiation, or inside the greenhouse where it’s either a 50°C sauna or a muddy rainforest. I was very bad at every job I was given, but it’s what my parents did for a living and I had to help them, no questions asked. The few hours that remained, usually very late at night, tired both physically and mentally, I spent practicing acoustic guitar, doing bodybuilding exercises, writing poetry or drawing portraits. me, ages ago, playing a classical guitar on someone's old couch I almost never did homework or memorize whatever had to be memorized for the next day of school. I just couldn’t justify spending those few hours I had left on even more stuff I did not want to do. When I found my liberty in college, hundreds of kilometers away from my parents, it’s like something clicked. I suddenly became incapable of doing work that I found meaningless. Failing classes became acceptable, quitting jobs was something I did with little remorse if I felt I wasn’t helping anyone with the work I was assigned, and bureaucracy became a disease I had to avoid at all costs. I still washed the dishes though. Cleaning and other “chores” never felt meaningless for some reason. The first wood thing I did … was a chess board and piece set. With magnets inside them. Where the pieces look nothing like ordinary chess pieces. chess board, first iteration I was trying to get the pieces to snap into place in a satisfying way, and make sure the game stays that way when kids or dogs inevitably bump the table where the board sits. You know how Magnus Carlsen always adjusts his pieces so meticulously before a game? Well I have half of that obsession as well so I wanted to avoid doing that. Magnus Carlsen adjusting his pieces before a game pawn snapping into its square because of the magnet inside How it was done I started with a cheap but hefty pine board which I rounded with a lot of sandpaper. Then I asked my wife to help me colour in the darker squares because I’m pretty bad at colouring inside the edges (both literally and figuratively). We used some wood floor markers for that and the colour seems to be holding well. Most chess board builds you see on YouTube are done by gluing squares of different wood species with alternating colors, but I had neither the skill nor the tools to do that. Then I drilled holes for the super strong neodymium magnets from the underside of the board, having to get really close to the top side without passing through. I failed on two squares, but some wood putty took care of that. sculpting chess pieces with my dremel on the balcony I spent a few sunny days on the balcony sculpting the pieces with a badly sharpened knife and my Dremel. This was quite satisfying, there’s something really nice about seeing a non-descript rectangle take the shape of a little horse in your hands. I mean knight, but in Romanian that piece is called “horse”, and I really don’t see any knight there. chess board, start to finish Regarding the design, I got some inspiration after seeing these modernist chess sets, which not only looked beautiful in my eyes, but also had these geometric shapes that didn’t need that much sculpting to replicate. I found ready-to-buy spheres and cubes of wood at a craft shop around me (which took care of pawns and rooks), and the rest were carved out of rectangles and cones of wood. Modernist chess set designs Kaval Two Octobers ago, a Romanian music band called Subcarpați was holding a free “make a Kaval with your own hands” course, where a flute artisan taught the basics of his trade for a week. The Kaval or “caval” is a long flute with 5 holes and a distinct lower register where notes can sound melancholic and coming from far away, as opposed to the thin cheerful sound of the small shepherd flute. Kaval sample in G minor Ever since I bought my first Kaval, I always wanted to learn how to build one myself. It’s one of those trades where there’s very little info on the internet, so it feels almost mystical compared to what I’m used to in programming. I would also have the chance to walk home with the finished flute, so of course I went to the course. Making my own Kaval, in B minor I loved the fact that we worked in teams of two, and that everything had to be done by hand with no power tools. Even the long bore through the 70cm branch of elder tree had to be done with a hand drill, taking turns to rest our hands. The artisan had been a shepherd himself since childhood, and taught himself with a lot of trial and error about how to build good sounding flutes and how to make the holes so that the flute stays in tune. But he didn’t know why the holes should be at those specific distances or why the wood tube should be of that specific length for each scale. I wanted to know those things, because I had an idea of making a universal Kaval that can play in any scale. You see, if you want to play on top of songs in various scales, you need a Kaval made for each specific scale. So you’ll need an A minor flute, and a B minor one and a C minor one and so on, for a total of 12 different flute lengths. I eventually found info on how a flute works by thinking about it as an open or closed tube where the vibrating air creates nodes and antinodes that should coincide with the hole position. At the moment I’m still studying this and working towards my “universal flute” goal. The physical world has no undo button A few days ago I was walking with my dog around the university and I saw an elderberry tree with a really straight and already dead branch. I thought that might be great for trying to do another kaval, so I went back home to grab my folding saw to cut this branch. I brought it home, cut it to about 78cm for an A minor kaval, straightened it in the vise and started boring a hole through it. I used a 12mm drill first because elder branches have this spongious core that was exactly 12mm in my case. I was able to drill end to end in less than 10 minutes, first time I managed to do this successfully. Drilling a hole through an elder tree branch For such a large flute, you usually need a larger 16mm or 18mm hole to get enough volume, so I went ahead and used the 16mm drill to enlarge the hole. After about 10cm, things started squeaking loudly and smoking so I got the branch out of the vise to inspect it. Because the branch was not completely straight, the drill came out of the side and it was hitting the harder wood of the vise. Damn.. another wasted branch, there’s not a lot of straight material around me in the city. Man, how I wish I could hit undo and just experiment with the good 12mm hole. This reality hit me many times while working with wood in the past 6 months. I didn’t even realise that my mind got so used to having git and backups and Cmd-Z that those expectations transferred to the physical world as well. Move fast and break things is no longer a good mantra for me. I gave the broken branch to my dog, she loves chewing large sticks and got a real kick out of it. Her face definitely said BEST STICK EVER!! for about 5 minutes of pure bliss, so apparently nothing was wasted in the end. What does this have to do with software? For the past 10 years I lived in rented apartments, usually at the 3rd or 4th story with no access to a courtyard. I was never able to get used to that, given that all my childhood I lived and played in a 2000m² courtyard, on a road where there were more slow horse carriages than noisy cars. This year I moved into a rented house with a tiny but welcoming garden and a bit of paved court and only now I notice the effect this has had on my mind and behaviour. I develop macOS apps for a living, and there are some unhealthy things in this field that piled up over the years. I get a lot of messages in a demanding and negative tone, and because walking outside the apartment meant unbearable car noise, obnoxious smells and zero privacy, I always defaulted to simply acting on the feedback, putting up with it and working long hours into the night, instead of going for a walk to calm down. A few months ago, the most absurd demands started coming up for my apps: things like “why does your app not control the volume of my <weird sound device>? why don’t you just do it, people pay you for it” when the app in question is Lunar, an app for controlling monitor brightness, not sound devices. Or “why do you disable your apps from working on Windows?”, or “make Clop compress text and copy it to clipboard” (where Clop is my app that automatically compresses copied images, videos and PDFs, I have no idea what compressing text even means in that context). But this time, I was able to simply walk out the front door, grab a branch of beech wood, and, because I remembered my wife saying we forgot to package the french rolling pin when moving, I took out my pocket knife and started carving a simple rolling pin for her. It was so liberating to be able to just ignore those messages for a while and do something with my hands. the rolling pin is such a simple tool and to this day, my wife still tells me how much she likes it because it's exactly the right length and thickness for making her tasty egg noodles.. and best of all, it was free I understand that those people don’t know better, and they would have no idea that there’s no checkbox where you can choose whether an app works on macOS, Windows or Linux. I understand how if the app does something with audio volume or compression, some think that it should do everything related to those workloads, even if it’s completely outside the scope of the app. But the combination of the negative tone and getting message after message, some people being so persistent that they insist on sending me those messages through all possible mediums (email, Discord, Twitter, contact form, they’ll find me everywhere), makes it hard to just ignore them. There’s also this oily smell of AI and machine learning in the tech atmosphere, where I no longer feel relevant and I seem to have stopped caring about new tech when I noticed that 8 in 10 articles are about some new LLM or image generation model. I guess I like the smell of wood better. Side tangent on privileges of being a software dev I know I’m privileged to even be able to have the choice of what to do with my time. I got lucky when I chose a computer science university at the right time which allowed me to progress towards a huge semi-passive income in the last 10 years. that doesn’t mean I didn’t work my ass off, but luck plays a huge role too I got “lucky” to have my mind traumatised into some kind of OCD-like state where I hate leaving a thing unfinished. So I plow through exhaustion, skip meals, miss house chores and annoy dear people around me because I know “I just need to fix this little thing” and I’ll finish this app/feature/task I started. Even though I also know there’s no real deadline and I can leave it half-finished and the world won’t end. But even if it sounds annoying for a person like me to whine about how I don’t feel good or I feel burnt out, the privilege doesn’t negate the feelings. The regression to the norm will make everyone, rich or poor, get used to the status quo and complain about every thing that’s just a little worse than their current state. That’s happiness and sadness in a nutshell. I’m also vaguely aware that software dev as we know it is about to disappear soon, and I got tired of learning the newest thing just to have it replaced next year. I got tired of back pain and chronic finger pain from so many hours of sitting and typing, I’d rather have pain from work that also builds some muscle. And I got so tired of everything being online, immaterial, ephemeral and lonely, like indie development tends to be. Woodworking with cheap tools and free wood This house we rented is small and the owners had to fit the bedroom upstairs. I really don’t like climbing stairs up and down, especially when I have to let my dog out three times per night. So we gave up a room and started furnishing our own bedroom downstairs. I didn’t want to buy bedside tables for the price of the bed itself, so I thought I could maybe make by own. I’m not yet skilled enough to build my own bed though, so we had to buy that. Another day on a walk with my dog, I noticed that some trees were getting trimmed in the vicinity of our house and there were a lot of white birch branches on the side of the road. I said why not? ¯\_(ツ)_/¯, grabbed some branches and walked like a lunatic with white long sticks dangling up and down and a black frenetic dog zig-zagging left and right, all the way home. I had another small pine panel left from that chess project so I started thinking about the simplest way to turn what I have into a bedside table. pine board with birch branches I used low-grit sandpaper to give the board some nice round corners because I love squircles, swallowed about a spoonful of sawdust because I couldn’t find any breathing mask left, criss-crossed 4 branches in a way that would give a stable base, and screwed them to the underside of the board with long wood screws. The legs would wobble around though, so I drilled small 3mm holes into each branch where they met in the middle, and weaved a florist wire through them to keep the table steady. Bedside table, made out of pine with birch legs The laptop bed table After I’ve shown the bedside table to a friend of mine, he said he also needed a laptop table for those mornings when he’d rather not get out of bed. I wanted to say that’s not very healthy, but what got out instead was sure thing, I’ll do it!. Oh well.. I still had the large desk top I glued from smaller beech boards, on which I worked for the past 4 years. It stayed unused currently, so I cut part of it and built this cute thing: cute but heavy laptop table, made out of glued beech wood You’ll notice three defining features that every laptop table should have: a hole for a charging cable a carved coaster for the coffee cup a mildly surprised face? 😦 To tell the truth, all those are side effects of me drilling holes where there should be no hole, and dropping the board on the ground multiple times because my workbench was not large enough. All the things that could go wrong, went wrong with this table. I hid the defects by turning them into features. The whole truth actually is that the table looks nothing like what I planned. I bought these nice hidden brass cylindrical hinges to make the table foldable. That way, you could fold the sides flat inside and use it as some kind of armchair desk if you wanted. Brass hinges I wasn’t able to drill the correctly sized or positioned holes for the hinges because I still lack a lot of knowledge and skill in working with wood. So after losing my temper with the frickin’ hinges that still didn’t fit after a full day of drilling and chiseling, I glued the sides and inserted 2 trusty long wood screws per side, which I patched with a glue gun that made the screw holes look like eyes. After I also carved the handles, the table grew kind of a personality of its own, as you can see above. Why didn’t I do some wood joint, like a dovetail instead of ugly screws and glue? Because I had no idea they existed. Also, I wasn’t even able to fit a simple hinge, I would’ve probably never finished this table if I tried learning wood joinery on it. This reminds me of how whenever I did pair programming with a colleague, I noticed how they were doing some “nonoptimal” action and I would say: Why don’t you just use ripgrep instead of sifting through all these files? Because they don’t know it exists, stupid. Or because they just want to get this thing done and move on, they don’t grep files all day like you do. Learn from my mistakes, don’t think you know better or assume the other person needs your way of doing things. Maybe let them know after the fact, in a short message linking to the tool, and let them try it in their own time. But in my ignorance, I seem to have chosen a good enough joining method. As you can see in this wood joinery comparison, 5cm (2inch) screws can hold more than 50kg (110lbs) of force, and I used even longer screws so I think it’s going to hold a 3kg laptop just fine. Oh right, forgot about this little detail.. I also added a cork pocket for holding a notebook, tablet, phone etc. which I lined with a microfiber cloth on the inside for strength and sewn to the wood with that leftover alpaca wool for style. Cork pocket sewn to the table side The bookshelf without books Large bookshelf (200x120x40 cm), made out of pine boards While we were stuck in the apartment in the 2020 pandemic, me and my wife bought a lot of stuff that we thought would help us learn new things and start new hobbies. I thought I’m going to build smart LED lighting all my life and my wife would become a professional wool knitter. We were losing our minds, for sure. So now we were stuck with crates of stuff we haven’t used in years, and didn’t want to start unpacking them around the house. The clutter that followed after the pandemic, tired our minds just as much as the lockdown itself. We dumped the crates on an unused stairway spot, and I thought that a bookshelf as large as that spot would clear the clutter. Before: clutter | After: organized clutter But I could not find any bookshelf that large, certainly not for cheap. So I traced a few lines in Freeform, took some measurements, and ordered a bunch of large pine boards and a ton of long screws. I also ordered the cheapest portable workbench I could find ($30) that had a vise, so I can stop making sawdust inside. A few days later, I got to sawing the shelves to size with my cheap Japanese pull saw I bought from Lidl years ago. Hint: Hand sawing a long wood board with no skill will certainly end up with a crooked edge. Stacking up 5 boards one on top of the other will still end up crooked. Uhm, I guess the hint is, buy a track saw, or make sure the crooked edge isn’t visible. Hand sawing a straight long edge is not easy. making the bookshelf My wife helped a lot with measuring and figuring out where to drill holes and place the screws, while my dog inspected the work regularly to make sure the defects were hidden correctly. It took two days of screwing.. erm.. driving screws, I mean. But in the end we got the result we wanted! And I got sores in my right arm for days, driving those long screws is harder than I thought. The desk that became a workbench In the thumbnail of this post you can see the current “workbench” I use, which is basically that $30 vise workbench I bought for the bookshelf, with the top of my previous “coding desk” attached in the front. my current workbench In the image you can see (bottom-left to top, then right): the cheapest block plane I could find ($8) a red no-name plane I found in the shed of that 100-year old house that we never finished rebuilding because of legal reasons an axe I found rusted and partly broken in the same shed, on which I learnt how to sharpen and restore axes a folding japanese pull saw that I take everywhere with me some grip blocks on which I place boards for sanding a bottle of Osmo Polyx oil I use for finishing (this is the Rubio Monocoat for poor people) a set of carving knives from Beavercraft (really good and they were available at a nice discount) a combination square (tucked somewhere at the top of the bench) a branch of elder tree, which is prepared for drilling a hole through it for making a kaval I also own some no-name chisels that work well enough for now and some card scrapers that I still struggle sharpening. The only power tools I have are a Makita drill and a random orbit sander on which I did spend some money, an old circular saw I found in that same old shed (it was good enough to cut miters on that laptop table) and a Dremel I use rarely because I don’t like its power cord. I prefer battery powered tools. The window bench Our dog Cora loves sitting at the window, growling at old people and barking at children passing around. Yeah, she’s terrified of children for some reason. But the window sill is not wide enough and her leg kept falling with a “clang” on the radiator below. So I widened it by placing two glued up boards of pine on top of the radiator, that I planed and smoothed beforehand. Cora sitting at the window Cora at the window, with the widened sill This is when I learned that a hand plane is not some antique tool that nobody uses anymore, but a quite versatile piece that can easily smoothen grain where I would waste 5 sheets of sandpaper and choke on sawdust. I had to still let the heat radiate somehow, so I drilled large holes with a forstner bit, but I also blew the grain fibers on the underside because I had no idea of this possible problem. Turns out there is a simple solution to drilling large holes without ripping the fibers: Drill a small 3-6mm hole in the center with a normal wood drill, all the way to the other side (this will help you see where the forstner bit should be placed from both sides of the board) Place the forstner bit in the hole (this also helps with keeping the bit centered) and drill the large hole, stopping midway through the board Turn the board around and repeat step 2 until you meet the other end of the hole We also wanted to sit with Cora and there was not much space between the bed and the radiator for a regular chair, so I built a narrow bench. I used another two pine boards of the same size, but this time glued them on the side to create a wider board. For the legs, well the tree trimming continued throughout the spring, so one day I found some thick cherry branches which I brought home, scraped the bark from them, then attached them to the bench using screws from the top side. I was ok with a rustic look so I didn’t spend much on finishing, patching holes, or even proper wood drying. I did use the hand plane to chamfer the edges though, I love taking those thin continuous wood shavings from the edge. Window bench, in the morning sun The trunk coffee table Coffee table made out of a beech log We recently visited my parents, and loved how the grass finally started growing in some spots where their house and court renovation was finished and was no longer spewing cement dust. It was an abnormally sunny April and I wanted to chat with them at a coffee outside in the early morning before they started the field work, but there was nowhere to place the coffee outside. First world problems right? If you’ve read about The tail end, you might already understand why a trivial thing like coffee time with my parents feels so important to me. So one day, while walking on a gravel road near their house, I noticed one neighbour had these huge logs of beech that were recently cut. I thought that would be easy to turn into a small exterior coffee table, so I went to ask if I could buy one. Well I kind of had to yell “HELLO!” at their gate because I didn’t know their name, and did that a few times until a seemingly sleepy old man in pyjamas (it was 5 in the afternoon) appeared at the front door asking what I want. I asked how much he’d want for one of those logs, but he just said to get one, no money needed. Ok, there’s no point in insisting, I chose a wide enough but not too wide log, because these things are heavy and I wasn’t sure I could lift it, and rolled it slowly back home. I didn’t have my usual tools at my parents house, so I improvised. I found a battered cleaver which my dad used for chopping kindling for the barbecue. I sharpened it as well as I could, then used a hammer to roll a burr on the back of the cleaver that I could use for scraping. Scraping the bark off the beech log Beech wood has such a smooth hard wood under the bark that it didn’t even need sanding. I used my dad’s power planer to smooth out the top and make a quasi-flat surface then finished it with some walnut oil and it was (almost) ready! Because the wood was so green, it was certain that it will crack and roughen as it dried. So I cut a groove and wrapped a flat iron band around the top to keep it from moving too much. The bottom can expand as much as it wants, I’m actually quite curious to watch the table morph throughout the summer as we use it. The orchard bench Bench made from reclaimed wood, for my parents-in-law orchard Because we were born in villages that aren’t that far apart, me and my wife always visit both our parents in the same trip. This time when I got to my parents-in-law, I took a stroll through their little orchard. They added new trees this year! I can’t wait to taste the large apricots. What struck me as odd about the orchard was that there was no patch of grass to lay on. They like digging up the soil every year, and leaving it like that: an arid looking patch of land made of dry dirt boulders. I thought a bench would be a good solution and what do you know, there was an old broken door thrown in the firewood pile just outside the orchard, that had the perfect length and width for a bench. I forgot to take a photo of the door, but it looked kind of like this one, only worse and with a large rhomboid ◊ hole at the top. old broken wooden door I got to work immediately, dismantling the door piece by piece and pulling out nail after nail (they really liked their nails in those old times). I was left with two long and narrow wooden boards, a pile of rotten wood and two pocketfuls of rusted nails. I sawed the broken ends of the boards, then I used my father-in-law’s power planer (do all Romanian dads have a power planer or what?) to remove the old gray wood from the top, bottom and sides to get to the fresh wood below. There were a lot of holes and valleys so I had to scrape them by hand with sandpaper rolled around a screwdriver. This took a few more days than I expected, but I eventually got two cleanish boards of.. fir? pine? No idea. I used a velcro sandpaper attachment for the battery powered drill to sand out the rotten sides and give the boards a curvy and smooth live edge. Curvy edge on the bench, made by sanding out the rotten wood For the legs, I stole some more firewood from my in-laws pile, where I found some thick branches of unidentified species that were roughly the same length. Stripping the bark with an axe made them look good enough so I screwed them in at the four corners of the board. The bench was wobbly with just the legs, so I strengthened it sideways by adding shorter and thinner branches of more unidentified wood between the legs and the center of the board. I had to do something with the rhomboid ◊ hole, so I filled it with a square 4-by-4 salvaged from a recently dismantled shed, and now the bench has 5 legs. Instead of sawing the leg to size, I left it protruding above the bench and placed another thick salvaged board on top of it to serve as an arm rest, or coffee table, or a place for the bowl of cherries. For the finish, I burned the bench and the bottom of the legs to get a honey-brown aspect and to make it water resistant. I put a very thin layer of whatever wood lacquer I found in my in-laws shed, just for resistance because I don’t like glossy wood. Side photo of the bench for a better view of the legs Other small wood things Water glass shelf We don’t have much space on the current eating table, so I built a two-shelf stand where we can place the always present water filter jug and the glasses and free up some of the center space. It’s incredible how strong just a few screws can be. Table shelf for holding water filter and glasses Kaval stand I thought I should finally do something about the kavals always rolling around on some table or couch throughout the house, so I made a stand from long thin wood boards glued on the side, and finished it with sunflower oil to give it a golden/orange colour. This way I can always expand it by adding more boards to the side if I want to add more flutes. Stand for holding my kaval collection Sharpening block I need to sharpen blades almost daily, be it the pocket knife, axe, plane blade or chisels. So I made a custom sharpening block with the perfect tools for my sharpening technique. Sharpening block, diamond plate with leather strop on a beech base It has a $5 diamond plate with 600 grit on one side and a $5 leather strop (a piece of leather belt might work just as well) on the other side. I attached the leather with two small screws at the top so I can take it out easily if I need a flexible strop for my carving gouge for example. It is loaded with 0.25 micron diamond paste which can be found for cheap at gemstone cutting online stores (the knife-specific pastes are a lot more expensive and I’m not sure why). To be honest, a $0.5 green compound (chromium oxide) works just as well for stropping, that’s what I used before and still use for my detail carving knives. It gives a smoother edge than the diamond, the disadvantage being that it needs to be re-applied more often on the leather and that you need a bit more blade passes to get the same result. The diamonds seem be cutting faster, but really not much faster. A bit of a tangent on the sharpening topic I went through all the phases with sharpening tools. I’ve used water stones, natural stones, ceramic stones, pull-through carbide sharpeners (don’t use these), powered belt sharpeners, wheel sharpeners. Aside from the pull-through sharpeners and the steel rods, all the others work just as well with the right technique. I settled on the diamond plate because they’re cheap, portable, stay flat, need zero maintenance, and can cut through any type of metal. Paired with a leather strop, for me it’s the simplest way to sharpen. I recommend this OUTDOORS55 video for a no-bullshit sharpening tutorial and the Science of Sharp blog if you’re curious what the different sharpening techniques do to an edge under a microscope.

9 months ago 27 votes
Woodworking as an escape from the absurdity of software

Some of you might remember the legendary comment of Eric Diven on a Docker CLI issue he opened years ago: @solvaholic: Sorry I missed your comment of many months ago. I no longer build software; I now make furniture out of wood. The hours are long, the pay sucks, and there’s always the opportunity to remove my finger with a table saw, but nobody asks me if I can add an RSS feed to a DBMS, so there’s that :-) I say legendary because it has over 9000 reactions and most are positive. There’s a reason why so many devs resonate with that comment. A lot of us said at some time things like “I’m gonna throw my laptop out the window and start a farm”. Even my last team leader sent me a message out of the blue saying “I think I’ll run a bar. I want to be a bartender and listen to other people’s stories, not figure out why protobuf doesn’t deserialize data that worked JUST FINE for the past three years”. You know the drill, sometimes the world of software development feels so absurd that you just want to buy a hundred alpaca and sell some wool socks and forget about solving conflicts in package.json for the rest of your life. I went through those stages too: when the Agile meetings got so absurd that we were being asked to estimate JIRA task time in T-shirt sizes, I quit my well paying job so I can spend that time creating macOS apps. Recently, when people started coming with so many unrealistic and absurd expectations and demands about my apps, I think I’ll soon quit software development altogether. It’s just not making sense anymore for me. A bit of history Most of my pre-college time was spent on things I didn’t want to do. I had a bit of childhood, but then I started going to school 6 hours per day, with 1-2 hours spent on commute after 5th grade. I only liked the 10-minute breaks between classes where I played basketball or practiced parkour. Every day after I came back from school, I had to work in agriculture, either out in the field with crazy winds and sun and UV radiation, or inside the greenhouse where it’s either a 50°C sauna or a muddy rainforest. I was very bad at every job I was given, but it’s what my parents did for a living and I had to help them, no questions asked. The few hours that remained, usually very late at night, tired both physically and mentally, I spent practicing acoustic guitar, doing bodybuilding exercises, writing poetry or drawing portraits. me, ages ago, playing a classical guitar on someone's old couch I almost never did homework or memorize whatever had to be memorized for the next day of school. I just couldn’t justify spending those few hours I had left on even more stuff I did not want to do. When I found my liberty in college, hundreds of kilometers away from my parents, it’s like something clicked. I suddenly became incapable of doing work that I found meaningless. Failing classes became acceptable, quitting jobs was something I did with little remorse if I felt I wasn’t helping anyone with the work I was assigned, and bureaucracy became a disease I had to avoid at all costs. I still washed the dishes though. Cleaning and other “chores” never felt meaningless for some reason. The first wood thing I did … was a chess board and piece set. With magnets inside them. Where the pieces look nothing like ordinary chess pieces. chess board, first iteration I was trying to get the pieces to snap into place in a satisfying way, and make sure the game stays that way when kids or dogs inevitably bump the table where the board sits. You know how Magnus Carlsen always adjusts his pieces so meticulously before a game? Well I have half of that obsession as well so I wanted to avoid doing that. Magnus Carlsen adjusting his pieces before a game pawn snapping into its square because of the magnet inside How it was done I started with a cheap but hefty pine board which I rounded with a lot of sandpaper. Then I asked my wife to help me colour in the darker squares because I’m pretty bad at colouring inside the edges (both literally and figuratively). We used some wood floor markers for that and the colour seems to be holding well. Most chess board builds you see on YouTube are done by gluing squares of different wood species with alternating colors, but I had neither the skill nor the tools to do that. Then I drilled holes for the super strong neodymium magnets from the underside of the board, having to get really close to the top side without passing through. I failed on two squares, but some wood putty took care of that. sculpting chess pieces with my dremel on the balcony I spent a few sunny days on the balcony sculpting the pieces with a badly sharpened knife and my Dremel. This was quite satisfying, there’s something really nice about seeing a non-descript rectangle take the shape of a little horse in your hands. I mean knight, but in Romanian that piece is called “horse”, and I really don’t see any knight there. chess board, start to finish Regarding the design, I got some inspiration after seeing these modernist chess sets, which not only looked beautiful in my eyes, but also had these geometric shapes that didn’t need that much sculpting to replicate. I found ready-to-buy spheres and cubes of wood at a craft shop around me (which took care of pawns and rooks), and the rest were carved out of rectangles and cones of wood. Modernist chess set designs Kaval Two Octobers ago, a Romanian music band called Subcarpați was holding a free “make a Kaval with your own hands” course, where a flute artisan taught the basics of his trade for a week. The Kaval or “caval” is a long flute with 5 holes and a distinct lower register where notes can sound melancholic and coming from far away, as opposed to the thin cheerful sound of the small shepherd flute. Kaval sample in G minor Ever since I bought my first Kaval, I always wanted to learn how to build one myself. It’s one of those trades where there’s very little info on the internet, so it feels almost mystical compared to what I’m used to in programming. I would also have the chance to walk home with the finished flute, so of course I went to the course. Making my own Kaval, in B minor I loved the fact that we worked in teams of two, and that everything had to be done by hand with no power tools. Even the long bore through the 70cm branch of elder tree had to be done with a hand drill, taking turns to rest our hands. The artisan had been a shepherd himself since childhood, and taught himself with a lot of trial and error about how to build good sounding flutes and how to make the holes so that the flute stays in tune. But he didn’t know why the holes should be at those specific distances or why the wood tube should be of that specific length for each scale. I wanted to know those things, because I had an idea of making a universal Kaval that can play in any scale. You see, if you want to play on top of songs in various scales, you need a Kaval made for each specific scale. So you’ll need an A minor flute, and a B minor one and a C minor one and so on, for a total of 12 different flute lengths. I eventually found info on how a flute works by thinking about it as an open or closed tube where the vibrating air creates nodes and antinodes that should coincide with the hole position. At the moment I’m still studying this and working towards my “universal flute” goal. The physical world has no undo button A few days ago I was walking with my dog around the university and I saw an elderberry tree with a really straight and already dead branch. I thought that might be great for trying to do another kaval, so I went back home to grab my folding saw to cut this branch. I brought it home, cut it to about 78cm for an A minor kaval, straightened it in the vise and started boring a hole through it. I used a 12mm drill first because elder branches have this spongious core that was exactly 12mm in my case. I was able to drill end to end in less than 10 minutes, first time I managed to do this successfully. Drilling a hole through an elder tree branch For such a large flute, you usually need a larger 16mm or 18mm hole to get enough volume, so I went ahead and used the 16mm drill to enlarge the hole. After about 10cm, things started squeaking loudly and smoking so I got the branch out of the vise to inspect it. Because the branch was not completely straight, the drill came out of the side and it was hitting the harder wood of the vise. Damn.. another wasted branch, there’s not a lot of straight material around me in the city. Man, how I wish I could hit undo and just experiment with the good 12mm hole. This reality hit me many times while working with wood in the past 6 months. I didn’t even realise that my mind got so used to having git and backups and Cmd-Z that those expectations transferred to the physical world as well. Move fast and break things is no longer a good mantra for me. I gave the broken branch to my dog, she loves chewing large sticks and got a real kick out of it. Her face definitely said BEST STICK EVER!! for about 5 minutes of pure bliss, so apparently nothing was wasted in the end. What does this have to do with software? For the past 10 years I lived in rented apartments, usually at the 3rd or 4th story with no access to a courtyard. I was never able to get used to that, given that all my childhood I lived and played in a 2000m² courtyard, on a road where there were more slow horse carriages than noisy cars. This year I moved into a rented house with a tiny but welcoming garden and a bit of paved court and only now I notice the effect this has had on my mind and behaviour. I develop macOS apps for a living, and there are some unhealthy things in this field that piled up over the years. I get a lot of messages in a demanding and negative tone, and because walking outside the apartment meant unbearable car noise, obnoxious smells and zero privacy, I always defaulted to simply acting on the feedback, putting up with it and working long hours into the night, instead of going for a walk to calm down. A few months ago, the most absurd demands started coming up for my apps: things like “why does your app not control the volume of my <weird sound device>? why don’t you just do it, people pay you for it” when the app in question is Lunar, an app for controlling monitor brightness, not sound devices. Or “why do you disable your apps from working on Windows?”, or “make Clop compress text and copy it to clipboard” (where Clop is my app that automatically compresses copied images, videos and PDFs, I have no idea what compressing text even means in that context). But this time, I was able to simply walk out the front door, grab a branch of beech wood, and, because I remembered my wife saying we forgot to package the french rolling pin when moving, I took out my pocket knife and started carving a simple rolling pin for her. It was so liberating to be able to just ignore those messages for a while and do something with my hands. the rolling pin is such a simple tool and to this day, my wife still tells me how much she likes it because it's exactly the right length and thickness for making her tasty egg noodles.. and best of all, it was free I understand that those people don’t know better, and they would have no idea that there’s no checkbox where you can choose whether an app works on macOS, Windows or Linux. I understand how if the app does something with audio volume or compression, some think that it should do everything related to those workloads, even if it’s completely outside the scope of the app. But the combination of the negative tone and getting message after message, some people being so persistent that they insist on sending me those messages through all possible mediums (email, Discord, Twitter, contact form, they’ll find me everywhere), makes it hard to just ignore them. There’s also this oily smell of AI and machine learning in the tech atmosphere, where I no longer feel relevant and I seem to have stopped caring about new tech when I noticed that 8 in 10 articles are about some new LLM or image generation model. I guess I like the smell of wood better. Side tangent on privileges of being a software dev I know I’m privileged to even be able to have the choice of what to do with my time. I got lucky when I chose a computer science university at the right time which allowed me to progress towards a huge semi-passive income in the last 10 years. that doesn’t mean I didn’t work my ass off, but luck plays a huge role too I got “lucky” to have my mind traumatised into some kind of OCD-like state where I hate leaving a thing unfinished. So I plow through exhaustion, skip meals, miss house chores and annoy dear people around me because I know “I just need to fix this little thing” and I’ll finish this app/feature/task I started. Even though I also know there’s no real deadline and I can leave it half-finished and the world won’t end. But even if it sounds annoying for a person like me to whine about how I don’t feel good or I feel burnt out, the privilege doesn’t negate the feelings. The regression to the norm will make everyone, rich or poor, get used to the status quo and complain about every thing that’s just a little worse than their current state. That’s happiness and sadness in a nutshell. I’m also vaguely aware that software dev as we know it is about to disappear soon, and I got tired of learning the newest thing just to have it replaced next year. I got tired of back pain and chronic finger pain from so many hours of sitting and typing, I’d rather have pain from work that also builds some muscle. And I got so tired of everything being online, immaterial, ephemeral and lonely, like indie development tends to be. Woodworking with cheap tools and free wood This house we rented is small and the owners had to fit the bedroom upstairs. I really don’t like climbing stairs up and down, especially when I have to let my dog out three times per night. So we gave up a room and started furnishing our own bedroom downstairs. I didn’t want to buy bedside tables for the price of the bed itself, so I thought I could maybe make by own. I’m not yet skilled enough to build my own bed though, so we had to buy that. Another day on a walk with my dog, I noticed that some trees were getting trimmed in the vicinity of our house and there were a lot of white birch branches on the side of the road. I said why not? ¯\_(ツ)_/¯, grabbed some branches and walked like a lunatic with white long sticks dangling up and down and a black frenetic dog zig-zagging left and right, all the way home. I had another small pine panel left from that chess project so I started thinking about the simplest way to turn what I have into a bedside table. pine board with birch branches I used low-grit sandpaper to give the board some nice round corners because I love squircles, swallowed about a spoonful of sawdust because I couldn’t find any breathing mask left, criss-crossed 4 branches in a way that would give a stable base, and screwed them to the underside of the board with long wood screws. The legs would wobble around though, so I drilled small 3mm holes into each branch where they met in the middle, and weaved a florist wire through them to keep the table steady. Bedside table, made out of pine with birch legs The laptop bed table After I’ve shown the bedside table to a friend of mine, he said he also needed a laptop table for those mornings when he’d rather not get out of bed. I wanted to say that’s not very healthy, but what got out instead was sure thing, I’ll do it!. Oh well.. I still had the large desk top I glued from smaller beech boards, on which I worked for the past 4 years. It stayed unused currently, so I cut part of it and built this cute thing: cute but heavy laptop table, made out of glued beech wood You’ll notice three defining features that every laptop table should have: a hole for a charging cable a carved coaster for the coffee cup a mildly surprised face? 😦 To tell the truth, all those are side effects of me drilling holes where there should be no hole, and dropping the board on the ground multiple times because my workbench was not large enough. All the things that could go wrong, went wrong with this table. I hid the defects by turning them into features. The whole truth actually is that the table looks nothing like what I planned. I bought these nice hidden brass cylindrical hinges to make the table foldable. That way, you could fold the sides flat inside and use it as some kind of armchair desk if you wanted. Brass hinges I wasn’t able to drill the correctly sized or positioned holes for the hinges because I still lack a lot of knowledge and skill in working with wood. So after losing my temper with the frickin’ hinges that still didn’t fit after a full day of drilling and chiseling, I glued the sides and inserted 2 trusty long wood screws per side, which I patched with a glue gun that made the screw holes look like eyes. After I also carved the handles, the table grew kind of a personality of its own, as you can see above. Why didn’t I do some wood joint, like a dovetail instead of ugly screws and glue? Because I had no idea they existed. Also, I wasn’t even able to fit a simple hinge, I would’ve probably never finished this table if I tried learning wood joinery on it. This reminds me of how whenever I did pair programming with a colleague, I noticed how they were doing some “nonoptimal” action and I would say: Why don’t you just use ripgrep instead of sifting through all these files? Because they don’t know it exists, stupid. Or because they just want to get this thing done and move on, they don’t grep files all day like you do. Learn from my mistakes, don’t think you know better or assume the other person needs your way of doing things. Maybe let them know after the fact, in a short message linking to the tool, and let them try it in their own time. But in my ignorance, I seem to have chosen a good enough joining method. As you can see in this wood joinery comparison, 5cm (2inch) screws can hold more than 50kg (110lbs) of force, and I used even longer screws so I think it’s going to hold a 3kg laptop just fine. Oh right, forgot about this little detail.. I also added a cork pocket for holding a notebook, tablet, phone etc. which I lined with a microfiber cloth on the inside for strength and sewn to the wood with that leftover alpaca wool for style. Cork pocket sewn to the table side The bookshelf without books Large bookshelf (200x120x40 cm), made out of pine boards While we were stuck in the apartment in the 2020 pandemic, me and my wife bought a lot of stuff that we thought would help us learn new things and start new hobbies. I thought I’m going to build smart LED lighting all my life and my wife would become a professional wool knitter. We were losing our minds, for sure. So now we were stuck with crates of stuff we haven’t used in years, and didn’t want to start unpacking them around the house. The clutter that followed after the pandemic, tired our minds just as much as the lockdown itself. We dumped the crates on an unused stairway spot, and I thought that a bookshelf as large as that spot would clear the clutter. Before: clutter | After: organized clutter But I could not find any bookshelf that large, certainly not for cheap. So I traced a few lines in Freeform, took some measurements, and ordered a bunch of large pine boards and a ton of long screws. I also ordered the cheapest portable workbench I could find ($30) that had a vise, so I can stop making sawdust inside. A few days later, I got to sawing the shelves to size with my cheap Japanese pull saw I bought from Lidl years ago. Hint: Hand sawing a long wood board with no skill will certainly end up with a crooked edge. Stacking up 5 boards one on top of the other will still end up crooked. Uhm, I guess the hint is, buy a track saw, or make sure the crooked edge isn’t visible. Hand sawing a straight long edge is not easy. making the bookshelf My wife helped a lot with measuring and figuring out where to drill holes and place the screws, while my dog inspected the work regularly to make sure the defects were hidden correctly. It took two days of screwing.. erm.. driving screws, I mean. But in the end we got the result we wanted! And I got sores in my right arm for days, driving those long screws is harder than I thought. The desk that became a workbench In the thumbnail of this post you can see the current “workbench” I use, which is basically that $30 vise workbench I bought for the bookshelf, with the top of my previous “coding desk” attached in the front. my current workbench In the image you can see (bottom-left to top, then right): the cheapest block plane I could find ($8) a red no-name plane I found in the shed of that 100-year old house that we never finished rebuilding because of legal reasons an axe I found rusted and partly broken in the same shed, on which I learnt how to sharpen and restore axes a folding japanese pull saw that I take everywhere with me some grip blocks on which I place boards for sanding a bottle of Osmo Polyx oil I use for finishing (this is the Rubio Monocoat for poor people) a set of carving knives from Beavercraft (really good and they were available at a nice discount) a combination square (tucked somewhere at the top of the bench) a branch of elder tree, which is prepared for drilling a hole through it for making a kaval I also own some no-name chisels that work well enough for now and some card scrapers that I still struggle sharpening. The only power tools I have are a Makita drill and a random orbit sander on which I did spend some money, an old circular saw I found in that same old shed (it was good enough to cut miters on that laptop table) and a Dremel I use rarely because I don’t like its power cord. I prefer battery powered tools. The window bench Our dog Cora loves sitting at the window, growling at old people and barking at children passing around. Yeah, she’s terrified of children for some reason. But the window sill is not wide enough and her leg kept falling with a “clang” on the radiator below. So I widened it by placing two glued up boards of pine on top of the radiator, that I planed and smoothed beforehand. Cora sitting at the window Cora at the window, with the widened sill This is when I learned that a hand plane is not some antique tool that nobody uses anymore, but a quite versatile piece that can easily smoothen grain where I would waste 5 sheets of sandpaper and choke on sawdust. I had to still let the heat radiate somehow, so I drilled large holes with a forstner bit, but I also blew the grain fibers on the underside because I had no idea of this possible problem. Turns out there is a simple solution to drilling large holes without ripping the fibers: Drill a small 3-6mm hole in the center with a normal wood drill, all the way to the other side (this will help you see where the forstner bit should be placed from both sides of the board) Place the forstner bit in the hole (this also helps with keeping the bit centered) and drill the large hole, stopping midway through the board Turn the board around and repeat step 2 until you meet the other end of the hole We also wanted to sit with Cora and there was not much space between the bed and the radiator for a regular chair, so I built a narrow bench. I used another two pine boards of the same size, but this time glued them on the side to create a wider board. For the legs, well the tree trimming continued throughout the spring, so one day I found some thick cherry branches which I brought home, scraped the bark from them, then attached them to the bench using screws from the top side. I was ok with a rustic look so I didn’t spend much on finishing, patching holes, or even proper wood drying. I did use the hand plane to chamfer the edges though, I love taking those thin continuous wood shavings from the edge. Window bench, in the morning sun The trunk coffee table Coffee table made out of a beech log We recently visited my parents, and loved how the grass finally started growing in some spots where their house and court renovation was finished and was no longer spewing cement dust. It was an abnormally sunny April and I wanted to chat with them at a coffee outside in the early morning before they started the field work, but there was nowhere to place the coffee outside. First world problems right? If you’ve read about The tail end, you might already understand why a trivial thing like coffee time with my parents feels so important to me. So one day, while walking on a gravel road near their house, I noticed one neighbour had these huge logs of beech that were recently cut. I thought that would be easy to turn into a small exterior coffee table, so I went to ask if I could buy one. Well I kind of had to yell “HELLO!” at their gate because I didn’t know their name, and did that a few times until a seemingly sleepy old man in pyjamas (it was 5 in the afternoon) appeared at the front door asking what I want. I asked how much he’d want for one of those logs, but he just said to get one, no money needed. Ok, there’s no point in insisting, I chose a wide enough but not too wide log, because these things are heavy and I wasn’t sure I could lift it, and rolled it slowly back home. I didn’t have my usual tools at my parents house, so I improvised. I found a battered cleaver which my dad used for chopping kindling for the barbecue. I sharpened it as well as I could, then used a hammer to roll a burr on the back of the cleaver that I could use for scraping. Scraping the bark off the beech log Beech wood has such a smooth hard wood under the bark that it didn’t even need sanding. I used my dad’s power planer to smooth out the top and make a quasi-flat surface then finished it with some walnut oil and it was (almost) ready! Because the wood was so green, it was certain that it will crack and roughen as it dried. So I cut a groove and wrapped a flat iron band around the top to keep it from moving too much. The bottom can expand as much as it wants, I’m actually quite curious to watch the table morph throughout the summer as we use it. The orchard bench Bench made from reclaimed wood, for my parents-in-law orchard Because we were born in villages that aren’t that far apart, me and my wife always visit both our parents in the same trip. This time when I got to my parents-in-law, I took a stroll through their little orchard. They added new trees this year! I can’t wait to taste the large apricots. What struck me as odd about the orchard was that there was no patch of grass to lay on. They like digging up the soil every year, and leaving it like that: an arid looking patch of land made of dry dirt boulders. I thought a bench would be a good solution and what do you know, there was an old broken door thrown in the firewood pile just outside the orchard, that had the perfect length and width for a bench. I forgot to take a photo of the door, but it looked kind of like this one, only worse and with a large rhomboid ◊ hole at the top. old broken wooden door I got to work immediately, dismantling the door piece by piece and pulling out nail after nail (they really liked their nails in those old times). I was left with two long and narrow wooden boards, a pile of rotten wood and two pocketfuls of rusted nails. I sawed the broken ends of the boards, then I used my father-in-law’s power planer (do all Romanian dads have a power planer or what?) to remove the old gray wood from the top, bottom and sides to get to the fresh wood below. There were a lot of holes and valleys so I had to scrape them by hand with sandpaper rolled around a screwdriver. This took a few more days than I expected, but I eventually got two cleanish boards of.. fir? pine? No idea. I used a velcro sandpaper attachment for the battery powered drill to sand out the rotten sides and give the boards a curvy and smooth live edge. Curvy edge on the bench, made by sanding out the rotten wood For the legs, I stole some more firewood from my in-laws pile, where I found some thick branches of unidentified species that were roughly the same length. Stripping the bark with an axe made them look good enough so I screwed them in at the four corners of the board. The bench was wobbly with just the legs, so I strengthened it sideways by adding shorter and thinner branches of more unidentified wood between the legs and the center of the board. I had to do something with the rhomboid ◊ hole, so I filled it with a square 4-by-4 salvaged from a recently dismantled shed, and now the bench has 5 legs. Instead of sawing the leg to size, I left it protruding above the bench and placed another thick salvaged board on top of it to serve as an arm rest, or coffee table, or a place for the bowl of cherries. For the finish, I burned the bench and the bottom of the legs to get a honey-brown aspect and to make it water resistant. I put a very thin layer of whatever wood lacquer I found in my in-laws shed, just for resistance because I don’t like glossy wood. Side photo of the bench for a better view of the legs Other small wood things Water glass shelf We don’t have much space on the current eating table, so I built a two-shelf stand where we can place the always present water filter jug and the glasses and free up some of the center space. It’s incredible how strong just a few screws can be. Table shelf for holding water filter and glasses Kaval stand I thought I should finally do something about the kavals always rolling around on some table or couch throughout the house, so I made a stand from long thin wood boards glued on the side, and finished it with sunflower oil to give it a golden/orange colour. This way I can always expand it by adding more boards to the side if I want to add more flutes. Stand for holding my kaval collection Sharpening block I need to sharpen blades almost daily, be it the pocket knife, axe, plane blade or chisels. So I made a custom sharpening block with the perfect tools for my sharpening technique. Sharpening block, diamond plate with leather strop on a beech base It has a $5 diamond plate with 600 grit on one side and a $5 leather strop (a piece of leather belt might work just as well) on the other side. I attached the leather with two small screws at the top so I can take it out easily if I need a flexible strop for my carving gouge for example. It is loaded with 0.25 micron diamond paste which can be found for cheap at gemstone cutting online stores (the knife-specific pastes are a lot more expensive and I’m not sure why). To be honest, a $0.5 green compound (chromium oxide) works just as well for stropping, that’s what I used before and still use for my detail carving knives. It gives a smoother edge than the diamond, the disadvantage being that it needs to be re-applied more often on the leather and that you need a bit more blade passes to get the same result. The diamonds seem be cutting faster, but really not much faster. A bit of a tangent on the sharpening topic I went through all the phases with sharpening tools. I’ve used water stones, natural stones, ceramic stones, pull-through carbide sharpeners (don’t use these), powered belt sharpeners, wheel sharpeners. Aside from the pull-through sharpeners and the steel rods, all the others work just as well with the right technique. I settled on the diamond plate because they’re cheap, portable, stay flat, need zero maintenance, and can cut through any type of metal. Paired with a leather strop, for me it’s the simplest way to sharpen. I recommend this OUTDOORS55 video for a no-bullshit sharpening tutorial and the Science of Sharp blog if you’re curious what the different sharpening techniques do to an edge under a microscope.

9 months ago 25 votes
The complex simplicity of my static websites

It was the spring of 2014, over 9 years ago, just 6 months into my first year of college, when my Computer Architecture teacher stopped in the middle of an assembly exercise to tell us that Bitdefender is hiring juniors for Malware Researcher positions. I had no idea what that is, but boy, did it sound cool?… I fondly remember how at that time we weren’t chasing high salaries and filtering jobs by programming languages and frameworks. We just wanted to learn something. As students, we needed money as well of course, but when I got the job for 1750 lei (~€350), I suddenly became the richest 18 year old in my home town, so it wasn’t the top priority. And we learnt so much in 2 years.. obscure things like AOP, a lot of x86 assembly, reverse engineering techniques which dumped us head first into languages like Java, .NET, ActionScript? (malware authors were creative). But most of all, we did tons of Python scripting, and we loved every minute of it. It was my first time getting acquainted with fast tools like Sublime Text and FAR Manager. Coming from Notepad++ and Windows Explorer, I felt like a mad hacker with the world at my fingertips. I’m known as a macOS app dev nowadays, but 9 years ago, I actually started by writing petty Python scripts which spurred the obsessive love I have nowadays for clean accolade-free code and indentation based languages. What does all that have to do with static websites though? Pythonic HTML Well, 5 years ago, when I launched my first macOS app, I found myself needing to create a simple webpage to showcase the app and at the very least, provide a way to download it. And HTML I did not want to write. The XML like syntax is something I always dreaded, so overfilled with unnecessary </> symbols that make both writing and reading much more cumbersome. I wanted Python syntax for HTML so I went looking for it. I went through pug… 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 doctype html html head title Lunar - The defacto app for controlling monitor brightness meta(itemprop='description' content='...') style. a.button { background: bisque; padding: 0.5rem 1rem; color: black; border-radius: 0.5rem; } body { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; } body h1(style='color: white; font: bold 3rem monospace') Lunar img(src='https://files.lunar.fyi/display-page.png' style='width: 80%') a.button(href='https://files.lunar.fyi/releases/Lunar.dmg') Download pretty, but still needs () for attributes, and I still need accolades in CSS and JS then haml… 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 !!! %html{lang: "en"} %head %meta{content: "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/ %title Lunar - The defacto app for controlling monitor brightness %meta{content: "...", itemprop: "description"}/ :css a.button { background: bisque; padding: 0.5rem 1rem; color: black; border-radius: 0.5rem; } body { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; } %body{style: "background: #2e2431; min-height: 90vh"} %h1{style: "color: white; font: bold 3rem monospace"} Lunar %img{src: "https://files.lunar.fyi/display-page.png", style: "width: 80%"}/ %a.button{href: "https://files.lunar.fyi/releases/Lunar.dmg"} Download even more symbols: %, :, => and / for self-closing tags …and eventually stumbled upon Slim and its Python counterpart: Plim 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 doctype html html lang="en" head title Lunar - The defacto app for controlling monitor brightness meta itemprop="description" content="..." -stylus a.button background bisque padding 0.5rem 1rem color black border-radius 0.5rem body display flex flex-direction column align-items center justify-content center text-align center body style="background: #2e2431; min-height: 90vh" h1 style="color: white; font: bold 3rem monospace" Lunar img src="https://files.lunar.fyi/display-page.png" style="width: 80%" a.button href="https://files.lunar.fyi/releases/Lunar.dmg" Download ahhh.. so clean! Here’s how that example looks like if I would have to write it as HTML: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <!DOCTYPE html> <html> <head> <title>Lunar - The defacto app for controlling monitor brightness</title> <meta itemprop="description" content="..."> <style> a.button { background: bisque; padding: 0.5rem 1rem; color: black; border-radius: 0.5rem; } body { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; } </style> </head> <body> <h1 style="color: white; font: bold 3rem monospace">Lunar</h1> <img src="https://files.lunar.fyi/display-page.png" style="width: 80%"> <a class="button" href="https://files.lunar.fyi/releases/Lunar.dmg">Download</a> </body> </html> not particulary hard to read, but writing would need a lot of Shift-holding and repeating tags The thing I like most about Plim, and why I stuck with it, is that it can parse my other favorite symbol-hating languages without additional configuration: Python for abstracting away repeating structures Stylus for writing style tags CoffeeScript for the script tags Markdown for long text content Here’s a more complex example to showcase the above features (might require sunglasses): example of writing a HDR page section, similar to the one on lunar.fyi 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 ---! # use Python to generate the dynamic image sizes for the srcset attr WIDTHS = [1920, 1280, 1024, 768, 640, 320] def srcset(image, ext, page_fraction=1.0): return ','.join( f'/img/{image}/{width}.{ext} {width // page_fraction:.0f}w' for width in WIDTHS ) doctype html html lang="en" head -stylus # use Stylus to do a readable media query that checks for wide color gamut @media screen and (color-gamut: p3) @supports (-webkit-backdrop-filter: brightness(1.5)) section#xdr -webkit-backdrop-filter: brightness(1) filter: brightness(1.5) body section#xdr picture source type="image/webp" srcset=${srcset('xdr', 'webp', 0.3)} source type="image/png" srcset=${srcset('xdr', 'png', 0.3)} -md # write markdown that renders as inline HTML Unlock the full brightness of your XDR display The **2021 MacBook Pro** and the **Pro Display XDR** feature an incredibly bright panel *(1600 nits!)*, but which is locked by macOS to a third of its potential *(500 nits...)*. Lunar can **remove the brightness lock** and allow you to increase the brightness past that limit. -coffee # use CoffeeScript to detect if the browser might not support HDR $ = document.querySelector safari = /^((?!chrome|android).)*safari/i.test navigator.userAgent window.onload = () -> if not safari $('#xdr')?.style.filter = "none" a[href="https://youtu.be/cVAcRH9b44w?t=55"] { display: none; } @media screen and (color-gamut: p3) { video#xdr { display: block !important; } a[href="https://youtu.be/cVAcRH9b44w?t=55"] { display: inline !important; } } And best of all, there is no crazy toolchain, bundler or dependency hell involved. No project structure needed, no configuration files. I can just write a contact.plim file, compile it with plimc to a readable contact.html and have a /contact page ready! So that’s how it went with my app: I wrote a simple index.plim, dropped it on Netlify and went on with my day. Complexity Cost 1 pip install for getting the Plim CLI 1 npm install for getting stylus and coffeescript (optional) 1 build command for generating the HTML files Complex simplicity The app managed to get quite a bit of attention, and while I kept developing it, for the next 4 years the website remained the same heading - image - download button single page. It was only a side project after all. Working for US companies from Romania made good money, but it was so tiring to get through 3h of video meetings daily, standups, syntax nitpicking in PR review, SCRUM bullshit, JIRA, task writing, task assigning, estimating task time in T-shirt sizes?? In April 2021 I finally got tired of writing useless code and selling my time like it was some grain silo I could always fill back up with even more work… I bet on developing my app further. Since my college days, I always chose the work that helps me learn new concepts. At some point I had to understand that I learnt enough and had to start sharing. This time I really wanted to write software that helped people, and was willing to spend my savings on it. Comically Stuffed Stylesheets A more complete app also required a more complete presentation website, but the styling was getting out of hand. You would think that with flexbox and grids, you can just write vanilla CSS these days, but just adding a bit of variation requires constant jumping between the CSS and HTML files. A presentation page is usually only 10% HTML markup. The rest is a ton of styling and copy text, so I wanted to optimize my dev experience for that. There’s no “go to definition” on HTML .classes or #ids because their styles can be defined ✨anywhere✨. So you have to Cmd-F like a madman and be very rigorous on your CSS structure. The controversial but very clever solution to this was Tailwind CSS: a large collection of short predefined classes that mostly style just the property they hint at. For example in the first code block I had to write a non-reusable 5-line style to center the body contents. 1 2 3 4 5 6 7 body { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; } With Tailwind, I would have written the body tag like so: 1 body.flex.flex-col.justify-center.items-center.text-center That might not seem like much, some would argue that it’s even a lot less readable than the CSS one. Can’t I just define a .center class that I can reuse? Well, think about a few things: this might repeat on many sections of the page, but with slight variations (what if I want a centered row, or longer paragraphs of text aligned to the left) responsive sections might need to alter layout (e.g. vertical on mobile, horizontal on desktop) and media queries will quickly blow up the style size .md:flex-row.flex-col is what you would write in Tailwind adding dark/light mode support is yet another media query .dark:bg-white.bg-black looks simple enough interactions like hover effects, complex shadows and filters like blur and brightness is syntax that’s often forgotten .shadow.hover:shadow-xl creates a lift off the page effect on hover by making the shadow larger .blur.active:blur-none un-blurs an element when you click on it choosing colors and reusing them needs a lot of attention .bg-red-500.text-white sets white text on saturated red red-100 is less saturated, towards white red-900 is darker, towards black li:nth-child(4) > ul > li > code { transition: box-shadow 0.55s ease-in-out, filter 0.55s ease-in-out; } #tailwind-usefulness + ul > li:nth-child(4) > ul > li > code:hover { transition: box-shadow 0.25s ease-in-out, filter 0.15s ease-out; } #tailwind-usefulness + ul > li:nth-child(3) > ul > li:nth-of-type(1) > code { background: black !important; color: rgb(255, 200, 149) !important; } @media (prefers-color-scheme: dark) { #tailwind-usefulness + ul > li:nth-child(3) > ul > li:nth-of-type(1) > code { background: white !important; color: hsl(19, 72%, 32%) !important; } } #tailwind-usefulness + ul > li:nth-child(4) > ul > li:nth-of-type(1) > code { box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); } #tailwind-usefulness + ul > li:nth-child(4) > ul > li:nth-of-type(1) > code:hover { box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); } @media (prefers-color-scheme: dark) { #tailwind-usefulness + ul > li:nth-child(4) > ul > li:nth-of-type(1) > code:hover { box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.5), 0 8px 10px -6px rgb(0 0 0 / 0.7); } } #tailwind-usefulness + ul > li:nth-child(4) > ul > li:nth-of-type(2) > code { filter: blur(4px); } #tailwind-usefulness + ul > li:nth-child(4) > ul > li:nth-of-type(2) > code:active { filter: blur(0) !important; } #tailwind-usefulness + ul > li:nth-child(5) > ul > li:nth-of-type(1) > code { background: #ef4444 !important; color: white !important; } #tailwind-usefulness + ul > li:nth-child(5) > ul > li:nth-of-type(2) > code { background: #fee2e2 !important; color: black !important; } #tailwind-usefulness + ul > li:nth-child(5) > ul > li:nth-of-type(3) > code { background: #7f1d1d !important; color: white !important; } Sure, long lines of classes might not be so readable, but neither are long files of CSS styling. At least the Tailwind classes are right there at your fingertips, and you can replace a -lg with a -xl to quickly fine tune your style. Complexity Cost: 1 command added for building the minimal CSS from the classes used 1 npm install for getting the Tailwind CLI 1 config file for defining custom colors, animations etc. (optional) Responsive images So many people obsess over the size of their JS or CSS, but fail to realize that the bulk of their page is unnecessarily large and not well compressed images. Of course, I was one of those people. For years, my app’s website had a screenshot of its window as an uncompressed PNG, loading slowly from top to bottom and chugging the user’s bandwidth. I had no idea, but screenshots and screen recordings are most of the time up to 10x larger than their visually indistinguishable compressed counterparts. I even wrote an app to fix that since I’m constantly sending screenshots to people and was tired of waiting for 5MB images to upload in rapid chats. It’s called Clop if you want to check it out. Yes, just like that famous ransomware, it wasn’t that famous at the time of naming the app. I needed a lot more images to showcase the features of an app controlling monitor brightness and colors, so I had to improve on this. Delivering the smallest image necessary to the user is quite a complex endeavour: Optimize the image using ImageOptim Resize it to fit multiple screen sizes using vipsthumbnail Figure out what fraction of the page width will be occupied by the image Write a suitable srcset attribute to load the suitable image Optional: convert the image to formats like webp, avif or JPEG XL for smallest file size I did so much of that work manually in the past… thankfully nowadays I have imgproxy to do the encoding, optimization and resizing for me. I just have to write the srcset, for which I defined Plim and Python functions to do the string wrangling for me. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 -def image(img, ext='png', factor=0.4, mobile_factor=1) picture -call img=${img} ext=${ext} factor=${factor} mobile_factor=${mobile_factor} self:sources img srcset=${srcset(img, ext, factor)} -def sources(img, ext='png', factor=0.4, mobile_factor=1) source type="image/avif" srcset=${srcset(img, ext, mobile_factor, convert_to="avif")} media="(max-width: 767px)" source type="image/avif" srcset=${srcset(img, ext, factor, convert_to="avif")} media="(min-width: 768px)" source type="image/webp" srcset=${srcset(img, ext, mobile_factor, convert_to="webp")} media="(max-width: 767px)" source type="image/webp" srcset=${srcset(img, ext, factor, convert_to="webp")} media="(min-width: 768px)" source type="image/${ext}" srcset=${srcset(img, ext, mobile_factor)} media="(max-width: 767px)" source type="image/${ext}" srcset=${srcset(img, ext, factor)} media="(min-width: 768px)" 1 2 3 4 5 6 7 8 9 10 11 12 WIDTHS = [1920, 1280, 1024, 768, 640, 320] def imgurl(image, width, ext="png", convert_to=""): conversion = f"@{convert_to}" if convert_to else "" return f"https://img.panaitiu.com/_/{width}/plain/https://lunar.fyi/img/{urllib.parse.quote(image)}.{ext}{conversion}" def srcset(image, ext="png", factor=1.0, convert_to=""): return ",".join( f"{imgurl(image, width, ext, convert_to)} {width // factor:.0f}w" for width in WIDTHS ) Complexity Cost 1 imgproxy server that needs to run somewhere publicly available, be kept alive and secure some Python and Plim code for generating srcsets Hot reloading After 2 weeks of editing the page, Cmd-Tab to the browser, Cmd-R to refresh, I got really tired of this routine. I worked with Next.js before on Noiseblend and loved how each file change automatically gets refreshed in the browser. Instantly and in-place as well, not a full page refresh. I got the same experience when I worked with React Native. There should be something for static pages too, I thought. Well it turns out there is, it’s called LiveReload and I had to slap my forehead for not searching for it sooner. After installing the browser extension, and running the livereloadx --static file watcher, I got my hot reloading dev experience back. Actually now that I think about it, Hugo has super fast hot reloading, how does it accomplish that? Yep, turns out Hugo uses LiveReload as well. Complexity Cost 1 more command to run in 1 more terminal panel, multiplex helps with that 1 browser extension to install and hope it’s not compromised or sold to a data thief 1 npm install for getting the livereloadx CLI Contact pages After releasing the new app version, many things were broken, expectedly. People tried to reach me in so many ways: Github issues, personal email, through the app licensing provider, even Facebook Messenger. I had no idea that including an official way of contact would be so vital. And I had no idea how to even do it. A contact form needs, like, a server to POST to, right? And that server needs to notify me in some way, and then I have to respond to the user in some other way… sigh I thought about those chat bubbles that a lot of sites have, but I used them on Noiseblend and did not like the experience. Plus I dislike seeing them myself, they’re an eyesore and a nuisance obscuring page content and possibly violating privacy. After long searches, not sure why it took so long, I stumbled upon Formspark: a service that gives you a link to POST your form to, and they send you an email with the form contents. The email will contain the user email in ReplyTo so I can just reply normally from my mail client. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 form action="https://submit-form.com/some-random-id" label for="name" Name input#from hidden="true" name="_email.from" type="text" input#name name="name" placeholder="John Doe" required="" type="text" label for="email" Email input#email name="email" placeholder="john@doe.com" required="" type="email" label for="subject" Subject input#email-subject hidden="true" name="_email.subject" type="text" input#subject name="subject" placeholder="What's this message about?" required="" type="text" label for="message" Message textarea#message name="message" placeholder="Something about our apps perhaps" required="" type="text" rows="6" -coffee # Custom subject and name: https://documentation.formspark.io/customization/notification-email.html#subject nameInput = document.getElementById("name") fromInput = document.getElementById("from") nameInput.addEventListener 'input', (event) -> fromInput.value = event.target.value subjectInput = document.getElementById("subject") emailSubjectInput = document.getElementById("email-subject") subjectInput.addEventListener 'input', (event) -> emailSubjectInput.value = event.target.value Complexity Cost None, I guess. I just hope that the prolific but unique Formspark dev doesn’t die or get kidnapped or something. And you call this “simple”? It’s not. Really. It’s crazy what I had to go through to get to a productive setup that fits my needs. One could say I could have spent all that time on writing vanilla HTML, CSS and JS and I would have had the same result in the same amount of time. I agree, if time would be all that mattered. But for some people (like me), feeling productive, seeing how easy it is to test my ideas and how code seems to flow from my fingertips at the speed of thought, is what decides if I’ll ever finish and publish something, or if I l’ll lose my patience and fallback to comfort zones. Having to write the same boilerplate code over and over again, constant context switching between files, jumping back into a project after a few days and not knowing where everything was in those thousand-lines files.. these are all detractors that will eventually make me say ”f••k this! at least my day job brings money”. Reusability So many JS frameworks were created in the name of reusable components, but they all failed for me. I mean sure, I can “npm install” a React calendar, and I am now “reusing” and not “reimplementing” the hard work of someone better than me at calendar UIs. But just try to stray away a little from the happy path that the component creator envisioned, and you will find it is mind-bendingly hard to bend the component to your specific needs. You might raise a Github issue and the creator will add a few params so you can customize that specific thing, but so will others with different and maybe clashing needs. Soon enough, that component is declared unwieldy and too complex to use, the dev will say “f••k this! I’d rather do furniture” and someone else will come out and say: here’s the next best thing in React calendar libraries, so much simpler to use than those behemoths! I never had this goal in mind but unexpectedly, the above setup is generic enough that I was able to extract it into a set of files for starting a new website. I can now duplicate that folder and start changing site-specific bits to get a new website. Here are the websites I’ve done using this method: lowtechguys.com / where I publish my apps subsol.one / app I made for my brother to publish parties on robert.panaitiu.com / my brother’s personal website lunar.fyi / the app I have been talking about above And the best thing I remember is that for each website I published a working version, good looking enough, with a contact page and small bandwidth requirements, in less than a day. How does this solve the problem of straying away from the happy path? Well, this is not an immutable library residing in node_modules, or a JS script on a CDN. It is a set of files I can modify to the site’s needs. There is no high wall to jump (having to fork a library, figuring out its unique build system etc.) or need to stick to a specific structure. Once the folder is duplicated, it has its own life. For those interested, here is the repo containing the current state of my templates: github.com/alin23/plim-website I don’t recommend using it, it’s possible that I’m the only one who finds it simple because I know what went into it. But if you do, I’d love to hear your thoughts. Gatsby? Jekyll? Hugo? Weirdly, this website I’m writing on is not made with Plim. At some point I decided to start a personal website, and I thought it probably needs a blog-aware site builder. At the time, I didn’t know that RSS is an easily templatable XML file, and that all I need for a blog is to write Markdown. I remember trying Gatsby and not liking the JS ecosystem around it. Jekyll was my second choice with Github Pages, but I think I fumbled too much with ruby and bundle to get it working and lost patience. Both problems stemmed from my lack of familiarity with their ecosystems, but my goal was to write a blog, not learn Ruby and JS. Hugo seemed much simpler, and it was also written in Go and distributed as a standalone binary, which I always like for my tools. I marveled at Hugo’s speed, loved the fact that it supports theming (although it’s not as simple as it sounds) and that it has a lot of useful stuff built-in like syntax highlighting, image processing, RSS generator etc. But it took me sooo long to understand its structure. There are many foreign words (to me) in Hugo: archetypes, taxonomies, shortcodes, partials, layouts, categories, series. Unfortunately, by the time I realized that I don’t need the flexibility that this structure provides, I had already finished this website and written my first article. I also used a theme that uses the Tachyons CSS framework, for which I can never remember the right class to use. I thought about rewriting the website in Plim but converting everything to Tailwind or simple CSS would have been a lot of work. I eventually started writing simple Markdown files for my notes, and have Caddy convert and serve them on the fly. Helps me write from my phone and not have to deal with Git and Hugo. I still keep this for longform content, where a laptop is usually needed anyway.

a year ago 13 votes

More in programming

Adding auto-generated cover images to EPUBs downloaded from AO3

I was chatting with a friend recently, and she mentioned an annoyance when reading fanfiction on her iPad. She downloads fic from AO3 as EPUB files, and reads it in the Kindle app – but the files don’t have a cover image, and so the preview thumbnails aren’t very readable: She’s downloaded several hundred stories, and these thumbnails make it difficult to find things in the app’s “collections” view. This felt like a solvable problem. There are tools to add cover images to EPUB files, if you already have the image. The EPUB file embeds some key metadata, like the title and author. What if you had a tool that could extract that metadata, auto-generate an image, and use it as the cover? So I built that. It’s a small site where you upload EPUB files you’ve downloaded from AO3, the site generates a cover image based on the metadata, and it gives you an updated EPUB to download. The new covers show the title and author in large text on a coloured background, so they’re much easier to browse in the Kindle app: If you’d find this helpful, you can use it at alexwlchan.net/my-tools/add-cover-to-ao3-epubs/ Otherwise, I’m going to explain how it works, and what I learnt from building it. There are three steps to this process: Open the existing EPUB to get the title and author Generate an image based on that metadata Modify the EPUB to insert the new cover image Let’s go through them in turn. Open the existing EPUB I’ve not worked with EPUB before, and I don’t know much about it. My first instinct was to look for Python EPUB libraries on PyPI, but there was nothing appealing. The results were either very specific tools (convert EPUB to/from format X) or very unmaintained (the top result was last updated in April 2014). I decied to try writing my own code to manipulate EPUBs, rather than using somebody else’s library. I had a vague memory that EPUB files are zips, so I changed the extension from .epub to .zip and tried unzipping one – and it turns out that yes, it is a zip file, and the internal structure is fairly simple. I found a file called content.opf which contains metadata as XML, including the title and author I’m looking for: <?xml version='1.0' encoding='utf-8'?> <package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="uuid_id"> <metadata xmlns:opf="http://www.idpf.org/2007/opf" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:calibre="http://calibre.kovidgoyal.net/2009/metadata"> <dc:title>Operation Cameo</dc:title> <meta name="calibre:timestamp" content="2025-01-25T18:01:43.253715+00:00"/> <dc:language>en</dc:language> <dc:creator opf:file-as="alexwlchan" opf:role="aut">alexwlchan</dc:creator> <dc:identifier id="uuid_id" opf:scheme="uuid">13385d97-35a1-4e72-830b-9757916d38a7</dc:identifier> <meta name="calibre:title_sort" content="operation cameo"/> <dc:description><p>Some unusual orders arrive at Operation Mincemeat HQ.</p></dc:description> <dc:publisher>Archive of Our Own</dc:publisher> <dc:subject>Fanworks</dc:subject> <dc:subject>General Audiences</dc:subject> <dc:subject>Operation Mincemeat: A New Musical - SpitLip</dc:subject> <dc:subject>No Archive Warnings Apply</dc:subject> <dc:date>2023-12-14T00:00:00+00:00</dc:date> </metadata> … That dc: prefix was instantly familiar from my time working at Wellcome Collection – this is Dublin Core, a standard set of metadata fields used to describe books and other objects. I’m unsurprised to see it in an EPUB; this is exactly how I’d expect it to be used. I found an article that explains the structure of an EPUB file, which told me that I can find the content.opf file by looking at the root-path element inside the mandatory META-INF/container.xml file which is every EPUB. I wrote some code to find the content.opf file, then a few XPath expressions to extract the key fields, and I had the metadata I needed. Generate a cover image I sketched a simple cover design which shows the title and author. I wrote the first version of the drawing code in Pillow, because that’s what I’m familiar with. It was fine, but the code was quite flimsy – it didn’t wrap properly for long titles, and I couldn’t get custom fonts to work. Later I rewrote the app in JavaScript, so I had access to the HTML canvas element. This is another tool that I haven’t worked with before, so a fun chance to learn something new. The API felt fairly familiar, similar to other APIs I’ve used to build HTML elements. This time I did implement some line wrapping – there’s a measureText() API for canvas, so you can see how much space text will take up before you draw it. I break the text into words, and keeping adding words to a line until measureText tells me the line is going to overflow the page. I have lots of ideas for how I could improve the line wrapping, but it’s good enough for now. I was also able to get fonts working, so I picked Georgia to match the font used for titles on AO3. Here are some examples: I had several ideas for choosing the background colour. I’m trying to help my friend browse her collection of fic, and colour would be a useful way to distinguish things – so how do I use it? I realised I could get the fandom from the EPUB file, so I decided to use that. I use the fandom name as a seed to a random number generator, then I pick a random colour. This means that all the fics in the same fandom will get the same colour – for example, all the Star Wars stories are a shade of red, while Star Trek are a bluey-green. This was a bit harder than I expected, because it turns out that JavaScript doesn’t have a built-in seeded random number generator – I ended up using some snippets from a Stack Overflow answer, where bryc has written several pseudorandom number generators in plain JavaScript. I didn’t realise until later, but I designed something similar to the placeholder book covers in the Apple Books app. I don’t use Apple Books that often so it wasn’t a deliberate choice to mimic this style, but clearly it was somewhere in my subconscious. One difference is that Apple’s app seems to be picking from a small selection of background colours, whereas my code can pick a much nicer variety of colours. Apple’s choices will have been pre-approved by a designer to look good, but I think mine is more fun. Add the cover image to the EPUB My first attempt to add a cover image used pandoc: pandoc input.epub --output output.epub --epub-cover-image cover.jpeg This approach was no good: although it added the cover image, it destroyed the formatting in the rest of the EPUB. This made it easier to find the fic, but harder to read once you’d found it. An EPUB file I downloaded from AO3, before/after it was processed by pandoc. So I tried to do it myself, and it turned out to be quite easy! I unzipped another EPUB which already had a cover image. I found the cover image in OPS/images/cover.jpg, and then I looked for references to it in content.opf. I found two elements that referred to cover images: <?xml version="1.0" encoding="UTF-8"?> <package xmlns="http://www.idpf.org/2007/opf" version="3.0" unique-identifier="PrimaryID"> <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf"> <meta name="cover" content="cover-image"/> … </metadata> <manifest> <item id="cover-image" href="images/cover.jpg" media-type="image/jpeg" properties="cover-image"/> … </manifest> </package> This gave me the steps for adding a cover image to an EPUB file: add the image file to the zipped bundle, then add these two elements to the content.opf. Where am I going to deploy this? I wrote the initial prototype of this in Python, because that’s the language I’m most familiar with. Python has all the libraries I need: The zipfile module can unpack and modify the EPUB/ZIP The xml.etree or lxml modules can manipulate XML The Pillow library can generate images I built a small Flask web app: you upload the EPUB to my server, my server does some processing, and sends the EPUB back to you. But for such a simple app, do I need a server? I tried rebuilding it as a static web page, doing all the processing in client-side JavaScript. That’s simpler for me to host, and it doesn’t involve a round-trip to my server. That has lots of other benefits – it’s faster, less of a privacy risk, and doesn’t require a persistent connection. I love static websites, so can they do this? Yes! I just had to find a different set of libraries: The JSZip library can unpack and modify the EPUB/ZIP, and is the only third-party code I’m using in the tool Browsers include DOMParser for manipulating XML I’ve already mentioned the HTML <canvas> element for rendering the image This took a bit longer because I’m not as familiar with JavaScript, but I got it working. As a bonus, this makes the tool very portable. Everything is bundled into a single HTML file, so if you download that file, you have the whole tool. If my friend finds this tool useful, she can save the file and keep a local copy of it – she doesn’t have to rely on my website to keep using it. What should it look like? My first design was very “engineer brain” – I just put the basic controls on the page. It was fine, but it wasn’t good. That might be okay, because the only person I need to be able to use this app is my friend – but wouldn’t it be nice if other people were able to use it? If they’re going to do that, they need to know what it is – most people aren’t going to read a 2,500 word blog post to understand a tool they’ve never heard of. (Although if you have read this far, I appreciate you!) I started designing a proper page, including some explanations and descriptions of what the tool is doing. I got something that felt pretty good, including FAQs and acknowledgements, and I added a grey area for the part where you actually upload and download your EPUBs, to draw the user’s eye and make it clear this is the important stuff. But even with that design, something was missing. I realised I was telling you I’d create covers, but not showing you what they’d look like. Aha! I sat down and made up a bunch of amusing titles for fanfic and fanfic authors, so now you see a sample of the covers before you upload your first EPUB: This makes it clearer what the app will do, and was a fun way to wrap up the project. What did I learn from this project? Don’t be scared of new file formats My first instinct was to look for a third-party library that could handle the “complexity” of EPUB files. In hindsight, I’m glad I didn’t find one – it forced me to learn more about how EPUBs work, and I realised I could write my own code using built-in libraries. EPUB files are essentially ZIP files, and I only had basic needs. I was able to write my own code. Because I didn’t rely on a library, now I know more about EPUBs, I have code that’s simpler and easier for me to understand, and I don’t have a dependency that may cause problems later. There are definitely some file formats where I need existing libraries (I’m not going to write my own JPEG parser, for example) – but I should be more open to writing my own code, and not jumping to add a dependency. Static websites can handle complex file manipulations I love static websites and I’ve used them for a lot of tasks, but mostly read-only display of information – not anything more complex or interactive. But modern JavaScript is very capable, and you can do a lot of things with it. Static pages aren’t just for static data. One of the first things I made that got popular was find untagged Tumblr posts, which was built as a static website because that’s all I knew how to build at the time. Somewhere in the intervening years, I forgot just how powerful static sites can be. I want to build more tools this way. Async JavaScript calls require careful handling The JSZip library I’m using has a lot of async functions, and this is my first time using async JavaScript. I got caught out several times, because I forgot to wait for async calls to finish properly. For example, I’m using canvas.toBlob to render the image, which is an async function. I wasn’t waiting for it to finish, and so the zip would be repackaged before the cover image was ready to add, and I got an EPUB with a missing image. Oops. I think I’ll always prefer the simplicity of synchronous code, but I’m sure I’ll get better at async JavaScript with practice. Final thoughts I know my friend will find this helpful, and that feels great. Writing software that’s designed for one person is my favourite software to write. It’s not hyper-scale, it won’t launch the next big startup, and it’s usually not breaking new technical ground – but it is useful. I can see how I’m making somebody’s life better, and isn’t that what computers are for? If other people like it, that’s a nice bonus, but I’m really thinking about that one person. Normally the one person I’m writing software for is me, so it’s extra nice when I can do it for somebody else. If you want to try this tool yourself, go to alexwlchan.net/my-tools/add-cover-to-ao3-epubs/ If you want to read the code, it’s all on GitHub. [If the formatting of this post looks odd in your feed reader, visit the original article]

4 hours ago 3 votes
Non-alcoholic apéritifs

I’ve been doing Dry January this year. One thing I missed was something for apéro hour, a beverage to mark the start of the evening. Something complex and maybe bitter, not like a drink you’d have with lunch. I found some good options. Ghia sodas are my favorite. Ghia is an NA apéritif based on grape juice but with enough bitterness (gentian) and sourness (yuzu) to be interesting. You can buy a bottle and mix it with soda yourself but I like the little cans with extra flavoring. The Ginger and the Sumac & Chili are both great. Another thing I like are low-sugar fancy soda pops. Not diet drinks, they still have a little sugar, but typically 50 calories a can. De La Calle Tepache is my favorite. Fermented pineapple is delicious and they have some fun flavors. Culture Pop is also good. A friend gave me the Zero book, a drinks cookbook from the fancy restaurant Alinea. This book is a little aspirational but the recipes are doable, it’s just a lot of labor. Very fancy high end drink mixing, really beautiful flavor ideas. The only thing I made was their gin substitute (mostly junipers extracted in glycerin) and it was too sweet for me. Need to find the right use for it, a martini definitely ain’t it. An easier homemade drink is this Nonalcoholic Dirty Lemon Tonic. It’s basically a lemonade heavily flavored with salted preserved lemons, then mixed with tonic. I love the complexity and freshness of this drink and enjoy it on its own merits. Finally, non-alcoholic beer has gotten a lot better in the last few years thanks to manufacturing innovations. I’ve been enjoying NA Black Butte Porter, Stella Artois 0.0, Heineken 0.0. They basically all taste just like their alcoholic uncles, no compromise. One thing to note about non-alcoholic substitutes is they are not cheap. They’ve become a big high end business. Expect to pay the same for an NA drink as one with alcohol even though they aren’t taxed nearly as much.

2 days ago 5 votes
It burns

The first time we had to evacuate Malibu this season was during the Franklin fire in early December. We went to bed with our bags packed, thinking they'd probably get it under control. But by 2am, the roaring blades of fire choppers shaking the house got us up. As we sped down the canyon towards Pacific Coast Highway (PCH), the fire had reached the ridge across from ours, and flames were blazing large out the car windows. It felt like we had left the evacuation a little too late, but they eventually did get Franklin under control before it reached us. Humans have a strange relationship with risk and disasters. We're so prone to wishful thinking and bad pattern matching. I remember people being shocked when the flames jumped the PCH during the Woolsey fire in 2017. IT HAD NEVER DONE THAT! So several friends of ours had to suddenly escape a nightmare scenario, driving through burning streets, in heavy smoke, with literally their lives on the line. Because the past had failed to predict the future. I feel into that same trap for a moment with the dramatic proclamations of wind and fire weather in the days leading up to January 7. Warning after warning of "extremely dangerous, life-threatening wind" coming from the City of Malibu, and that overly-bureaucratic-but-still-ominous "Particularly Dangerous Situation" designation. Because, really, how much worse could it be? Turns out, a lot. It was a little before noon on the 7th when we first saw the big plumes of smoke rise from the Palisades fire. And immediately the pattern matching ran astray. Oh, it's probably just like Franklin. It's not big yet, they'll get it out. They usually do. Well, they didn't. By the late afternoon, we had once more packed our bags, and by then it was also clear that things actually were different this time. Different worse. Different enough that even Santa Monica didn't feel like it was assured to be safe. So we headed far North, to be sure that we wouldn't have to evacuate again. Turned out to be a good move. Because by now, into the evening, few people in the connected world hadn't started to see the catastrophic images emerging from the Palisades and Eaton fires. Well over 10,000 houses would ultimately burn. Entire neighborhoods leveled. Pictures that could be mistaken for World War II. Utter and complete destruction. By the night of the 7th, the fire reached our canyon, and it tore through the chaparral and brush that'd been building since the last big fire that area saw in 1993. Out of some 150 houses in our immediate vicinity, nearly a hundred burned to the ground. Including the first house we moved to in Malibu back in 2009. But thankfully not ours. That's of course a huge relief. This was and is our Malibu Dream House. The site of that gorgeous home office I'm so fond to share views from. Our home. But a house left standing in a disaster zone is still a disaster. The flames reached all the way up to the base of our construction, incinerated much of our landscaping, and devoured the power poles around it to dysfunction. We have burnt-out buildings every which way the eye looks. The national guard is still stationed at road blocks on the access roads. Utility workers are tearing down the entire power grid to rebuild it from scratch. It's going to be a long time before this is comfortably habitable again. So we left. That in itself feels like defeat. There's an urge to stay put, and to help, in whatever helpless ways you can. But with three school-age children who've already missed over a months worth of learning from power outages, fire threats, actual fires, and now mudslide dangers, it was time to go. None of this came as a surprise, mind you. After Woolsey in 2017, Malibu life always felt like living on borrowed time to us. We knew it, even accepted it. Beautiful enough to be worth the risk, we said.  But even if it wasn't a surprise, it's still a shock. The sheer devastation, especially in the Palisades, went far beyond our normal range of comprehension. Bounded, as it always is, by past experiences. Thus, we find ourselves back in Copenhagen. A safe haven for calamities of all sorts. We lived here for three years during the pandemic, so it just made sense to use it for refuge once more. The kids' old international school accepted them right back in, and past friendships were quickly rebooted. I don't know how long it's going to be this time. And that's an odd feeling to have, just as America has been turning a corner, and just as the optimism is back in so many areas. Of the twenty years I've spent in America, this feels like the most exciting time to be part of the exceptionalism that the US of A offers. And of course we still are. I'll still be in the US all the time on both business, racing, and family trips. But it won't be exclusively so for a while, and it won't be from our Malibu Dream House. And that burns.

2 days ago 6 votes
Slow, flaky, and failing

Thou shalt not suffer a flaky test to live, because it’s annoying, counterproductive, and dangerous: one day it might fail for real, and you won’t notice. Here’s what to do.

3 days ago 7 votes
Name that Ware, January 2025

The ware for January 2025 is shown below. Thanks to brimdavis for contributing this ware! …back in the day when you would get wares that had “blue wires” in them… One thing I wonder about this ware is…where are the ROMs? Perhaps I’ll find out soon! Happy year of the snake!

3 days ago 5 votes