# Use Redoc CE in HTML

To render API documentation in an HTML page:

1. Paste the following template into an HTML file.

  ```html
  <!DOCTYPE html>
  <html>
    <head>
      <title>Redoc CE</title>
      <!-- needed for adaptive design -->
      <meta charset="utf-8"/>
      <meta name="viewport" content="width=device-width, initial-scale=1">

      <!--
      Redoc CE doesn't reset the body margin
      -->
      <style>
        body {
          margin: 0;
          padding: 0;
        }
      </style>
    </head>
    <body>
      <redoc spec-url="https://redocly.github.io/redoc/cafe.yaml"></redoc>
      <script type="module" src="https://cdn.redoc.ly/redoc/v3.x/bundles/redoc.standalone.js"></script>
    </body>
  </html>
  ```
2. Replace the value of `spec-url` with either:

    - a path to a local description file, for example: `spec-url="openapi.yaml"` or `spec-url="/openapi.yaml"`
    - a full URL, for example: `spec-url="https://redocly.github.io/redoc/cafe.yaml"`
  The description can be an OpenAPI, AsyncAPI, or GraphQL file.
  A relative path is resolved against the page URL, like any other link: `spec-url="openapi.yaml"` on the page `/docs/index.html` loads `/docs/openapi.yaml`.
  A root-relative path, which starts with `/`, loads the same file from any page: `spec-url="/openapi.yaml"` loads `/openapi.yaml`.
  If the server serves the page at `/docs` without a trailing slash, a relative path resolves against the site root instead, so `spec-url="openapi.yaml"` loads `/openapi.yaml`.

To test the HTML file, open it in your browser.
The page works directly from disk when the script comes from the CDN and the description from a URL.
A description file on your disk does not load from a `file://` page, so serve the folder with a static file server, for example `npx http-server` or `python3 -m http.server`, or reference the file by URL.

When the description cannot be loaded or parsed, Redoc CE shows a **Failed to load API description** message in the element.
The message includes the underlying error.

## Render AsyncAPI and GraphQL descriptions

The same element renders AsyncAPI and GraphQL descriptions, and Redoc CE detects the specification type from the file.

```html
<redoc spec-url="https://redocly.github.io/redoc/specs/cafe-asyncapi-amqp.yaml"></redoc>
```

```html
<redoc spec-url="https://redocly.github.io/redoc/specs/cafe.graphql"></redoc>
```

A GraphQL schema served from an API endpoint works as well.
A URL that does not load as OpenAPI or AsyncAPI is read as a GraphQL schema.
The detection rules and the supported versions are listed in [Supported specifications](/docs/redoc/v3.x/supported-specifications).

## Configure Redoc CE

Redoc CE is highly configurable - see the [full list of configuration options](/docs/redoc/v3.x/config).

To configure Redoc CE in HTML, add options as attributes of the `<redoc>` element.
Attribute names are the kebab-case form of the option names: `sortRequiredPropsFirst` becomes `sort-required-props-first`.
A camelCase attribute is ignored, because HTML lowercases attribute names.
For an on/off option, a bare attribute or any value except `false` turns the option on.
The exception is `disable-telemetry`, which works only with the value `true`.

The following example lists required properties first, groups all schemas under a **Schemas** entry in the sidebar, and hides the download panel:

```html
<redoc
  spec-url="https://redocly.github.io/redoc/cafe.yaml"
  sort-required-props-first="true"
  schema-definitions-tag-name="Schemas"
  hide-download-buttons="true"
></redoc>
```

You can add as many configuration attributes as you need.

### Theme configuration

