> For the complete documentation index, see [llms.txt](https://nodemods.gitbook.io/nodemods-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://nodemods.gitbook.io/nodemods-docs/ls-customs/framework-setup.md).

# Framework Setup Guide

## Overview

LS Customs supports QBCore, QBox, ESX out of the box, plus Standalone, vRP and vRPv2 as adapter templates you finish yourself. Set `Config.Framework` in `config/config.lua` to match yours, then follow the permission setup below (it differs per framework) and getting it wrong is the most common reason Advanced Systems or the admin panel silently fails to gate correctly.

## Requirements

* `oxmysql`
* One of: `qb-core` (QBCore), `qbx_core` (QBox), `es_extended` (ESX), or nothing (Standalone / custom framework)

## Permission Model

Permission checks (Advanced Systems purchases, the admin panel, and per-entry permissions in `config/config_advanced_systems.lua`) are resolved differently depending on framework:

* **QBCore / QBox**: permission names are passed to `QBCore.Functions.HasPermission` (QBCore) or checked as ACE permissions (QBox).
* **ESX / Standalone**: permission names are checked as ACE permissions via `IsPlayerAceAllowed`. Grant them in `server.cfg`, for example:

  ```cfg
  add_ace group.admin nm-ls-customs.admin allow
  add_ace group.admin advancedSystems allow
  ```
* **vRP / vRPv2**: these adapters are templates only — `HasPermission` returns `false` and `GetWalletBalance`/`TryPayment` are unimplemented until you fill them in under `server/framework/<framework>/`.

## Persistent Vehicle Ownership (Biometric, Locator, Dashcam)

The remote security features (biometric authorization, Locator, Dashcam) require the framework adapter to prove *persistent* vehicle ownership — a database record tying the vehicle to an account — not just current-session access.

This is implemented for **QBCore, QBox, and ESX only.**

**Standalone, vRP, vRPv2 do not support these features out of the box.** Installing or using biometric security, Locator, or Dashcam on those frameworks will fail with an error, by design, until you implement `persistentOwnership`/`hasPersistentRecordAccess` in your `server/framework/<framework>/db_mapping.lua` adapter. If you don't need these features on an unsupported framework, disable them in `Config.Features.Security` in `config/config.lua`.

| Framework   | Core customization | Advanced Systems  | Persistent security (Biometric/Locator/Dashcam) |
| ----------- | ------------------ | ----------------- | ----------------------------------------------- |
| QBCore      | ✅                  | ✅                 | ✅                                               |
| QBox        | ✅                  | ✅                 | ✅                                               |
| ESX         | ✅                  | ✅                 | ✅                                               |
| Standalone  | ✅                  | ✅ (ACE)           | ❌ (until adapter is implemented)                |
| vRP / vRPv2 | ✅                  | ❌ (template only) | ❌ (until adapter is implemented)                |

## Implementing an Unsupported Framework Adapter

To add persistent-ownership support (or finish a vRP/vRPv2 template) for a framework that doesn't have it yet:

1. Open `server/framework/<framework>/db_mapping.lua`.
2. Implement `persistentOwnership` and `hasPersistentRecordAccess` so they resolve a stable, account-tied identifier for the vehicle (not the current server ID or plate — those change).
3. For vRP/vRPv2 specifically, also implement `HasPermission`, `GetWalletBalance`, and `TryPayment` in `server/framework/<framework>/`.
4. Test the full lifecycle: install, add/remove an authorized user, authorized vs. unauthorized driving, uninstall/reinstall, and a resource restart.

## QBCore Mechanic Job Stream Conflict

`qb-mechanicjob` ships its own copies of the chameleon paint stream files (`veh_xs_vehicle_mods_*.ypt`, `vehicle_paint_ramps.ytd`). Because both resources register the same GTA stream names, whichever resource starts last wins, which can silently break or revert LS Customs' chameleon paint effects.

If you run `qb-mechanicjob` alongside LS Customs, either:

1. Remove the conflicting `veh_xs_vehicle_mods_*.ypt` and `vehicle_paint_ramps.ytd` files from `qb-mechanicjob`'s stream folder, or
2. Disable `qb-mechanicjob`'s own chameleon/paint job feature entirely,

so only LS Customs' copies (in `stream/`) are loaded.

## Best Practices

1. Set `Config.Framework` correctly before first launch — the wrong value will cause permission checks to fail closed for everyone, including admins.
2. If your framework isn't QBCore/QBox/ESX, disable `Config.Features.Security.biometric`/`.locator`/`.dashcam` until you've implemented the ownership adapter, rather than leaving buyers to hit a runtime error.
3. Grant Advanced Systems permissions deliberately — the default permission name (`advancedSystems`) is shared by every entry unless you set a per-entry `permission` in `config_advanced_systems.lua`.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://nodemods.gitbook.io/nodemods-docs/ls-customs/framework-setup.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
