# How to Perform Navigation Using the Ego-Lite Browser Facade API

> Learn to perform navigation with the ego-lite browser facade API. Use the nav.goto helper for simple, Promise-based page navigation with CDP command integration.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: how-to-guide
- Published: 2026-08-22

---

**TLDR:** The ego-lite browser facade exposes a `nav.goto(url, opts?)` helper that wraps Chrome DevTools Protocol (CDP) commands, session management, and load-event waiting, letting agents navigate pages with a single Promise-based call.

The Ego-Lite project (citrolabs/ego-lite) provides a lightweight browser automation runtime for AI agents. Its facade API, shipped in the `ego-browser` package, abstracts away raw CDP messaging so you can drive navigation through a clean, injected helper context. This guide explains how the navigation facade works under the hood and shows you exactly how to use it in your scripts, with references to the underlying source files in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) and [`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts).

## How the Ego-Lite Navigation Facade Works

The navigation API is built around a two-layer design: a **public helper layer** and a **driver layer**.

When a script is executed through the CLI or embedded runtime, the `helperContext()` function in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) constructs the helper environment. Among the registered public helpers is `nav`, which gets injected directly into the agent's execution scope. That means you never import anything — you simply call `await nav.goto(...)` inside your script.

Internally, `nav.goto()` delegates to the `NavDriver` class in [`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts). The driver performs these steps in sequence:

1. **Ensure session** – `ensureSession()` in [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) confirms a CDP browser session exists, reusing one where possible.
2. **Send CDP command** – The driver calls `ego.sendCDPMessage('Page.navigate', { url })` over the transport.
3. **Wait for load** – By default, it waits for the `load` event using the `waitForLoad()` utility in [`src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/waits.ts).
4. **Return control** – Once the page finishes loading (or the wait strategy is skipped), the Promise resolves back to the agent.

This design keeps the agent script free from CDP protocol details while still giving you control over load behavior.

## Using nav.goto for Basic Navigation

**`nav.goto(url, opts?)`** is the core method of the navigation facade. The first argument is the target URL; the second optional argument configures the load-wait strategy.

Here's a minimal navigation call:

```javascript
await nav.goto('https://example.com');

```

That single line:

- Opens a new tab in the current task space (or reuses an existing one).
- Sends `Page.navigate` over the CDP transport.
- Waits for the page's `load` event before resolving.

```javascript
// Navigate and wait only for DOMContentLoaded
await nav.goto('https://example.org', { waitUntil: 'domcontentloaded' });

// Fire-and-forget: navigate without waiting for any event
await nav.goto('https://example.net', { waitUntil: 'none' });

```

The `waitUntil` option accepts these values:

- `load` (default) – waits for the `load` event.
- `domcontentloaded` – waits for `DOMContentLoaded`.
- `networkidle` – waits for network to settle.
- `none` – returns immediately after issuing the CDP command.

Refer to [`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts) for the exact implementation of this option handling.

## Task-Space Integration for Navigations

Each navigation runs within the current **task space** — an isolated browser namespace created via `newTaskSpace()` or `useOrCreateTaskSpace()`. The facade automatically tracks the active tab, so after `nav.goto()` resolves, all subsequent helper calls (e.g., `click`, `type`, `js`) operate on the page opened by that navigation.

```javascript
// Create and switch to a dedicated task space before navigating
const ts = await newTaskSpace('my-space');
await switchTaskSpace(ts.id);

// Navigation now happens inside 'my-space'
await nav.goto('https://docs.ego-lite.com');

```

This separation lets multiple agents or tasks maintain distinct browser contexts without collisions. The task space driver (see [`src/driver/taskspace.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/taskspace.ts)) handles creation, switching, and teardown of task namespaces.

## Combining Navigation with Other Helpers

The injected facade exposes more than just `nav` — you get `click`, `type`, `js`, and related helpers as well. A common pattern is to navigate, locate an element, type input, and click:

```javascript
// Step 1: go to the search engine
await nav.goto('https://search.com');

// Step 2: type a query into the search field
await type('#search', 'ego-lite');

// Step 3: click the submit button
await click('#searchButton');

// Step 4: wait for the navigation event that follows the click
await waitForNavigation();

```

The `waitForNavigation()` helper (in [`src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/waits.ts)) is a separate utility that resolves when the browser is about to navigate or when the navigation event fires — useful after a click that triggers a page change. Together, these helpers create a fluent, declarative API for multi-step browsing workflows.

## Key Source Files for Navigation

| File | Role |
|------|------|
| [[`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) | Builds the helper context and registers `nav` plus other public helpers. |
| [[`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/driver/nav.ts) | Implements the `NavDriver` that wraps CDP `Page.navigate` and load waits. |
| [[`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/browser-runtime.ts) | Manages CDP transport, session creation, and event buffering. |
| [[`src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/waits.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/driver/waits.ts) | Provides `waitForLoad` and `waitForNavigation` used by `nav.goto`. |
| [[`src/driver/taskspace.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/taskspace.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/driver/taskspace.ts) | Handles task-space lifecycles that isolate navigation contexts. |

These files together form the complete navigation layer of the Ego-Lite browser facade.

## Summary

- **Call `await nav.goto(url, opts?)`** in any injected helper context — no imports required.
- The facade routes navigation through `NavDriver` in [`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts), which sends `Page.navigate` via CDP.
- **Control load behavior** with the `waitUntil` option: `load`, `domcontentloaded`, `networkidle`, or `none`.
- Navigation runs inside the current **task space**, and subsequent helpers operate on the resulting page automatically.
- Combine `nav.goto` with `waitForNavigation()` to handle multi-step agent workflows.

## Frequently Asked Questions

### Do I need to import the navigation helper in my ego-lite script?

No. The `nav` helper is injected automatically through `helperContext()` in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) whenever your script runs. You simply call `await nav.goto(url)` directly in your agent code.

### What does the `waitUntil` option actually do?

The `waitUntil` option determines which browser event must fire before `nav.goto()` resolves. The default is `load`; `domcontentloaded` resolves earlier at the `DOMContentLoaded` event, and `none` skips waiting entirely, returning immediately after the CDP command is dispatched.

### Can I navigate multiple tabs or task spaces at once?

Ego-Lite associates navigation with a task space. Use `newTaskSpace()` and `switchTaskSpace(ts.id)` to isolate navigation contexts and drive separate tabs concurrently — each task space tracks its own active tab.

### How do I know when a navigation caused by a click is complete?

Use the `waitForNavigation()` helper from the ego-browser facade (implemented in [`src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/waits.ts)). Call it right after a `click()` or another action that may trigger navigation, and it resolves with the next navigation event.