XonSight
Guide

How Xon Sight fits together

Xon Sight is four pieces working together: a bodycam app that captures and uploads footage in-game, this website that stores and reviews it, and two ways to reach the website without leaving the game - an in-hand tablet prop and an LB Phone app. This page covers what each one does and how they talk to each other. For the webhook wire format, see the API reference instead.

4 components Flask + FiveM Self-hosted
Just want it installed? Quick start →

Overview

Nothing here gives a website a live video feed - Xon Sight (the in-game resource) has no documented way to stream actual camera frames out of the game. What moves between the pieces below is: finished clips (uploaded after the fact), a schematic position feed ("who's recording and roughly where"), and the portal's own pages, which the tablet and phone app simply display in a window rather than rebuilding.

Architecture

evidence sources · any webhook-compatible resource OPS Phone·LB Phone camera·your own
webhook · clips / roster / alerts ▼
The Portalxonsight.opslabsystems.cloud
iframe · same pages, no separate backend ▼
In-game Tabletheld prop
LB Phone Appviewer + capture

The portal is the only piece holding data - the tablet and phone app are just windows onto it, so there's nothing to keep in sync between them. Xon Sight doesn't require OPS Phone specifically - its webhook is generic, so the LB Phone app above can submit evidence straight from LB Phone's own camera too, alongside (or instead of) a dedicated bodycam resource.

Multiple servers, one portal

One Xon Sight deployment can host more than one FiveM server, each in its own dedicated MySQL database - nobody's evidence, live roster, or alerts end up in anyone else's. Each of these communities gets its own API token; point your bodycam script at that token instead of the shared webhook key and everything it sends lands in that community's own database from then on.

1
Bring your own server onto Xon Sight

