# Reverse-proxy — any HTTP origin
experimental · Next.js, Astro, Nuxt, SvelteKit, Rails, Django, WordPress…
Sit in front of your existing app as a Node reverse-proxy. Your framework runs unchanged on a localhost port; agentsite intercepts HTML responses and injects the bundle.
**Start here first.** Every platform recipe below assumes the canonical Express + Docker install at [/install/express-docker](/install/express-docker). The snippets on this page are the platform-specific deltas on top of that baseline.
Rather than ship a per-framework adapter, agentsite can sit in front of your existing app as a Node reverse-proxy. Your framework runs unchanged on a localhost port; agentsite intercepts HTML responses, mutates the `<head>` + injects the markdown body inside a preboot `<div>` (CSS-hidden the moment JS boots), and serves `/llms.txt` / `/.well-known/*` on the same domain.
```
your domain (:443/:80)
│
▼
┌─────────────────────────────────┐
│ agentsite (Node, :3000) │ ← reads HTML responses, injects
│ - express + agentsite.cjs │ <head> tags, JSON-LD, markdown
│ - proxies through to upstream │ preboot <div>, /llms.txt, etc.
└──────────┬──────────────────────┘
│ HTTP fetch
▼
┌─────────────────────────────────┐
│ your framework (:3001) │ ← unchanged: 'next start',
│ next / nuxt / astro / sveltekit│ 'nuxt preview', 'astro preview',
│ rails / django / wordpress │ 'rails s', 'gunicorn', anything
└─────────────────────────────────┘
```
agentsite/server.mjscopy
```js
// agentsite/server.mjs — reverse-proxy mode (Express-Sidecar)
import express from 'express'
import { createRequire } from 'node:module'
const require = createRequire(import.meta.url)
const agentsite = require('./agentsite.cjs')
const PORT = parseInt(process.env.PORT || '3000', 10)
const UPSTREAM = process.env.UPSTREAM_ORIGIN || 'http://127.0.0.1:3001'
const SITE = process.env.AGENTSITE_SITE
const TOKEN = process.env.AGENTSITE_TOKEN
const app = express()
app.set('trust proxy', true)
app.use(agentsite({
upstream: UPSTREAM, // ← no distDir; we fetch HTML from your app
site: SITE,
token: TOKEN,
fetchTimeoutMs: 4000,
log: process.env.NODE_ENV !== 'production',
}))
app.listen(PORT, () => console.log(`agentsite proxy → ${UPSTREAM} on :${PORT}`))
```
docker-compose.ymlcopy
```yaml
# docker-compose.yml — agentsite in front, your framework behind
services:
agentsite:
build: ./server
ports: ['3000:3000']
environment:
AGENTSITE_TOKEN: ${AGENTSITE_TOKEN}
AGENTSITE_SITE: https://yoursite.com
UPSTREAM_ORIGIN: http://app:3001
depends_on: [app]
app:
# Your framework's container — runs 'next start' / 'nuxt preview' /
# 'astro preview' / 'rails s' / whatever — listening on :3001.
build: .
expose: ['3001']
environment:
PORT: 3001
# (your framework's normal env)
```
Framework-specific notes:
- **Next.js:** `next start` on `PORT=3001`. App Router and Pages Router both work; agentsite sees the rendered HTML the same way a browser does.
- **Astro / Nuxt / SvelteKit:** use the framework's Node-server adapter (`@astrojs/node`, `nuxt build --preset=node-server`, `@sveltejs/adapter-node`) on `PORT=3001`.
- **Rails / Django / Laravel / WordPress / anything else that speaks HTTP:** point `UPSTREAM_ORIGIN` at it. Works the same way.
**Streaming SSR — use the SDK install instead.** The reverse-proxy buffers the upstream response, which kills time-to-first-byte and may break framework streaming guarantees for React Server Components / Suspense / chunked HTML. For those stacks the SDK install (in-process hooks calling our `/bundle` API during SSR) preserves streaming. Runnable references: [`demos/after/next/`](https://github.com/agentsite/integration/tree/main/demos/after/next) and [`demos/after/nuxt/`](https://github.com/agentsite/integration/tree/main/demos/after/nuxt).