Extensions
What extensions are

Extensions

An extension is a package that plugs into — and requires — one or more existing base systems. It cannot run on its own. Instead of shipping its own engine, it drops content into base systems that are already installed.

  • Base system: a standalone, feature-complete system that ships an engine plus a registry or dispatch layer that auto-discovers content (e.g., Skill System, DevProducts Handler, Combat System).
  • Extension: a smaller package that adds entries into those base systems.

An extension is not a special package type — in the marketplace it's still a normal system/library. What makes it an extension is two things working together:

  1. It declares its base system(s) as required dependencies in relevant_systems.json (always_on: true).
  2. Its files and Instructions.md register its content into those base systems rather than standing alone.

Note: extensions go by different names in different systems' docs (the DevProducts Handler calls its shop extensions "Connected Shop Libraries"). "Extension" is the umbrella term for all of them.

Walkthroughs by system family

Different base systems expose different extension points, so each family has its own concrete, end-to-end walkthrough. This page covers the shared contract; pick the family that matches what you're building:

WalkthroughExtension → baseWhat's distinctive
Skill extensionFireball Skill → Skill SystemRegistry entry via Instructions.md, drop-in modules, VFX, animation upload
Shop extensionCash Pack Shop → DevProducts HandlerMultiple required deps, drop-in shop section + product set, dev-product upload
Combat extensionMelee System → Combat SystemRequired and optional deps, drop-in moveset, animation upload

The rest of this page is the contract every extension follows.

Step 1 — Declare required (and optional) systems

Use relevant_systems.json at the zip root. Mark every system your extension needs with always_on: true; mark systems that merely enhance it with always_on: false. The installer pulls required systems in first if missing, and offers optional ones as unchecked choices.

Melee System shows both in one file — Combat System and DamageHandler are required, NPC System is optional:

[
  {
    "display_name": "Combat System",
    "unique_id": "144835c0-4f96-43ea-8707-8429b4f99b22",
    "always_on": true,
    "isInitiallyChecked": true
  },
  {
    "display_name": "DamageHandler",
    "unique_id": "ca59f635-993a-4741-8c81-c9f7370fbf48",
    "always_on": true,
    "isInitiallyChecked": true
  },
  {
    "display_name": "NPC System",
    "unique_id": "07473040-45dc-4afa-bb24-462e187d10ee",
    "always_on": false,
    "isInitiallyChecked": false
  }
]

Rules:

  • List every system your extension needs to function — not just the obvious one.
  • always_on: true → hard requirement, can't be unchecked. always_on: false → optional; use isInitiallyChecked to decide if it's pre-selected.
  • Use the real unique_id from the marketplace registry — never a path or download URL.
  • Dependencies chain automatically: a base system's own relevant_systems.json may be [] (standalone, like DevProducts Handler) or may list its dependencies (Combat System requires DamageHandler + NPC System).

See the relevant_systems.json page for the full contract.

Step 2 — Ship drop-in files into the base's extension points

Base systems expose folders they auto-discover. Put your extension's files there under the normal service-folder layout in Unpack_On_Source/, using unique names so extensions don't collide — that's what lets many extensions live in the same folder without editing each other.

Each family uses different extension-point folders (Skills/…, DevProductSets/, Shop/Sections/, Combat/…) — see the walkthroughs for the exact paths.

Binary assets destined for the DataModel (UI, VFX, models) go in Unpack_On_Roblox_Studio/, mirroring the base's asset hierarchy, one .rbxm per instance. A package may include an unpack_on_roblox_studio_meta.json manifest describing those exports. Folder rules are identical to any system — see How to add a template asset.

Step 3 — Register via Instructions.md

Drop-in files cover new, non-conflicting files. When an extension must add an entry to a shared file that may already exist (and may be shared with other extensions), do it in Instructions.md so the AI edits it idempotently ("if the file exists, add the entry; if not, create it").

Write instructions that state the required base system up front, give exact paths and concrete values, and spell out any required edits to shared files (e.g., ProfileTemplate.lua). See the Instruction Runner section in How to add a template asset.

Step 4 — Wire user-uploaded asset IDs with tokens

If your extension references assets the user must create under their own account (dev products, gamepasses, animations, sounds), ship them under To_Upload_By_User/ with a superbullet_metadata.json mapping a placeholder token to the real ID.

Two methods:

  • Primary (token + source_path) — the token is replaced in-place inside a Lua source file. Used by Cash Pack Shop (dev products) and Melee System (animations).
  • Fallback (instruction_token) — the real ID is surfaced through Instructions.md instead of a Lua file. Used by Fireball Skill (animation).

For the full contract and when to use each, see the dedicated pages: Developer products, Gamepasses, Animations, and Sounds.

metadata.json

Same file as any system. Real extensions fill in name and description too, not just version:

{
  "name": "Melee System",
  "description": "Melee combat with punches and kicks...",
  "version_number": "1.0.3",
  "created_by": "Superbullet"
}
  • Bump version_number (semantic versioning) on every re-upload so the extension updates for everyone.
  • If the extension relies on behavior added in a specific base-system version, say so in Instructions.md. always_on guarantees the base is installed, not that it's a particular version.

Shared checklist

  • relevant_systems.json lists every required system with always_on: true and a valid unique_id; optional systems use always_on: false.
  • Drop-in source files use unique names and live in the folders the base system auto-discovers.
  • Instructions.md registers into shared files idempotently, with exact paths and concrete values.
  • Any user-uploaded assets have a To_Upload_By_User/**/superbullet_metadata.json with correct token/source_path (or instruction_token).
  • Binary DataModel assets are in Unpack_On_Roblox_Studio/; .rbxm filenames match instance names; no scripts there.
  • metadata.json has name, description, and a bumped semantic version_number.