Project layout
A @teakit/napi project is a Zig project and a Node.js project sharing one root. This page is a one-stop map: every file in the project, every directory the build creates, and where to look for more on each.
The same layout applies whether you scaffolded with napikit new or wired things up by hand following Manual setup.
Source tree
After napikit build
<name>.js lets import addon from "./<name>.js" work locally without going through the npm package layout. It points at zig-out/lib/<name>.node. Both <name>.js and <name>.d.ts at the project root are gitignored; they are derived artifacts.
After napikit build --release
This is the publishable tree. napikit publish ships every package discovered under npm/ to npm. The tree is reconciled on every release build: policy fields come from build.zig, your version and user-edited fields are preserved. With .dts = .none, index.d.ts and the manifest's types/managed files entries are absent; switching to .none removes that stale build-owned declaration. See Cross-compiling for the full rules.
If build.zig calls addLib more than once, each addon gets its own npm/<name>/ subtree alongside the others. See Multiple addons in one repo.
Where to put your code
- One file is fine. Keep adding to
src/lib.ziguntil it feels too large. - Splitting into namespaces. A
pub const x = @import("x.zig")inlib.zigbecomes the JS namespaceaddon.x. See Namespaces. - Shared Zig modules outside the root. Pass them through
.importsso they are importable as@import("name")from anywhere in your addon. SeeaddLibImport.
Generated and ignored
Exclude everything derived from version control: node_modules, zig-out, .zig-cache, zig-pkg, and the project-root <name>.js / <name>.d.ts re-exporters. (napikit new writes a .gitignore with all of these; if you set up by hand, see Manual setup, step 5.) Commit npm/ once you start publishing. Every release build keeps it in sync with build.zig automatically.