To_Upload_By_User/
Add developer products to your asset template

How to add developer products to your asset template

This guide shows how to package developer products so SuperbulletAI can guide users to create them and wire the correct asset IDs automatically.

Why re-upload is required

Due to Roblox platform permissions, developer products must be created by the experience creator (you or your group). Even if developer product metadata is included in a template, the actual product must be created under your account or group to be usable in your game.

Prerequisite: connect the SuperbulletAI plugin and server

For the assets to appear under ReplicatedStorage/To_Upload_By_User/DevProducts in Studio, ensure the SuperbulletAI Plugin is installed and connected to the local SuperbulletAI server.

  • Open the SuperbulletAI application to start the local server.
  • In Roblox Studio, enable the SuperbulletAI plugin and confirm it shows as connected.
  • If disconnected, the To_Upload_By_User/DevProducts folder may not appear and validation will not work.

What you need to include in your zip

Place developer product icon images (.png or .jpg) under the required folder. Each image will be used as the icon for a developer product the user creates.

TemplateSystem.zip
└─ To_Upload_By_User/
   └─ DevProducts/
      ├─ 100_coins_icon.png
      ├─ 500_coins_icon.png
      └─ extra_life_icon.jpg

Notes:

  • Use .png or .jpg format for icons.
  • Recommended icon size: 150x150 pixels (Roblox standard).
  • Do not add scripts or extra folders here.
  • If you include icon files, you must reference them via icon_path inside superbullet_metadata.json.

Where these appear in Roblox Studio

When the template is opened in Studio, these will appear at:

ReplicatedStorage/To_Upload_By_User/DevProducts

You'll see each icon image ready to be used when creating developer products.

Warning: If the SuperbulletAI plugin is not connected to the local SuperbulletAI server, this folder may not appear and developer products cannot be validated. Open the SuperbulletAI application to start the server and reconnect the plugin in Studio.

How users create developer products (Roblox steps)

For each developer product defined in the template:

  1. Go to the Roblox Creator Dashboard.
  2. Select your experience.
  3. Navigate to Monetization → Developer Products.
  4. Click "Create a Developer Product".
  5. Upload the icon from To_Upload_By_User/DevProducts/.
  6. Set the name and description as suggested in the template.
  7. Set the price (can differ from suggested price).
  8. Save and note the Developer Product ID.

Important: Developer products must be created under the same account or group that owns the experience.

How SuperbulletAI uses the IDs

During extraction, SuperbulletAI detects entries in To_Upload_By_User/DevProducts and prompts for the newly created Developer Product IDs. The importer blocks progress until valid IDs are provided.

On save, the app writes a mapping (Lua or JSON) the systems can consume, for example:

-- ReplicatedStorage/SharedSource/Datas/AssetIds.lua
return {
  DevProducts = {
    Coins_100 = "111222333",
    Coins_500 = "444555666",
    ExtraLife = "777888999"
  }
}

How replacements are determined (path + placeholders)

  • Source file path: Pre-extraction. Start at the service root (e.g., ReplicatedStorage/SharedSource/... or ServerScriptService/Server/...). The Unpack_On_Source/ root is implied; do not include it.
  • Placeholder pattern: Use unique, collision-resistant tokens like [===[DEVPRODUCT_100_COINS]===] inside text files (Lua/JSON/etc.).
  • Key matching: The placeholder name (e.g., DEVPRODUCT_100_COINS) should match the developer product key shown in the Assets Modal.
  • Replacement value: Each [===[<Key>]===] is replaced with the Developer Product ID number only (e.g., 111222333), not including rbxassetid:// prefix.

Note: Unlike animations and sounds which use rbxassetid:// URLs, developer products use numeric IDs directly.

Example (inline placeholder in Lua):

-- Before
local COINS_100_PRODUCT_ID = "[===[DEVPRODUCT_100_COINS]===]"
 
-- After providing IDs (DEVPRODUCT_100_COINS => 111222333)
local COINS_100_PRODUCT_ID = "111222333"

superbullet_metadata.json (token-to-file mapping)

Add a mapping file at To_Upload_By_User/DevProducts/superbullet_metadata.json so the importer knows which developer product icon to use and where to replace placeholder tokens. There are two methods for specifying replacements:

Method 1: Primary (token-based) — Replaces in Lua source files

Use this method when you want the developer product ID inserted directly into your Lua code automatically.

FieldRequiredDescription
icon_pathNoPath from zip root to the icon file (if bundling an icon)
source_pathYesPath to the Lua file containing the token
tokenYesExact placeholder string to replace in the Lua file
display_nameYesName shown in Assets Modal and suggested for product creation
descriptionYesSuggested description for the developer product
suggested_priceYesSuggested Robux price for the developer product
[
  {
    "token": "[===[DEVPRODUCT_100_COINS]===]",
    "display_name": "100 Coins",
    "description": "Purchase 100 coins to spend in-game",
    "suggested_price": 10,
    "icon_path": "To_Upload_By_User/DevProducts/100_coins_icon.png",
    "source_path": "ReplicatedStorage/SharedSource/Datas/ProductData.lua"
  },
  {
    "token": "[===[DEVPRODUCT_500_COINS]===]",
    "display_name": "500 Coins",
    "description": "Purchase 500 coins to spend in-game (best value!)",
    "suggested_price": 40,
    "icon_path": "To_Upload_By_User/DevProducts/500_coins_icon.png",
    "source_path": "ReplicatedStorage/SharedSource/Datas/ProductData.lua"
  }
]

