# Showing Adaptive Cards while players connect

> Build interactive connecting screens with Adaptive Cards in FiveM: presentCard, designing cards in the Adaptive Cards Designer, text, images, inputs and buttons, reading Action.Submit data and submitId, chaining cards, rules acceptance and password examples, and keeping cards simple.

Source: https://fam-tools.com/guides/fivem-adaptive-cards-deferrals · FAM Tools · published 2026-09-11 · updated 2026-09-11 · about 10 min

**Short answer.** Design a card in the Adaptive Cards Designer (adaptivecards.io), export its JSON, and show it with `deferrals.presentCard(card, function(data, rawData) ... end)`. `Action.Submit` buttons call your function with the input values (and the button’s `id` as `submitId`). Chain cards by calling `presentCard` again, and end with `deferrals.done()`. Stick to simple 1.x elements and test in game.

## Key points

- `presentCard` accepts a table or a JSON string.
- `Action.Submit` → your callback gets inputs + `submitId`.
- `Action.OpenUrl` opens links (Discord, rules page).
- Always end the flow with `deferrals.done`.
- Simple layouts render most reliably.

A plain “Checking whitelist…” line is fine, but deferrals can do more: they can show an Adaptive Card — a small layout with text, images, inputs and buttons — before the player loads. Servers use it for rule acceptance, Discord links, language choice or a server password.

## Designing the card

Open the Adaptive Cards Designer, build your layout with TextBlock, Image, Input.Text, Input.ChoiceSet and ActionSet elements, and copy the card JSON. Keep images hosted on HTTPS and small.

## Example: accept the rules

*server.lua*

```lua
local card = {
    type = 'AdaptiveCard',
    version = '1.0',
    body = {
        { type = 'TextBlock', text = 'Welcome to Los Santos RP', size = 'Large', weight = 'Bolder' },
        { type = 'TextBlock', text = 'No random deathmatch. Value your life. Respect staff decisions.', wrap = true },
    },
    actions = {
        { type = 'Action.Submit', title = 'I accept the rules', id = 'accept' },
        { type = 'Action.OpenUrl', title = 'Read all rules', url = 'https://example.com/rules' },
        { type = 'Action.Submit', title = 'Leave', id = 'leave' },
    },
}

AddEventHandler('playerConnecting', function(name, setKickReason, deferrals)
    deferrals.defer()
    Wait(0)

    deferrals.presentCard(card, function(data)
        if data.submitId == 'accept' then
            deferrals.done()
        else
            deferrals.done('You need to accept the rules to play.')
        end
    end)
end)
```

Remember accepted players (for example by licence in the database) so the card only appears on their first join.

## Reading inputs

*server.lua — a password field*

```lua
local passwordCard = {
    type = 'AdaptiveCard', version = '1.0',
    body = {
        { type = 'TextBlock', text = 'This server is in closed testing.', wrap = true },
        { type = 'Input.Text', id = 'password', placeholder = 'Password' },
    },
    actions = { { type = 'Action.Submit', title = 'Join', id = 'join' } },
}

-- inside playerConnecting, after defer + Wait(0):
deferrals.presentCard(passwordCard, function(data)
    if data.password == GetConvar('beta_password', '') then
        deferrals.done()
    else
        deferrals.done('Wrong password.')
    end
end)
```

Input values arrive keyed by their `id`. Keep the password in a server-only convar (`set`, not `setr`). The field is not masked, so treat it as a light gate, not real security.

## Chaining cards

Call `presentCard` again inside the callback to show the next step — language choice, then rules, then a welcome — and call `done` at the end. Two or three steps are plenty; players want to play.

## Tips

- Test every card in the real client — not every designer feature renders the same in FiveM.
- Do not rely on colours or fancy layouts; the host app decides much of the styling.
- Keep text short; long rules belong on a website or the loading screen — see [rules on the loading screen](https://fam-tools.com/guides/fivem-loading-screen-rules-and-info).
- Handle players who close the game mid-card: nothing to clean up, but do not leave state waiting for them.

## Questions

### How do I show a card when players connect to FiveM?

Call `deferrals.presentCard(cardJsonOrTable, callback)` inside `playerConnecting` after `deferrals.defer()` and a one-tick wait.

### How do I know which button was pressed?

Give each `Action.Submit` an `id`; it arrives in the callback data as `submitId`.

### Where can I design Adaptive Cards?

In the Adaptive Cards Designer on adaptivecards.io; copy the JSON into your script.

### Can I put a password on my FiveM server?

Yes — show a card with an `Input.Text` and compare the submitted value with a server-only convar.

## Related

- https://fam-tools.com/guides/fivem-deferrals-connecting-cards
- https://fam-tools.com/guides/fivem-connect-queue-priority
- https://fam-tools.com/guides/fivem-loading-screen-rules-and-info
- https://fam-tools.com/guides/fivem-whitelist-application-process
