Ultralight uses the `URL` type to represent parsed web addresses. It lets you inspect address components, resolve relative paths, and format query strings.

## Creating URLs

You can create a `URL` by parsing a string, converting a local file path, or resolving a relative path against an existing address.

### Parsing Text

Pass an address string to the constructor to parse it:

```cpp
URL url(text);  // eg, "https://example.com/docs"
if (url)
  view->LoadURL(url);
```

Testing a `URL` in a conditional evaluates to `true` when parsing succeeds and `false` when the input is invalid.

The object converts to `String` automatically, so you can pass it directly to `View::LoadURL()`.

Ultralight stores valid addresses in canonical form— `str()` reflects the lowercased scheme and host rather than the raw input text.

> 🚧 Absolute Schemes and Direct Initialization
>
> Parsing requires an absolute address with a scheme— input like `example.com` fails to parse. You must initialize the object directly using `URL url("...")` because copy initialization like `URL url = "..."` does not compile.

### Converting File Paths

Call `URL::FromFilePath()` to convert a local file path into a file URL:

```cpp
URL page = URL::FromFilePath("C:\\Games\\Starlight\\ui\\menu.html");
String path = page.ToFilePath();  // back to the native path
```

Path conversion follows the conventions of the OS your app runs on— drive letters and backslashes apply only on Windows.

Call `ToFilePath()` to convert a `file:` URL back into a local file path.

### Resolving Relative URLs

Resolve a relative link against an existing base URL with `Resolve()`:

```cpp
URL base(view->url());
URL logo = base.Resolve("../images/logo.png");
```

The `Resolve()` method resolves references using the same rules a web browser applies to page links.

You can resolve relative paths, root-relative paths starting with `/`, fragment identifiers, or complete URLs against a base like `View::url()`.

## Reading Components

Inspect individual parts of a parsed URL with component accessors:

```cpp
URL url("https://example.com/search?q=maps#top");

String host = url.host();                 // "example.com"
String path = url.path();                 // "/search"
String terms = url.query_parameter("q");  // "maps"
```

Accessors like `scheme()`, `host()`, `path()`, `query()`, and `fragment()` return their respective components, returning an empty string when a component is absent.

Call `query_parameter()` with a key name to read a single parameter— it returns the decoded value.

## Building Query Strings

Append key-value pairs to an address using `AppendQueryParameter()`:

```cpp
URL search("https://www.google.com/search");
search.AppendQueryParameter("q", "C++ URL & more");
// https://www.google.com/search?q=C%2B%2B+URL+%26+more
```

This method encodes both the key and the value automatically, making it safe to build URLs from user input.
