App Registration & Lifecycle
Learn how to register your custom app with 5M Phone and handle start/restart lifecycles reliably.
RegisterApp API Specification
Custom apps register via exports['5M_Phone']:RegisterApp(data) on the client:
Lua
local ok, err = exports['5M_Phone']:RegisterApp({
id = 'my-custom-app', -- (string, required) Unique ID
name = 'My Custom App', -- (string, required) Display title
description = 'My custom app', -- (string, optional) App Store description
developer = 'Developer Studio', -- (string, optional) Studio author name
defaultApp = true, -- (boolean, optional) Auto-install on home screen
ui = 'ui/dist/index.html', -- (string, required) HTML path or https:// URL
icon = 'ui/dist/icon.svg', -- (string, required) Icon path or URL
color = '#6366f1', -- (string, optional) HEX accent color
screenshots = { -- (table, optional) Gallery images for App Store
'ui/dist/store/shot1.svg',
'ui/dist/store/shot2.svg',
},
})Parameter Reference
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique app slug (e.g. 'crypto-tracker'). Letters, digits, hyphens, and underscores. |
name | string | Yes | Display title rendered beneath the app icon and on the App Store card. |
description | string | No | Description displayed on the App Store product details page. |
developer | string | No | Studio or author name. |
defaultApp | boolean | No | Default false. If true, the app is pre-installed on the home screen. If false, it appears in the App Store. |
ui | string | Yes | Path to the built HTML file relative to your resource, or a remote https:// URL. |
icon | string | Yes | Path to the icon image (.svg or .png) relative to your resource, or a remote URL. |
color | string | No | HEX color string (e.g. '#3b82f6') used for app badges and accent highlights. |
screenshots | table | No | Array of relative asset paths or URLs displayed in the App Store screenshot carousel. |
Production Lifecycle Pattern (client/main.lua)
To ensure your app registers cleanly regardless of start order or resource restarts, implement the following pattern:
Lua
local PHONE = '5M_Phone'
local function phoneReady()
return GetResourceState(PHONE) == 'started'
end
local function register()
if not phoneReady() then return false end
local ok, err = exports[PHONE]:RegisterApp({
id = Config.AppId,
name = Config.Name,
description = Config.Description,
developer = Config.Developer,
defaultApp = Config.DefaultApp == true,
ui = Config.UiPath,
icon = Config.IconPath,
color = Config.Color,
screenshots = Config.Screenshots,
})
if not ok then
print(('[5M_CustomApp] RegisterApp failed: %s'):format(tostring(err)))
return false
end
print(('[5M_CustomApp] Successfully registered on %s as "%s"'):format(PHONE, Config.AppId))
return true
end
-- 1. Initial startup: wait until 5M_Phone is started
CreateThread(function()
while not phoneReady() do
Wait(400)
end
Wait(800)
register()
end)
-- 2. Phone restarted in-game: re-register automatically
AddEventHandler('onResourceStart', function(res)
if res == PHONE then
CreateThread(function()
Wait(1000)
register()
end)
end
end)
-- 3. App resource stopping: unregister cleanly from phone home screen
AddEventHandler('onResourceStop', function(res)
if res == GetCurrentResourceName() and phoneReady() then
pcall(function()
exports[PHONE]:UnregisterApp(Config.AppId)
end)
end
end)Unregistering an App
If you need to dynamically remove an app from the phone:
Lua
exports['5M_Phone']:UnregisterApp('my-custom-app')Startup Order in server.cfg
Always start 5M_Phone before custom developer apps:
Config
ensure 5M_Phone
ensure 5M_CustomApp