So, browsing the zola codebase, I think the main gateay for making this happen is to use Tera’s register_function. Basically, after loading the WASM module, the exported functions are enumerated (with their signature). Instances of a hypothetical PluginFunction type (which implements the Tera Function trait) are created for each of these WASM functions, and .. Bob’s your uncle.
As a first experiment, I’d restrict exported functions to strictly take strings (or [u8]), and have the template user pass the output of things like get_page and page.description and what have you. The output would be similarly a stream of bytes, the encoding of which is determined by the plugin author. (could be an image ..)
So far, this closely mirrors the Typst architecture, incidentally, and it is specifically for pure functions only with no interaction with the file system, unless ..
No need for WASI shenanigans at all, but Zola could expose a number of functions that WASM modules can import. One possible idea of these functions would be create_file to create a file. create_file would take as input the file content (say a created image) and a desired file name and/or extension; and give as output the final path which then can be passed on to the exported functions. Implementation of this function is opaque to the module, but could for example create plugins/ directory in public where these files are saved. Any further capabilities to the plugin system would simply be more exposed functions to the modules (say a json site map .. the sky is the limit).
Plugins could even be registered wither with shortcode functions or global functions (with different exposed functions, maybe?). Say plugins in plugins directory register with globals and in plugins/shortcodes register with shortcods.
I’d be happy to work on this if y’all like the idea. It is not difficult work (I’ve done it before) just a bit time consuming.