---
title: "Component: Page"
---
The Page component allows plugins to register custom visual pages in the LangBot WebUI sidebar. Pages run inside an iframe sandbox, communicate with the host via the Page SDK, and can call the plugin's backend API.
## Use Cases
- **Admin panels**: Provide visual configuration and data management interfaces (e.g., FAQ management, analytics dashboards)
- **Data displays**: Show runtime statistics, logs, charts, etc.
- **Interactive tools**: Provide forms, editors, and other interactive interfaces
## Adding a Page Component
Run the following command in the plugin directory:
```bash
lbp comp Page
```
After entering the page name, the CLI will generate page files under `components/pages/`:
```bash
├── components
│ └── pages
│ └── dashboard
│ ├── dashboard.yaml # Page manifest
│ ├── dashboard.py # Backend handler
│ ├── index.html # Page entry point
│ └── i18n # Translation files (optional)
│ ├── en_US.json
│ └── zh_Hans.json
```
The plugin's `manifest.yaml` will also be updated with the component discovery config:
```yaml
spec:
components:
Page:
fromDirs:
- path: components/pages/
maxDepth: 2
```
## Manifest File: Page
```yaml
apiVersion: v1 # Do not modify
kind: Page # Do not modify
metadata:
name: dashboard # Unique page ID within the plugin
label:
en_US: Dashboard # Display name shown in the WebUI sidebar, supports i18n
zh_Hans: 仪表盘
spec:
path: index.html # HTML entry file, relative to this YAML file's directory
execution:
python:
path: dashboard.py # Backend handler file
attr: DashboardPage # Handler class name
```
## Backend Handler
The Page component's backend handler extends the `Page` base class and implements `handle_api` to process API requests from the frontend page.
```python
from langbot_plugin.api.definition.components.page import Page, PageRequest, PageResponse
class DashboardPage(Page):
async def handle_api(self, request: PageRequest) -> PageResponse:
# request.endpoint: API endpoint path, e.g. '/stats'
# request.method: HTTP method (GET, POST, PUT, DELETE)
# request.body: Request body (parsed JSON, or None)
if request.endpoint == '/stats' and request.method == 'GET':
# Access shared plugin state via self.plugin
return PageResponse.ok({
'total': len(self.plugin.entries),
})
return PageResponse.fail(f'Unknown endpoint: {request.endpoint}')
```
### PageRequest Fields
| Field | Type | Description |
|-------|------|-------------|
| `endpoint` | `str` | API endpoint path (e.g. `'/entries'`) |
| `method` | `str` | HTTP method (`GET`, `POST`, `PUT`, `DELETE`) |
| `body` | `Any` | Request body (parsed JSON, or `None`) |
### PageResponse Construction
| Method | Description |
|--------|-------------|
| `PageResponse.ok(data)` | Success response. `data` can be any JSON-serializable value |
| `PageResponse.fail(error)` | Error response. `error` is a human-readable error string |
## Frontend Page Development
Include the Page SDK in your HTML file to communicate with the plugin backend:
```html