So far, we have used single-file programs.
A single-file Zig program looks like this:
hello.zigYou can run it with:
zig run hello.zigThis 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.zigEach 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 buildyou 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.zigThe 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.zigFor projects, we usually use:
zig buildThe 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.zonstores 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_projectThen run:
zig initThis creates a basic project structure.
You should see files similar to:
build.zig
build.zig.zon
src/Now run:
zig buildThis builds the project.
Depending on the generated template, you may also be able to run:
zig build runThe 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.zigThe 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:
5The word pub in math.zig matters:
pub fn add(a: i32, b: i32) i32It 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.zigEach 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 buildZig 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.zigWhen the program grows, add more files:
my_project/
build.zig
build.zig.zon
src/
main.zig
cli.zig
config.zig
app.zigAvoid 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 buildThe most important source file at the beginning is:
src/main.zigAs your program grows, split code into small files with clear responsibilities.