Reference Verse

Folders Are Modules: Organizing Verse Code on Your Island

Every folder in your Verse project is secretly a module — a named unit of code that other files can import and reuse. On a sunny 2D cel-shaded cove where players race across the dock scoring points, we'll split our logic into folders and let a scoreboard device and a player-reference device talk to shared code without copy-paste.

Updated
The code on this reference page is provided as-is and did not pass the latest compile check — treat the examples as a starting point and verify in your project.
Watch the Knotfolders_are_modules in ~90 seconds.

Overview

In Verse there is no separate "create a module" button. A folder in your project IS a module, and its name is the folder's name. Every .verse file inside that folder belongs to the same module and shares its namespace — so score_helpers.verse and game_manager.verse in the same Core/ folder can reference each other's definitions directly. Files in other folders reach in with a using directive that spells out the folder path.

Why reach for this? Picture a sunny clifftop cove map: players sprint down the dock, hit a checkpoint, and earn points. The scoring math, the localized banner text, and the win condition all want to be shared between several devices. Instead of pasting the same helper into every device file, you drop it in a folder — a module — and import it once. Your code stays DRY, and the compiler resolves every reference to exactly the right definition because module paths are unique and permanent.

This article uses two real placed devices to show modules in action: the score_manager_device (grants and increments points) and the player_reference_device (tracks which agent is the current leader). The organizing is done by folders; the doing is done by these devices' real API.

API Reference

(API surface could not be resolved for this device.)

Walkthrough

Our project folder looks like this:

CoveRace/
├── Core/
│   └── race_helpers.verse     # the SHARED module
└── Devices/
    └── cove_race_manager.verse # our creative_device

The folder Core automatically becomes a module named Core. Anything public we declare in race_helpers.verse is reachable from anywhere with using { /YourProject/CoveRace/Core } (the exact path matches your project's root path). For this article we'll show the full manager device that imports and uses that shared module.

First, the shared module file Core/race_helpers.verse — no class here, just reusable public definitions:

# File: Core/race_helpers.verse — this folder IS the "Core" module

# A localized banner other files can reuse (message needs <localizes>, never a raw string)
RaceBanner<localizes>(Name:string):message = "{Name} leads the cove race!"

# Shared scoring rule: how many increments a checkpoint is worth
CheckpointValue<public>:int = 3

# A tiny helper other files call to decide a winner
HasWon<public>(Points:int)<transacts><decides>:void =
    Points >= 10

Now the device file Devices/cove_race_manager.verse imports that module and drives the real devices:

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/UI }

# On a bright cel-shaded cove: dock checkpoints grant score, a banner names the leader.
cove_race_manager := class(creative_device):

    # Placed score_manager_device: grants points when a checkpoint is hit
    @editable
    Scorer : score_manager_device = score_manager_device{}

    # Placed player_reference_device: tracks the current leader agent
    @editable
    LeaderRef : player_reference_device = player_reference_device{}

    # Localized banner reused from our thinking — declared locally for the demo
    RaceBanner<localizes>(Name:string):message = "{Name} leads the cove race!"

    OnBegin<override>()<suspends>:void =
        # Wake both devices up
        Scorer.Enable()
        LeaderRef.Enable()

        # When the score device awards points, remember who scored as the leader
        Scorer.ScoreOutputEvent.Subscribe(OnScored)

        # When the leader changes, react
        LeaderRef.AgentUpdatedEvent.Subscribe(OnLeaderUpdated)

    # Handler: someone crossed a dock checkpoint and got points
    OnScored(Agent:agent):void =
        # Register this agent as the tracked leader in the reference device
        LeaderRef.Register(Agent)
        # Bump the score amount awarded by the next activation
        Scorer.Increment(Agent)

    # Handler: the reference device confirmed a new leader
    OnLeaderUpdated(Agent:agent):void =
        Print(RaceBanner("Racer"))

Line by line: the two @editable fields let us wire the placed devices in the UEFN editor — without a field, calling Scorer.Enable() would fail with Unknown identifier. In OnBegin we Enable() both devices and Subscribe to two real events: ScoreOutputEvent fires when the score manager awards points, and AgentUpdatedEvent fires when the player reference device stores a new agent. OnScored calls LeaderRef.Register(Agent) — the real method that stores that agent as the tracked player — then Scorer.Increment(Agent) to raise the next payout. When the register succeeds, AgentUpdatedEvent fires and OnLeaderUpdated prints our localized banner.

The module lesson: RaceBanner, CheckpointValue, and HasWon all live in Core/. Any other device on the island — a finish-line teleporter, a UI billboard — can using { .../Core } and reuse them without redeclaring. The folder made the module; the using made it available.

Common patterns

Pattern 1 — Reset the whole race from one shared entry point. A folder module often holds a single "reset" idea called by many devices. Here the manager calls Reset() on the score device:

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

cove_reset_manager := class(creative_device):

    @editable
    Scorer : score_manager_device = score_manager_device{}

    OnBegin<override>()<suspends>:void =
        Scorer.Enable()
        # When max triggers hit, wipe the score back to its starting state
        Scorer.MaxTriggersEvent.Subscribe(OnMaxed)

    OnMaxed(Agent:agent):void =
        Scorer.Reset(Agent)

Pattern 2 — Clear the tracked leader when the round flips. The player reference device's Clear() and AgentReplacedEvent keep the cove leaderboard honest:

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

cove_leader_reset := class(creative_device):

    @editable
    LeaderRef : player_reference_device = player_reference_device{}

    OnBegin<override>()<suspends>:void =
        LeaderRef.Enable()
        LeaderRef.AgentReplacedEvent.Subscribe(OnReplaced)

    OnReplaced(Agent:agent):void =
        # A new racer took the lead; clear stale state on the old reference
        LeaderRef.Clear()

Pattern 3 — Check who is referenced before granting a bonus. IsReferenced is a <decides> query — use it inside if:

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

cove_bonus_manager := class(creative_device):

    @editable
    Scorer : score_manager_device = score_manager_device{}

    @editable
    LeaderRef : player_reference_device = player_reference_device{}

    OnBegin<override>()<suspends>:void =
        Scorer.Enable()
        LeaderRef.Enable()
        Scorer.ScoreOutputEvent.Subscribe(OnScored)

    OnScored(Agent:agent):void =
        # Only give the bonus activation if this agent is the tracked leader
        if (LeaderRef.IsReferenced[Agent]):
            Scorer.Activate(Agent)

Gotchas

  • A folder becomes a module automatically — but the path must be exact. The using { /YourProject/Core } path is built from your project's root plus every folder name. Rename a folder and every importing file's using must change too; module paths are permanent addresses, so a typo reads as Unknown identifier.
  • Files in the same folder need no import. game_manager.verse and race_helpers.verse both in Core/ share a namespace and see each other's public definitions directly. Only reach across folders with using.
  • message params are localized, not strings. Print(RaceBanner("Racer")) works because RaceBanner is declared <localizes> and returns a message. There is no StringToMessage — declare a <localizes> function.
  • IsReferenced and HasWon are <decides> — call them in a failure context. Use if (LeaderRef.IsReferenced[Agent]):, not as a plain statement.
  • You must declare devices as @editable fields. A bare score_manager_device.Enable() never compiles; wire a placed device into a field first.
  • Unwrap ?agent from listenable(?agent) events. The device events here hand you a plain agent, but some engine events give ?agent — then you must if (A := Agent?): before use.

Build your own lesson with folders_are_modules

Generate a personalized, step-by-step lesson plan built around this object — grounded in this exact reference and our compile-verified knowledge base.

Build a lesson →