Beside the client, the request the reader has built — written out in the language
they work in, and rewritten on every keystroke.

## What ships

| Group        | Clients                             |
| :----------- | :---------------------------------- |
| `curl`       | curl                                |
| TypeScript   | `fetch`, `$fetch`, `useFetch`, axios |
| Python       | requests, httpx, urllib             |
| Go           | `net/http`                          |
| PHP          | Guzzle, Laravel `Http`, curl extension |

**Seven are on by default:** curl, `fetch`, `$fetch`, Python requests, Go, Guzzle
and Laravel `Http`. The other five are the second client for a language that
already has one on screen, and a picker is for choosing rather than for listing
everything that exists.

## Two levels

The language is the tab and the client a select inside it, so PHP with three
clients costs one tab. A site adding three of its own for one language still
costs one. The reader's choice is remembered across pages — a reader who works in
curl works in curl on the next endpoint too.

## Configuring the list

```ts
export default defineAppConfig({
  duxt: {
    requestSamples: ['curl', 'php-guzzle', 'php-laravel']
  }
})
```

A string picks one that ships; the ids are `curl`, `fetch`, `ofetch`,
`use-fetch`, `axios`, `python-requests`, `python-httpx`, `python-urllib`, `go`,
`php-guzzle`, `php-laravel`, `php-curl`.

The list **replaces** rather than extends, like every other list in the config:
otherwise a site documenting a PHP API could add its clients but never drop the
ones it does not want. The order is the order they appear in.

## Your own generator

An object adds one of your own — or replaces one that ships, by reusing its id.

```ts
requestSamples: [
  'curl',
  {
    id: 'ruby',
    group: 'Ruby',
    label: 'Net::HTTP',
    language: 'ruby',
    generate: (request) => `
uri = URI('${request.url}')
Net::HTTP.get(uri)
`.trim()
  }
]
```

| Field      | Type                                    | Notes                                     |
| :--------- | :-------------------------------------- | :---------------------------------------- |
| `id`       | `string`                                | Stable: it is also the remembered value   |
| `group`    | `DuxtText`                              | The tab                                   |
| `label`    | `DuxtText`                              | The entry inside the tab                  |
| `language` | `string`                                | A Shiki id — it decides the grammar       |
| `generate` | `(request) => string`                   | Synchronous, pure, no network, no DOM     |

`generate` runs in the **browser**, on every keystroke, because the sample has to
follow the request being edited. `request` is `{ method, url, headers, body?, responseType? }`,
where `body` is the editor's text and not parsed — a generator that wants it as
data parses it itself, and gets to decide what to do when it is not JSON.


### Why TypeScript and not JavaScript

`$fetch`, `useFetch` and axios all take the response shape as a type parameter,
and `responseType` is what fills it: `$fetch<Widget>(…)` is the line somebody
actually writes. `fetch` has none — it returns a `Response` whatever the body
turns out to be — so its sample is the same in either language.

That is also why there is one group and not two. A JavaScript group beside this
one would carry a `fetch` that never differs and three clients that differ only
where the document named its response schema, for twice the tabs.

`responseType` is the component name of what a successful response returns —
`Widget`, or `Widget[]` for a list. It is absent where the response schema is
inline rather than a `$ref`, and a sample then simply has no type parameter:
nothing here invents a name the document did not give.

## What a sample shows

**The request, and nothing after it.** The response is already on screen in the
panel below the editor, so a sample that fetched it a second time would be showing
the reader something they can see — at the cost of an error branch in every
language that has one.

Go is the exception and keeps its `err` checks: without them it is not Go, and a
snippet that does not compile is worse than a long one.

## Grammars are paid for, not assumed

These samples are coloured in the browser, so every language is bytes a reader
downloads — unlike a Markdown fence, whose grammar is a build-time cost and never
reaches a browser at all.

So the grammar set is **generated from the list above**: a site ships exactly the
languages its samples name. The default seven need six grammars. Loading Shiki's
own lazy map instead would cost 3 KB and make every build emit 242 grammar
chunks.

## Samples from the document

`x-codeSamples` — under either spelling, the older `x-code-samples` included — is
read off an operation, and **replaces the generated samples for its language**.
The person who owns the API knows its idioms better than a generator does.

```yaml
paths:
  /pets:
    get:
      x-codeSamples:
        - lang: ruby
          label: Net::HTTP
          source: |
            Net::HTTP.get(URI('https://api.example.com/pets'))
```

Such a sample is **static** — it cannot follow the reader's edits — so the panel
says who wrote it and that it does not follow the edits above. A reader who
changed the body and switched to it would otherwise conclude the editor is broken
rather than that this sample is fixed.

Its language is not visible where the grammar set is written: a remote source has
not been cloned yet. So name it:

```ts
duxt: {
  sampleLanguages: ['ruby']
}
```

Without that the sample renders as plain text.