Authoring & Publishing UEFN Packages
Verse only compiles inside a UEFN project, so you author a Forest package in place, inside the same ForestPackages mount consumers install into. This makes your development environment bit-identical to every consumer’s install.
Scaffolding a package
Run forest init inside a Content/ForestPackages/<Scope>/<Name>/ folder and Forest scaffolds a package there: a forest.json, a README.md, and a starter .verse file.
forest init infers what to create from where you run it. Inside ForestPackages/<Scope>/<Name> it scaffolds a package; at Content/ it initializes the project manifest. Pass --project to force the bare project manifest regardless of where you run it.
Scaffolding a package is login-gated: Forest asks you to sign in and pick a scope you can publish under (your username or a Studio you’re an admin or owner of). The scope you pick becomes the folder your package lives in, so the folder always matches a scope you can actually publish to.
The folder name becomes the package’s Verse module identifier, so it must be a valid, non-reserved Verse identifier as typed. Forest never auto-renames it; if the name isn’t valid, rename the folder and try again.
The package is the folder
A UEFN package has no single entry module and no root field. The folder is the package: every .verse file in it shares the folder’s module namespace, and subfolders are nested modules. To expose a nested module to consumers, ship your own <public> marker for that subfolder inside the package. Forest only generates the scope-level and name-level markers.
- forest.json
- README.md
- LICENSE
- NavMesh.verse
Depending on other packages
Install dependencies from inside your package as usual:
forest i another-studio/pathingRunning install from inside an authored package declares the dependency in that package’s forest.json, but resolves and installs it at the project level (one lockfile, one shared mount). The single-version rule spans the whole project, so all authored packages and the project agree on one version of each dependency.
Authoring in place is a default, not a requirement. A standalone package compiles anywhere in Content/ because its imports are ancestor-resolved and its own internal references don’t name a location. In-place authoring is required only when your locally-authored packages depend on each other, since one’s using { ForestPackages.MyScope.Other } needs the other package sitting at the mount.
Publishing
Run forest publish from inside the package folder (ForestPackages/<Scope>/<Name>):
forest publishPublishing packs the package folder verbatim. A few rules are specific to UEFN:
- Publish from a package, not the project. Running
forest publishatContent/or the project root is refused, since that would upload the entire project. Scaffold or move into a package folder first. - The scope folder must match the author. You publish under the scope whose mapped folder your package lives in. If the folder is
cool_studio/you publish ascool-studio, not some other scope. - Verse code only. The registry rejects binary UE assets (
.uasset,.umap) and Epic-generated digest files (.digest.verse). Forest warns about these before uploading; add them to.forestignoreor remove them. compatibilityVersionis attached automatically. Forest reads it from your.uefnprojectand records it with the published version, so consumers know which UEFN release the package was built against. There’s no field for it inforest.json.- The generated markers are siblings of your package folder, not inside it, so they’re naturally excluded. The install receipt is excluded too.
For the shared publish flow (versioning, visibility, dependencies), see Publishing a Package.
One naming convention worth adopting: prefer distinctive exported member names. Two packages that export the same name with the same signature create call-site friction for consumers who import both, so NavMeshQuery is a better public name than Query. See Scopes & Collisions.