Project Structure
So far, we have used single-file programs.
Project Structure
So far, we have used single-file programs.
A single-file Zig program looks like this:
hello.zig
You can run it with:
zig run hello.zig
This is good for learning small examples. But real programs usually need more structure. They may have source files, tests, dependencies, documentation, generated files, and build settings.
A Zig project gives those pieces a predictable place.
A Small Zig Project
A simple Zig project often looks like this:
my_project/
build.zig
build.zig.zon
src/
main.zig
Each part has a job.
| File or folder | Purpose |
|---|---|
build.zig |
Build script for the project |
build.zig.zon |
Package metadata and dependencies |
src/ |
Source code folder |
src/main.zig |
Main program file |
The exact layout can vary, but this is a common starting point.
The Project Folder
The outer folder is the project root:
my_project/
This is the main directory for the program.
When you run project commands such as:
zig build
you usually run them from this folder.
The project root is important because Zig looks for build.zig there.
The Source Folder
The src folder contains your Zig source code:
src/
main.zig
The file main.zig is commonly the entry point for an executable program.
A simple src/main.zig may look like this:
const std = @import("std");
pub fn main() void {
std.debug.print("Hello from a Zig project!\n", .{});
}
This is similar to the earlier hello.zig, but now it lives inside a project.
The Build File
The file build.zig describes how to build the project.
For small single-file programs, we used:
zig build-exe hello.zig
For projects, we usually use:
zig build
The zig build command reads build.zig.
A simple build file tells Zig:
Build an executable from src/main.zig.
You do not need to understand every line of build.zig yet. For now, understand its role: it is the project’s build recipe.
The Package File
The file:
build.zig.zon
stores package metadata and dependency information.
ZON means Zig Object Notation. It is a data format used by Zig.
This file can describe things such as:
| Field | Meaning |
|---|---|
| Project name | The package name |
| Version | The package version |
| Dependencies | Other Zig packages used by the project |
| Paths | Files included in the package |
Beginners do not need to edit this file often at first, but it becomes important when using dependencies.
Creating a New Project
Zig can create a starter project for you.
Make a new folder:
mkdir my_project
cd my_project
Then run:
zig init
This creates a basic project structure.
You should see files similar to:
build.zig
build.zig.zon
src/
Now run:
zig build
This builds the project.
Depending on the generated template, you may also be able to run:
zig build run
The exact generated files may change between Zig versions, but the core idea is the same: zig init creates a starting project.
Single File vs Project
Both styles are useful.
| Style | Example | Best for |
|---|---|---|
| Single file | hello.zig |
Small experiments |
| Project | build.zig plus src/ |
Real programs |
When learning a new syntax feature, single files are faster.
When building an actual program, use a project.
A good rule:
Use zig run for experiments.
Use zig build for projects.
Splitting Code into Multiple Files
As programs grow, one file becomes too large.
You can place helper code in another file.
Example project:
my_project/
build.zig
src/
main.zig
math.zig
The file src/math.zig might contain:
pub fn add(a: i32, b: i32) i32 {
return a + b;
}
Then src/main.zig can import it:
const std = @import("std");
const math = @import("math.zig");
pub fn main() void {
const result = math.add(2, 3);
std.debug.print("{}\n", .{result});
}
Output:
5
The word pub in math.zig matters:
pub fn add(a: i32, b: i32) i32
It makes the function visible to other files.
Without pub, main.zig cannot call it.
Imports Are File-Based
This line:
const math = @import("math.zig");
imports another Zig file.
The imported file becomes a namespace. That means you access its public declarations through its name:
math.add(2, 3)
This keeps code organized.
You can think of math.zig as a small module.
Keeping Files Small
A beginner mistake is to put everything in main.zig.
That works for tiny programs, but it becomes difficult to read.
A better habit is to separate code by responsibility.
For example:
src/
main.zig
config.zig
parser.zig
server.zig
database.zig
Each file should have a clear purpose.
| File | Purpose |
|---|---|
main.zig |
Program entry point |
config.zig |
Configuration loading |
parser.zig |
Parsing input |
server.zig |
Network server logic |
database.zig |
Database access |
The goal is not to create many files for no reason. The goal is to keep related code together.
Where Tests Go
Zig tests can live in the same file as the code they test.
Example:
pub fn add(a: i32, b: i32) i32 {
return a + b;
}
test "add two numbers" {
try @import("std").testing.expect(add(2, 3) == 5);
}
This is common in Zig.
You can also create separate test files for larger projects, but colocated tests are simple and useful.
A test near the function it checks is easy to find and easy to update.
Build Output
When you run:
zig build
Zig creates build output directories.
You may see folders such as:
zig-out/
.zig-cache/
Their roles are different.
| Folder | Purpose |
|---|---|
zig-out/ |
Final build outputs |
.zig-cache/ |
Cached intermediate build data |
Usually, you do not edit these folders by hand.
Your source code lives in src/.
Your build outputs are generated by Zig.
What to Commit to Git
If you use Git, commit your source and build files:
build.zig
build.zig.zon
src/
Usually, do not commit generated build output:
zig-out/
.zig-cache/
A simple .gitignore may include:
zig-out/
.zig-cache/
This keeps the repository clean.
A Practical Starting Layout
For most beginner projects, this layout is enough:
my_project/
build.zig
build.zig.zon
src/
main.zig
When the program grows, add more files:
my_project/
build.zig
build.zig.zon
src/
main.zig
cli.zig
config.zig
app.zig
Avoid designing a huge folder structure before the program needs it.
Start simple, then split code when it becomes hard to read.
What You Should Remember
A Zig project usually has a project root, a build.zig file, a build.zig.zon file, and a src/ folder.
Use single files for experiments.
Use a project structure for real programs.
The most important project command is:
zig build
The most important source file at the beginning is:
src/main.zig
As your program grows, split code into small files with clear responsibilities.