HZ Scripts

Phone Weather Apps

Hz-Weather Pro has dedicated weather apps for LB Phone and QS Smartphone. Both apps display the same features — install the one matching your phone system.

LB Phone App | QS Smartphone App
QS Smartphone V3 users: qs-hzweather v2.0.0+ targets QS Smartphone V3 (resource name qs-smartphone). For the legacy V2 build (qs-smartphone-pro), keep using qs-hzweather v1.x. See the QS Smartphone V2 (Pro) section below.

Features

  • Current weather — condition, temperature, wind speed & direction
  • Interactive satellite map — zoom/pan with zone markers and live weather overlay
  • Hourly forecast — scrollable forecast per zone
  • Sun tracker — animated sunrise/sunset arc synced with game time
  • Dynamic backgrounds — animated weather-based backgrounds (rain, snow, sun, clouds, thunder)
  • Season display — current season with icon
  • Wind card — speed, direction, and compass display
  • Zone list — all weather zones with current conditions, clickable to view details
  • Current zone indicator — shows which zone the player is currently in
  • Real-time updates — auto-refreshes every 30s + instant updates on zone/temperature/season changes

Requirements

Both apps require HZ-Weather to be running on your server.

LB Phone App

ResourceVersionLink
HZ-Weatherv1.1.0+Hz-Scripts shop
LB PhoneLatestLB Scripts
ox_libv3.0+GitHub

QS Smartphone V3 App

ResourceVersionLink
HZ-Weatherv1.1.4+Hz-Scripts shop
QS SmartphoneV3+Quasar Store
ox_libv3.0+GitHub
qs-hzweather v2.0.0+ required. v1.x targets the legacy QS Smartphone Pro (V2) — see the V2 section.

Installation

LB Phone

  1. Download lb-hzweather from your Keymaster
  2. Place it in your server's resources/ folder
  3. Add to your server.cfg:
ensure ox_lib
ensure HZ-Weather
ensure lb-phone
ensure lb-hzweather
lb-hzweather must start after lb-phone and HZ-Weather.
  1. Restart your server — the app appears automatically in the LB Phone app list (pre-installed by default).

QS Smartphone V3

  1. Download qs-hzweather v2.0.0+ from your Keymaster
  2. Place it in your server's resources/ folder
  3. Disable the native Weather app. QS Smartphone V3 keeps built-in apps (phoneApplications) and custom apps (customApps) in two separate routing tables — registering a custom app with id = 'weather' does not override the native (the native always wins). Edit qs-smartphone/config/main.lua (around line 1578) and comment out the native weather entry:
Config.PhoneApplications = {
    -- { id = 'weather', label = 'Weather', icon = 'weather.webp', category = 'Information & Reading' }, -- disabled: replaced by qs-hzweather
    { id = 'calendar',   label = 'Calendar',    icon = 'calendar.webp',   category = 'Productivity & Finance' },
    -- ...
}

Leave firstPageItems = { 'weather', 'calendar' } untouched — our custom app registers under id = 'weather' so the home-screen slot is filled by our iframe.

  1. Add to your server.cfg:
ensure ox_lib
ensure HZ-Weather
ensure qs-smartphone
ensure qs-hzweather
qs-hzweather must start after qs-smartphone and HZ-Weather.
  1. Restart your server. Open the phone → the Weather icon now opens our iframe.
How it works: qs-hzweather registers a custom app via exports['qs-smartphone']:addCustomApp({ id = 'weather', appStoreOnly = false, iframe = { url = ... }, custom = { enabled = true, bridge = {...} } }). With the native entry disabled, our app is the only one bound to id = 'weather', so the home-screen layout (firstPageItems) lights up our iframe directly. To revert, simply uncomment the native line.
Migration from QS Smartphone Pro (V2): If you were previously on qs-hzweather v1.x with qs-smartphone-pro, you need to:
  1. Stop and remove qs-smartphone-pro (the V2 resource).
  2. Install QS Smartphone V3 (qs-smartphone) from Quasar Store.
  3. Update to qs-hzweather v2.0.0+ from your Keymaster.
  4. Apply the config edit (step 3 above).
  5. Reset phone data if needed — V3 uses a different schema than V2:
