- Core API
- Window Management
- WebView Integration
- JavaScript Bridge
- Native Dialogs
- Clipboard
- Configuration
- Logging
- CLI Options
The main application struct that manages windows and the event loop.
const craft = @import("craft");
var app = craft.App.init(allocator);
defer app.deinit();Create a new application instance.
Clean up and free all resources.
Create a window with HTML content.
Parameters:
title: []const u8- Window titlewidth: u32- Window width in pixelsheight: u32- Window height in pixelshtml: []const u8- HTML content to display
Returns: Pointer to the created window
Example:
const window = try app.createWindow("My App", 800, 600, "<h1>Hello!</h1>");Create a window that loads a URL directly (no iframe).
Parameters:
title: []const u8- Window titlewidth: u32- Window width in pixelsheight: u32- Window height in pixelsurl: []const u8- URL to loadstyle: WindowStyle- Window style options
Returns: Pointer to the created window
Example:
const window = try app.createWindowWithURL(
"My App",
1200,
800,
"http://localhost:3000",
.{
.frameless = true,
.transparent = false,
.always*on*top = false,
.resizable = true,
},
);Start the application event loop. This blocks until all windows are closed.
Example:
try app.run();Configure window appearance and behavior.
pub const WindowStyle = struct {
frameless: bool = false, // Remove title bar and borders
transparent: bool = false, // Make window background transparent
always*on*top: bool = false, // Keep window above others
resizable: bool = true, // Allow window resizing
closable: bool = true, // Show close button
miniaturizable: bool = true, // Show minimize button
};Example:
// Frameless, transparent overlay
const style = WindowStyle{
.frameless = true,
.transparent = true,
.always*on*top = true,
.resizable = false,
};WebKit Developer Tools are enabled by default. Users can access them by:
- Right-clicking anywhere in the window
- Selecting "Inspect Element"
To disable DevTools:
craft --url http://localhost:3000 --no-devtoolsOr in configuration:
[webview]
dev*tools = falseThe window.craft API is automatically injected into every page.
Send a message to Zig.
Parameters:
name: string- Handler namedata: any- Data to send (will be JSON serialized)
Returns: Promise<any> - Response from Zig handler
Example:
const result = await window.craft.send('myHandler', { foo: 'bar' });
console.log('Response from Zig:', result);Show a notification (convenience wrapper).
Example:
await window.craft.notify('Hello from JavaScript!');Read a file from the filesystem.
Example:
const content = await window.craft.readFile('/path/to/file.txt');Write a file to the filesystem.
Example:
await window.craft.writeFile('/path/to/file.txt', 'Hello, World!');Get clipboard contents.
Example:
const text = await window.craft.getClipboard();Set clipboard contents.
Example:
await window.craft.setClipboard('Copied text!');Open a native file dialog.
Example:
const path = await window.craft.openDialog({
title: 'Select a file',
multiple: false
});Fired when the Craft API is ready.
Example:
window.addEventListener('craft:ready', () => {
console.log('Craft is ready!');
console.log('Platform:', window.craft.platform);
console.log('Version:', window.craft.version);
});Evaluate JavaScript from Zig (coming soon).
Native file dialogs using Cocoa APIs.
const macos = @import("macos.zig");
const path = try macos.showOpenDialog("Select a file", false);
if (path) |p| {
std.debug.print("Selected: {s}\n", .{p});
}Parameters:
title: []const u8- Dialog titleallow*multiple: bool- Allow multiple file selection
Returns: ?[]const u8 - Selected file path or null if canceled
const path = try macos.showSaveDialog("Save file", "document.txt");
if (path) |p| {
std.debug.print("Save to: {s}\n", .{p});
}Parameters:
title: []const u8- Dialog titledefault*name: ?[]const u8- Default file name
Returns: ?[]const u8 - Selected file path or null if canceled
const macos = @import("macos.zig");
try macos.setClipboard("Hello, clipboard!");const text = try macos.getClipboard(allocator);
defer allocator.free(text);
std.debug.print("Clipboard: {s}\n", .{text});const config*mod = @import("config.zig");
const config = try config*mod.Config.loadFromFile(allocator, "craft.toml");[window]
title = "My App"
width = 1200
height = 800
resizable = true
frameless = false
transparent = false
always*on*top = false
[webview]
dev*tools = true
user*agent = "MyApp/1.0"const config = config*mod.Config{
.window = .{
.title = "My App",
.width = 1200,
.height = 800,
},
};
try config.saveToFile("craft.toml");const log = @import("log.zig");
log.debug("Debug message: {}", .{value});
log.info("Info message: {s}", .{str});
log.warn("Warning message");
log.err("Error message");log.setLevel(.Debug); // Show all messages
log.setLevel(.Info); // Show Info, Warning, Error
log.setLevel(.Warning); // Show Warning, Error only
log.setLevel(.Error); // Show Error only[HH:MM:SS] LEVEL Message
[22:45:31] INFO Application started
[22:45:32] WARN Configuration file not found
[22:45:33] ERROR Failed to load resource
craft [OPTIONS] [URL]| Flag | Description | Default |
|---|---|---|
-u, --url <URL> |
Load URL in window | - |
--html <HTML> |
Load HTML content | - |
-t, --title <TITLE> |
Window title | "Craft App" |
-w, --width <WIDTH> |
Window width | 1200 |
--height <HEIGHT> |
Window height | 800 |
--frameless |
Frameless window | false |
--transparent |
Transparent window | false |
--always-on-top |
Always on top | false |
--no-resize |
Disable resizing | false |
--no-devtools |
Disable DevTools | false |
-h, --help |
Show help | - |
-v, --version |
Show version | - |
# Load URL
craft http://localhost:3000
# Custom size and title
craft --url http://example.com --width 800 --height 600 --title "My App"
# Frameless window
craft http://localhost:3000 --frameless
# Transparent overlay
craft http://localhost:3000 --transparent --always-on-top --frameless
# Load HTML
craft --html "<h1>Hello, World!</h1>"
# Multiple options
craft --url http://localhost:3000 \
--title "Dev Server" \
--width 1600 \
--height 900 \
--framelessCraft supports all standard Zig build modes:
# Debug mode (default) - fast compilation, debug info
zig build
# ReleaseSafe - optimized with safety checks
zig build -Doptimize=ReleaseSafe
# ReleaseFast - maximum performance, no safety
zig build -Doptimize=ReleaseFast
# ReleaseSmall - smallest binary size
zig build -Doptimize=ReleaseSmall| Mode | Binary Size | Safety | Performance |
|---|---|---|---|
| Debug | ~1.5MB | ✅ Full | Medium |
| ReleaseSafe | ~1.3MB | ✅ Full | High |
| ReleaseFast | ~1.2MB | ❌ None | Maximum |
| ReleaseSmall | ~1.0MB | ❌ None | Medium |
| Feature | macOS | Linux | Windows |
|---|---|---|---|
| Window Creation | ✅ | 🚧 | 🚧 |
| WebView | ✅ | 🚧 | 🚧 |
| DevTools | ✅ | 🚧 | 🚧 |
| Dialogs | ✅ | ❌ | ❌ |
| Clipboard | ✅ | ❌ | ❌ |
| Menu Bar | 🚧 | ❌ | ❌ |
| System Tray | ❌ | ❌ | ❌ |
Legend:
- ✅ Implemented and working
- 🚧 API ready, implementation pending
- ❌ Not yet implemented
All fallible operations return Zig error unions:
const window = app.createWindow("Title", 800, 600, html) catch |err| {
std.debug.print("Failed to create window: {}\n", .{err});
return;
};Common errors:
error.UnsupportedPlatform- Feature not available on this OSerror.NoWindows- No windows created beforerun()error.HandlerNotFound- JavaScript bridge handler not registerederror.NoClipboardContent- Clipboard is empty
For more examples, see the examples/ directory.