919phone

919PHONE
The Lightest FiveM Phone

The Lightest Price


690x387
690x61
690x57
690x57


Brochure

Product Details

Feature Highlights

22 Built-In Apps — calls, texts, mail, bank, maps, camera, social, marketplace & more
Pay For What You Use — core phone + optional game packs + SDK apps; disable any app in config
Services Dispatch — job calls & texts, worker inbox, call log, ring-like-normal incoming calls
Banking That RP’s — transfers, payment requests, job invoices, balance widget
Live Home Screen — drag-and-drop icons, folders, dock, scroll/swipe pages, live widgets
pma-voice Calling — dialer, history, voicemail, block list, hide caller ID
Messages Done Right — groups by number, read receipts, typing, gallery attachments
Social Stack — Tweeder, Cloutgram stories/posts, Hagglr classifieds, Snitch reviews
Maps & GPS — Atlas / satellite / standard layers, POIs, pins, waypoints, offline-aware
Camera & Gallery — photo + video, landscape mode, FiveManage-backed media everywhere
Lock Screen + Control Center — flashlight, DND, connectivity toggles, music, quick share
Notification Deep Links — tap a banner, land in the exact thread, invoice, or voicemail
Verified Badges — configurable per app for official city accounts & creators
Walk While Open — stay in the world; phone size, frame color, themes, wallpapers
Moderation Built In — reports, blocked words, admin tools, Discord / FiveManage logs
Full Developer SDK — register external apps, iframe isolation, 50 slots, App Store ready

Tech Specs

Truly Drop-In — import SQL, ensure resource, add phone item; framework auto-detects
Framework-Agnostic — QBox, QBCore, ESX, standalone fallback
6+ Inventory Bridges — ox, qs, origen, codem, tgiann, ps + framework default
Svelte 5 + TypeScript — compiled, lean NUI; not a bloated React phone clone
Open Bridge & Locale — customize money, jobs, stats, strings without recompiling
Per-App Toggles — hide apps from home & App Store from config.lua alone
OneSync Ready — built for modern FiveM stacks (ox_lib + oxmysql)
Optional Game Packs — Snake, Flappy, 2048, Block Stack, Brick Breaker, Mine Sweep

Raw Screenshots
























Config
---919PHONE shared configuration.
---Loaded on both client and server. Restart the resource after making changes.
---For server-only secrets, see config_s.lua.
Config = {}

-- ── General ───────────────────────────────────────────────────────────────────

---FiveM keybind used to open and close the phone.
---Uses standard FiveM key names (https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/).
Config.OpenKey = 'M'

---When true, players can walk and move while the phone NUI is open.
---When false, movement input is blocked while the phone is open.
Config.AllowWalkingWhileOpen = true

---Phone item requirement. When Enabled is true, the player must carry the configured
---inventory item to open the phone (keybind and usable item both respect this).
Config.PhoneItem = {
    ---Set to false to allow opening the phone without an inventory item.
    Enabled = true,
    ---Inventory item name. Must match your framework/inventory item definition exactly.
    Item    = 'phone',
}

---World prop shown in the player's hand during open and call animations.
Config.PhoneProp = {
    ---Set to false to disable the hand prop entirely.
    Enabled  = true,
    ---GTA prop model name.
    Model    = 'prop_npc_phone_02',
    ---Ped bone index the prop attaches to (28422 = right hand).
    Bone     = 28422,
    ---Local offset from the attachment bone.
    Offset   = { x = 0.0,  y = 0.0,  z = 0.0  },
    ---Local rotation applied after attachment.
    Rotation = { x = 0.0,  y = 0.0,  z = 0.0  },
}

---Phone holding animation profile. Valid values: 'oneHanded', 'twoHanded'.
Config.PhoneAnimation = 'twoHanded'

---When true, the flashlight turns off automatically when the phone is put away.
Config.FlashlightOffOnClose = true

---Maximum distance in meters for sharing a contact with nearby players.
Config.ContactShareRange = 8.0

---Number of consecutive wrong passcode attempts before the lock screen temporarily blocks input.
Config.PasscodeMaxAttempts = 5

---How long the passcode lockout lasts in seconds after too many failed attempts.
Config.PasscodeLockoutDuration = 30

