> ## Documentation Index
> Fetch the complete documentation index at: https://ej3mplo.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# The kit

> Optional modules with no dependencies, in /_sdk/kit/.

Modules with no dependencies, in `/_sdk/kit/`. Import only what you use:

```js theme={null}
import { h, img, keyed, debounce, initials, hueOf } from "/_sdk/kit/dom.js";
import { createFocus, bindNav } from "/_sdk/kit/focus.js";
import { createBackdrop, attachStream, trailerPlayer, idle } from "/_sdk/kit/media.js";
import { playtime, relative, date, year, description, SOURCE_LABEL } from "/_sdk/kit/format.js";
import { visible, sort, recent, favorites, byGenre, search, inCollection, canUninstall, SORTS } from "/_sdk/kit/library.js";
import { clock } from "/_sdk/kit/clock.js";
import { artFor } from "/_sdk/kit/art.js";
import { hints, glyph } from "/_sdk/kit/hints.js";
import { createGuideView, createGuides, renderGuide, renderBlocks, GUIDE_CATEGORIES } from "/_sdk/kit/guides.js";
```

* **`createFocus` + `bindNav`**: spatial navigation with a controller. Mark what can be
  reached with `data-focus`, group rows with `data-focus-group` (it remembers each
  group's last focus) and enclose dialogs with `data-focus-trap`. The focused element
  receives the class `is-focused`.
  * **With the mouse:** passing over focuses, and leaving removes the class so it
    does not stay marked. With a controller, the cursor is hidden and `:hover` does
    not apply.
  * **`onChange(el, prev, { pointer })`:** if `pointer` is `true`, focus came from
    the mouse. In that case do not scroll or select anything, because the element
    would move out from under the cursor.
* **`artFor(game, "portrait" | "square" | "landscape")`**: art that fits the frame
  without cropping logos. In square and landscape it composes the game's background
  with its logo on top. If something is missing, it falls back to the centered cover,
  the header, or the name. It returns an element that fills its container.
* **`hints(container, [[action, text], …])`**: the control hint bar.
* **`keyed(container, list, key, render)`**: reuses nodes when redrawing, so focus
  does not jump and it stays fast with hundreds of games.
* **`createBackdrop`**: a background that crossfades between images, with video on top.
* **`createGuideView`**: a game's Steam community guides, with a list, a reader and
  controller support, ready to mount in your theme (with `/_sdk/kit/guides.css`). See
  [Community guides](https://ej3mplo.mintlify.site/referencia/guias.md).
* **`createHomebrewView`**: the Homebrew view (emulators and console games, with links
  to their stores), with a controller and a layout per platform. See [Homebrew](https://ej3mplo.mintlify.site/referencia/homebrew.md).

A minimal skeleton:

```js theme={null}
import { h, img, keyed } from "/_sdk/kit/dom.js";
import { createFocus, bindNav } from "/_sdk/kit/focus.js";
import { visible, sort } from "/_sdk/kit/library.js";

const ejg = await window.ejg.ready();
const grid = document.querySelector("#grid");
const focus = createFocus();
bindNav(focus, { y: () => ejg.game.favorite(Number(focus.current?.dataset.id)) });

function render() {
  keyed(grid, sort(visible(ejg.library.all)), (g) => g.id, (g, prev) =>
    prev ?? h("button", { class: "card", "data-focus": "", "data-id": g.id, onclick: () => ejg.game.launch(g.id) },
      img(g.media.coverThumb), h("span", null, g.title)));
}
ejg.library.onChange(render);
render();
focus.first(grid);
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.