TRUNCATE TABLE phone_metadata;
TRUNCATE TABLE phone_app_store;

This is only needed once when migrating from V2 to V3.

QS Smartphone V2 (Pro) — legacy

For servers still running QS Smartphone Pro (V2, resource name qs-smartphone-pro), use qs-hzweather v1.x:

  1. Download qs-hzweather v1.x from your Keymaster (older releases tab)
  2. Place it in your server's resources/ folder
  3. Add to your server.cfg:
ensure ox_lib
ensure HZ-Weather
ensure qs-smartphone-pro
ensure qs-hzweather
  1. Restart your server — no config edit needed. V2 supports same-id override natively, so the app replaces the native Weather automatically.
V2 (Pro) is no longer the primary target. Bug fixes ship to the V3 branch first. Plan a migration to V3 when convenient.

Configuration

LB Phone

Edit config.lua in the lb-hzweather resource:

Config.Identifier = "hz-weather"    -- Unique app ID (do not change if already deployed)
Config.DefaultApp = true            -- true = pre-installed, false = downloadable from app store
Config.Name = "Weather"             -- App name shown in phone
Config.Description = "Real-time weather forecast powered by HZ-Weather"
Config.Developer = "HZ Development" -- Developer name in app store
ParameterTypeDefaultDescription
Identifierstring"hz-weather"Unique app ID — do not change after deployment
DefaultAppbooleantruetrue = pre-installed, false = app store
Namestring"Weather"Display name in phone
Descriptionstring"Real-time..."App description in app store
Developerstring"HZ Development"Developer name in app store

QS Smartphone V3

No configuration file in qs-hzweather itself — registration is hardcoded for the weather id. The only edit required is the one-line comment-out in qs-smartphone/config/main.lua documented in step 3 of the install section.


How It Works

Both apps use the same data flow:

Phone UI (React) → NUI Callback → lib.callback → HZ-Weather Server → Response

The app calls lib.callback('hz-weather:getMapData') to fetch all weather data (current weather, zones, forecast, temperatures, wind, season, game time, sunrise/sunset). No server-side Lua file is needed in the app resource — lib.callback handles the client-server round-trip via ox_lib.

Real-time updates are received via client events:


  • hz_weather:zoneChanged — player changed zone

  • hz_weather:syncTemperatures — temperature update

  • hz_weather:syncSeason — season change


QS Smartphone V3 — Technical Details

The QS V3 app is registered as a custom app (iframe-based) that visually replaces the native Weather:

  • App identifier: id = 'weather' — registered via addCustomApp({ id = 'weather', ... appStoreOnly = false ... }). V3 keeps phoneApplications (native) and customApps (third-party) in two separate tables; the native always wins routing, which is why disabling the native config entry is mandatory.
  • Icon: Served from our resource — ui/build/icon.svg. The native weather.webp is no longer used since the native entry is disabled.
  • Iframe URL: https://cfx-nui-qs-hzweather/ui/build/index.html — loaded by QS V3's custom-app iframe component. The iframe doesn't get a sandbox attribute, allows clipboard/camera/microphone.
  • NUI rendering: The app runs inside V3's iframe slot. fetchNui() POSTs to https://qs-hzweather/... (same-origin to the iframe), hitting our RegisterNUICallback handlers. The body { visibility: hidden; display: none } CSS guard is undone explicitly in useEffect (V2 relied on qs-smartphone-pro sending an app-opened postMessage to flip it — V3 doesn't).
  • Bridge SDK (optional): V3 exposes QSPhoneBridge at https://cfx-nui-qs-smartphone/web/build/bridge/qs-phone-bridge.js for theme detection, toast notifications, and event communication. qs-hzweather currently doesn't use it (30 s polling is enough); future versions may integrate it for instant push.
  • Widget: The home-screen weather widget is built into QS Smartphone V3 and reads its data from GTA natives independently of HZ-Weather — qs-hzweather does not control it.

