> ## Documentation Index
> Fetch the complete documentation index at: https://docs.plannotator.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-Host Plannotator's Deprecated Share Services

> Deploy the deprecated OSS share portal and encrypted paste service for compatibility with asynchronous Plannotator share links.

Plannotator has two self-hostable services for the deprecated OSS share-link flow:

| Service       | Deploy it when                                                         |
| ------------- | ---------------------------------------------------------------------- |
| Share portal  | You need your own static site to open hash-based Markdown share links. |
| Paste service | You need encrypted short links for large Markdown reviews or raw HTML. |

<Warning>
  The OSS share-link flow is deprecated and retained for compatibility. No removal date has been announced. For new team sharing and collaboration, [sign up for Workspaces](https://plannotator.ai/workspaces).
</Warning>

You do not need either service for normal local reviews or to open a temporary session from another device. Install Plannotator and run it beside your coding agent for local use. See [Remote access](/open-source/remote-access) for phones, tablets, Tailscale, private networks, SSH, and development containers.

## Understand the sharing services

The share portal is a static browser application. It has no application database, accounts, or built-in access control.

For a normal Markdown share, Plannotator compresses the review into the complete URL after `#`. The browser does not send that fragment to the portal in its HTTP request. The portal loads the application, then the browser decodes the review locally. The fragment is not encrypted, so anyone with the complete URL can read the review.

Large Markdown reviews and raw HTML use the paste service. The Plannotator client encrypts the payload before upload. The paste service stores ciphertext, while the decryption key stays in the complete share URL after `#`. Anyone with the complete link can fetch and decrypt the content.

Deploy only the portal when hash-based Markdown links are enough. Deploy both services when you need encrypted short links or raw HTML sharing.

<Warning>
  Neither service provides application authentication or certificates. Your hosting layer must provide HTTPS, access controls, rate limits, and network isolation where required.
</Warning>

## Deploy the share portal

Build the portal from a Plannotator source checkout. Check out the release tag or reviewed commit you intend to operate before installing dependencies:

```bash theme={null}
git clone https://github.com/backnotprop/plannotator.git
cd plannotator
git checkout <release-tag-or-commit>
bun install
bun run build:portal
```

Deploy the contents of `apps/portal/dist/` to a static host. Configure unknown paths, including `/p/<paste-id>`, to return `index.html` so direct short-link visits load the application. The hosting layer must provide HTTPS, access logs, caching rules, and any access control you require.

Point new Plannotator sessions at the portal:

```bash theme={null}
export PLANNOTATOR_SHARE_URL=https://share.example.com
```

The process that starts Plannotator must inherit this variable. Existing sessions do not change their share base URL.

The portal performs Plannotator's automatic GitHub release check when it loads. Rendered shared content can also request remote images, fonts, scripts, or other resources it references. There is no setting that disables the release check.

## Deploy the paste service

The paste service exposes `POST /api/paste` and `GET /api/paste/:id`. The repository includes two targets:

* A Bun server with filesystem storage.
* A Cloudflare Worker with KV storage.

Neither target authenticates callers. CORS controls which browser origins can use responses. It does not authenticate callers or block direct HTTP clients.

The shared CORS helper always allows `http://localhost` and `https://localhost` origins, including ports. Setting an explicit origin list does not remove that localhost exception.

### Run the Bun filesystem target

From the Plannotator source checkout:

```bash theme={null}
PASTE_PORT=19433 \
PASTE_DATA_DIR=/var/lib/plannotator-paste \
PASTE_TTL_DAYS=7 \
PASTE_MAX_SIZE=5242880 \
PASTE_ALLOWED_ORIGINS=https://share.example.com \
bun run apps/paste-service/targets/bun.ts
```

Run the process under your normal service supervisor. The Bun target listens on all interfaces by default, even though its startup message prints a `localhost` URL. Enforce firewall or private-network isolation and put it behind an HTTPS reverse proxy. Do not leave port `19433` directly reachable from an untrusted network.

The API has no authentication. If it is reachable beyond a trusted private network, add authentication and request-rate controls at the proxy or edge. The payload limit caps each upload, not the number of uploads or total storage growth.

The data directory must have the ownership and backup policy you want. The process creates it when it is absent. The default maximum is 5 MiB of encrypted payload data. Each filesystem paste records its expiry time. An expired file is deleted when that paste is read or when the service next starts, so expired bytes can remain on disk past their logical expiry while a long-running service is idle.

GitHub releases also include `plannotator-paste-*` binaries and matching `.sha256` files for macOS, Linux, and Windows. Download the binary and same-named checksum file from the same release. Verify them before running the binary with the same `PASTE_*` variables:

```bash theme={null}
# Linux
sha256sum -c plannotator-paste-linux-x64.sha256

# macOS
shasum -a 256 -c plannotator-paste-darwin-arm64.sha256
```

On Windows, run `Get-FileHash .\plannotator-paste-win32-x64.exe -Algorithm SHA256` and compare the result with `plannotator-paste-win32-x64.exe.sha256`.

### Run the Cloudflare KV target

The repository's `apps/paste-service/wrangler.toml` is a deployment example, not a namespace allocation for your account. Create your own KV namespace, replace both namespace IDs, and set `ALLOWED_ORIGINS` to your portal origin before deployment. Do not deploy the checked-in hosted namespace IDs into another environment.

```bash theme={null}
cd apps/paste-service
bunx wrangler kv namespace create PASTE_KV
bunx wrangler kv namespace create PASTE_KV --preview
bun run deploy:cf
```

Put the first command's namespace ID in `id` and the preview command's ID in `preview_id` before deploying.

The current Worker target uses Cloudflare KV expiry with a fixed seven-day TTL and a fixed 5 MiB encrypted payload limit. Its supported runtime setting is `ALLOWED_ORIGINS`. The Bun-only `PASTE_TTL_DAYS`, `PASTE_DATA_DIR`, and `PASTE_MAX_SIZE` variables do not configure the Worker target.

## Connect Plannotator to both services

Set both URLs in the environment that starts your coding agent:

```bash theme={null}
export PLANNOTATOR_SHARE_URL=https://share.example.com
export PLANNOTATOR_PASTE_URL=https://paste.example.com
```

Custom short links include the paste-service origin in the URL fragment so the static portal knows where to fetch the ciphertext. Anyone with the complete link has the paste ID and decryption key.

## Deployment variables

| Variable                | Default                                              | Applies to                                  |
| ----------------------- | ---------------------------------------------------- | ------------------------------------------- |
| `PLANNOTATOR_SHARE_URL` | `https://share.plannotator.ai`                       | Share portal used in generated links        |
| `PLANNOTATOR_PASTE_URL` | `https://plannotator-paste.plannotator.workers.dev`  | Paste API used for short links and raw HTML |
| `PASTE_PORT`            | `19433`                                              | Bun paste-service port                      |
| `PASTE_DATA_DIR`        | `~/.plannotator/pastes`                              | Bun filesystem paste storage                |
| `PASTE_TTL_DAYS`        | `7`                                                  | Bun paste logical expiry                    |
| `PASTE_MAX_SIZE`        | `5242880`                                            | Bun maximum encrypted payload bytes         |
| `PASTE_ALLOWED_ORIGINS` | `https://share.plannotator.ai,http://localhost:3001` | Bun CORS allowlist                          |
| `ALLOWED_ORIGINS`       | `https://share.plannotator.ai,http://localhost:3001` | Cloudflare Worker CORS allowlist            |

See [Environment variables](/open-source/reference/environment-variables) for general `PLANNOTATOR_*` precedence and the setting that disables sharing.

## Operator responsibilities

### Authentication and network exposure

* The static portal and paste API have no application authentication. Add access control at your hosting layer if your reviewers require it, then test the complete redirect and URL-fragment flow.
* CORS is a browser boundary, not caller authentication.
* A public paste API needs rate limits or equivalent abuse controls. The payload-size limit alone does not prevent repeated uploads.

### TLS and link handling

* The repository does not provision certificates or an HTTPS reverse proxy. The operator owns TLS for the portal and paste API.
* Treat every complete share URL as a credential. Hash-based Markdown is readable from the URL. Short links contain the decryption key in the fragment.
* Avoid putting complete share URLs in analytics, support tickets, screenshots, or logs with broader retention than the review.

### Persistence, retention, and backup

* Keep the Bun paste data directory on persistent storage only if short links must survive restarts.
* Decide whether ephemeral ciphertext belongs in backups. A backup can retain bytes after the live paste expires, so its deletion schedule must match your policy.
* Monitor disk use for the Bun target. Logical expiry does not guarantee immediate file removal from an idle, continuously running service.

## Verify the deployment

**1. Check the portal.** Confirm that a direct portal route reaches the static application:

```bash theme={null}
curl -fsS -o /dev/null -w '%{http_code}\n' https://share.example.com/p/test
```

A working single-page application fallback returns `200`.

**2. Check the paste API.** Send harmless data and inspect the CORS response:

```bash theme={null}
curl -i https://paste.example.com/api/paste \
  -H 'Origin: https://share.example.com' \
  -H 'Content-Type: application/json' \
  --data '{"data":"deployment-check"}'
```

Expect `201`, an `Access-Control-Allow-Origin` header for the portal, and a JSON paste ID.

**3. Test the deprecated sharing flow.** Start a new Plannotator session with the custom variables. Create a normal Markdown link and an explicit short link. Confirm both use your portal, the short link fetches from your paste API, and an imported returned link restores the review annotations.

For failures, check [Troubleshooting](/open-source/troubleshooting), the browser network panel, the static host's single-page application fallback, and the exact origin in the paste-service CORS setting.

## What this deployment does not provide

The share portal and paste service do not provide a persistent Plannotator review server, account system, built-in authentication, certificate management, live collaborative editing, or centrally managed document history. They support asynchronous links for a deprecated OSS workflow.

For new team sharing, durable documents, access management, and live collaboration, [sign up for Workspaces](https://plannotator.ai/workspaces).

Last verified on August 10, 2026, against Plannotator product commit `f8951cd` and release `v0.26.7`. Maintained by the Plannotator project.
