The `Renderer` is the central singleton that creates views, manages sessions, and runs web pages inside your app.

It coordinates page loading, JavaScript execution, and View painting across the entire library.

> 📘 Using AppCore
>
> When using AppCore, the `Renderer` is automatically created and managed for you in `App::Create()` (you can still customize the `Config`, however)— see [App Lifecycle and Settings](/docs/2.0/app-lifecycle-and-settings).

## Setup Order

Before creating views or rendering frames, you must configure the library and initialize the platform singleton. Steps 1 and 2 can run in either order, but both must finish before calling `Renderer::Create()`.

| Step | Action | Guide |
| :--- | :--- | :--- |
| 1 | Set library configuration options on the platform singleton using `Platform::instance().set_config()`. | This page |
| 2 | Register platform handlers on `Platform::instance()`, such as a font loader and file system. | [Setting Up the Platform](/docs/2.0/setting-up-the-platform) |
| 3 | Create the renderer instance with `Renderer::Create()`. | This page |
| 4 | Configure sessions for storing site data and cookies (a default session is created automatically). | [Sessions and Site Data](/docs/2.0/sessions-and-site-data) |
| 5 | Create views using `Renderer::CreateView()`. | [Creating Views](/docs/2.0/creating-views) |
| 6 | Update timers, advance animations, and render frames in the main loop. | [Updating and Rendering](/docs/2.0/updating-and-rendering) |

## Creating the Renderer Instance

Call `Renderer::Create()` after registering platform handlers, storing the instance in a `RefPtr` to keep it alive (see [Setting Up the Platform](/docs/2.0/setting-up-the-platform)):

```cpp
RefPtr<Renderer> renderer;

void CreateRenderer() {
  ///
  /// Register the platform handlers first.
  ///
  InitPlatform();

  renderer = Renderer::Create();
}
```

> 🚧 Create One Renderer Per Application
>
> You should create only one `Renderer` during the lifetime of your program. Initialize the instance once at startup and keep it alive until shutdown.

### The Renderer's Thread

The thread that calls `Renderer::Create()` becomes the Renderer's thread. Tasks posted with `Renderer::PostTask()` run on the Renderer's thread during a later call to `Renderer::Update()`.

> 🚧 Thread Restrictions
>
> You must make all `Renderer` and `View` calls on the Renderer's thread only. Both `Renderer::PostTask()` and `Renderer::PostDelayedTask()` are safe to call from any thread to hand work to the Renderer's thread— see [Integrating into a Game Engine](/docs/2.0/integrating-into-a-game-engine).

## Configuring the Library

The `Config` struct sets library-wide options, while per-view options use `ViewConfig`— see [Creating Views](/docs/2.0/creating-views).

Populate the struct and pass it to `Platform::instance().set_config()` before calling `Renderer::Create()`. The renderer reads these settings when it is created.

The library copies the configuration immediately, so allocating a `Config` on the stack is fine.

Set configuration values on the platform singleton before creating the renderer (the C version sits in the tab below):

<!-- tabs:start -->
```cpp
void Init() {
  InitPlatform();

  ///
  /// Let's set some custom global CSS to make our background
  /// purple by default.
  ///
  Config config;
  config.user_stylesheet = "body { background: purple; }";

  ///
  /// Store persistent Session data in a writable folder.
  ///
  config.cache_path = "./ultralight_cache/";

  ///
  /// Pass our configuration to the Platform singleton, then create
  /// the Renderer.
  ///
  Platform::instance().set_config(config);
  renderer = Renderer::Create();
}
```
```c
#include <Ultralight/CAPI.h>

static ULRenderer renderer = NULL;

void Init(void) {
  ULConfig config = ulCreateConfig();

  ///
  /// Let's set some custom global CSS to make our background
  /// purple by default.
  ///
  ULString css = ulCreateString("body { background: purple; }");
  ulConfigSetUserStylesheet(config, css);
  ulDestroyString(css);

  ///
  /// Store persistent Session data in a writable folder.
  ///
  ULString cache_path = ulCreateString("./ultralight_cache/");
  ulConfigSetCachePath(config, cache_path);
  ulDestroyString(cache_path);

  ///
  /// Pass our configuration to the library when creating the Renderer
  /// (after the platform handlers are set up), then destroy it.
  ///
  renderer = ulCreateRenderer(config);
  ulDestroyConfig(config);
}
```
<!-- tabs:end -->

