Thank you for your interest in contributing to ZigCraft! This is primarily a solo, AI-assisted project, but well-scoped contributions are welcome. This document covers the development workflow, coding conventions, and how to get started.
- Quick Start
- Development Environment
- Branching Strategy
- Workflow
- PR Templates
- Code Style
- Testing
- Common Tasks
- Nix package manager (installed via NixOS or Determinate Nix Installer)
- Git
# Clone repository
git clone https://github.com/OpenStaticFish/ZigCraft.git
cd ZigCraft
# Enter dev environment
nix develop
# Build and run tests
zig build testThe project uses Nix for reproducible builds. All commands must be run with nix develop --command.
# Build
nix develop --command zig build
# Run
nix develop --command zig build run
# Release build (optimized)
nix develop --command zig build -Doptimize=ReleaseFast
# Clean build artifacts
rm -rf zig-out/ .zig-cache/# Run all unit tests (also validates Vulkan shaders)
nix develop --command zig build test
# Run a specific test
nix develop --command zig build test -- --test-filter "Vec3 addition"
# Integration test (window init smoke test)
nix develop --command zig build test-integration# Format code
nix develop --command zig fmt src/
# Fast type-check (no full compilation)
nix develop --command zig build check# Process PBR textures (Standardize 4k sources to 512px PNGs)
./scripts/process_textures.sh assets/textures/<pack_name> 512main <- Production-ready code
|
dev <- Staging branch for integrated features
|
+- feature/* <- New features
+- bug/* <- Non-critical bug fixes
+- hotfix/* <- Critical bug fixes (crashes, data loss)
+- ci/* <- CI/workflow changes
| Branch Type | Purpose | Merge Flow | Examples |
|---|---|---|---|
feature/* |
New features, enhancements | feature -> dev -> main |
feature/lod-system |
bug/* |
Non-critical bugs | bug -> dev -> main |
bug/rendering-artifact |
hotfix/* |
Critical bugs (crashes, data loss) | hotfix -> dev -> main |
hotfix/crash-on-load |
ci/* |
CI/workflow changes | ci -> dev -> main |
ci/update-runner |
dev |
Staging/integration | All PRs target dev | - |
main |
Production | dev -> main promotions |
- |
- Use kebab-case for branch names
- Be descriptive:
feature/lod-system,bug/chunk-leak,hotfix/save-corruption - No strict format required (issue numbers optional)
- CI branches:
ci/prefix for.github/changes
# Always branch from dev
git checkout dev
git pull origin dev
# Create your branch
git checkout -b feature/your-feature-name
# or
git checkout -b bug/your-bug-fix
# or
git checkout -b hotfix/critical-fix
# or
git checkout -b ci/workflow-changeFollow the coding conventions in Code Style below. The AGENTS.md file contains detailed internal guidelines used by AI coding agents and may also be a useful reference.
# Format your code before committing
nix develop --command zig fmt src/
# Run tests
nix develop --command zig build testUse conventional commits for clear commit messages:
feat: add LOD system for distant terrain
fix: resolve chunk mesh memory leak
hotfix: prevent crash on save file corruption
ci: update runner configuration for faster builds
refactor: extract lighting calculation to separate module
test: add unit tests for Vec3 operations
docs: update CONTRIBUTING.md with workflow changes
# Push your branch
git push origin feature/your-feature-name- Open a PR on GitHub
- Select the appropriate template (feature, bug, hotfix, ci)
- Base branch:
dev(all PRs should targetdev) - Mark as [Draft] if work-in-progress
- Wait for CI checks to pass:
build,unit-test,integration-test,opencode - Address review feedback
- Once approved, merge using Squash and merge
- Delete your branch after merging
When dev has stable features ready for production:
# Create PR from dev -> main
git checkout main
git pull origin main
git checkout -b promote/dev-to-main-$(date +%Y%m%d)
git push origin promote/dev-to-main-$(date +%Y%m%d)- Create a PR with base
main, comparedev - Verify all CI checks pass
- Merge after final review
We have 4 PR templates to help standardize contributions:
- feature.md - New features and enhancements
- bug.md - Non-critical bug fixes
- hotfix.md - Critical issues requiring immediate attention
- ci.md - Workflow and CI changes
Each template includes:
- Type classification
- Related issue links
- Checklist of requirements
- Testing steps
- Types/Structs/Enums:
PascalCase(RenderSystem,BufferHandle) - Functions/Variables:
snake_case(init_renderer,mesh_queue) - Constants/Globals:
SCREAMING_SNAKE_CASE(MAX_CHUNKS) - Files:
snake_case.zig
// 1. Standard library
const std = @import("std");
const Allocator = std.mem.Allocator;
// 2. C imports (always via c.zig)
const c = @import("../c.zig").c;
// 3. Local modules (relative paths)
const Vec3 = @import("../math/vec3.zig").Vec3;
const log = @import("../engine/core/log.zig");- Functions allocating heap memory MUST accept
std.mem.Allocator - Use
defer/errdeferfor cleanup immediately after allocation - Prefer
std.ArrayListUnmanagedin structs that store the allocator elsewhere
- Propagate errors with
try; define subsystem-specific error sets - Log errors:
log.log.err("msg: {}", .{err}) - Use
//!for module-level docs,///for public API docs
For full coding guidelines, see AGENTS.md (internal AI agent reference, contains detailed conventions).
# Format code
nix develop --command zig fmt src/
# Run all tests
nix develop --command zig build test- Add unit tests for new utility, math, or worldgen logic
- Use descriptive test names:
test "Vec3 normalize" - Test error paths and edge cases
For rendering changes:
- Run the app and verify visually
- Test multiple graphics presets (LOW, MEDIUM, HIGH, ULTRA)
- Check for regressions in shadows, lighting, fog
- Add entry to
BlockTypeenum insrc/world/block.zig - Register properties (
isSolid,isTransparent,getLightEmission,getColor) - Add textures to
src/engine/graphics/texture_atlas.zig - Standardize PBR textures:
./scripts/process_textures.sh - Update
src/world/chunk_mesh.zigfor special face/transparency logic
- GLSL sources in
assets/shaders/(Vulkan shaders invulkan/subdirectory) - Vulkan SPIR-V validated during
zig build testviaglslangValidator - Uniform names must match exactly between shader source and RHI backends
Add tests to src/tests.zig using std.testing assertions:
expectEqual- exact value comparisonexpectApproxEqAbs- floating point comparisonexpect- boolean/boolean expressions
src/
engine/ # Core engine systems
core/ # Window, time, logging, job system
graphics/ # RHI, shaders, textures, camera, shadows
input/ # Input handling
math/ # Vec3, Mat4, AABB, Frustum
ui/ # Immediate-mode UI, fonts, widgets
world/ # Voxel world logic
worldgen/ # Terrain generation, biomes, caves
block.zig # Block types and properties
chunk.zig # Chunk data structure (16x256x16)
chunk_mesh.zig # Mesh generation from chunks
world.zig # World management
game/ # Application logic, state, menus
c.zig # Central C interop (@cImport)
main.zig # Entry point
tests.zig # Unit test suite
libs/ # Local dependencies (zig-math, zig-noise)
assets/shaders/ # GLSL shaders (vulkan/ contains SPIR-V)
- 📖 Issues - Report bugs or request features
- 💬 Discussions - Ask questions
- 📚 AGENTS.md - Agent coding guidelines
By contributing, you agree that your contributions will be licensed under the project's license.