You kind of have two main approaches, the LISP way or the text way.
The beauty of the LISP way is that (= code data), so you can generate some s-expressions and print them out. The downside is that you have no control over formatting, but you can generate the unformatted version first and then run a code formatter over that like zprint.
Another annoying thing is that syntax quote actually does more than what you want for this use case, which is why you end up with all of those ~' in your code. As @didibus mentioned this is a sign you want to look at the backtick library, especially backtick/template.
Or you use something like Mustache, which is actually what most Leiningen templates do. You get a lot more control over formatting this way, and you can print out things that aren’t really homoiconic (what if you want to generate code which contains backticks and reader conditionals?), but getting whitespace right is still a huge pain. When creating Chestnut I put a lot of effort into generating correctly formatted code because it annoyed me a lot when templates didn’t do this, and boy it is not fun. Probably still better to just run a formatter over it afterwards