### Common Options

Most applications configure only a few common settings before creating the renderer.

| Option | Default | Description |
| :--- | :--- | :--- |
| `cache_path` | Empty | Writable OS file path for persistent session data, such as cookies, local storage, and IndexedDB. |
| `user_stylesheet` | Empty | Global CSS string loaded before any page styles (this is CSS text, not a file path). |
| `resource_path_prefix` | `"resources/"` | Relative path to the library's runtime resources folder, loaded via the file system. See [Custom File System](/docs/2.0/custom-filesystem). |
| `diagnostics.developer_mode` | `false` | Enables diagnostic warnings for API misuses across all build configurations. Enable this in development builds and disable it in shipped builds. See [Developer Mode and Diagnostics](/docs/2.0/developer-mode-and-diagnostics). |
| `effect_quality` | `EffectQuality::Medium` | Quality of blurs, CSS filters, SVG filters, and canvas filters across both CPU and GPU renderers. |

### Other Options

The remaining options tune specific subsystems, grouped by purpose below. The linked guide for each group covers its settings in detail, and the [`Config`](/api/cpp/2_0_0/structultralight_1_1_config.html) API reference lists every field.

#### Text Rendering

Configure font appearance, glyph hinting, and vector text rendering. See [Text Rendering and Fonts](/docs/2.0/text-rendering-and-fonts) for font configuration details.

| Option | Default | Description |
| :--- | :--- | :--- |
| `font_profile` | `FontProfile::Default` | Font appearance preset providing default values for hinting, blend mode, gamma, contrast, stem darkening, and emboldening. |
| `font_hinting` | `FontHinting::Normal` | Glyph hinting algorithm. `FontHinting::Normal` uses the hinting set by `font_profile`. |
| `font_blend_mode` | `FontBlendMode::Profile` | Controls how antialiased glyph edges blend into the page. |
| `font_gamma` | `0` | Glyph compositing gamma. Lower values produce heavier text. Passing 0 uses the value from `font_profile`. |
| `font_contrast` | `-1` | Extra contrast applied to glyph edges. Values below 0 use the value from `font_profile`. |
| `font_stem_darkening` | `-1` | Stem coverage boost to preserve thin stems on light backgrounds. Values below 0 use the value from `font_profile`. |
| `font_embolden` | `-1` | Extra stroke weight as a fraction of font size. Values below 0 use the value from `font_profile`. |
| `enable_photon` | `true` | Enables analytic path fills and strokes on GPU views to stay sharp at any scale. Disabling this also turns off `enable_photon_text`. |
| `enable_photon_text` | `true` | Enables analytic text rendering and color emoji so CPU and GPU views match. |
| `photon_text_min_px` | `16` | Minimum glyph size in pixels for analytic text. Smaller glyphs render from a texture atlas. Setting this to 0 renders all text analytically. |

#### Memory and Reclamation

Tune cache limits, heap sizing, and automatic garbage collection. See [Managing Memory](/docs/2.0/managing-memory) for memory management strategies.

| Option | Default | Description |
| :--- | :--- | :--- |
| `memory_profile` | `MemoryProfile::Balanced` | Balance between memory footprint and execution speed for engine heaps. |
| `memory_cache_size` | `256 MiB` | Maximum cache size in bytes for decoded images, compiled scripts, and other assets. |
| `page_cache_size` | `0` | Number of visited pages kept in memory for instant back and forward navigation. |
| `recycle_delay` | `0.5 s` | Interval in seconds between automatic cache recycles. Set to 0 to disable automatic recycling. |
| `idle_gc_enabled` | `true` | Collects garbage automatically and returns freed memory to the OS during `Renderer::Update()`. |
| `idle_gc_idle_time` | `2.0 s` | Seconds a page must receive no user input before idle garbage collection runs. |
| `max_heap_size` | `0` | Soft target in bytes for total JavaScript heap size. When 0, the value is derived from `memory_profile`. |
| `min_large_heap_size` | `0` | Initial allocation size in bytes for large JavaScript heaps. When 0, the value is derived from `memory_profile`. |
| `min_small_heap_size` | `1 MiB` | Initial allocation size in bytes for small JavaScript heaps. |
| `override_ram_size` | `0` | Overrides detected physical RAM size in bytes. Lower values make JavaScript allocation more conservative. Passing 0 uses detected RAM. |