-- ── Admin ─────────────────────────────────────────────────────────────────────
---ACE permission required for admin chat commands (/resetphonepasscode, /resetphonedata).
Config.Admin = {
    Ace = 'admin',
}

-- ── Voicemail ─────────────────────────────────────────────────────────────────

Config.Voicemail = {
    MaxRecordingSeconds = 60,
    MaxMessagesPerPhone = 50,
    RetainDays          = 30,
}

-- ── Default player settings ───────────────────────────────────────────────────
---Applied when a character's phone row is first created or fully reset by an admin.
---Players can change most of these in the in-game Settings app after setup.

Config.DefaultSettings = {
    ---UI color scheme. Valid values: 'dark', 'light'.
    theme           = 'dark',
    ---When false, the first-run setup wizard is shown on first phone open.
    setupCompleted  = false,
    ---Display brightness percentage (0–100).
    brightness      = 100,
    ---Master volume percentage (0–100).
    volume          = 75,
    ---Default notification sound. Must match a name from Config.Texttones.
    texttone        = 'Tone 1',
    ---When true, mutes ringtones and notification sounds.
    silentMode      = false,
    ---When true, suppresses most notifications while the phone is locked.
    doNotDisturb    = false,
    ---Phone frame size on screen. Valid values: 'small', 'medium', 'large', 'extraLarge'.
    phoneSize       = 'large',
    ---Phone bezel color. Valid values: 'black', 'white', 'natural', 'blue', 'pink', 'teal',
    ---'desert', 'purple', 'neonBlue', 'neonGreen', 'neonPink', 'neonYellow'.
    frameColor      = 'black',
    ---Home screen icon entry animation when unlocking or closing an app.
    ---Valid values: 'bounce', 'drop', 'flip', 'focus', 'none'.
    homeIconAnimation = 'bounce',
    ---Default home/lock screen wallpaper. Use url("./path") for bundled images under web/build/.
    wallpaper       = 'url("./wallpapers/wallpaper1.jpg")',
    ---Phone numbers blocked from calling or messaging this character.
    blockedNumbers  = {},
    ---When false, outgoing calls appear as "No Caller ID" to recipients.
    showCallerID    = true,
    ---Custom voicemail greeting URL on FiveManage. Empty string uses the bundled default.
    voicemailGreetingUrl    = '',
    ---FiveManage file id for the custom greeting (used when replacing or resetting).
    voicemailGreetingFileId = '',
    ---Low-stat notification thresholds shown in the Health app and home widget.
    healthAlerts    = {
        ---When true, fire a notification when hunger drops below hungerThreshold.
        hungerEnabled     = true,
        ---Hunger percentage (0–100) that triggers a low-hunger alert.
        hungerThreshold   = 25,
        ---When true, fire a notification when thirst drops below thirstThreshold.
        thirstEnabled     = true,
        ---Thirst percentage (0–100) that triggers a low-thirst alert.
        thirstThreshold   = 25,
        ---When true, fire a notification when stress rises above stressThreshold.
        stressEnabled     = true,
        ---Stress percentage (0–100) that triggers a high-stress alert.
        stressThreshold   = 75,
    },
}

-- ── Services app ──────────────────────────────────────────────────────────────
---Services app UI and behaviour (separate from the job entries in Config.Services).
Config.ServicesApp = {
    ---When false, the Services list hides how many workers are online (no count in the status badge).
    ---Call and text actions still require at least one available worker.
    ShowOnlineWorkers = false,
}

---Job-linked service entries shown in the Services app. Players can call or text
---workers who are on duty for the matching job and have not disabled that service.
---@type { id: string, label: string, icon: string, color: string, job: string, numbers: string[] }[]
Config.Services = {
    ---id: unique service identifier used internally.
    ---label: display name shown in the Services app.
    ---icon: Font Awesome solid icon name (include the fa- prefix).
    ---color: hex color used for the service card accent.
    ---job: framework job name that counts as an on-duty worker for this service.
    ---numbers: phone numbers displayed to customers for this service.
    { id = 'mechanic',  label = 'Mechanic',   icon = 'fa-wrench',         color = '#ff9f0a', job = 'mechanic',  numbers = { '555-MECH' } },
    { id = 'taxi',      label = 'Taxi',        icon = 'fa-taxi',           color = '#ffd60a', job = 'taxi',      numbers = { '555-TAXI' } },
    { id = 'ems',       label = 'EMS',         icon = 'fa-star-of-life',   color = '#ff453a', job = 'ambulance', numbers = { '911'      } },
    { id = 'police',    label = 'Police',      icon = 'fa-shield-halved',  color = '#0a84ff', job = 'police',    numbers = { '911'      } },
    { id = 'tow',       label = 'Tow Truck',   icon = 'fa-truck-pickup',   color = '#30d158', job = 'towtruck',  numbers = { '555-TOW'  } },
}

