Skip to content

Choose your mod type#

Pick the smallest approach that fits your goal. You can combine types in one package later.

Quick picker#

You want to... Start here Needs mod.json?
Change colors or post-processing Shader mod Optional (per-mod shaders yes, mods/shaders/ no)
Replace a model, texture, or room file Asset modding Yes
Run logic when the game calls a function Create your first mod Yes
Show a menu or overlay in-game Build a CReact mod Yes
Swap dialogue or sign text at runtime Courage.Bmg Yes
Persist settings per player Petrichor.Storage Yes

Visual-only: shaders#

  • Put .hlsl under mods/<id>/assets/ or drop files in mods/shaders/
  • Toggle from Luau with Courage.Shaders or from the dev Shader Mod Loader
  • Read Shader guides and try the playground

Asset replacements#

  • Path pattern: mods/<mod-id>/res/<path-on-disc>
  • Master Sword: mods/my-master-sword/res/Object/Alink.arc/bmwe/al_swm.bmd
  • Lakebed Temple room 10: mods/my-lakebed-fix/res/Stage/D_MN01/R10_00.arc/dzr/room.dzr
  • Ship your own converted files. Do not redistribute Nintendo originals.

Scripted: Luau hooks#

UI: CReact panels#

  • TSX under creact/, compile to panel.bundle.js and/or popup.bundle.js with Bun
  • Luau opens a menu panel with Courage.UI.show(modId) or an in-game popup with UI.showPopup(modId). Pass state with UI.setState.
  • Panel actions return to Luau through Petrichor.Events

Start with Build a CReact mod or the Cat Companion walkthrough in User Interfaces with CReact.

Mixed package#

A single folder can include several layers:

my-mod/
├── mod.json
├── main.luau
├── assets/
│   ├── my_effect.hlsl
│   └── overrides/res/something.bti   # optional custom asset
└── creact/
    └── creact/
        ├── panel.bundle.js   (menu panel, optional)
        └── popup.bundle.js   (in-game overlay, optional)

Set "kind": "mixed" in mod.json when you publish. See Publishing a mod.

Next steps#