Skip to content

Project Structure

So far, we have used single-file programs.

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 folderPurpose
build.zigBuild script for the project
build.zig.zonPackage metadata and dependencies
src/Source code folder
src/main.zigMain 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:

FieldMeaning
Project nameThe package name
VersionThe package version
DependenciesOther Zig packages used by the project
PathsFiles 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.

StyleExampleBest for
Single filehello.zigSmall experiments
Projectbuild.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.

FilePurpose
main.zigProgram entry point
config.zigConfiguration loading
parser.zigParsing input
server.zigNetwork server logic
database.zigDatabase 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.

FolderPurpose
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.