Redoc CE uses [CSS variables](https://redocly.com/docs/realm/branding/css-variables) under the hood.
To customize your API documentation's appearance, override these variables in a stylesheet on your page.

Redoc CE sets a `light` or `dark` class on the `<html>` element.
It follows the reader's system preference at first, and the choice they make with the color mode switcher at the bottom of the sidebar afterwards.
Scope every override to a color mode: `:root.light` for light, `:root.dark` for dark, and `:root.light, :root.dark` for values shared by both.
A plain `:root` rule has no effect, because Redoc CE adds its own `:root` styles when it starts and they override yours.

The following example sets the sidebar width for both color modes, and the accent color and the sidebar background for each one:

```css
/* Shared by both color modes */
:root.light,
:root.dark {
  --sidebar-width: 280px;
}

/* Light mode */
:root.light {
  --color-primary-base: #2563eb;
  --sidebar-bg-color: #eef2ff;
}

/* Dark mode */
:root.dark {
  --color-primary-base: #60a5fa;
  --sidebar-bg-color: #1e293b;
}
```

To use this code, either:

- Put the CSS code inside a `<style>` tag in the `<head>` of your page.
- Create a new CSS file and link it on your page: `<link rel="stylesheet" href="redoc-theme.css">`.

The [common CSS variables](https://redocly.com/docs/realm/branding/css-variables/common) and [API docs CSS variables](https://redocly.com/docs/realm/branding/css-variables/api-docs) list the variables you can override.

## Advanced options

### The `init` function

As an alternative to the HTML attributes, you can also initialize Redoc CE from JavaScript.
Use this method to:

- pass options that are objects or arrays
- render into your own container
- create dynamic content in a page

The standalone bundle is an ES module that exports an `init` function:

```js

import { init } from 'https://cdn.redoc.ly/redoc/v3.x/bundles/redoc.standalone.js';

init(specOrSpecUrl, options, element);
```

Where:

- `specOrSpecUrl`: a URL or path to the description file, a parsed description object, a JSON string, or a GraphQL schema in SDL
- `options` (optional): the [configuration options](/docs/redoc/v3.x/config), plus the standalone options `router`, `basePath`, and `disableTelemetry`
- `element` (optional): the DOM element Redoc CE renders into.
  Defaults to the first `<redoc>` element on the page.
  If you omit `element` and the page has no **redoc**  element, `init` throws an error.

Attributes on the target element are merged into the options and take precedence over them, so a page can combine both approaches.
When you call `init` yourself, leave the `spec-url` attribute off the element.
Otherwise, the element also initializes itself.

The following example is an HTML page with a `<div>` container and a module script that renders Redoc CE into it.
It shows specification extensions, lists required properties first, and adds a download link to the panel on the overview page:

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Redoc CE</title>
  </head>
  <body>
    <h1>Redoc CE in action</h1>
    <div id="redoc-container"></div>

    <script type="module">
      import { init } from 'https://cdn.redoc.ly/redoc/v3.x/bundles/redoc.standalone.js';

      init(
        'https://redocly.github.io/redoc/cafe.yaml',
        {
          showExtensions: true,
          sortRequiredPropsFirst: true,
          downloadUrls: [
            { title: 'Download OpenAPI description', url: 'https://redocly.github.io/redoc/cafe.yaml' },
          ],
        },
        document.getElementById('redoc-container'),
      );
    </script>
  </body>
</html>
```

### The `hydrate` function

The bundle also exports `hydrate`, which attaches Redoc CE to markup that was rendered on a server, instead of replacing it.
Hydration adds interactivity to server-rendered pages, such as the static HTML that Redocly CLI `build-docs` produces.
It takes the same arguments as `init` and returns a promise.
The spec must be the same pre-bundled document the server rendered from.

```js
import { hydrate } from 'https://cdn.redoc.ly/redoc/v3.x/bundles/redoc.standalone.js';

await hydrate(spec, { router: 'history', basePath: '/docs' });
```

### Self-host dependencies

You can reference the Redoc CE script in two ways.
Use a link to the files hosted on a CDN, or install Redoc CE in your `node_modules` folder.
Self-hosting is useful when you need to host in a closed environment or have requirements around external dependencies.

The standalone bundle includes React and every other dependency, so a single file is all you need to serve.

**Use CDN**

To reference Redoc CE hosted on a CDN:

- In the `<script>` tag, add an `src` attribute with the URL to the Redoc CE script.

  ```html
  <script type="module" src="https://cdn.redoc.ly/redoc/v3.x/bundles/redoc.standalone.js"></script>
  ```

The `v3.x` path follows the newest 3.x release.
To pin an exact version, replace `v3.x` with the version number, in the form `v3.<minor>.<patch>`.
The `latest` path follows the newest release across major versions.

The same file is available from jsDelivr, which mirrors the npm package:

```html
<script type="module" src="https://cdn.jsdelivr.net/npm/redoc@3/bundles/redoc.standalone.js"></script>
```

**Self-host dependencies**

To host the dependencies yourself:

1. Install `redoc` using `npm`.

  ```sh
  npm install redoc
  ```
2. Reference the Redoc CE script with a node modules link.

  ```html
  <script type="module" src="node_modules/redoc/bundles/redoc.standalone.js"></script>
  ```

## Use Redoc CE with FastAPI

FastAPI serves Redoc CE 2.x at `/redoc` with its `get_redoc_html()` function.
The function loads the script with a classic `<script>` tag, and the Redoc CE 3.x bundle loads only as a module script.
Passing a 3.x URL in `redoc_js_url` alone renders a blank page, and the browser console shows `Cannot use 'import.meta' outside a module`.

To serve Redoc CE 3.x, turn off the built-in page and add a route that changes the tag to `<script type="module">`:

```python
from fastapi import FastAPI
from fastapi.openapi.docs import get_redoc_html
from fastapi.responses import HTMLResponse

app = FastAPI(redoc_url=None)

@app.get("/redoc", include_in_schema=False)
async def redoc():
    response = get_redoc_html(
        openapi_url=app.openapi_url,
        title=f"{app.title} - Redoc",
        redoc_js_url="https://cdn.redoc.ly/redoc/v3.x/bundles/redoc.standalone.js",
        with_google_fonts=False,
    )
    html = response.body.decode("utf-8")
    html = html.replace("<script src=", '<script type="module" src=', 1)
    return HTMLResponse(html)
```

`with_google_fonts=False` skips the Google Fonts stylesheet.
Redoc CE 3.x uses the system font, instead of the Montserrat and Roboto fonts that FastAPI loads for Redoc CE 2.x.

The [FastAPI example](https://github.com/Redocly/redoc/tree/main/examples/fastapi) is a complete app with this route.
The route depends on the HTML that `get_redoc_html()` generates.
To own the whole page instead, return the HTML template from the start of this page, with `spec-url` set to `app.openapi_url`.

## Resources

- **[Redoc CE deployment guide](/docs/redoc/v3.x/deployment/intro)** - Step-by-step instructions for setting up your Redoc CE project
- **[Configure Redoc CE](/docs/redoc/v3.x/config)** - Every option you can pass as an attribute or in the `init` options object
- **[Telemetry in Redoc CE](/docs/redoc/v3.x/telemetry)** - What Redoc CE collects and how to turn it off
