# How to Use the Playwright-Style Page Facade in ego-lite

> Learn to use the Playwright-style page facade in ego-lite with createPageFacade(). Automate browsers efficiently using familiar methods like page.goto() and page.locator().

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

---

**The Playwright-style page facade in ego-lite provides a lightweight, familiar browser automation API through the `createPageFacade()` function in [`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts), exposing familiar methods like `page.goto()`, `page.locator()`, and `page.screenshot()` that delegate to an internal CDP driver layer.**

ego-lite is a minimal browser automation runtime that eliminates the heavyweight dependency of full Playwright while preserving its ergonomic API. The **page facade** is the primary interface developers use to control browser sessions, enabling rapid migration of existing Playwright scripts with minimal code changes.

## Architecture of the Page Facade

The facade implementation spans multiple source files, each with a distinct responsibility in the call chain.

### Core Construction: `createPageFacade()`

The facade object is manufactured by **`createPageFacade()`** defined in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) at **line 684**. This factory function constructs an object where each method proxies to the underlying driver helpers:

- **`nav`** – navigation operations (`goto`, `goBack`, `reload`)
- **`pointer`** – mouse movements, clicks, scrolls
- **`keyboard`** – key presses, typing shortcuts
- **`element-ops`** – element queries, attribute extraction, visibility checks

[View `createPageFacade()` implementation](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts#L684)

### Global Exposure via Helpers Export

Once constructed, the facade is attached to the runtime's global helper context at **line 824** in the same file:

```typescript
// helpers.ts line 824
page: createPageFacade()

```

This makes `page` directly available in agent scripts without manual instantiation.

[View helpers export](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts#L824)

### Public API Signatures in [`format.ts`](https://github.com/citrolabs/ego-lite/blob/main/format.ts)

Method signatures and inline documentation for the facade reside in **[`src/format.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/format.ts)** (lines 32–84). This file serves as the contract definition, specifying:

- Parameter types and defaults
- Return type annotations
- Usage examples for IDE autocomplete

