Modules: Organizing and Sharing Verse Code
Tutorialbeginnercompiles

Modules: Organizing and Sharing Verse Code

Updated beginnerFundamentalsCode verified

Modules: Organizing and Sharing Verse Code

A growing UEFN project is dozens — sometimes hundreds — of .verse files. Without a way to group them and control what's visible across them, every name would collide and every file would see everything. Verse's answer is the module: a named container for related code. Modules are how you split a project into systems (SaveSystem, NpcSystem, UISystem), how you pull in Fortnite's APIs with using, and how you decide what's <public> (shared) versus <internal> (private to the module). This lesson ties the whole track together: the access specifiers you'll set here use the same angle-bracket syntax as the effect labels from earlier lessons.

Two kinds of module you already use

<!-- section-art:two-kinds-of-module-you-already-use --> Modules: Organizing and Sharing Verse Code: Two kinds of module you already use

Dual Module Paths

Every using line at the top of a Verse file names a module. You've been using modules since your first device:

using { /Fortnite.com/Devices }                 # Fortnite's device APIs
using { /Verse.org/Simulation }                  # agent, @editable, core sim types
using { /UnrealEngine.com/Temporary/Diagnostics } # Print and logging

Those slash-paths are Epic's modules: /Fortnite.com/..., /Verse.org/..., /UnrealEngine.com/.... A using opens a module so you can write its names unqualified — button_device instead of the full path. These three are the most common in real code (/Verse.org/Simulation and /Fortnite.com/Devices appear in the vast majority of device files).

The second kind is your own modules — the systems you build. In our project, a file opens sibling systems the same way:

# Real corpus using-lines for project modules.
using { Verse.Scripts.Utils }
using { SaveSystem }
using { ConfigSystem }

So using is a single idea applied to both Epic's library and your own code: bring this module's public names into scope.

How a module is structured

A module is declared with := module. There are two forms.

Folder modules — a folder in your Verse project is a module, named after the folder. Our project's permissions.verse declares the whole tree this way. This is real, lightly trimmed corpus code:

# Real shape from permissions.verse — folders declared as modules.
Scripts<public> := module:
    SaveSystem<public> := module:
        Core<public> := module:
    NpcSystem<public> := module:
    UISystem<public> := module:
    Utils<public> := module:
    Unused<internal> := module:    # visible only inside Scripts

Indentation shows nesting: Core lives inside SaveSystem, which lives inside Scripts. The full path to Core is Scripts.SaveSystem.Core.

Inline modules — you can also declare a small module right in a file with braces:

# An inline module grouping math helpers in one named box.
MathHelpers<public> := module {}

Either way, the module is a namespace: a box that holds names (functions, classes, constants) and keeps them from colliding with names in other boxes.

Accessing module contents: using vs. qualified names

Once a module exists, there are two ways to reach what's inside.

1. Open it with using — then write its names bare:

using { Verse.Scripts.Utils }   # open the Utils module

# now Format (a public function inside Utils) is available unqualified
Label := Format("Score", Points)

2. Qualify the name — write the path inline without a using. The digest does this constantly to disambiguate:

# Fully-qualified call — no using needed, path written inline.
Color := (/Verse.org/Colors:)MakeColorFromHex("FF8800")

Use using for modules you touch a lot (cleaner), and qualified names when you reference something once or need to disambiguate two same-named things from different modules.

Scoping: <public> vs. <internal>

This is the part that trips people up, and it's the reason modules are more than just folders. Each name in a module carries an access specifier — the same angle-bracket syntax as effect labels — that controls who can see it:

  • <public> — visible to code outside the module. This is the module's published surface.
  • <internal> — visible only within the same module (and its submodules). A private helper.
  • <protected> / <private> — finer-grained, mainly for class members (private = only this class; protected = this class and subclasses).
# A module that exposes one function and hides its helper.
ScoreUtils<public> := module:

    # Published — other systems may call this.
    FormatScore<public>(Points : int) : string =
        "Score: {PadNumber(Points)}"

    # Internal — only ScoreUtils itself can use this. Outsiders can't see it.
    PadNumber<internal>(N : int) : string =
        if (N < 10) then "00{N}" else "{N}"

From another system, ScoreUtils.FormatScore(...) works after using { ScoreUtils }, but PadNumber is invisible — it's an implementation detail. This is the same instinct as keeping classes focused: expose the smallest surface that does the job, and hide the rest. Our permissions.verse uses exactly this — most systems are <public> so games can use them, while Unused<internal> stays hidden.

The default matters: if you don't write an access specifier, a member is more restricted than <public> — so to share something across modules you must explicitly mark it <public>. Forgetting that is the #1 module mistake (covered below).

A worked example: a small shared utility module

Putting it together — a focused Utils module with a public helper, opened from a device:

