> ## 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.

# Community guides

> ejg.guides: each game's Steam guides, ready to read in your theme.

ejGames brings each game's **Steam community guides** (by the game's appid: the
emulator's, or the one found when the game was identified). They arrive as
**blocks**, never as HTML. Your theme decides how each title, paragraph, list,
table or image looks, and no theme receives third-party code.

If your theme paints its own guides, declare it in `theme.json`:

```json theme={null}
"features": { "explore": true, "guides": true }
```

and the host (the quick menu, or a guide link) will ask you to open them:

```js theme={null}
ejg.ui.onView(({ view, gameId, guideId }) => {
  if (view === "guides") openGuides(gameId, guideId); // guideId: open that guide now (or null)
});
```

Without `features.guides`, the host has its own window. Open it with
`ejg.ui.open("guides", { id: gameId })`.

## The fast way: the kit view

`/_sdk/kit/guides.js` brings the complete view (a list with filters, saved guides,
"keep reading", a reader with a table of contents, image zoom and a controller).
You provide the place and the look:

```html theme={null}
<link rel="stylesheet" href="/_sdk/kit/guides.css" />
```

```js theme={null}
import { createGuideView } from "/_sdk/kit/guides.js";

const view = createGuideView({
  ejg,
  root: document.getElementById("guias"), // a visible container, with a height
  focus,                                  // your createFocus()
  gameId,
  gameTitle: game.title,
  layout: "grid",                          // "list" (rows) | "grid" (cards)
  guide: guideId,                          // optional: open a guide immediately
  labels: { title: "Ayuda del juego" },    // any text can be changed
  onExit: closeGuides,                     // "Back" from the list
  onChange: () => hints.set(view.hints()),
});

// Before your own navigation: the view uses the controller first.
bindNav(focus, {
  back: () => view.nav("back") || myBack(),
  up: () => view.nav("up"),
  down: () => view.nav("down"),
  lb: () => view.nav("lb") || myTab(-1),
  rb: () => view.nav("rb") || myTab(1),
  x: () => view.nav("x"),
  y: () => view.nav("y"),
});

// On the way out (it remembers where you were):
view.destroy();
```

In the reader, **up/down** scroll the text, **LB/RB** jump between sections, **Y**
saves the guide, **X** opens it on Steam and **Back** returns to the list (or
leaves, if it was opened directly).

The look is changed with variables on `.g-view` (`--g-fg`, `--g-muted`, `--g-accent`, `--g-bg`,
`--g-surface`, `--g-surface-2`, `--g-line`, `--g-radius`, `--g-focus`, `--g-body-font`,
`--g-body-size`) and, if you want to go further, with rules on its `g-…` classes (`g-item`,
`g-chip`, `g-rbar`, `g-section-title`…). The built-in themes are good examples: each
one dresses it like its platform.

## The API

```js theme={null}
await ejg.guides.list(gameId, { page: 1, sort: "toprated", query: "", category: "", allLanguages: false });
// { appid, items: [{ id, title, desc, author, stars, preview, lang }], page, pages, total, next, filtered }

await ejg.guides.get(id);
// { id, title, authors, stars, ratings, published, updated, preview, intro: Block[],
//   sections: [{ id, title, blocks: Block[] }], lang, url, pinned, progress }

await ejg.guides.shelf(gameId);            // { pinned: [...], recent: [...] } for the profile
await ejg.guides.pin(gameId, guide, true); // save (it is listed first and can be read offline)
await ejg.guides.progress(gameId, guide, section, 0.4); // where you are (0..1 inside the section)
ejg.guides.openInBrowser(id);              // the guide on Steam's website
ejg.guides.openLink(span.href);            // a link from a guide you already read
```

* `appid: null` means the game is not identified on Steam: there are no guides to search.
* `sort`: `toprated` (highest rated), `trend` (popular) or `mostrecent` (newest).
* `category`: one of Steam's categories. The kit has the list with its Spanish name
  (`GUIDE_CATEGORIES`).
* Steam does not filter by language without a session, so ejGames guesses from the
  text. Without `allLanguages`, only **Spanish and English** guides come back (and
  the ones it cannot tell). Ask for the `next` page **from the response** to continue.

## The blocks

| `t` | What it is |
| - | - |
| `h` | a title inside a section (`level` 1–3) with `spans` |
| `p` | a paragraph. `"\n"` in the text are line breaks |
| `list` | `ordered` and `items: [{ depth, spans }]` (sublists use `depth` 1, 2…) |
| `quote` / `code` | a quote (`spans`) and code (`text`) |
| `img` | `src` served by ejg-media. `thumb`: the author made it small, off to the side |
| `table` | `rows` of cells (each cell is `spans`). `head`: the first row is a header |
| `video` | a YouTube video: `thumb` and `url` (open it with `openLink`) |
| `hr` | a separator |

Each `span` is `{ text, b, i, u, s, spoiler, href, guide }`. `href` is a website
(open it with `ejg.guides.openLink(href)`) and `guide` is another guide (open it
in your reader). If you do not want to paint them by hand, the kit's
`renderBlocks(blocks, { onLink, onGuide, onImage })` and `renderGuide(guide)` turn
them into DOM nodes with `g-…` classes.


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