By the way, the following wrapper function can be used to get an interface that is similar to the Diet render!() function:

static import embd;
void renderEmbd(string FILE, ALIASES...)(OutputStream dst)
{

	mixin(vibe.templ.utils.localAliases!(0, ALIASES));

	class Context : embd.Context {
		OutputStream output__;

		mixin(renderer);

		void write(string content, dchar eval_code)
		{
			if (eval_code == '=')
				filterHtmlEscape(output__, content);
			else
				output__.write(content, false);
		}
	}

	scope Context ctx = new Context;
	ctx.output__ = dst;
	ctx.render!(import(FILE), `!=`, `<%`, `%>`)();
}

void renderEmbd(string FILE, ALIASES...)(HTTPServerResponse res, string content_type = "text/html; charset=UTF-8")
{
	res.contentType = content_type;
	renderEmbd!(FILE, ALIASES)(res.bodyWriter);
}

void renderEmbdCompat(string FILE, TYPES_AND_NAMES...)(OutputStream dst, ...)
{
	import core.vararg;
	import std.variant;
	mixin(localAliasesCompat!(0, TYPES_AND_NAMES));

	class Context : embd.Context {
		OutputStream output__;

		mixin(renderer);

		void write(string content, dchar eval_code)
		{
			if (eval_code == '=')
				filterHtmlEscape(output__, content);
			else
				output__.write(content, false);
		}
	}

	scope Context ctx = new Context;
	ctx.output__ = dst;
	ctx.render!(import(FILE), `!=`, `<%`, `%>`)();
}

Example usage:

string caption = "Hello, World!";
//res.renderEmbd!("test.embd", caption, req)();
res.bodyWriter.renderEmbdCompat!("test.embd",
	string, "caption",
	HTTPServerRequest, "req")(caption, req);

The non-compat version may suffer from a memory corruption bug in DMD, so I would avoid it for now. I'll prepare a pull request to see if Nathan is willing to include them.