Method 2: Fallback (instruction_token) — Replaces in Instructions.md

Use this method when you want the developer product ID communicated via instructions instead of automatic code insertion. The user will see the replaced IDs in the chat instructions and can manually copy them where needed.

FieldRequiredDescription
icon_pathNoPath from zip root to the icon file (if bundling an icon)
instruction_tokenYesPlaceholder string to replace in Instructions.md
display_nameYesName shown in Assets Modal and suggested for product creation
descriptionYesSuggested description for the developer product
suggested_priceYesSuggested Robux price for the developer product
tokenMust be absentIf present, primary method is used instead
source_pathNoNot needed (targets Instructions.md, not a Lua file)
[
  {
    "instruction_token": "{{DEVPRODUCT_100_COINS}}",
    "display_name": "100 Coins",
    "description": "Purchase 100 coins to spend in-game",
    "suggested_price": 10,
    "icon_path": "To_Upload_By_User/DevProducts/100_coins_icon.png"
  },
  {
    "instruction_token": "{{DEVPRODUCT_500_COINS}}",
    "display_name": "500 Coins",
    "description": "Purchase 500 coins to spend in-game (best value!)",
    "suggested_price": 40,
    "icon_path": "To_Upload_By_User/DevProducts/500_coins_icon.png"
  }
]

Instructions.md example (before upload):

After creating developer products, configure your code:
- 100 Coins Product ID: {{DEVPRODUCT_100_COINS}}
- 500 Coins Product ID: {{DEVPRODUCT_500_COINS}}

Instructions.md sent to chat (after upload):

After creating developer products, configure your code:
- 100 Coins Product ID: 111222333
- 500 Coins Product ID: 444555666

When to use each method

Use CaseMethod
Product ID needs to be inserted directly into Lua codePrimary (token)
Template creator has control over the Lua source filesPrimary (token)
Automatic code integration is desiredPrimary (token)
Product ID should be communicated via instructionsFallback (instruction_token)
User will manually copy the ID into their codeFallback (instruction_token)
Template doesn't have a specific Lua file to modifyFallback (instruction_token)

Rules for primary method (token)

  • icon_path (optional): Full path from the zip root to the icon file to use, including the leading To_Upload_By_User/DevProducts/ folder. Use forward slashes. Examples: To_Upload_By_User/DevProducts/100_coins_icon.png, To_Upload_By_User/DevProducts/Currency/500_coins.jpg. If omitted, users will need to create their own icon.
  • Use source_path as a pre-extraction path starting at the Roblox service root (e.g., ReplicatedStorage/, ServerScriptService/), using forward slashes. The Unpack_On_Source/ root is implied; do not include it.
  • The token is the exact placeholder string to replace. It must appear verbatim in the target file.
  • Provide one entry per placeholder occurrence you want replaced.
  • Do not include the token string anywhere in the source_path or its folders/filename. Tokens must appear only inside file contents, never in paths.

If the token is not found in the specified file, validation will fail and you'll be prompted to fix the path or the token.

Rules for fallback method (instruction_token)

  • icon_path (optional): Full path from the zip root to the icon file. If omitted, users will need to create their own icon.
  • instruction_token (required): The exact placeholder string to find and replace in Instructions.md. Use a distinctive format like {{DEVPRODUCT_NAME}} to avoid accidental matches.
  • display_name (required): The name shown in the Assets Modal and suggested for product creation.
  • description (required): The suggested description for the developer product.
  • suggested_price (required): The suggested Robux price.
  • Do not include a token field — its presence activates the primary method instead.
  • The instruction_token placeholder must exist in your Instructions.md file.

Best practices

  • Store developer product IDs in a centralized source file (for example ReplicatedStorage/SharedSource/Datas/AssetIds.lua) and reference them from code.
  • Use descriptive token names that clearly indicate what the product provides (e.g., DEVPRODUCT_100_COINS, DEVPRODUCT_EXTRA_LIFE).
  • Provide clear descriptions that explain what the player receives.
  • Set reasonable suggested prices based on the product value.
  • Developer products can be purchased multiple times (unlike gamepasses), so design them accordingly.

Example (processing developer product purchases):

local MarketplaceService = game:GetService("MarketplaceService")
local AssetIds = require(ReplicatedStorage.SharedSource.Datas.AssetIds)
 
MarketplaceService.ProcessReceipt = function(receiptInfo)
  local player = game.Players:GetPlayerByUserId(receiptInfo.PlayerId)
  if not player then return Enum.ProductPurchaseDecision.NotProcessedYet end
 
  local productId = receiptInfo.ProductId
 
  if productId == tonumber(AssetIds.DevProducts.Coins_100) then
    -- Grant 100 coins to player
    grantCoins(player, 100)
  elseif productId == tonumber(AssetIds.DevProducts.Coins_500) then
    -- Grant 500 coins to player
    grantCoins(player, 500)
  end
 
  return Enum.ProductPurchaseDecision.PurchaseGranted
end

Checklist

  • Each developer product has an icon image (.png or .jpg).
  • Icon files live under To_Upload_By_User/DevProducts/.
  • You create each developer product in the Roblox Creator Dashboard.
  • Provide the resulting developer product IDs when prompted by SuperbulletAI.
  • Each metadata entry optionally includes icon_path pointing to the icon file (full path from zip root).
  • Each metadata entry includes display_name, description, and suggested_price.