# How the Page-Agent Monorepo Structure Organizes Inter-Package Dependencies

> Discover how the Page-Agent monorepo uses npm workspaces to organize inter-package dependencies ensuring topological order and seamless local imports.

- Repository: [Alibaba/page-agent](https://github.com/alibaba/page-agent)
- Tags: internals
- Published: 2026-03-09

---

**The Alibaba Page-Agent repository leverages npm workspaces to maintain six internal packages in strict topological order, enabling downstream modules like `@page-agent/core` to import upstream modules like `@page-agent/page-controller` via standard npm specifiers that resolve to local source code.**

The `alibaba/page-agent` project implements a browser automation agent using a modular **monorepo structure** that separates concerns across distinct npm packages. This architecture isolates the DOM controller, LLM client, UI components, and core agent logic into discrete workspaces while preserving a unified build pipeline.

## Workspace Architecture and Package Topology

The repository defines six active workspaces in the root [`package.json`](https://github.com/alibaba/page-agent/blob/main/package.json) array. The order follows the dependency graph—packages that serve as dependencies for others appear earlier in the list to ensure correct linking during installation.

| Workspace | Purpose | Internal Dependencies |
|-----------|---------|---------------------|
| `packages/page-controller` | DOM extraction, element actions, and visual masks | None |
| `packages/ui` | Reusable UI components and internationalization | None |
| `packages/llms` | LLM client with reflection-before-action model | None |
| `packages/core` | Core agent logic (headless, no UI) | `@page-agent/llms`, `@page-agent/page-controller` |
| `packages/page-agent` | Public entry point adding UI panel on top of core | `@page-agent/core`, `@page-agent/llms`, `@page-agent/page-controller`, `@page-agent/ui` |
| `packages/extension` | Browser extension scaffolding (WXT + React) | None |
| `packages/website` | Documentation site | None |

The root [`package.json`](https://github.com/alibaba/page-agent/blob/main/package.json) declares these workspaces at lines 6–13 in the exact topological sequence required for successful builds. This ordering guarantees that `npm install` can hoist shared third-party dependencies while correctly linking intra-repo packages.

## Declaring Dependencies Between Packages

Each package lists its **runtime dependencies** using the published package names (`@page-agent/*`), allowing npm to resolve them to the locally built versions within the monorepo.

In [`packages/core/package.json`](https://github.com/alibaba/page-agent/blob/main/packages/core/package.json) (lines 45–48), the core module declares its upstream requirements:

```json
{
  "dependencies": {
    "@page-agent/llms": "workspace:*",
    "@page-agent/page-controller": "workspace:*"
  }
}

```

Similarly, the public entry point in [`packages/page-agent/package.json`](https://github.com/alibaba/page-agent/blob/main/packages/page-agent/package.json) (lines 46–51) aggregates all internal components:

```json
{
  "dependencies": {
    "@page-agent/core": "workspace:*",
    "@page-agent/llms": "workspace:*",
    "@page-agent/page-controller": "workspace:*",
    "@page-agent/ui": "workspace:*"
  }
}

```

Because these references use the workspace protocol, running `npm install` at the repository root automatically symlinks the local packages together. This eliminates the need to publish interim versions to npm during development.

## Build Pipeline and Topological Execution

Running `npm run build` executes the `build:libs` script, which triggers each workspace’s individual build process (most use Vite). The build system respects the dependency graph, ensuring that `@page-agent/core` compiles before `@page-agent/page-agent` attempts to bundle it.

Key characteristics of this pipeline include:

- **Isolated Artifacts** – Each package maintains its own `dist` directory, source maps, and TypeScript declarations, preventing build pollution between UI components and headless logic.
- **Explicit Local Links** – Using the `@page-agent/` namespace ensures that import statements remain identical whether the code runs inside the monorepo or is consumed from the npm registry.
- **Workspace Hoisting** – The topological order in the root `workspaces` array allows npm to deduplicate shared third-party dependencies (like React or Vite) across packages while preserving strict intra-repo linking.

## Cross-Package Import Patterns

The dependency organization enables straightforward TypeScript imports between workspaces. These patterns demonstrate how the monorepo structure facilitates code reuse while maintaining type safety.

The **core** package imports DOM and LLM utilities from its upstream workspaces in [`packages/core/src/tools/index.ts`](https://github.com/alibaba/page-agent/blob/main/packages/core/src/tools/index.ts):

```typescript
import { PageController } from '@page-agent/page-controller'
import { LLMClient } from '@page-agent/llms'

export class ClickTool {
  constructor(private pc: PageController, private llm: LLMClient) {}
  async click(index: number) {
    await this.pc.clickElement(index)
  }
}

```

The **page-agent** public package composes core logic with UI components in [`packages/page-agent/src/PageAgent.ts`](https://github.com/alibaba/page-agent/blob/main/packages/page-agent/src/PageAgent.ts):

```typescript
import { PageAgentCore } from '@page-agent/core'
import { Panel } from '@page-agent/ui'

export class PageAgent extends PageAgentCore {
  private panel = new Panel()
  // ...
}

```

Even the documentation site consumes the built packages, as seen in [`packages/website/src/App.tsx`](https://github.com/alibaba/page-agent/blob/main/packages/website/src/App.tsx):

```typescript
import { PageAgent } from '@page-agent/page-agent'

```

These imports resolve correctly because npm maps the `@page-agent/*` specifiers to the local directories defined in the workspace configuration.

## Summary

- The Page-Agent monorepo uses **npm workspaces** to manage six internal packages in topological order, ensuring dependencies build before dependents.
- **Internal dependencies** are declared via standard npm specifiers (`@page-agent/core`) with the workspace protocol, enabling seamless local development and future publishing.
- The **root [`package.json`](https://github.com/alibaba/page-agent/blob/main/package.json)** workspace array (lines 6–13) explicitly orders packages from low-level utilities (page-controller, llms) to high-level aggregates (page-agent).
- Each package maintains **isolated build configurations** (primarily Vite), producing separate distributable artifacts while sharing devDependencies through hoisting.
- **Import statements** remain consistent across the repository and for external consumers, as all internal modules use the scoped `@page-agent/` namespace.

## Frequently Asked Questions

### How does npm resolve local workspace dependencies without publishing to the registry?

Npm resolves the `@page-agent/*` specifiers to the local file system using the workspace protocol defined in the root [`package.json`](https://github.com/alibaba/page-agent/blob/main/package.json). When you run `npm install` at the repository root, npm creates symlinks from `node_modules/@page-agent/core` to `packages/core`, allowing Node.js module resolution to find the local source code as if it were a published package.

### Why does the order of workspaces in the root package.json matter?

The workspaces array follows a **topological sort** where foundational packages like `@page-agent/page-controller` appear before dependent packages like `@page-agent/core`. This ordering ensures that during the initial installation and build phases, npm can link upstream packages before downstream packages attempt to import them, preventing "module not found" errors in CI pipelines.

### Can I use individual Page-Agent packages in my own project without installing the entire monorepo?

Yes. Because each package uses the scoped npm namespace (`@page-agent/core`, `@page-agent/llms`, etc.), they can be published to the registry independently and consumed separately. The architecture intentionally separates concerns—allowing you to import just the headless core agent without the React-based UI components if you only need programmatic browser automation.

### What build tool does the Page-Agent monorepo use to compile TypeScript?

The majority of packages use **Vite** as their build tool, configured individually in each workspace’s [`vite.config.ts`](https://github.com/alibaba/page-agent/blob/main/vite.config.ts). The root [`package.json`](https://github.com/alibaba/page-agent/blob/main/package.json) orchestrates these builds via the `build:libs` script, which runs `npm run build` in each workspace in dependency order, ensuring that type definitions and JavaScript bundles propagate correctly through the internal dependency chain.