-- ── App visibility ────────────────────────────────────────────────────────────
---Set any app to false to remove it from all players' phones.
---Disabled apps are hidden from the home screen and cannot be opened.
---App Store apps (tweeder, hagglr, cloutgram, snitch) are also removed from the
---App Store catalog when disabled. Changes apply after a resource restart.
---@type table<string, boolean>
Config.Apps = {
    phone       = true,
    messages    = true,
    contacts    = true,
    settings    = true,
    clock       = true,
    calendar    = true,
    camera      = true,
    photos      = true,
    notes       = true,
    appstore    = true,
    health      = true,
    weather     = true,
    calculator  = true,
    music       = true,
    maps        = true,
    banking     = true,
    mail        = true,
    tweeder     = true,
    hagglr      = true,
    cloutgram   = true,
    services    = true,
    snitch      = true,
}

-- ── External App SDK ──────────────────────────────────────────────────────────
---Settings for third-party apps registered via exports['amzn_smartphone']:registerApp().
Config.Sdk = {
    ---Set to false to block all external app registration.
    Enabled                 = true,
    ---Maximum number of external apps registered at once.
    MaxExternalApps         = 50,
    ---Maximum encoded JSON payload size in bytes for fetchNui requests/responses.
    MaxFetchPayload         = 65536,
    ---If true, sendAppMessage deliveries are held until the target app is opened.
    QueueMessagesWhenClosed = false,
}

---External app ids allowed to register with category = 'default' (always on home screen).
---@type table<string, boolean>
Config.AllowedDefaultApps = {}

-- ── Media ─────────────────────────────────────────────────────────────────────
---Audio and image files must live under web/public/ in the source tree so they are
---copied into web/build/ when you run the release build. Paths below are relative
---to web/build/ as served to the phone NUI.

---Ringtones selectable in Settings and used for incoming calls.
---name: label shown in the Settings picker.
---file: path relative to web/build/.
---@type { name: string, file: string }[]
Config.Ringtones = {
    { name = 'Default', file = 'ringtones/midnight.mp3' },
    { name = 'Classic', file = 'ringtones/oldphone.mp3' },
    { name = 'Office',  file = 'ringtones/office.mp3'  },
}

---Notification sounds selectable in Settings for texts and app alerts.
---@type { name: string, file: string }[]
Config.Texttones = {
    { name = 'Tone 1', file = 'texttones/texttone1.mp3' },
    { name = 'Tone 2', file = 'texttones/texttone2.mp3' },
    { name = 'Tone 3', file = 'texttones/texttone3.mp3' },
}

---Tracks available in the Music app.
---art is optional; omit it to show the generic music-note placeholder.
---@type { name: string, artist: string, file: string, art?: string }[]
Config.MusicTracks = {
    { name = 'Test Track',  artist = '919DESIGN',  file = 'music/TestTrack.mp3', art = 'music/TestTrack.png'  },
}

---Wallpaper images selectable in Settings.
---@type { name: string, file: string }[]
Config.Wallpapers = {
    { name = 'Colorful I', file = 'wallpapers/wallpaper1.jpg' },
    { name = 'Nature',   file = 'wallpapers/wallpaper2.jpg'   },
    { name = 'Flowers',   file = 'wallpapers/wallpaper3.jpg'   },
    { name = 'Colorful II', file = 'wallpapers/wallpaper4.jpg' },
    { name = 'Rain', file = 'wallpapers/wallpaper5.jpg' },
}

