module organization
patterns for organizing zig modules, derived from ghostty and tigerbeetle.
file + directory pattern
idiomatic zig uses foo.zig alongside foo/ directory:
src/
├── apprt.zig # entry point / public API
└── apprt/ # implementation files
├── action.zig
├── structs.zig
└── gtk.zig
the parent file re-exports from the subdirectory:
// apprt.zig
pub const action = @import("apprt/action.zig");
pub const structs = @import("apprt/structs.zig");
pub const Action = action.Action;
pub const Runtime = @import("apprt/runtime.zig").Runtime;
no ambiguity because import paths are explicit:
@import("apprt.zig")→ the file (public API)@import("apprt/action.zig")→ from the directory
anti-patterns
don't do foo/foo.zig - redundant naming:
src/
└── orchestration/
└── orchestration.zig # wrong
don't do foo/mod.zig - this is rust convention, not zig:
src/
└── orchestration/
└── mod.zig # wrong (rust pattern)
examples in the wild
ghostty:
src/apprt.zig+src/apprt/src/cli.zig+src/cli/src/config.zig+src/config/
tigerbeetle:
src/io.zig+src/io/src/lsm.zig+src/lsm/
prefect-server:
src/orchestration.zig+src/orchestration/src/broker.zig+src/broker/src/services.zig+src/services/