[View format.ts signatures](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/format.ts#L32)

### Description and Capabilities

An in-code description at **line 810** in [`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts) documents the facade's **strict, auto-waiting behavior**:

> The facade automatically retries locator operations until elements reach a stable state, eliminating explicit `sleep()` calls.

[View facade description](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts#L810)

## Driver Layer: Where Facade Methods Execute

All facade methods ultimately delegate to the **`src/driver/`** directory, which communicates with the browser via Chrome DevTools Protocol (CDP):

| Driver Module | Facade Methods Powered |
|-------------|------------------------|
| [`nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/nav.ts) | `page.goto()`, `page.goBack()`, `page.reload()`, `page.waitForURL()` |
| [`pointer.ts`](https://github.com/citrolabs/ego-lite/blob/main/pointer.ts) | `page.click()`, `page.hover()`, `page.scroll()` |
| [`keyboard.ts`](https://github.com/citrolabs/ego-lite/blob/main/keyboard.ts) | `page.keyboard.press()`, `page.keyboard.type()` |
| [`element-ops.ts`](https://github.com/citrolabs/ego-lite/blob/main/element-ops.ts) | `page.locator()`, `page.$()`, `page.$$()` |
| [`screencast.ts`](https://github.com/citrolabs/ego-lite/blob/main/screencast.ts) | `page.screencast.start()`, `page.screencast.stop()` |
| [`screenshot.ts`](https://github.com/citrolabs/ego-lite/blob/main/screenshot.ts) | `page.screenshot()` |

The driver layer is orchestrated by **[`browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/browser-runtime.ts)**, which manages CDP transport, session lifecycle, and event buffering.

## Runtime Entry Point: [`index.ts`](https://github.com/citrolabs/ego-lite/blob/main/index.ts)

The façade is re-exported through **[`src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/index.ts)** (lines 41–53), making it available to the CLI entry point and programmatic API consumers.

[View index.ts exports](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts#L41)

## Practical Code Examples

### Navigation and Page State

```javascript
// Navigate with timeout and wait for network idle
await page.goto('https://example.com', { timeout: 15000 });
await page.waitForLoadState('networkidle');

// Extract page metadata
console.log('Current URL:', await page.url());
console.log('Page title:', await page.title());

```

### Locator-Based Interactions

```javascript
// Fill forms using CSS selectors
await page.locator('input[name="search"]').fill('ego-lite');
await page.locator('button[type="submit"]').click();

// Text-based locators with exact matching
await page.getByText('Search Results', { exact: true }).waitFor();

// Chain locators for precision
await page.locator('nav').getByRole('link', { name: 'Documentation' }).click();

```

### Keyboard Shortcuts and Special Keys

```javascript
// Native keyboard shortcuts
await page.keyboard.type('Ctrl+L');  // Focus address bar
await page.keyboard.press('Enter');

// Sequential key presses
await page.keyboard.press('Tab');
await page.keyboard.type('hello world');

```

### Visual Capture

```javascript
// Static screenshot
await page.screenshot({ path: 'capture.png', fullPage: true });

// Video recording (screencast)
await page.screencast.start({
  path: 'session.webm',
  size: { width: 1280, height: 720 }
});
// ... perform actions ...
await page.screencast.stop();

```

### Advanced Waiting Patterns

```javascript
// Wait for URL pattern
await page.waitForURL(url => url.pathname.startsWith('/dashboard'), {
  timeout: 10000
});

// Wait for specific network response
await page.waitForResponse(resp =>
  resp.status() === 200 && resp.url().includes('/api/data')
);

// Wait for element state
await page.locator('.loading-spinner').waitFor({ state: 'hidden' });

```

## Key Behavioral Guarantees

| Guarantee | Implementation Source |
|-----------|----------------------|
| **Auto-retry on locator actions** | [`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts) line 812 description |
| **Consistent async/await API** | All facade methods return Promises for browser-communicating operations |
| **Playwright parity** | [`format.ts`](https://github.com/citrolabs/ego-lite/blob/main/format.ts) signatures match Playwright's public API |
| **Zero Playwright dependency** | Direct CDP driver layer eliminates native module requirements |

## Migration from Full Playwright

Scripts written for standard Playwright require minimal adaptation:

- **Remove import statements**: `page` is globally injected by ego-lite's runtime
- **Adjust launch configuration**: Browser instances are managed by the runtime, not `chromium.launch()`
- **Preserve method calls**: Core APIs like `page.goto()`, `page.locator()`, and `page.screenshot()` remain identical

## Summary

- **The page facade is constructed by `createPageFacade()` in [`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts) (line 684)** and exposed globally at line 824
- **Public API contracts live in [`format.ts`](https://github.com/citrolabs/ego-lite/blob/main/format.ts) (lines 32–84)**, ensuring Playwright-compatible method signatures
- **Actual browser control delegates to `src/driver/` modules** ([`nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/nav.ts), [`pointer.ts`](https://github.com/citrolabs/ego-lite/blob/main/pointer.ts), [`keyboard.ts`](https://github.com/citrolabs/ego-lite/blob/main/keyboard.ts), [`element-ops.ts`](https://github.com/citrolabs/ego-lite/blob/main/element-ops.ts))
- **The facade provides auto-waiting, retry-based element interaction** without explicit sleeps
- **Migration from Playwright is streamlined** due to deliberate API parity

## Frequently Asked Questions

### What is the difference between ego-lite's page facade and full Playwright?

ego-lite's facade implements the most commonly used Playwright methods but executes them through a lightweight CDP driver rather than Playwright's native binary stack. This eliminates ~150MB of dependencies while preserving the ergonomic API. Methods like `page.goto()`, `page.locator()`, and `page.screenshot()` behave identically, though advanced features like browser contexts and multiple pages per context have simplified implementations.

### How do I access the page object in my ego-lite scripts?

The `page` object is automatically injected into the global scope by the runtime. No import or instantiation is required. According to the source in [`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts) line 824, the runtime calls `createPageFacade()` and assigns the result to `page` before your script executes.

### Where are the actual browser commands implemented?

Facade methods proxy to the driver layer in `src/driver/`. Navigation maps to [`nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/nav.ts), pointer actions to [`pointer.ts`](https://github.com/citrolabs/ego-lite/blob/main/pointer.ts), keyboard input to [`keyboard.ts`](https://github.com/citrolabs/ego-lite/blob/main/keyboard.ts), and element queries to [`element-ops.ts`](https://github.com/citrolabs/ego-lite/blob/main/element-ops.ts). These modules serialize commands to CDP and deserialize responses, as coordinated by [`browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/browser-runtime.ts).