# How the `page` Facade Works in ego-lite: Architecture and API Reference

> Understand the ego-lite page facade. Discover how `createPageFacade` uses CDP commands for async navigation, element interaction, and network monitoring in your scripts.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: architecture
- Published: 2026-08-27

---

**The `page` facade is a Playwright-style API created by `createPageFacade()` in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) that wraps Chrome DevTools Protocol (CDP) commands to provide async navigation, element interaction, and network monitoring for ego-lite scripts.**

This facade serves as the primary interface between user scripts and the embedded browser. It abstracts low-level CDP transport—handled in [`package/ego-browser/src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/browser-runtime.ts)—into a synchronous-looking, fully async API that manages retries, timeouts, and auto-waiting behaviors.

## Core Architecture and Initialization

The facade originates in the `createPageFacade()` function defined at line 684 of [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts). This factory constructs a `HelperContext` object that encapsulates all page-level operations and maintains internal state for timeouts and CDP session references.

During script execution, the runtime injects this context via the helper registry at line 824 in the same file. When a script calls `page.goto()` or `page.locator()`, it is invoking methods on this pre-bound context, which forwards commands to the browser process through the transport layer implemented in [`browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/browser-runtime.ts).

## Navigation and Async State Access

The facade exposes async getters that resolve to current browser state. Methods such as `page.url()`, `page.title()`, and `page.info()` return Promises defined in [`package/ego-browser/src/format.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/format.ts) (lines 72-84), ensuring you receive up-to-date values after navigation or DOM mutations.

Navigation helpers including `page.goto(url, options?)`, `page.reload(options?)`, and `page.waitForLoadState(state?, options?)` forward arguments to CDP commands `Page.navigate` and `Page.reload`, then automatically poll until the requested load state is achieved. These implementations appear in [`format.ts`](https://github.com/citrolabs/ego-lite/blob/main/format.ts) (lines 32-65).

## Element Locators and DOM Interaction

The `page.locator(selector)` method returns a strict, auto-waiting locator object implemented in [`package/ego-browser/src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/element-resolver.ts). This façade exposes Playwright-style query shortcuts—`getByRole()`, `getByText()`, `getByLabel()`—and interaction methods like `click()` and `fill()`, all defined in [`format.ts`](https://github.com/citrolabs/ego-lite/blob/main/format.ts) (lines 84-215).

Because the locator waits for element stability before acting, scripts avoid manual polling. The resolver retries queries until the element appears or the default timeout expires.

## Network Monitoring and Event Handling

To handle asynchronous page events, the facade provides `page.waitForEvent(event)`, `page.waitForURL(url|predicate)`, `page.waitForRequest(predicate)`, and `page.waitForResponse(predicate)`. These methods subscribe to the CDP `Network` event stream and resolve when conditions are met, as implemented in [`format.ts`](https://github.com/citrolabs/ego-lite/blob/main/format.ts) (lines 290-333).

This architecture allows deterministic waiting for XHR fetches, navigation commits, or custom emissions without brittle `sleep` calls.

## Script Evaluation and Input Simulation

`page.evaluate(expression)` executes JavaScript directly in the page context via CDP `Runtime.evaluate`. For visual capture, `page.screencast.start()` and `stop()` interact with the CDP `Screencast` domain defined in [`package/ego-browser/src/driver/screencast.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/driver/screencast.ts).

Low-level input simulation is delegated to dedicated drivers: `page.keyboard.press()` routes to [`package/ego-browser/src/driver/keyboard.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/driver/keyboard.ts), while `page.mouse.click()` routes to [`package/ego-browser/src/driver/pointer.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/driver/pointer.ts), both utilizing the CDP `Input` domain.

## Timeout Configuration

Global timeout behavior is controlled via `page.setDefaultTimeout(ms)`, which stores the duration in the helper state at lines 690-704 of [`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts). All subsequent facade calls respect this value unless overridden by an explicit `timeout` option in individual method calls.

## Practical Usage Example

```javascript
// Simple navigation and title extraction
await page.goto('https://example.com', { timeout: 15000 });
console.log('URL →', await page.url());
console.log('Title →', await page.title());

// Interaction with a form using locator shortcuts
await page.getByLabel('Email').fill('hello@world.com');
await page.getByPlaceholder('Password').fill('s3cr3t');
await page.getByRole('button', { name: 'Sign in' }).click();

// Waiting for a network request and validating its response
const req = await page.waitForRequest(req => /api\/login/.test(req.url()));
const resp = await req.response();
console.log('Login status:', resp.status());

// Capture a screenshot after the page settles
await page.waitForLoadState('networkidle');
await page.screenshot({ path: 'login.png' });

```

## Summary

- **`createPageFacade()`** in [`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts) (line 684) constructs the facade and binds it to the CDP transport.
- The facade provides **async state getters** (`url()`, `title()`) and **auto-waiting navigation** (`goto()`, `reload()`) defined in [`format.ts`](https://github.com/citrolabs/ego-lite/blob/main/format.ts).
- **Strict locators** from [`element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/element-resolver.ts) offer Playwright-style querying with built-in retry logic.
- **Network and event waiting** methods tap into CDP `Network` events for deterministic async handling.
- **Global timeouts** are configurable via `setDefaultTimeout()` (lines 690-704) and apply to all subsequent operations.

## Frequently Asked Questions

### What file defines the `createPageFacade()` function?

The factory function is defined at line 684 of [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts). This function initializes the `HelperContext` and registers the `page` object with the runtime registry at line 824.

### How does the `page` facade handle element waiting?

The facade uses a **strict, auto-waiting locator** pattern. When you call `page.locator()` or shortcuts like `getByRole()`, the underlying resolver in [`element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/element-resolver.ts) repeatedly queries the DOM until the element meets stability criteria or the timeout expires.

### Can the default timeout be configured for all `page` operations?

Yes. Call `page.setDefaultTimeout(ms)` to store a global timeout in the helper state (lines 690-704 of [`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts)). This value applies to all subsequent navigation, locator, and waiting operations unless overridden by method-specific options.

### What protocol powers the `page` facade's browser communication?

The facade wraps the **Chrome DevTools Protocol (CDP)**. All high-level methods ultimately translate to CDP commands—such as `Page.navigate`, `Runtime.evaluate`, and `Network` events—transported through the low-level driver in [`package/ego-browser/src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/browser-runtime.ts).