I still have a bit of JS in the demo viewer (you can drag the map, and click forward to page 2), but it's much simpler so I'm less likely to get it wrong. After changing my mind a few times, I settled on showing the map as two layers: the background is the same for every view, and then each turn's worth of moves is a layer on top. This is way slower in the browser than one single image, but a single image per turn is 500kb per image and this way each turn is just 40kb more data.
Today I played around a bit with the rendering. It still doesn't show convoys, and I'd really like to use curved arrows to represent supports, but I haven't quite figured out the best way to visualize everything.
This project may be my first where I'm attempting to use Haskell to solve a "real" problem, so I've been learning a lot about practical strengths and weaknesses. But I also haven't been able to devote much time to this or other personal projects, as I've been pretty busy lately with Real Life and work.