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) — required by devenv
- devenv (
nix profile add nixpkgs#devenv) - direnv (optional; auto-activates the shell on
cd) - Git
# Clone repository
git clone https://github.com/OpenStaticFish/ZigCraft.git
cd ZigCraft
# Enter dev environment
devenv shell
# Build and run tests
zig build testThe project uses devenv (Nix-based) for reproducible builds. All commands must be run with devenv shell.
# Build
devenv shell zig build
# Run
devenv shell zig build run
# Release build (optimized)
devenv shell zig build -Doptimize=ReleaseFast
# Clean build artifacts
rm -rf zig-out/ .zig-cache/# Run all unit tests (also validates Vulkan shaders)
devenv shell zig build test
# Run a specific test
devenv shell zig build test -- --test-filter "Vec3 addition"
# Integration test (window init smoke test)
devenv shell zig build test-integration# Format code
devenv shell zig fmt src/
# Fast type-check (no full compilation)
devenv shell 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
devenv shell zig fmt src/
# Run tests
devenv shell zig build testUse conventional commits for clear commit messages and PR titles. Allowed types are feat, fix, refactor, test, docs, ci, chore, perf, build, style, and revert.
feat: add LOD system for distant terrain
fix: resolve chunk mesh memory leak
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
Every PR commit must include a Signed-off-by trailer certifying the Developer Certificate of Origin. Create signed-off commits with git commit -s:
git commit -s -m "fix: resolve chunk mesh memory leak"If a commit is already created, amend it with git commit --amend -s before pushing. The DCO check validates the trailer on every PR commit.
# 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. Project modules by package name
const Vec3 = @import("engine-math").Vec3;
const log = @import("engine-core").log;- 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
devenv shell zig fmt src/
# Run all tests
devenv shell 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 inmodules/world-core/src/block.zig - Register properties (
isSolid,isTransparent,getLightEmission,getColor) - Add textures to
modules/engine-graphics/src/texture_atlas.zig - Standardize PBR textures:
./scripts/process_textures.sh - Update
modules/world-meshing/src/chunk_mesh.zigfor special face/transparency logic
Keep the block catalog under the current u8 capacity policy documented in docs/roadmap/block-id-capacity.md. Open or update a follow-up issue before adding large block families that would push the catalog toward the documented threshold.
- 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
modules/
engine-* # Engine packages for core, graphics, RHI, math, input, UI, ECS, audio
world-core/ # Blocks, chunks, coordinates, and light packing
world-worldgen/ # Terrain generation, biomes, caves, decorations, generator registry
world-meshing/ # Chunk storage, chunk mesh generation, GPU block buffers
world-lod/ # Distant terrain LOD chunks, meshes, scheduler, renderer, manager
world-runtime/ # World facade, streamer, renderer, mutation, GPU meshing runtime
world-persistence/# Level data, region files, chunk serialization, save manager
src/
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.