A production-ready Zig starter template for building libraries and CLI applications. This template integrates essential Zig utilities and follows best practices for project structure, dependency management, testing, and version control.
- Modern Dependency Management - Uses Pantry for managing local and remote dependencies
- CLI Framework - zig-cli with type-safe argument parsing and interactive prompts
- Configuration Management - zig-config with multi-source loading and type safety
- Error Handling - zig-error-handling with Rust-inspired Result types
- Testing Framework - zig-test-framework with Jest/Vitest-style syntax
- Version Management - zig-bump for automatic version bumping and changelog generation
- Production Ready - Optimized build configuration for multiple platforms
- Zig 0.15.1 or later
- Pantry package manager
- Git
# Copy to a new project
cp -r zig-starter my-new-project
cd my-new-project# Using Pantry package manager
pantry install
# This will install:
# - zig-cli
# - zig-config
# - zig-error-handling
# - zig-test-framework
# - zig-bump# Build the project
zig build
# Or using package.jsonc scripts
pantry run build# Run all tests
zig build test
# Or using package.jsonc scripts
pantry run test# Run with default command
zig build run
# Run with arguments
zig build run -- --help
zig build run -- config --show
zig build run -- process input.txt -o output.txtzig-starter/
├── build.zig # Build configuration
├── build.zig.zon # Zig package manifest
├── package.jsonc # Pantry dependency configuration
├── README.md # This file
├── CHANGELOG.md # Auto-generated changelog (via zig-bump)
├── src/
│ ├── main.zig # CLI entry point
│ └── lib.zig # Core library functionality
└── zig-out/ # Build output (generated)
├── bin/
└── lib/
The package.jsonc file manages your dependencies and build configuration:
For production releases, update package.jsonc to use GitHub repositories:
{
"dependencies": {
// Production (GitHub releases)
"stacksjs/zig-cli": "latest",
"stacksjs/zig-config": "latest",
"stacksjs/zig-error-handling": "latest",
"stacksjs/zig-test-framework": "latest",
"stacksjs/zig-bump": "latest"
}
}const std = @import("std");
const starter = @import("starter");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
var lib = try starter.StarterLib.init(allocator);
defer lib.deinit();
const result = lib.processData("Hello, Zig!");
if (result.isOk()) {
const data = result.unwrap();
defer allocator.free(data);
std.debug.print("Processed: {s}\n", .{data});
}
}# Show version
./zig-out/bin/zig-starter --version
# Show configuration
./zig-out/bin/zig-starter config --show
# Process a file
./zig-out/bin/zig-starter process input.txt -o output.txt
# Enable verbose output
./zig-out/bin/zig-starter --verbose process data.txtconst errors = @import("zig-error-handling");
fn riskyOperation() errors.Result(i32, error{Failed}) {
if (some_condition) {
return errors.Result(i32, error{Failed}).ok(42);
} else {
return errors.Result(i32, error{Failed}).err(error.Failed);
}
}
// Usage
const result = riskyOperation();
if (result.isOk()) {
std.debug.print("Success: {}\n", .{result.unwrap()});
} else {
std.debug.print("Error: {}\n", .{result.unwrapErr()});
}const testing = @import("zig-test-framework");
test "example test" {
const value = 42;
try testing.expect(value == 42);
try testing.expectEqual(42, value);
}
test "string comparison" {
const str = "hello";
try testing.expectEqualStrings("hello", str);
}
test "error handling" {
try testing.expectError(error.EmptyData, someFunction());
}-
Create feature branch
git checkout -b feature/my-feature
-
Implement and test
# Edit source files vim src/lib.zig # Run tests continuously zig build test
-
Commit changes
git add . git commit -m "feat: add new feature"
This template uses zig-bump for version management:
# Bump patch version (0.1.0 → 0.1.1)
pantry run bump:patch
# Bump minor version (0.1.0 → 0.2.0)
pantry run bump:minor
# Bump major version (0.1.0 → 1.0.0)
pantry run bump:major
# These commands will:
# 1. Update version in build.zig.zon
# 2. Generate CHANGELOG.md entry
# 3. Create git commit
# 4. Create git tag
# 5. Push to remote (if configured)# Without pantry scripts
bump patch --changelog
bump minor --changelog --no-push
bump major --dry-run# Build with optimizations
zig build -Doptimize=ReleaseFast
# Build for multiple targets
zig build -Dtarget=x86_64-linux
zig build -Dtarget=aarch64-macos
zig build -Dtarget=x86_64-windowszig build install
# Output: zig-out/lib/libzig-starter.azig build install
# Output: zig-out/bin/zig-starterzig build test# Filter by test name
zig build test --test-filter "processData"zig build test -- --coverageEdit build.zig.zon:
.{
.name = "my-project",
.version = "0.1.0",
// ...
}Edit package.jsonc:
{
"name": "my-project",
// ...
}Edit package.jsonc:
{
"dependencies": {
"my-new-dep": "~/Code/my-new-dep"
}
}Then run:
pantry installUpdate build.zig to add the module:
const my_dep_mod = b.addModule("my-dep", .{
.root_source_file = b.path("../my-new-dep/src/root.zig"),
.target = target,
});
// Add to imports
lib_mod.addImport("my-dep", my_dep_mod);Edit src/main.zig:
var new_cmd = try app.addCommand("mycommand", .{
.description = "My new command",
.handler = myCommandHandler,
});
try new_cmd.addArgument("arg", .{
.description = "Command argument",
.required = true,
});# Update dependencies to use GitHub releases
# Edit package.jsonc to reference GitHub repos
# Install production dependencies
pantry install --frozen-lockfile
# Build optimized binary
zig build -Doptimize=ReleaseFast
# Binary is in: zig-out/bin/zig-starter# Linux
zig build -Dtarget=x86_64-linux -Doptimize=ReleaseFast
# macOS (Intel)
zig build -Dtarget=x86_64-macos -Doptimize=ReleaseFast
# macOS (Apple Silicon)
zig build -Dtarget=aarch64-macos -Doptimize=ReleaseFast
# Windows
zig build -Dtarget=x86_64-windows -Doptimize=ReleaseFast# Clean build cache
rm -rf zig-cache zig-out
# Rebuild
zig build# Reinstall dependencies
rm -rf .pantry node_modules
pantry install
# Check dependency status
pantry listEnsure build.zig has the correct relative paths to dependencies:
.root_source_file = b.path("../zig-cli/src/root.zig"),- Fork the repository
- Create your feature branch
- Commit your changes (follow conventional commits)
- Push to the branch
- Create a Pull Request
MIT License - feel free to use this template for any project.
- Zig Documentation
- Pantry Package Manager
- zig-cli Documentation
- zig-config Documentation
- zig-error-handling Documentation
- zig-test-framework Documentation
- zig-bump Documentation
For issues, questions, or contributions, please open an issue in the repository.
Happy Coding with Zig! 🚀
{ "name": "zig-starter", "version": "0.1.0", "dependencies": { // Local development paths (fast iteration) "zig-cli": "~/Code/zig-cli", "zig-config": "~/Code/zig-config", // ... etc }, "scripts": { "build": "zig build", "test": "zig build test", "run": "zig build run" } }