# How to Use the Page Facade API in ego-lite: A Playwright-Style Interface for Browser Automation

> Learn to use the Page Facade API in ego-lite for Playwright-style browser automation. Control Chrome DevTools Protocol commands with simple async methods like page.goto() and page.screenshot().

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

---

**The Page Facade API in ego-lite provides a Playwright-style interface that wraps Chrome DevTools Protocol (CDP) commands, exposing high-level methods like `page.goto()`, `page.evaluate()`, and `page.screenshot()` through the `ego` helper context with automatic Promise-based async handling.**

The Page Facade API in ego-lite offers agent developers a concise, high-level abstraction for browser automation without directly managing CDP message construction. Built on top of the Chrome DevTools Protocol transport, this facade is constructed in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) and injected into scripts via `helperContext()`, making the `page` object automatically available under the top-level `ego` helpers when running inside the ego-lite harness.

## Architecture and Initialization

The facade is created by the `createPageFacade()` function defined in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts). When a script executes within the ego-lite harness, this object is registered in the helper context, enabling immediate access to browser control methods. Unlike raw CDP implementations, the facade handles reference management and message serialization internally, presenting a clean surface that mirrors Playwright's API design.

Under the hood, the implementation spans several key modules:

- **[`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts)** – Backs navigation primitives including `page.goto()` and URL-related wait conditions.
- **[`src/driver/locator.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/locator.ts)** – Implements selector resolution for `page.locator()` and convenience methods like `getByText()`.
- **[`src/cdp-eval.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/cdp-eval.ts)** – Powers `page.evaluate()` through `cdp()` and `js()` helper functions.
- **[`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts)** – Manages the CDP transport layer and event buffering required by all facade operations.

## Core API Methods

### Navigation and URL Management

Use `page.goto(url)` to load destinations and `await page.url()` to retrieve the current address. Because the facade operates over the CDP transport provided by [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts), the URL method returns a Promise and must be awaited.

```javascript
await page.goto('https://example.com')
const current = await page.url()

```

For redirect synchronization, `page.waitForURL(pattern)` supports glob patterns to match against the final navigation target:

```javascript
await page.waitForURL('**/dashboard', { timeout: 15000 })

```

### Element Locators and Interaction

The facade provides `page.locator(selector)` for raw CSS selectors and semantic helpers: `getByText()`, `getByLabel()`, `getByPlaceholder()`, and `getByTestId()`. These return locators supporting click and type operations, implemented atop the resolution logic in [`src/driver/locator.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/locator.ts).

Input simulation is available through `page.keyboard` and `page.mouse`:

```javascript
await page.getByText('Accept Terms').click()
await page.getByLabel('Email').type('user@example.com')
await page.keyboard.press('Enter')
await page.mouse.click(100, 200)

```

### Page Evaluation

Execute JavaScript in the browser context using `page.evaluate()`. The expression runs in the page's execution context with full access to the DOM, backed by the evaluation infrastructure in [`src/cdp-eval.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/cdp-eval.ts).

```javascript
const title = await page.evaluate(() => document.title)
const data = await page.evaluate(() => window.myAppState)

```

### Visual Capture and Recording

Capture static PNGs with `page.screenshot()` or record dynamic sessions via the `screencast` sub-object:

```javascript
await page.screenshot({ path: 'state.png' })

await page.screencast.start({ 
  path: 'session.webm', 
  size: { width: 1280, height: 720 }, 
  quality: 80 
})
await page.waitForLoadState('networkidle')
await page.screencast.stop()

```

### Synchronization and Timeouts

Control default waiting behavior with `page.setDefaultTimeout(ms)`. Fine-grained synchronization methods include `waitForLoadState()`, `waitForRequest()`, `waitForResponse()`, and `waitForEvent()` for download monitoring.

```javascript
page.setDefaultTimeout(10_000)
await page.waitForLoadState('networkidle')
const download = await page.waitForEvent('download')

```

## Complete Usage Example

This example demonstrates navigation, form interaction, and visual capture using the Page Facade API:

```javascript
// Navigate and extract metadata
await page.goto('https://example.com')
const title = await page.evaluate(() => document.title)
console.log('Page title:', title)

// Fill and submit a form using semantic locators
await page.getByLabel('Email').type('user@example.com')
await page.getByLabel('Password').type('secret')
await page.keyboard.press('Enter')

// Wait for post-login navigation and capture result
await page.waitForURL('**/dashboard', { timeout: 15000 })
await page.screenshot({ path: 'final.png' })

// Record a short screencast of the session
await page.screencast.start({ path: 'session.webm', size: { width: 1280, height: 720 }, quality: 80 })
await page.waitForLoadState('networkidle')
await page.screencast.stop()

```

## Summary

- The Page Facade API in ego-lite wraps CDP complexity in a Playwright-compatible interface defined in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) via `createPageFacade()`.
- Access the `page` object through the `ego` helper context automatically provided to scripts running in the ego-lite harness.
- All methods are asynchronous and return Promises, requiring `await` for result retrieval due to the underlying CDP transport in [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts).
- The architecture delegates to specialized modules: [`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts) for navigation, [`src/driver/locator.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/locator.ts) for element selection, and [`src/cdp-eval.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/cdp-eval.ts) for script execution.
- Built-in support for screenshots, screencasts, downloads, and network synchronization eliminates boilerplate CDP message handling.

## Frequently Asked Questions

### How do I access the page object in an ego-lite script?

The `page` object is automatically available through the top-level `ego` helpers when your script runs inside the ego-lite harness. It is constructed by `createPageFacade()` in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) and injected via `helperContext()`, requiring no manual initialization or import statements.

### Does the Page Facade API support parallel browser contexts?

While the facade itself manages a single page instance per script execution, the underlying [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) handles CDP transport multiplexing. For parallel operations, spawn separate script executions, as each receives its own isolated `page` facade instance bound to its CDP session.

### Why must I await page.url() when other properties might be synchronous?

All facade methods abstract asynchronous CDP operations. The `page.url()` method queries the browser's current state through the protocol transport, making it inherently asynchronous and Promise-based for consistency with the rest of the API surface and to ensure accurate state retrieval from the remote browser.

### How does page.evaluate() differ from direct CDP evaluate calls?

`page.evaluate()` wraps the low-level CDP evaluation mechanisms found in [`src/cdp-eval.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/cdp-eval.ts), handling script context isolation, exception serialization, and return value marshaling automatically. This provides safer execution compared to raw `Runtime.evaluate` CDP commands while maintaining full access to the page's JavaScript context.