-- ── Maps app ──────────────────────────────────────────────────────────────────
---Permanent map pins shown to all players in the Maps app.
---Players can also save personal pins; those persist per character in the database.
---@type { label: string, x: number, y: number, icon?: string, color?: string }[]
Config.MapPins = {
    ---label: pin name shown in the Maps UI.
    ---x/y: GTA V world coordinates.
    ---icon: Font Awesome solid icon name (optional).
    ---color: hex color for the pin marker (optional).
    { label = 'Hospital',   x = 295.9,   y = -1446.7, icon = 'fa-hospital',      color = '#ff3b30' },
    { label = 'Police HQ',  x = 440.4,   y = -980.8,  icon = 'fa-shield-halved', color = '#0a84ff' },
    { label = 'Airport',    x = -1037.0, y = -2738.0, icon = 'fa-plane',         color = '#5ac8fa' },
    { label = 'Car Dealer', x = -39.4,   y = -1100.0, icon = 'fa-car',           color = '#ff9f0a' },
}

-- ── Health app ────────────────────────────────────────────────────────────────
---Controls how often the client checks hunger/thirst/stress and when alerts fire.
---Stat values are read from your framework via modules_editable/bridge/bridge_c.lua.
Config.Health = {
    ---Milliseconds between background stat checks while the phone is in use.
    PollInterval    = 5000,
    ---Seconds before the same alert type can fire again for one player.
    AlertCooldown   = 120,
    ---Percentage the stat must recover past its threshold before the alert can re-arm.
    RecoveryMargin  = 5,
}

-- ── Notes app ─────────────────────────────────────────────────────────────────
---Server-side limits for notes saved per character. Payloads that exceed these are rejected.
Config.Notes = {
    ---Maximum number of notes stored per character.
    MaxCount       = 100,
    ---Maximum characters allowed in a note id or ISO lastModified timestamp.
    IdLimit        = 64,
    ---Maximum characters allowed in a note title.
    TitleLimit     = 120,
    ---Maximum characters allowed in a note body.
    ContentLimit   = 10000,
    ---Maximum characters allowed in the generated preview string.
    PreviewLimit   = 120,
    ---Maximum encoded JSON size in bytes for the full notes array.
    MaxPayloadSize = 256000,
}

