> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# Recipes

These snippets use only public APIs and omit the host's own data loading and error handling. Component overrides, resolvers, and plugins are trusted code; review them against the [security model](/guide/security.md) before shipping.

## Site theme and dark mode

Styles are driven by CSS variables. Classes and attributes on the container can participate in selectors:

```css
.wiki-article {
  --wtr-text: #1f2328;
  --wtr-accent: #0969da;
  --wtr-border: #d0d7de;
  --wtr-placeholder-bg: #f6f8fa;
}

.wiki-article[data-theme="dark"] {
  --wtr-text: #e6edf3;
  --wtr-accent: #4493f8;
  --wtr-border: #30363d;
  --wtr-placeholder-bg: #161b22;
}
```

```tsx
import { Wikitext } from "react-wikitext";
import "react-wikitext/styles.css";

<Wikitext source={source} className="wiki-article" containerProps={{ "data-theme": theme }} />;
```

The same source in light and dark themes:

```tsx preview
import { Wikitext } from "react-wikitext";
import "react-wikitext/styles.css";

const source = `== Theme example ==
'''Body text''', ''emphasis'', and a [[link]].

{{Infobox|title=Template placeholder}}`;

const css = `
.recipe-theme {
  --wtr-text: #1f2328;
  --wtr-muted: #57606a;
  --wtr-border: #d0d7de;
  --wtr-accent: #0969da;
  --wtr-accent-soft: #ddf4ff;
  --wtr-placeholder-bg: #f6f8fa;
  padding: 12px;
  border: 1px solid #d0d7de;
  border-radius: 8px;
  background: #ffffff;
}
.recipe-theme--dark {
  --wtr-text: #e6edf3;
  --wtr-muted: #8b949e;
  --wtr-border: #30363d;
  --wtr-accent: #58a6ff;
  --wtr-accent-soft: #172a45;
  --wtr-placeholder-bg: #161b22;
  border-color: #30363d;
  background: #0d1117;
}
.recipe-theme + .recipe-theme { margin-top: 12px; }
`;

export default function Demo() {
  return (
    <div>
      <style>{css}</style>
      <div className="recipe-theme">
        <Wikitext source={source} lang="en" />
      </div>
      <div className="recipe-theme recipe-theme--dark">
        <Wikitext source={source} lang="en" />
      </div>
    </div>
  );
}
```

See [Styling and components](/guide/customization.md) for the variable list.

## Site routes and an image CDN

Leave routing and media URLs to the host; the library only validates and renders. Define resolvers at module scope so preparation is not repeated:

```tsx
import type { WikitextImageResolver, WikitextLinkResolver } from "react-wikitext/hast";

const resolveLink: WikitextLinkResolver = (request) => {
  if (request.kind !== "internal") return undefined;
  const page = request.page ?? request.target;
  const fragment = request.fragment ? `#${request.fragment}` : "";
  return { href: `/wiki/${encodeURIComponent(page)}${fragment}`, target: "_self" };
};

const resolveImage: WikitextImageResolver = (request) => ({
  src: `https://cdn.example.com/wiki/${encodeURIComponent(request.name)}`,
  alt: request.alt ?? request.name,
  ...(request.width === undefined ? {} : { width: request.width }),
  ...(request.height === undefined ? {} : { height: request.height }),
});
```

```tsx
<Wikitext source={source} prepareOptions={{ resolveLink, resolveImage }} lang="en" />
```

Return-value semantics and policy are in [Links and images](/guide/links-and-images.md).

## Template cards

Do not expand templates, but render the invocation as a site-specific card:

```tsx preview
import { Wikitext } from "react-wikitext";
import { WikitextFragment, type WikitextTemplateComponentProps } from "react-wikitext/view";
import "react-wikitext/styles.css";

function TemplateCard({ displayName, node }: WikitextTemplateComponentProps) {
  return (
    <aside style={{ border: "1px solid #d0d7de", borderRadius: 8, padding: 12, margin: "8px 0" }}>
      <strong>{displayName}</strong>
      <WikitextFragment nodes={node.children} mode="block" />
    </aside>
  );
}

export default function Demo() {
  return (
    <Wikitext
      source={"{{Infobox|title=Example|body=Template arguments appear in the card}}"}
      lang="en"
      semanticComponents={{ template: TemplateCard }}
    />
  );
}
```

`WikitextFragment` must be used inside the `WikitextView` context and can only render nodes from the current document.

## Article table of contents

The library does not have to own the TOC. For a site sidebar, read `headings` from the render snapshot and pin the anchor strategy:

```tsx
import { useMemo } from "react";
import { createWikiparser } from "react-wikitext/parse";
import { prepareWikitext } from "react-wikitext/hast";
import { WikitextView } from "react-wikitext/view";
import "react-wikitext/styles.css";

const parser = createWikiparser();

export function Article({ source }: { source: string }) {
  const prepared = useMemo(
    () => prepareWikitext(parser.parse(source), { headingIdStrategy: "mediawiki" }),
    [source],
  );

  return (
    <div className="article-layout">
      <nav aria-label="Contents">
        <ol>
          {prepared.headings.map((heading) => (
            <li key={heading.nodeId} data-level={heading.level}>
              {heading.id ? <a href={`#${heading.id}`}>{heading.text}</a> : heading.text}
            </li>
          ))}
        </ol>
      </nav>
      <WikitextView document={prepared} />
    </div>
  );
}
```

- The `mediawiki` strategy writes bare anchors and assumes a single instance per page.
- For multiple instances, keep the default `instance` strategy; inside the view, use `useWikitextIds().toHref` to get the real link.
- The in-page TOC is still generated; to keep only the sidebar, hide `.wtr-toc` with host CSS or use `__NOTOC__` in the source.

## Reporting render failures

The view isolates failures per top-level block; parse and prepare errors belong to the caller:

```tsx
import type { WikitextDocument } from "react-wikitext/ast";
import type { WikitextPrepareOptions } from "react-wikitext/hast";
import { prepareWikitext, WikitextPrepareError } from "react-wikitext/hast";
import { WikitextView } from "react-wikitext/view";

function renderPrepared(document: WikitextDocument, prepareOptions: WikitextPrepareOptions) {
  try {
    return <WikitextView document={prepareWikitext(document, prepareOptions)} />;
  } catch (error) {
    if (error instanceof WikitextPrepareError) {
      report(error.code, error.stage, error.cause);
    }
    throw error;
  }
}
```

```tsx
<Wikitext
  source={source}
  onRenderError={(error, { node }) => {
    report("render", error, { nodeId: node.id, nodeType: node.type });
  }}
/>
```

`labels.renderFailed` controls the block placeholder title; see [Errors and diagnostics](/api/errors.md).