Development

LB Phone App

cd lb-hzweather/ui/
npm install
npm run dev      # Hot reload on localhost:3000

Switch to dev mode in fxmanifest.lua:

ui_page "http://localhost:3000/"
-- ui_page "ui/dist/index.html"

Build for production:

npm run build

QS Smartphone V3 App

cd qs-hzweather/ui/
npm install
npm run dev      # Hot reload on localhost:5173

Build for production:

npm run build

After building, make sure ui/build/icon.svg still exists. The Vite build process copies files from ui/public/ to ui/build/ — the icon is in public/ and should be preserved automatically.

After rebuilding, restart qs-hzweather on the server so QS V3's iframe reloads the new bundle.


Troubleshooting

LB Phone

ProblemSolution
App doesn't appearMake sure lb-hzweather starts after lb-phone in server.cfg
"HZ-Weather is not running"Ensure HZ-Weather is started before lb-hzweather
No weather dataCheck that HZ-Weather is properly configured and working
Zones not showing on map/listUpdate to v1.1.4+ — fixed isActive nil handling

QS Smartphone V3

ProblemSolution
Tapping Weather opens the native QS screen, not HZYou skipped step 3 of the install — comment out the native weather entry in qs-smartphone/config/main.lua and restart both qs-smartphone and qs-hzweather. V3 does not auto-override built-in apps by id.
Iframe loads but shows a blank white screenqs-hzweather v1.x bundle running on V3. The V2 build relies on qs-smartphone-pro flipping body { visibility: hidden; display: none } via postMessage — V3 doesn't send that signal. Update to qs-hzweather v2.0.0+ which sets the body visible unconditionally in useEffect.
Two Weather apps on the home screenThe native entry is still in Config.PhoneApplications AND our custom app is also registered. Disable the native entry as per install step 3.
Weather icon disappears from the home screenThe home layout cached an older state. Open the App Drawer (swipe up), drag Weather back to the home page, or reset the per-player phone layout via the in-game settings.
[qs-hzweather] addCustomApp failed (…) and updateCustomApp failed (…) in server consoleThe phone resource refused our registration payload. Check the parenthesized error code — common values are INVALID_PAYLOAD (icon URL or iframe URL malformed) and BRIDGE_DISABLED (custom bridge feature turned off in QS config). Verify ui/build/icon.svg and ui/build/index.html both exist.
"Connection error" in the appEnsure HZ-Weather is started before qs-hzweather.
Map tiles not loadingTiles are served from HZ-Weather — make sure it's running and that the player has network access to cfx-nui-HZ-Weather/web/dist/tiles/.
Console error about lib.callbackMake sure ox_lib is installed and started before qs-hzweather.

QS Smartphone V2 (Pro) — legacy

ProblemSolution
"This app was not found"Reset phone data (see migration note above), then restart server
App opens fullscreen instead of in phoneUpdate to qs-hzweather v1.1.4+ — fixed CSS visibility and 100vh issues
0 locations on map / empty zone listUpdate to v1.1.4+ — fixed isActive nil handling
"Connection error" in the appEnsure HZ-Weather is started before qs-hzweather
Two Weather apps on home screenUpdate to v1.1.4+ — app overrides native Weather app on V2
App doesn't appear at allCheck that qs-smartphone-pro is running and qs-hzweather v1.x starts after it
Map tiles not loadingTiles are served from HZ-Weather — make sure it's running
Sunrise/sunset stuck at 6:00/8:00PMUpdate to v1.1.4+ — now reads from Config.NightTime

Need help? Join our Discord and open a ticket!