I repurposed this LP example and it still solved the hardest puzzles in 100ms, while the regular puzzles were somewhat faster.
That's pretty impressive to me, since other approaches were slower on the hard puzzles and I hardly had to do anything.
It's probably possible for a backtracking heuristic to be a bit better, but could be annoying to figure out on my own.
Now the question is whether this LP-based Sudoku solver is sufficient for generating puzzles.
It needs to be run twice every time it's used with an extra constraint negating the first solution, to detect if there's more than one solution.
Since the solver will be run many times, it's probably still going to be too slow to be useful in the browser.
However I want to try and make a local generator anyway, it's still usable like this.
It would be nice if the user can choose which types of modifier they want, but it's not necessary.