Getting Started with Selene Bundles

Learn how to create, structure, and package bundles for the Selene engine using the example bundles in this repository.

Getting Started with Selene Bundles

This guide walks you through creating your first Selene bundle: what a bundle is, the recommended directory layout, and how to declare your bundle metadata in bundle.json. It draws from the example bundles in this repository under bundles/:

  • bundles/illarion-gobaith-data/
  • bundles/illarion-gobaith-ui/
  • bundles/moonlight-inventory/

What is a Selene bundle?

A Selene bundle is a self-contained package of logic and/or data that the Selene engine can load. Bundles can provide:

  • Data definitions (for tiles, entities, items, etc.)
  • Client UI logic and behaviors
  • Server-side game logic
  • Shared/common Lua modules

Each bundle lives in its own directory and is described by a bundle.json file at its root.

Minimal bundle

The smallest possible bundle needs only a bundle.json with a unique name and description:

{
  "name": "moonlight-inventory",
  "description": "Basic implementation for slot-based inventories."
}

Place this file in your bundle directory, for example bundles/my-first-bundle/bundle.json.

Directory layout

Bundles commonly organize content into client/, server/, and common/ to clarify runtime ownership and to keep resources discoverable:

  • client/ – Code and data used by the client (e.g., UI, input handling, visuals)
  • server/ – Code and data used by the server (e.g., NPCs, quests, spawns)
  • common/ – Code and data shared between client and server

Within those, you’ll often see:

  • lua/ – Lua modules and scripts
  • data/ – Static JSON data files consumed by systems

Examples from this repo:

  • bundles/illarion-gobaith-ui/client/lua/
  • bundles/illarion-gobaith-data/common/lua/
  • bundles/illarion-gobaith-data/server/data/

You can also include a README.md and LICENSE at the root of your bundle for documentation and licensing.

Declaring entrypoints

If your bundle includes executable logic (Lua modules to load on startup), list them in the entrypoints array in bundle.json.

  • Paths are relative to the bundle root
  • They are typically Lua files located under client/lua/ or common/lua/
  • Data-only bundles can omit entrypoints

Examples:

Data bundle with a single shared entrypoint:

{
  "name": "illarion-gobaith-data",
  "description": "Data definitions for Illarion as a Selene bundle.",
  "entrypoints": [
    "common/lua/grid.lua"
  ]
}

Client UI bundle with multiple entrypoints:

{
  "name": "illarion-gobaith-ui",
  "description": "Illarion UI based on Gobaith era.",
  "entrypoints": [
    "client/lua/viewport.lua",
    "client/lua/cursor.lua",
    "client/lua/input.lua",
    "client/lua/ui.lua"
  ]
}

Data-only bundle without entrypoints:

{
  "name": "moonlight-inventory",
  "description": "Basic implementation for slot-based inventories."
}

Common file types

  • JSON under data/ – Structured data used by Selene systems, e.g.:
    • bundles/illarion-gobaith-data/common/data/tiles.json
    • bundles/illarion-gobaith-data/server/data/items.json
  • Lua under lua/ – Logic modules and scripts, e.g.:
    • bundles/illarion-gobaith-ui/client/lua/input.lua
    • bundles/illarion-gobaith-data/common/lua/grid.lua

Note: The specific shape of JSON files is determined by the systems that consume them (tiles, entities, skills, etc.). Use existing examples as templates and keep paths consistent.

Creating your own bundle

  1. Create the directory
  • Choose a unique, URL-safe name
  • Create a folder under bundles/, e.g. bundles/my-bundle/
  1. Add bundle.json
  • Start with name and description
  • Add entrypoints only if you have Lua modules to load
  1. Add code and data
  • Place shared modules under common/lua/
  • Place client-only modules under client/lua/
  • Place server-only modules under server/lua/
  • Put static data under */data/ next to where it is consumed
  1. Document and license
  • Add a README.md describing what your bundle provides and any external dependencies
  • Add a LICENSE if you plan to distribute it
  1. Validate your layout
  • Ensure every path in entrypoints exists and is correct relative to the bundle root
  • Keep JSON valid; run a linter/formatter if available

Referencing external assets

Some bundles may rely on external graphics or asset bundles. For example, illarion-gobaith-data notes that it depends on a separate asset bundle for visuals and does not embed restricted assets. If you reference external assets:

  • Document the dependency in your README.md
  • Avoid redistributing licensed assets unless permitted

Tips and conventions

  • Use lowercase, hyphenated bundle names (e.g., my-feature-pack)
  • Keep entrypoints minimal: load a top-level module that in turn requires other modules
  • Co-locate data with the runtime that consumes it (server/data/ for server-side systems, etc.)
  • Prefer deterministic file names and folder structures for discoverability

Troubleshooting

  • A module does not load: double-check the entrypoints path and module syntax
  • Data not applied: ensure the JSON structure matches what the consuming system expects
  • Asset missing: verify the asset bundle or path is available and correctly referenced

Examples to study

  • Data-centric bundle: bundles/illarion-gobaith-data/
  • Client UI bundle: bundles/illarion-gobaith-ui/
  • Minimal bundle: bundles/moonlight-inventory/

Open these bundles to copy patterns for your own. Start small, add a single entrypoint if needed, and grow from there.