Get started to sign up yourself - name your community and you're the first admin - or ask an existing deployment's operator to create one for you from Admin → Communities. Either way, Xon Sight provisions a fresh MySQL database and user for it on the spot and shows its API token once (it's only ever masked after that).

2
The token goes in the bodycam script's config

xonsight-lbphone / xonsight-livesync: config.lua → Config.CommunityToken. opslabs-bodycam: config_server.lua → ServerConfig.XonSight.Token (support for sending it as X-XonSight-Token is still on opslabs-bodycam's side to ship - use the shared webhook key there for now). Set it instead of (not alongside) the existing shared key field - whichever resources that server runs will send X-XonSight-Token from then on, and the portal routes every evidence upload, live-roster sync, and alert from that token into the matching community's database automatically.

3
Their staff browse it with a normal portal login

A self-signed-up community's admin lands on /integration after creating it - the token, setup steps, and a regenerate button all live there, reachable again any time from the account menu.

Scope today: only Dashboard/Evidence/Live are tenant-aware. Cases, the Assistant, the public Community tip line, Analytics, and Admin itself still run against this portal's own original database regardless of which community you're on - a deliberate, incremental rollout rather than a half-migrated everything-at-once. A self-signed-up community's admin sees their own tenant data as soon as they're logged in, on this same primary URL - dedicated subdomains (<slug>.opslabsystems.cloud) work too once the operator points a wildcard DNS record here, but aren't required to get started.

Components

01

OPS Phone · a bodycam

Reference implementation FiveM resource · opslabs-bodycam

Xon Sight's webhook contract is generic - it doesn't require OPS Phone or any other specific resource, it just needs something to POST evidence to it. OPS Phone is the reference bodycam implementation this portal was built against: a bodycam app on an officer's in-game phone. When they stop recording, the finished clip uploads to wherever LB Phone's camera upload is configured to put it (Fivemanage, S3, etc. - this site never touches the raw video), and a webhook tells the portal the clip exists, who submitted it, and a caption. The LB Phone App below can submit evidence the same way, straight from LB Phone's own camera, if you'd rather not run a separate bodycam resource at all.

  • Sends the device serial automatically, so the Evidence viewer's Metadata tab fills itself in
  • Fires an alert (shots fired, weapon drawn) the instant it happens - raises the banner on the Live page
  • Pushes the live roster on start/stop, not just on a timer - a new recorder shows up on /live within ~1s
  • Optional chest-mounted camera mode for a true body-worn-camera angle instead of free-look
Slide deck: how recording, the evidence pipeline and performance on low-end PCs all work
02

The Portal · this website

Core Web app · Flask

Everything OPS Phone sends lands here. It's the one place all of it gets reviewed, organized, and searched - the tablet and phone app don't have their own separate view of this data, they just open these same pages. Everything below needs a staff login except the public tip line.

Dashboard
/dashboard

Recent submissions and a quick count of what's active, at a glance.

Evidence
/evidence

Every clip, with a frame-stepping player, markers, clips-within-clips, and a transcript tab.

Live
/live

Who's recording right now and their last known position on a schematic map.

Cases
/cases

Group evidence under a status (open / under review / closed) with an audit trail.

Community
/community

The public tip line and per-case request links - no account needed on their end.

Assistant
/assistant

AI-drafted report narratives, footage summaries, and BOLOs.

Analytics
/analytics

Submission volume, alert types, case status, top submitting officers.

Admin
/admin/*

Users, communities, Discord notifications, and the audit log.

03

In-game Tablet · held prop

Optional FiveM resource · xonsight-tablet

A stock in-game prop an officer holds and reads from without tabbing out of GTA. It's the real portal in a window, not a reimplementation of it.

  • Stock GTA prop (prop_cs_tablet) - no custom model to source or stream in
  • Opens on a configurable key (F6 by default); closes with the same key, the on-screen ×, or Esc
  • Logs in once and stays logged in between uses, same as a normal browser tab
04

LB Phone App · installable app, viewer + capture

Optional FiveM resource · xonsight-lbphone · requires LB Phone

Installed as a proper app icon on an officer's LB Phone - open it from the home screen like any other app. It's the only piece that's two things at once: a viewer onto the portal, and - with a tap of its "Record evidence" button - an independent way to submit evidence too, using LB Phone's own camera. Third-party phone frameworks work with Xon Sight through this same path: nothing about the webhook cares what recorded the footage.

  • Records video with LB Phone's camera and posts it straight to the evidence webhook - no bodycam resource required
  • The webhook key stays server-side (server.lua) - never exposed to the NUI/browser layer
  • Capture can be turned off (Config.AllowCapture = false) to ship this as a viewer-only app instead
  • Registers itself via lb-phone's own AddCustomApp export - nothing to edit in lb-phone's config
  • Free, paid, or installed on every phone automatically - your choice per server
  • Same persistent login as the tablet, inside the phone's own NUI browser

Requirements

Xon Sight can host the portal for you - there's nothing to deploy, patch, or keep online yourself. With a hosted portal, the only real requirement is the FiveM side: a server to add resources to, and something sending it evidence over its webhook - OPS Phone is the reference implementation, but it's not mandatory; the LB Phone app can submit evidence directly from LB Phone's own camera instead. Self-hosting the portal instead is supported too, if you'd rather run your own.

In-game · the FiveM side
Required either way
  • A FiveM server you can add resources to
  • One evidence source speaking Xon Sight's webhook contract - OPS Phone / opslabs-bodycam is the reference one, but not mandatory
  • ...or just xonsight-lbphone with Config.AllowCapture on - it can be that evidence source by itself, via LB Phone's own camera
  • lb-phone already installed and running - only if you want xonsight-lbphone
  • xonsight-tablet and xonsight-livesync need nothing extra - stock GTA assets only, no other resource dependency
  • Every piece just needs the portal's URL and (for the webhook-speaking ones) its key - nothing else to provision
The portal
Hosted or self-hosted
Hosted by Xon Sight · default
  • Nothing to install - you get a portal URL and a webhook key, ready to point OPS Phone at
  • Uptime, backups, and updates are handled for you
Self-hosting instead · optional
  • Python 3.10+ and the packages in requirements.txt (Flask, SQLAlchemy, Flask-Login, Flask-Limiter, Flask-WTF, PyMySQL, gunicorn)
  • A database - SQLite works with zero setup (default if DATABASE_URL is blank); MySQL only for multi-tenancy
  • A reverse proxy (nginx or similar) with TLS - session cookies are hardcoded Secure, so logins silently won't work over plain HTTP
  • SECRET_KEY and XONSIGHT_WEBHOOK_KEY set in .env at minimum - see .env.example for the full list
  • Optional: ANTHROPIC_API_KEY (Assistant), hCaptcha keys (Community form), a Discord webhook URL (notifications)

Self-hosting behind multiple gunicorn workers? Point RATELIMIT_STORAGE_URI at a shared backend (e.g. redis://...) - the default in-memory limiter counts per worker, not per actual visitor, once you're past a single process.

Setting it up

Each in-game piece is an independent FiveM resource - install whichever ones your server actually uses.

1
Pick an evidence source

OPS Phone / opslabs-bodycam is the reference bodycam, but the only real requirement is something posting to the webhook - xonsight-lbphone with capture enabled can be that on its own, no separate bodycam resource needed.

2
xonsight-livesync · optional

Pushes the active-recorder roster so the Live page shows more than "no active recorders." Only meaningful alongside a bodycam resource that exposes a roster, like OPS Phone.

3
xonsight-tablet and/or xonsight-lbphone · optional

Either or both, depending on whether officers should reach the portal via a held prop, an LB Phone app, or neither - the website works fine on its own in a browser tab.

Each resource ships with its own README.md and config.lua covering exactly what to edit (mainly the portal's URL, and either the shared webhook key or a per-community token if this portal hosts more than one server). See the API reference for the wire format if you're writing your own bridge instead of using the ones above.