# --- file: Games/MyGame/banner_device.verse ---
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

banner_device := class(creative_device):

    OnBegin<override>()<suspends> : void =
        Line := "===================="
        Print(Line)```

One module owns the helper; the device opens it with `using` and calls it unqualified. If `Repeat` weren't marked `<public>`, the device couldn't see it — the compiler would say the name is unknown.

## Naming and layout conventions

Our project organizes each system as a folder-module with a consistent file pattern (from the project conventions): `_module.verse` (shared functions), `_data.verse` (data structures), `_config.verse` (configuration), `_controller.verse` (the `creative_device`). A system is **self-contained**: it exposes a public surface and keeps its internals private. Following a predictable layout means anyone — human or AI helper — can find the right file by name.

## The pitfalls — what trips people up

<!-- section-art:the-pitfalls-what-trips-people-up -->
![Modules: Organizing and Sharing Verse Code: The pitfalls — what trips people up](/static/lesson-sections/verse-modules--the-pitfalls-what-trips-people-up.png)

*Module Pitfalls*


**1. Forgetting `<public>`.** A function or class with no access specifier is **not** automatically visible across modules. You `using` the module, the name still isn't found, and it's baffling — until you realize you never marked it `<public>`. To share, you must say so.

**2. Confusing `using` with importing the file.** `using` opens a *module* (a namespace), not a file. The folder structure defines the module path; `using { Verse.Scripts.Utils }` opens the `Utils` folder-module, regardless of how many files are in it.

**3. Wrong module path.** `using { Utils }` vs `using { Verse.Scripts.Utils }` — the path must match the actual nesting. If `Utils` is nested under `Scripts`, you generally need the qualified path (or a `using` of the parent). A path that doesn't match the folder tree won't resolve.

**4. Over-exposing internals.** Marking every helper `<public>` turns your module into a tangle that other systems start depending on, so you can't change it later. Publish the minimum; keep helpers `<internal>`. This is single-responsibility at the module level.

**5. Circular `using`.** Two modules that each `using` the other create a dependency cycle. Keep dependencies flowing one direction (e.g. games depend on systems, not the reverse), as the project's layered structure does.

**6. Treating Epic paths and project paths as different mechanisms.** They're the same: `/Fortnite.com/Devices` and `Verse.Scripts.Utils` are both module paths opened by `using`. Epic's just start with a slash (absolute, from the engine root).

## Recap

- A **module** is a named container (namespace) for related code; `:= module` declares one, as a **folder module** or an **inline** `module {}`.
- **`using`** opens a module so you can write its names unqualified — the same idea for Epic's APIs (`/Fortnite.com/Devices`) and your own systems (`Verse.Scripts.Utils`). You can also write **qualified names** inline.
- **`<public>`** publishes a name across modules; **`<internal>`** keeps it private to the module. No specifier means *not* public — you must explicitly mark what you share.
- Expose the **smallest public surface** and hide the rest; lay systems out predictably (`_module`/`_data`/`_config`/`_controller`).
- Watch for the classics: forgetting `<public>`, wrong module paths, over-exposing internals, and circular dependencies.

## References

- [Verse Language Reference (Epic)](https://dev.epicgames.com/documentation/en-us/uefn/verse-language-reference)
- [Modules and paths in Verse (Epic)](https://dev.epicgames.com/documentation/en-us/uefn/modules-and-paths-in-verse)
- [Access specifiers in Verse (Epic)](https://dev.epicgames.com/documentation/en-us/uefn/access-specifiers-in-verse)
- Grounded in the Verse Cortex knowledge base: real corpus `permissions.verse` (folder-module tree with `<public>`/`<internal>`), corpus `using` lines (`/Fortnite.com/Devices`, `/Verse.org/Simulation`, `Verse.Scripts.Utils`, `SaveSystem`), the digest's qualified-name calls, and project conventions (CityOfBrains module layout: `_module`/`_data`/`_config`/`_controller`).

Get the complete code — free

You've read the full walkthrough. The complete, copy-paste-ready Verse solution is free for members — sign in to unlock it.

Free with your BrainDead.TV / BrainDeadGuild Discord account. The walkthrough above is always free.

Check your understanding

Test yourself with an interactive quiz and track your progress + earn XP — free for members.

Turn this into a guided course

Add Verse modules — folder vs inline modules, namespaces and paths, the using statement, qualified names, and access specifiers (<public> / <internal> / scoping) to your free study plan — we'll suggest related pages and stitch the lot into one compile-checked, self-guided lesson with worked examples and quizzes.

Original tutorial generated by Verse Island from the Verse/UEFN knowledge base, with references to the Epic Games sources above. Code is validated against the knowledge base.

Comments

    Sign in to vote, comment, or suggest an edit.Sign in