-- ── Calendar app ──────────────────────────────────────────────────────────────
---Server-side limits for calendar events saved per character.
Config.Calendar = {
    ---Maximum number of events stored per character.
    MaxCount       = 200,
    ---Maximum characters allowed in an event id.
    IdLimit        = 64,
    ---Maximum characters allowed in an event title.
    TitleLimit     = 120,
    ---Maximum characters allowed in the ISO date string.
    DateLimit      = 40,
    ---Maximum characters allowed in the formatted time label.
    TimeLimit      = 40,
    ---Maximum characters allowed in the hex color string (#RRGGBB).
    ColorLimit     = 7,
    ---Maximum encoded JSON size in bytes for the full events array.
    MaxPayloadSize = 128000,
}

-- ── Mail app ──────────────────────────────────────────────────────────────────
Config.Mail = {
    ---Suffix appended to a player's chosen username to form their mail address.
    EmailSuffix  = '@celltowa.com',
    ---Maximum characters allowed in a mail subject line.
    SubjectLimit = 80,
    ---Maximum characters allowed in a mail body.
    BodyLimit    = 2000,
    ---Minimum seconds between outbound mails sent by the same player.
    SendCooldown = 10,
    ---Number of messages loaded per inbox/sent page in the Mail app.
    PageSize     = 25,
    ---Local-part used for system/no-reply senders (e.g. noreply@celltowa.com).
    NoReplyName  = 'noreply',
    ---Character identifiers that show a verified badge on inbound mail from their address.
    ---@type table<string, boolean>
    VerifiedIdentifiers = {
        ['18K5B061'] = true,
    },
}

-- ── Hagglr app (classifieds) ──────────────────────────────────────────────────
Config.Hagglr = {
    ---Minimum seconds between new listings posted by the same player.
    PostCooldown = 60,
    ---Maximum characters allowed in a listing title.
    TitleLimit   = 80,
    ---Maximum characters allowed in a listing description.
    BodyLimit    = 500,
    ---Maximum characters allowed in the price field text.
    PriceLimit   = 30,
    ---When false, players cannot attach photos to listings.
    AllowImages  = true,
    ---Number of listings loaded per feed page.
    PageSize       = 20,
    ---Minimum seconds before the same player can report the same listing again.
    ReportCooldown = 300,
    ---Character identifiers that show a verified badge on Hagglr listings.
    ---@type table<string, boolean>
    VerifiedIdentifiers = {
        ['18K5B061'] = true,
    },
}

-- ── Banking app ───────────────────────────────────────────────────────────────
Config.Banking = {
    ---Minimum whole-dollar amount for transfers and payment requests.
    TransferMinAmount  = 1,
    ---Maximum open incoming payment requests a character can have at once.
    MaxPendingIncoming = 50,
    ---Maximum open outgoing payment requests a character can have at once.
    MaxPendingOutgoing = 20,
    ---Days after which unpaid payment requests expire automatically.
    RequestExpireDays  = 30,
    ---Jobs allowed to send invoices from the Banking app.
    ---Key = framework job name, value = label shown on the invoice.
    ---@type table<string, string>
    InvoiceJobs = {
        mechanic  = 'Mechanic',
        police    = 'Police',
        ambulance = 'EMS',
        taxi      = 'Taxi',
        towtruck  = 'Tow Truck',
    },
}

-- ── Tweeder app (social feed) ─────────────────────────────────────────────────
Config.Tweeder = {
    ---Minimum seconds between new posts by the same player.
    PostCooldown   = 30,
    ---Minimum seconds between replies by the same player.
    ReplyCooldown  = 15,
    ---Minimum seconds between like toggles by the same player on the same post.
    LikeCooldown   = 2,
    ---Minimum seconds before the same player can report the same post again.
    ReportCooldown = 300,
    ---Maximum characters allowed in a post body.
    CharLimit      = 280,
    ---Maximum characters allowed in a reply body.
    ReplyCharLimit = 280,
    ---Number of posts loaded per feed page.
    PageSize       = 30,
    ---ACE permission required for in-game post deletion/moderation actions.
    ModerateAce    = 'admin',
    ---Lower-case substrings blocked from post and reply text, e.g. { 'badword' }.
    BlockedWords   = {},
    ---When false, players cannot attach photos to posts.
    AllowImages    = true,
    ---When true, all online players with Tweeder set up get a phone notification for every new post.
    NotifyNewPosts = true,
    ---Character identifiers (framework citizenid / ESX char id) that show a verified badge on Tweeder.
    ---@type table<string, boolean>
    VerifiedIdentifiers = {
        ['18K5B061'] = true,
    },
}

-- ── Cloutgram app (photo social) ─────────────────────────────────────────────
Config.Cloutgram = {
    ---Minimum seconds between new posts by the same player.
    PostCooldown    = 30,
    ---Minimum seconds between comments by the same player.
    CommentCooldown = 10,
    ---Minimum seconds between new stories by the same player.
    StoryCooldown   = 60,
    ---Minimum seconds between like toggles by the same player on the same post.
    LikeCooldown    = 2,
    ---Minimum seconds before the same player can report the same post again.
    ReportCooldown  = 300,
    ---Maximum characters allowed in a post caption.
    CaptionLimit    = 2200,
    ---Maximum characters allowed in a profile bio.
    BioLimit        = 150,
    ---Maximum characters allowed in a profile website field.
    WebsiteLimit    = 100,
    ---Maximum photos/videos attached to a single post.
    MaxMediaPerPost = 10,
    ---Number of posts loaded per feed page.
    PageSize        = 20,
    ---How long stories remain visible, in seconds (86400 = 24 hours).
    StoryDuration   = 86400,
    ---ACE permission required for in-game moderation actions.
    ModerateAce     = 'admin',
    ---Lower-case substrings blocked from captions, bios, and comments.
    BlockedWords    = {},
    ---When false, players cannot upload or attach images and videos.
    AllowImages     = true,
    ---Character identifiers that show a verified badge on Cloutgram.
    ---@type table<string, boolean>
    VerifiedIdentifiers = {
        ['18K5B061'] = true,
    },
}

-- ── Snitch app (business reviews) ─────────────────────────────────────────────
Config.Snitch = {
    ---Minimum seconds between reviews posted by the same player.
    ReviewCooldown = 60,
    ---Maximum characters allowed in a review body.
    BodyLimit      = 1000,
    ---Number of reviews loaded per page.
    PageSize       = 20,
    ---When false, players cannot attach photos to reviews.
    AllowImages    = true,
    ---Minimum seconds before the same player can report the same review again.
    ReportCooldown = 300,
    ---Character identifiers that show a verified badge on Snitch reviews.
    ---@type table<string, boolean>
    VerifiedIdentifiers = {
        ['18K5B061'] = true,
    },
    ---Static business catalog reviewed in the Snitch app. These are config-driven,
    ---not stored in the database.
    ---@type { id: string, name: string, category: string, description: string, address?: string, phone?: string, x?: number, y?: number, imageUrl?: string }[]
    Businesses = {
        ---id: unique business identifier used for reviews.
        ---name: business display name.
        ---category: grouping label shown in browse filters.
        ---description: short summary shown on the business detail page.
        ---address: optional street/area label.
        ---phone: optional contact number shown in the UI.
        ---x/y: optional GTA V coordinates for map display.
        ---imageUrl: optional header image URL.
        { id = 'bennys',       name = "Benny's Original Motor Works", category = 'Automotive',  description = 'Custom upgrades and repairs in Strawberry.',           address = 'Strawberry',           phone = '555-BENNY', x = -205.0,  y = -1310.0 },
        { id = 'ls_customs',   name = 'Los Santos Customs',           category = 'Automotive',  description = 'Full-service mod shop and paint.',                     address = 'Burton',               phone = '555-MODS',  x = -339.0,  y = -136.0  },
        { id = 'pillbox',      name = 'Pillbox Hill Medical',         category = 'Medical',     description = 'Emergency care and routine treatment.',                address = 'Pillbox Hill',         phone = '911',       x = 295.9,   y = -1446.7 },
        { id = 'mrpd',         name = 'Mission Row PD',               category = 'Government',  description = 'City police headquarters and front desk.',             address = 'Mission Row',          phone = '911',       x = 440.4,   y = -980.8  },
        { id = 'upnatom',      name = 'Up-n-Atom Burger',             category = 'Food',        description = 'Classic burgers, shakes, and late-night bites.',       address = 'Vinewood Blvd',        phone = '555-ATOM',  x = 81.0,    y = 275.0   },
        { id = 'bean_machine', name = 'Bean Machine',                 category = 'Food',        description = 'Coffee, pastries, and a quiet place to sit.',          address = 'Legion Square',        phone = '555-BEAN',  x = 120.0,   y = -1036.0 },
        { id = 'tequi_la',     name = 'Tequi-la-la',                  category = 'Nightlife',   description = 'Live music, strong drinks, questionable decisions.',   address = 'Vinewood',             phone = '555-TEQUI', x = -565.0,  y = 276.0   },
        { id = 'vanilla',      name = 'Vanilla Unicorn',              category = 'Nightlife',   description = 'Upscale lounge with nightly entertainment.',           address = 'Strawberry',           phone = '555-VU',    x = 127.0,   y = -1298.0 },
        { id = 'pdm',          name = 'Premium Deluxe Motorsport',    category = 'Retail',      description = 'New and used vehicles with financing options.',      address = 'Power St',             phone = '555-PDM',   x = -39.4,   y = -1100.0 },
        { id = 'ammunation',   name = 'Ammu-Nation Legion',           category = 'Retail',      description = 'Licensed firearms and accessories.',                   address = 'Legion Square',        phone = '555-AMMO',  x = 22.0,    y = -1105.0 },
        { id = '247_grove',    name = '24/7 Supermarket',             category = 'Retail',      description = 'Groceries, snacks, and essentials open around the clock.', address = 'Grove St',         phone = '555-247',   x = -47.0,   y = -1758.0 },
        { id = 'airport',      name = 'Los Santos International',     category = 'Travel',      description = 'Flights in and out of the city.',                      address = 'LSIA',                 phone = '555-LSIA',  x = -1037.0, y = -2738.0 },
    },
}

-- ── Camera app ────────────────────────────────────────────────────────────────
Config.Camera = {
    ---Maximum video recording length in seconds.
    MaxVideoDuration   = 30,
    ---Target video encoder bitrate in bits per second for in-game recordings.
    VideoBitsPerSecond = 2500000,
}
Code is accessible No - partial
Subscription-based Available
Lines (approximately) 20,000+
Requirements & dependencies ox_lib, pma-voice
Support Yes
7 Likes

This looks cool :slight_smile: good job dude!

1 Like