# Overview

koja-lib abstracts the differences between ESX and QBCore so your scripts work on both without any changes.

***

## Supported Frameworks

| Framework | Resource Name | Config value |
| --------- | ------------- | ------------ |
| ESX       | `es_extended` | `"esx"`      |
| QBCore    | `qb-core`     | `"qb"`       |
| QBX Core  | `qbx_core`    | `"qb"`       |
| Custom    | —             | `"custom"`   |

QBCore and QBX Core both map to the `"qb"` internal identifier. koja-lib resolves the correct core object automatically.

***

## Detection Order

When `Config.Framework = "auto"`, koja-lib checks resources in this order:

1. `es_extended`
2. `qbx_core`
3. `qb-core`

The first one found in `started` state is used. If none are running, the framework is set to `"custom"`.

***

## Runtime Value

The resolved framework is available at runtime:

```lua
-- Shared (client and server)
print(KOJA.Framework)  -- "esx" | "qb" | "custom"
```

***

## Forcing a Framework

Set `Config.Framework` to skip auto-detection:

```lua
Config.Framework = "qb"  -- always use QBCore, even if ESX is also running
```

***

## How the Bridge Works

Every public koja-lib function is framework-agnostic. Internally, koja-lib maps each call to the correct native API:

```lua
-- Your script:
local job = KOJA.Server.GetPlayerJob(source)
-- Returns: { name = "police", grade = 2 }

-- On ESX this calls:    ESX.GetPlayerFromId(source).getJob()
-- On QBCore this calls: QBCore.Functions.GetPlayer(source).PlayerData.job
```

You never need to check `KOJA.Framework` in your scripts unless you are doing something framework-specific.

## Related pages

- [Custom Framework](/koja-lib/frameworks/custom-framework) — If you run a framework other than ESX or QBCore, set Config.Framework = "custom" and fill in the stub files.
- [Frameworks](/koja-lib/frameworks) — back to the section overview
