Get started
Configuration
The config files, what each one controls, and the IDs to fill in before launch.
Most of what you'll change lives in these seven files, plus the DEMO flag. Each system page covers its own settings in detail; this page is the map.
| File | Controls |
|---|---|
src/shared/Config.ts |
Currencies, products, gamepasses, multiplier sources, rebirth, event multipliers, boosts, items, variants, inventory, the index, group, friend and invite rewards, daily and playtime rewards, onboarding steps, leaderboard, admins, audio, DataStore names, trading |
src/shared/EggsConfig.ts |
EGGS |
src/shared/WheelConfig.ts |
WHEEL |
src/shared/QuestsConfig.ts |
QUEST_BOARDS, ACHIEVEMENTS |
src/shared/SeasonConfig.ts |
SEASON_PASS, SEASONS |
src/server/CodesConfig.ts |
CODES |
src/client/Theme.ts |
Every color, font, size and animation timing in the UI |
DEMO at the end of Config.ts turns the demo hub on or off: DEMO = { enabled: true }. Set enabled to false for a game that doesn't want the hub, or delete the demo folders (see Project layout).
Everything under src/shared/ is replicated, so players can read it. Promo codes are in src/server/CodesConfig.ts for that reason.
IDs of 0 mean "not set up yet"
Product, pass, badge and group IDs all start at 0. An entry with ID 0 is hidden in the UI and ignored by the server, so the game runs before you've made anything on the Creator Dashboard. From the top of Config.ts:
/**
* IDs come from the Creator Dashboard (create.roblox.com > your experience >
* Monetization). An ID of 0 means "not set up yet": that product or pass is
* hidden in the shop and ignored by the server.
The define helper
Most config tables are written with define<T>(), which checks each entry against one shape and keeps the table's own keys as a type:
export function define<D>() {
return <K extends string>(entries: Record<K, D>): Record<K, D> => entries;
}
export const CURRENCIES = define<CurrencyDefinition>()({
coins: { name: "Coins", startingAmount: 100, soldForRobux: true },
gems: { name: "Gems", startingAmount: 0, soldForRobux: false },
});
export type CurrencyKey = keyof typeof CURRENCIES;
So after you add tokens to CURRENCIES, "tokens" is a valid CurrencyKey everywhere, and a typo like "token" is a compile error.
Checks at startup
Some config mistakes stop the server at startup with an error message:
Eggs.tserrors on an unknown item, an item listed twice in one egg, an egg with noopenCounts, or an egg whose only entries are once-only.Wheel.tserrors on a prize that gives nothing, a wheel with no prize weight above 0, and, once a spin product ID is set, a prize that gives a currency withoutsoldForRobux.Season.tserrors when a premium reward gives a currency withoutsoldForRobux.
TypeScript catches the rest. For example, every key in PRODUCTS needs an entry in PRODUCT_GRANTS in server/Purchases.ts, or the build fails.
Before launch
Work through this list on the Creator Dashboard (create.roblox.com > your experience > Monetization), pasting each ID into config:
- One developer product per entry in
PRODUCTS(Pile of Coins, Chest of Coins, Starter Pack). Paste each into itsid. - One pass per entry in
GAMEPASSES(2x Coins, VIP, +2 Equips). Paste intoid. - For each pass you want to be giftable, one more developer product priced like the pass. Paste into
giftProductId. - To sell a boost, a developer product for it, pasted into its
productIdinBOOSTS. - Egg opens and wheel spins: the
productsentries inEggsConfig.tsandWheelConfig.ts. - Season premium and tier skips:
premiumProductIdandtierSkipProductIdinSeasonConfig.ts. - Your group ID in
GROUP.id, if you have a group. - Your Roblox user ID in
ADMIN_USER_IDS, so admin commands work in live servers. - Badge IDs in achievement tiers (
badgeId), if you want badges. - Sound asset IDs in
AUDIO(musicId,clickSoundId,coinSoundId).
Then decide which currencies are sold for Robux and set soldForRobux to match. That one flag decides which eggs count as paid random items, which ones restricted regions can open, and what can be traded where. See Currencies and Eggs and odds.
DataStore names
DATA in Config.ts names the stores:
export const DATA = {
/**
* DataStore name for player data. Changing it gives everyone fresh data,
* so only do that before launch. To change the shape of saved data later,
* add a migration in src/server/data/Schema.ts instead.
*/
storeName: "PlayerData_v1",
/** Passes gifted to each player, kept apart so a gift can reach someone in another server. */
giftStoreName: "GiftedPasses_v1",
/** Invite rewards waiting for each inviter. */
referralStoreName: "Referrals_v1",
After launch, leave storeName alone. Changing it starts every player over. To change what's saved, add a migration (see Player data).