Docz supports a core + plugin architecture, allowing developers to extend functionality without bloating the core. Plugins enable new directives, renderers, exporters, logic, and interactivity while maintaining security and modularity.
- Modularity → Keep the core lightweight.
- Flexibility → Add features on demand.
- Security → Isolate and sandbox risky operations.
- Community Ecosystem → Share, discover, and reuse plugins globally.
Examples of plugins:
plugin-zeno→ Real-time physics simulation.plugin-qdraw→ Interactive diagramming.plugin-python→ Execute Python code in a sandbox.plugin-audio→ Execute Audio code.
| Category | Purpose |
|---|---|
| Directives | Introduce new syntax elements (e.g., @diagram, @qdraw). |
| Renderers | Define how directives render (HTML, Canvas, WebGL). |
| Exporters | Output formats like PDF, EPUB, or Static HTML. |
| Logic | Add interactivity or event-driven behavior. |
| Themes | Define visual design language. |
A plugin typically includes:
- Manifest: Metadata and directive registration.
- Core Logic (Zig): Implements functionality and hooks.
- Optional Frontend: UI components for Quartz (SvelteKit).
.{
.name = "plugin-qdraw",
.version = "0.1.0",
.author = "Quartz Team",
.directives = .{
"qdraw" = .{
.type = "diagram",
.description = "Draw diagrams inside Docz"
}
}
}
plugin-qdraw/
├── src/
│ └── main.zig
├── plugin.zon
├── README.md
└── examples/
└── usage.dcz
For JSON-based metadata (optional):
{
"name": "docz-plugin-zeno",
"version": "1.0.0",
"description": "Render interactive Zeno Engine scenes",
"author": "Your Name",
"entry": "plugin.zig",
"hooks": {
"register": "registerPlugin"
}
}Plugins integrate via hooks:
| Hook Name | Purpose |
|---|---|
onRegister |
Initialize plugin and directives. |
onParse |
Extend tokenization or AST. |
onRender |
Control rendering of custom directives. |
onExecute |
Run WASM execution for code-based tasks. |
onTeardown |
Cleanup on shutdown. |
mkdir docz-plugin-hello
cd docz-plugin-hello
touch plugin.zon src/main.zig README.mdconst std = @import("std");
pub fn registerPlugin() void {
std.debug.print("Hello Plugin Registered!\n", .{});
}Example: @hello(name="Docz")
- Hook into
Parserto detect@hello(...). - Inject AST node:
DirectiveNode(name="hello", params=...).
Output HTML:
<p>Hello, Docz!</p>const std = @import("std");
test "hello plugin outputs correct HTML" {
const result = renderHello("Docz");
try std.testing.expectEqualStrings("<p>Hello, Docz!</p>", result);
}Run tests:
zig build testDeclare in docz.zig.zon:
.plugins = .{
.docz-plugin-hello = .{
.url = "https://github.com/user/docz-plugin-hello",
.hash = "1220abc..."
}
}
Install:
qz install plugin-hello- Custom Renderers: HTML, Canvas, WebGL.
- Secure Execution: WASM sandboxes for untrusted code.
- Access Document Metadata:
pub fn onRender(meta: Meta, content: []const u8) void {
if (meta.title) |title| {
std.debug.print("Title: {s}\n", .{title});
}
}Add Svelte components for UI:
plugin-math3d/
└── ui/
└── Math3D.svelte
Quartz auto-detects ui components via manifest.
- Use semantic versioning.
- Keep plugins small and focused.
- Validate user input strictly.
- Avoid heavy dependencies in core.
- Write unit tests for all hooks.
- Push to GitHub.
- Tag a release.
- Add
plugin.zonand README. - Submit to Docz Plugin Registry.
qz publish plugin-hello- Validate all inputs.
- Sandbox dynamic execution.
- Verify plugin hashes for integrity.
Directive:
@embed(type="zeno-scene", source="scene.zson")
Features:
- Real-time simulation.
- WASM execution.
- WebSocket streaming.
Plugin Source → Compile Zig → Register in manifest → Install via CLI → Use in Docz