#### Page Settling

Control how long the engine waits before declaring a loaded page settled. See [Handling View Events](/docs/2.0/handling-view-events) for listening to load and settle events.

| Option | Default | Description |
| :--- | :--- | :--- |
| `page_settle_delay` | `0.1 s` | Additional delay in seconds added after layout and animations finish before the page settles. |
| `page_settle_cycles` | `5` | Consecutive idle samples required before declaring the page settled. |
| `page_settle_tick` | `0.006 s` | Sampling interval in seconds used to check whether a loading page is idle. |

#### Threads and Timing

Configure worker thread counts, timer update budgets, and CPU bitmap row alignment.

| Option | Default | Description |
| :--- | :--- | :--- |
| `num_renderer_threads` | `0` | Number of worker threads used for parallel CPU painting. Setting this to 0 lets the library pick the thread count automatically. |
| `max_update_time` | `1/200 s` | Time budget in seconds for repeating timers during each call to `Renderer::Update()`. Timers exceeding this limit are throttled. |
| `bitmap_alignment` | `16` | Byte alignment of pixel rows in CPU view bitmaps. Setting this to 0 disables row padding. |

#### GPU and Debugging

Configure GPU geometry winding and diagnostic painting modes. See [Implementing a GPUDriver](/docs/2.0/implementing-a-gpudriver) for custom rendering backends.

| Option | Default | Description |
| :--- | :--- | :--- |
| `face_winding` | `FaceWinding::CounterClockwise` | Front-facing triangle winding order for GPU views. |
| `force_repaint` | `false` | Repaints every view each frame regardless of whether content changed, for profiling and shader debugging. |
| `paint_full_layers` | `false` | Repaints entire layers instead of dirty subrectangles when content changes. |

#### Network Security

Manage certificate verification for network requests.

| Option | Default | Description |
| :--- | :--- | :--- |
| `ignore_ssl_errors` | `false` | Disables SSL certificate verification for local development and testing. Never enable this in production builds. |
| `use_system_certificate_store` | `false` | Validates certificates using the OS trust store rather than the bundled certificate authority list. Supported on Windows. |

#### Diagnostics and Profiling

Configure logging verbosity and runtime metrics sampling.

| Option | Default | Description |
| :--- | :--- | :--- |
| `diagnostics.javascript` | `DiagnosticsLevel::Auto` | Diagnostics level for JavaScript API calls. See [Developer Mode and Diagnostics](/docs/2.0/developer-mode-and-diagnostics). |
| `diagnostics.dom` | `DiagnosticsLevel::Auto` | Diagnostics level for DOM APIs and data bindings. |
| `diagnostics.min_log_level` | `LogLevel::Info` | Minimum severity level forwarded to the registered logger. Messages below this level are dropped. |
| `resource_sample_interval` | `500 ms` | Interval in milliseconds between resource counter samples emitted to the profiler. Set to 0 to disable sampling. See [Profiling and Tracing](/docs/2.0/profiling-and-tracing). |

#### Media (Pro Edition and Higher)

Tune media decoding and buffering behavior. See [Media and Audio](/docs/2.0/media-and-audio) for media playback options.

| Option | Default | Description |
| :--- | :--- | :--- |
| `media_profile` | `MediaProfile::Balanced` | Balances memory consumption against playback smoothness for `<video>` and `<audio>` tags. Read once when each media element begins loading. |

## The Default Session

`Renderer::Create()` automatically creates a persistent session named `"default"`. Views created without a session use it— see [Sessions and Site Data](/docs/2.0/sessions-and-site-data) to configure custom storage locations, in-memory sessions, or session sharing.
