ODGN

Home Blog Posts Work About
    Jun 10, 2025

    Todays fun has been discovering that my assumptions about OSM data are once again lacking.

    This is a map of George Hill.

    There are two nodes (green and red marker), and there are two edges (or ways) - one straight, and one which curves around.

    Both start and end at the same nodes.

    First problem

    Up to this point, i have been happily generating hashes of edges/ways using their start and end coordinates.

    I do this by Geohashing each coordinate pair and then concatenating them into a single string.

    So the first edge has a hash of gcj2uwcjs.gcj2ux08n and the second, yep gcj2uwcjs.gcj2ux08n.

    And there is the issue - both edges have the same hash despite being different. And since these get placed in a DB, I was getting missing edges.

    What I should probably do is hash all the coordinates in the edge into a single value. But I like the characteristics of my hash - it can be broken apart and reversed into two coordinate pairs. Useful for debugging and indexing!

    Solution - I have appended the number of coordinates in the edge. So they now become gcj2uwcjs.gcj2ux08n.3 and gcj2uwcjs.gcj2ux08n.18.

    Second problem

    There’s a larger context to be understood, but essentially I am trying to pick out Cycles from map data. Where a cycle is a closed loop of edges, which doesn’t contain any other cycles.

    The algorithm is a little clunky, but one thing it does not like is being fed two edges which have the same start and end coordinates.

    The solution is pretty straightforward - subdivide the edges, so that extra nodes are created. Feed that into the algorithm, and then replace the subdivided edges with the original ones.

    #
    osm strix
    Jun 2, 2025

    Today I finished migrating an existing Wordpress site i have been running over to Astro.

    There was nothing especially interesting about the site - it’s a basic community web site with information and contact details. It’s main feature is being able to view the monthly published PDF newsletters.

    Previously I would be emailed the PDF, and then go manually go through a short workflow of extracting a cover image from the PDF in order to display it on the site. Then I would create a new post to contain the PDF, and update a few fields of metadata.

    Nothing fancy, but slightly tedious.

    With the new version of the site, those manual steps have been eliminated.

    What I have now is a script which will read each PDF in a folder and extract from it a cover image and a few key paragraphs of text.

    The extraction from the PDF itself is slightly ridiculous, but then PDF is itself an ‘interesting’ file format.

    In broad terms, what I ended up doing is defining bounding Rectangles onto selected pages of the document where the image or text I need exist.

    Once the data is extracted, it is then placed within the sites filesystem as images or JSON, ready to be picked up by Astro for display.

    Previously, the dynamic wordpress site was hosted on its own (small-ish) linode server - running nginx, PHP, and mysql.

    But now, the new Astro site is entirely static, (cheekily) hosted on github pages, and fronted by Cloudflare.

    Quite a reduction in resources!

    #
    astro pdf wordpress

    Apparently the browser Arc is dead.

    Well not dead, but discontinued in favour of a new AI centric browser called Dia. I remain unconvinced.

    I made Arc my primary browser a couple of months ago. Safari was my main for quite some time almost by default. Chrome for some tasks, Firefox mainly for dev.

    What I like about Arc is the side-bar of tabs. Even if I wish I could have it on the right rather than left. It makes in painful to use with the Mac dock when I am in laptop mode, if you must know.

    Spaces are also great. I have one for Dev, another for news and socials.

    It has some annoyances. I wish that pinned tabs would revert back to their origin after a certain time. I wish there was an iOS version so I could sync. But otherwise, pretty happy.

    Given that even now, there is an update waiting to apply, my perception is that it’s not quite lifeless.

    Nonetheless, I am open to options again.

    Back in the day, I used to avidly follow a site called browserwatch. Which at one point would have daily updates on the latest browser advances. Now, I can’t even find an archive link to it.

    It does seem like Chrome has won. I don’t think the space has stagnated completely. There are promising rumours.

    Most likely I will migrate to Zen, and hope that its Firefox core doesn’t fall too far behind.

    #
    browsers
    May 28, 2025

    After seemingly an eternity of fiddling, i finally moved this site from hugo to Astro.

    Why? Hugo is great at what it does, but one thing I found lacking was the ability to interleave interactive javascript, one thing Astro excels at.

    The conversion hasn’t been that straightforward. Astro is no-where near as batteries included as Hugo.

    Tags? Had to roll that myself. Pagination? Not quite implemented yet, but again custom code.

    #
    astro odgn
    Mar 16, 2025

    Weeknotes 005

    This week dev has mostly been about implementing authentication, both app and server side. Because I am now at a point where the app is able to send data to the server.

    The first step was server side. And by server I mean both Web front-end and API.

    I have elected to go with Elixir for this project. I have done a fair amount of it in the past, but not so much in recent years, so it has taken a while to recall the way of doing things.

    Because I wanted to use React for the web front-end, LiveView was not such an attractive option. Instead I have opted to use Inertia to bridge between Phoenix and React. It appears to be quite oriented towards Laravel, but there is an adapter.

    Implementing Apple and Google sign-in was mostly straightforward. Using the same authentication for the API hit a few stumbling blocks with quite poor library documentation, which wasn’t spelling out exactly the steps required, but I got there in the end.

    In the app, Expo had me covered for Apple, and for google a non-expo library, which rather worryingly warns that the free version will stop working later in the year.


    Again docker made my life a misery this week. In particular this little line of joy which hung the build completely.

    [debug] Downloading esbuild from https://registry.npmjs.org/@esbuild/linux-arm64/0.17.11

    turns out the cause of this was in mix.exs, in particular the assets.build and assets.deploy.

    when i have:

    "assets.deploy": [
      "tailwind default --minify",
      "esbuild default --minify",
      "phx.digest"
    ]

    it hangs.

    But changing it to the package name works.

    "assets.deploy": [
      "tailwind strix_server --minify",
      "esbuild strix_server --minify",
      "phx.digest"
    ]

    I have no idea why it was set to default to begin with.


    The week ended with deploying the app release build onto iOS and failing with a cryptic ‘Maximum update depth exceeded’ error, despite working without issue as dev builds. So now begins the slow process of disabling lines one by one. App dev can be so insanely fragile sometimes.


    A lot of online discussion this week about ‘Vibe coding’. This talk was fairly excruciating.

    Even though I use an LLM quite a lot, it’s still done with a tight knot in my stomach waiting to see whether it has decided to delete half my code, or got confused and started using a totally different framework. That’s a vibe for sure. Certainly not relaxing.


    In minor trivia, mac Spotlight Search again became unable to recall any of my apps.

    So in disgust, I installed Raycast and now i feel incredibly stupid for not doing so earlier.

    I’m using the free version, which does everything I need. Being able to calculate time differences ( November 2025 - March 2025 ) is wonderful


    Links of Note

    Describer

    Simon Willison wrote a very informative post on how he uses LLMs to write code.

    In particular he described a technique for generated a document about how a given codebase works.

    I tried it out myself, and the results were… not great. This tool appears to wrap the same process.

    #
    weeknotes
    Mar 9, 2025

    Weeknotes 004

    So yes, clearly I lapsed hard and lost that weeknotes feeling. But I’m back. Honest.

    In my defence, VO Pads was all consuming. And everything else sort of fell by the wayside.

    It was wonderful of course, being that focussed on a single thing. I haven’t been that into a project for quite some time.

    And of course, the downside is that other activities receive less focus - sleep, eating properly, interviews. It wasn’t as bad as some other ocassions in my past. I have other, wonderful, things which keep me grounded.

    And the fact that there was a definite stopping point helped a great deal.

    This week some fixes to the playback were applied, and I made the interval slider background stripey.

    The next chunk of work is likely to make the interval slider zoomable - it’s near useless when the video is long and the chosen interval is short.


    This week I returned properly to the project codenamed Strix. What I really should have been working on.

    It’s always strange to return to previous work. Re-learning the original thought processes. Looking at it from a new perspective.

    I have decided to reduce the scope of the project a little. It’s still ambitious. But there is a definite core functionality now which will be good enough for v1.

    Coming back to React Native after several care-free months of React Web has been hard. Entire mornings lost to a sudden Red Screen with non-obvious reasons. Feels brittle. I discovered that working with XML is not something RN cares for.

    Going forward, I am determined to always have a current working build on my phone. I want to move to testflight quickly so that others can get it in there hands.


    Some time this week was spent re-examining which state manager to use.

    Xstate/Store mostly worked out fine in the last project, but i ran up against some limitations in being able to call other actions/events from within events.

    So I decided to try something else. The project started with Zustand, but I have found it gets kind of messy organisationally.

    I started with Legend/state. A bit more of signals/observable based approach.

    Two things didn’t work so well for me: the first is that I ran into a situation where an observable wouldn’t update as expected. This may have been because I was calling it from an interval timer. But I had to use an awkward work-around.

    Next, is that it seems to come batteries included with sqlite persistence that appears to conflict with op-sqlite.

    So, fickle creature that I am, I decided to go with Jotai instead.

    Similar concepts to Legend, so I still have a hill to climb to get used to the composition of individual state.


    • One of the more serious casulaties of my recent work sprint was losing momentum on my Person Of Interest watch-through.

    • White Lotus already seems better than the previous entries.

    • Prime Target ended this week. Enjoyable Dan Brown-ish adventure.

    • Severance is not something I am super enthusiastic about, but it’s clearly top tier viewing.

    • Did I mention that I finally watched Wild Robot? Didn’t have much expectations, but it was wonderful. The opening half an hour is free of talking, much like Wall-E which I loved.

    Links of Note

    Max Cooper - On Being

    Needs more listens, but have been enjoying this a lot this week.

    Trip Simulator

    Simulating walking routes in the iOS simulator is not great DX. This tool makes it slightly easier.

    Tempted to fork it to allow drag/drop of a GPX file.

    Screen Now

    A (so far) free alternative to Screen Capture. Not quite as full featured, but has some nice things missing from SC like adding captions.

    Senior TV producers take shelf-stacking jobs as UK industry remains in crisis

    As someone who is currently experiencing a longer than expected paid work shortage, this hit hard.

    #
    weeknotes
    Feb 26, 2025

    Introducing VO Pads

    Building a video player that feels like an Akai MPC

    Feb 26, 2025

    react vo-pads
    Jan 19, 2025

    Weeknotes 002

    This week was dedicated entirely to the vidpad project - an experiment which has turned into something i want to ship in some form or another.

    As usual the mood has veered from “this is crappy” to “actually, its quite fun”. Regardless, i am determined to see it through to some sort of conclusion.

    A fair amount of time was dedicated to getting the Youtube player to do something it doesn’t naturally want to do. With some careful application of state machines and careful management, it just about works.

    Another important milestone was getting the import and export nailed. Its possible to recreate projects purely from a URL now, which is great as I don’t want this to initially have any server requirements. So sharing creations is trivial. I do love URLs.

    As the codebase size has increased, so the familiar growing pains have increased. It’s not particularly pretty in come parts. I’ve had to rely on events a lot more, which always feels dirty in a React app.

    This is also the first time i’ve used Tanstack Query in any serious way, and so far it has impressed. I don’t have any server interactions, but do have a number of local db interactions, all of which i’ve wrapped in queries. Once I got my head around invalidating correctly, it worked very well.

    Links of Note

    React Scan

    A tool which highlights components that need to be optimised

    Hex.Dance

    A binary/file analysis, hex dump viewer & editor in the browser.

    Downloading every video for a TikTok account

    An excellent write-up. I need to investigate Whisper for transcript generation.

    Oodles of O’s

    One of my top De La Soul tracks gets a video after 33 years. It has a lovely postscript explaining the videos origin. Three Feet high and Rising was one of my first hip-hop loves.

    Savoury Midwestern Buns

    A recipe to try out. Haven’t come across these before.

    Radicle

    Recent github outages reminded everyone how centralised and fragile our source code could be. If I was so minded, i would probably deploy something like this on my own servers.

    Rhythm Doggo

    A rhythm platformer with adaptive music. And a dog.

    The Magical World of Shaders

    Bookmarked this as I have an upcoming task to get particle effects in a game I’m writing.

    Five Years of RN @ Shopify

    Interesting to read. Dedicated Native devs (or knowledge) for an app at scale is indeed essential. My last place had teams dedicated to iOS and Android. Fortuneatly we also had a dedicated upgrade resource haha.

    Powerdrift Arcade

    I’m quite obsessed with this game. The extreme sprite scaling, and the music. Ports to other systems were usually pale in comparison. Super hard to find a good emulation solution. And then, all of a sudden, in the browser.

    #
    weeknotes
    Jan 12, 2025

    Weeknotes 001

    The first proper back to work week of the year, after a concerted effort to make sure I didn’t spend too much time at the keyboard over christmas.

    I have an ever changing list of things I want to work on - a mix of both short experiments, and longer term projects. The trouble is that the short-term items end up being not so short term and start pushing the longer ones out. I’m getting better at evaluating whether something is worth pursuing, and the result is that i am still building, so I’m not too worried.


    The majority of this week was spent on a new ‘experiment’ i’m calling for the time being vidpads. As the week progressed, it became clear that i might want to push this beyond quick and dirty into something more polished.

    It’s essentially a video player with a few bells and whistles. So a lot of the first tasks were about getting a video to play.

    Typically, most of my projects are React Native, or at least heavily mobile centric. This project however is primarily browser based, with mobile compatibility. React is much the same in the browser, but the surrounding stack is quite different. Although I have long been familiar with building for web, there has been plenty of “updating of knowledge”.


    A early task was extracting a thumbnail from a html video element. There were three approaches I considered:

    • using ffmpeg.wasm
    • using webcodecs
    • simply drawing the video to a html canvas

    The first was in play because I had already built ffmpeg.wasm into the app with a view to using some of its features to manipulate videos. And indeed it works fine, if you can ignore the fact that its a 30meg+ dependency.

    Webcodecs are an interesting relatively recent development, which at first glance should give much of the power of ffmpeg without the large dependency. With further investigation, it turns out to be surprisingly low level for a browser api, to the point where I needed a companion library MP4Box.js to achieve anything. And still it is non-trivial. I did eventually get a thumbnail out of it, but getting one from an arbitrary time proved tricky, at which point I realised how much time I’d spent and left it there.

    The last option was simple, and just worked. I felt a bit cheated out of the time I had spent on the other two options, but I had learnt at least something new. Webcodecs is perhaps something to return to.


    The rest of the week was spent building out features and refining - progress was quite speedy.

    HTML Drag and Drop is still a mess when it comes to controlling the drag thumbnail - hacks applied. Claude/Cursor AI made a fair effort at translating my requirements, but just got into a mess. In the end I solved it by disregarding it’s advice.

    I was able to get controlled HTML video playback working well, with custom start/end and looping. I was dreading implementing Youtube playback, but in the end it wasn’t so bad. Thumbnail extraction seems like it will need server functions (to hide an API key), which I really want to avoid, but there is some hope in oEmbed


    I’ve been writing this in Zed, as the constant “helpful” auto-complete in Cursor drives me insane for writing. As it’s new and unfamiliar, here are some things I had to do in order to get it to behave:

    • word wrap - add { "soft_wrap": "editor_width" } in settings.json
    • you can indeed open links in the web browser with cmd-click)
    • i still can’t get cmd-1,2,3… etc to switch between editors. the keymap seems to be there, but nothing happens…
    • seems to be no color picker available yet - there is this but is fairly primitive

    Yeah, this has been way too long for weeknotes. Will refine for next week…


    Links of Note

    Pimosa

    A simple Video/Photo/etc editor. I have found myself needing to edit videos more often, and existing tools look just frightful.

    Synthesizing Music from JSON

    I have a real thing for web based synths.

    tl;dr: pl_synth is a tiny music synthesizer for C & JS and an editor (“tracker”) to create instruments and arrangements.

    Literate Flatbush

    A detailed technical explanation of Flatbush, an efficient JavaScript implementation of a static, packed RTree spatial index that uses Hilbert curves for data organization.

    I’ve been somewhat mindlessly using RBush quite a bit in recent projects.

    Building Bauble

    A great piece of writing about a shader DSL written in Janet - which I want to play with at some point.

    #
    weeknotes
    Nov 25, 2024

    Gradient Trails in Skia

    A dive into creating animated gradient trails in React Native Skia

    Nov 25, 2024

    react react-native reanimated skia
    Oct 25, 2024

    Messing with Skia

    An exploration into using Skia in a React Native app

    Oct 25, 2024

    react react-native reanimated skia zustand
    Oct 7, 2024

    Counting in Three

    Creating a shader based animated counter in React Three Fiber

    Oct 7, 2024

    react react-three-fiber shaders
© 2025 Alexander Veenendaal
Follow Alex on Bluesky Go to Alex's GitHub repo Connect with Alex on LinkedIn Follow Alex on Twitter