# Is There a Backend Component to the pi-web Project? Yes, Here's How It Works

> Explore the backend component of the pi-web project built with Next.js API routes. Learn how it manages agent sessions, file access, authentication, and git integration.

- Repository: [Alex Yang/pi-web](https://github.com/agegr/pi-web)
- Tags: internals
- Published: 2026-08-09

---

**Yes, pi-web contains a full backend component built as Next.js API routes that handle agent sessions, file access, authentication, and git integration.**

The pi-web repository is a full-stack application where the backend runs in-process with the Next.js server. While the frontend consists of React components in the `app/` directory, the backend component delivers a REST-style API through Next.js Route Handlers under `app/api/`. This architecture enables the web-based Pi client to manage persistent sessions, execute tools, and integrate with git repositories without requiring a separate server process.

## What Is the pi-web Backend Component?

The backend component in pi-web is implemented as a collection of **API routes** that execute server-side logic within the Next.js runtime. Unlike traditional separate backend services, these routes run in-process with the frontend server but handle all data persistence, external API calls, and file system operations securely on the server side.

The frontend consumes these APIs through the typed helper [`lib/agent-client.ts`](https://github.com/agegr/pi-web/blob/main/lib/agent-client.ts), which abstracts the HTTP layer into clean async functions. This design keeps API keys, OAuth tokens, and file system access confined to the server while exposing a type-safe interface to the React components.

## Core Backend Responsibilities

The backend component manages six primary domains essential to pi-web's functionality.

### Agent Lifecycle and RPC Management

The core orchestration logic lives in [`lib/rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts). This module creates and manages `AgentSession` wrappers, handles tool presets, manages model selection, and streams events back to the client via Server-Sent Events (SSE).

Session state normalization occurs in [`lib/session-reader.ts`](https://github.com/agegr/pi-web/blob/main/lib/session-reader.ts), which reads and writes JSONL session files and constructs the navigation tree data displayed in the UI.

### File and Worktree Access Control

Security-critical file operations are centralized in [`lib/file-access.ts`](https://github.com/agegr/pi-web/blob/main/lib/file-access.ts) and [`lib/worktree.ts`](https://github.com/agegr/pi-web/blob/main/lib/worktree.ts). These modules enforce **allowed-root rules** to prevent directory traversal attacks, resolve git worktree paths, list repository status, and serve file contents to the frontend. All path resolution happens server-side, ensuring the UI never directly accesses the file system.

### Authentication and Model Configuration

The backend handles sensitive credentials through [`lib/provider-listing.ts`](https://github.com/agegr/pi-web/blob/main/lib/provider-listing.ts), which stores API keys and OAuth tokens securely on the server. This module also discovers available language models and caches provider information, keeping authentication secrets out of browser memory.

### Plugin and Skill Management

Dynamic functionality arrives via [`lib/skills-service.ts`](https://github.com/agegr/pi-web/blob/main/lib/skills-service.ts), which manages npm-based plugins and skill packages. The backend handles installation, enabling, disabling, and updates of these packages, isolating the package management logic from the client.

### Git Integration

Repository visibility comes from [`lib/git-status.ts`](https://github.com/agegr/pi-web/blob/main/lib/git-status.ts), which provides `git status` and `git diff` data through dedicated API endpoints. This allows the frontend to display repository state without executing shell commands in the browser.

## API Route Structure

The backend exposes functionality through specific REST endpoints in the `app/api/` directory. Each route file corresponds to a discrete operation:

- **Create a new agent session** – `POST /api/agent/new` → [`app/api/agent/new/route.ts`](https://github.com/agegr/pi-web/blob/main/app/api/agent/new/route.ts)
- **Send a message to an existing session** – `POST /api/agent/[id]` → `app/api/agent/[id]/route.ts`
- **Stream SSE events for a session** – `GET /api/agent/[id]/events` → `app/api/agent/[id]/events/route.ts`
- **List all sessions** – `GET /api/sessions` → [`app/api/sessions/route.ts`](https://github.com/agegr/pi-web/blob/main/app/api/sessions/route.ts)
- **Check git status** – `GET /api/git/status` → [`app/api/git/status/route.ts`](https://github.com/agegr/pi-web/blob/main/app/api/git/status/route.ts)
- **Handle OAuth login** – `GET /api/auth/login/[provider]` → `app/api/auth/login/[provider]/route.ts`

These routes form the **backend component** that powers the Pi-Web UI, handling everything from session persistence to real-time streaming.

## Frontend-Backend Communication

The frontend interacts with the backend through the typed client in [`lib/agent-client.ts`](https://github.com/agegr/pi-web/blob/main/lib/agent-client.ts). This abstraction layer ensures type safety across the API boundary.

### Creating a New Session

```typescript
import { createAgentSession } from '@/lib/agent-client';

async function startSession() {
  const session = await createAgentSession({
    cwd: '/home/user/project',
    message: 'Explain the repo structure.',
    toolNames: ['file-access', 'git-status'],
  });
  console.log('New session id:', session.id);
}

```

### Sending Messages

```typescript
import { postMessage } from '@/lib/agent-client';

async function sendMessage(sessionId: string, text: string) {
  const result = await postMessage(sessionId, { role: 'user', content: text });
  console.log('Assistant reply:', result.reply);
}

```

### Streaming Real-Time Events

```typescript
import { subscribeToSessionEvents } from '@/lib/agent-client';

function watchSession(sessionId: string) {
  const source = subscribeToSessionEvents(sessionId);
  source.addEventListener('message', (e) => {
    console.log('New event:', JSON.parse(e.data));
  });
}

```

## Summary

- **pi-web is a full-stack Next.js application** with a backend component running in-process via API routes.
- **Core backend files** include [`lib/rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts) for agent orchestration, [`lib/session-reader.ts`](https://github.com/agegr/pi-web/blob/main/lib/session-reader.ts) for persistence, and [`lib/file-access.ts`](https://github.com/agegr/pi-web/blob/main/lib/file-access.ts) for secure file operations.
- **REST endpoints** under `app/api/` handle sessions, authentication, git operations, and streaming events.
- **Security-sensitive operations** like OAuth token storage and file system access remain server-side, accessed only through the typed [`lib/agent-client.ts`](https://github.com/agegr/pi-web/blob/main/lib/agent-client.ts) interface.

## Frequently Asked Questions

### Does pi-web use a separate backend server?

No. The backend component runs in-process with the Next.js server using Next.js Route Handlers. This architecture eliminates the need for a separate backend process while still keeping sensitive operations and data on the server side.

### How does pi-web handle authentication securely?

Authentication logic resides in [`lib/provider-listing.ts`](https://github.com/agegr/pi-web/blob/main/lib/provider-listing.ts) and the auth route handlers under `app/api/auth/`. API keys and OAuth tokens never reach the browser; they are stored and applied server-side when proxying requests to language model providers.

### What storage format does pi-web use for sessions?

Sessions are stored as **JSONL files** (newline-delimited JSON) managed by [`lib/session-reader.ts`](https://github.com/agegr/pi-web/blob/main/lib/session-reader.ts). This format supports appending streaming updates efficiently and allows the backend to normalize tool call structures while maintaining a complete history of each session.

### Can the pi-web backend run independently from the frontend?

No, the backend is tightly coupled to the Next.js application architecture. The API routes in `app/api/` require the Next.js runtime and cannot be deployed as a standalone service. This colocation simplifies deployment but requires running the full Next.js application to access backend functionality.