Having looked around the web a bit for options for upgrading to vinyl cutting, I wasn't impressed. The general idea is to buy a cutter (e.g. Graphtec CB09) and fit it to the hotend assembly, but almost all designs were entirely rigid, meaning that the Z height had to be very carefully set (and the bed levelled) to avoid catastrophe. Obviously a cutter on a spring-loaded linear bearing is the answer, but the only design I found like that is a bit bulky for my needs. So this is my attempt at a solution.
After a few minor iterations, the backplate, carriage and rails were fabricated and assembled. The cutter fitted perfectly. Spring duties performed by something I robbed from an old ballpoint pen. The only snag was that the two mounting holes present in the CAD for the Ender 3 v2 hotend assembly were not in quite the same places on my machine!
The little clip is an afterthough which allows the carriage to be held in the retracted position so that the printer can be used as a printer (or for bed-levelling etc.) without the cutter crashing into the bed.
To generate the G-code, I first tried jscut (which works well, but requires a lot of mouse clicks!) and then Inkscape's gcodetools extension (which was totally impenetrable and didn't work at all). For now I've settled on Gcodeplot for Inkscape which works really well. I found the install instructions weren't quite right (the folder should be C:\Program Files\Inkscape\share\inkscape\extensions), and I had to modify gcodeplot.py to change the G-code it produces from making 'G00' and 'G01' commands to simply 'G0' and 'G1' which my printer can understand. Just a find-and-replace for 'G0' should do it.
The G-code output can then either be printed directly on the machine, or down a USB cable using Pronterface (if you like the security of seeing a preview and doing test runs first).