Skip to main content

sidepage

Local-first hosting and tunneling for code, static sites, and notebooks. sidepage serve wraps almost anything — a script, a static site, a Streamlit, FastAPI, or Gradio app, a Python MCP server, a Jupyter notebook — behind a local reverse proxy and hands you a URL. sidepage proxy does the same for a service you already have running (npm run dev, a container, anything already listening on a port).

Everything shipped is tested end to end; anything needing a cloud backend that doesn't exist yet says "not implemented" rather than failing silently (Project status).

Install

pip install sidepage
sidepage setup      # installs cloudflared — needed for --anon/--domain tunneling

Needs Python 3.12+ and uv on PATH — sidepage shells out to it to run whatever serve points at. Contributing? See docs/DEVELOPMENT.md.

Quickstart

sidepage serve, from command to public URL

sidepage serve ./my-site --name demo              # static site
sidepage serve app.py --name demo --auth token    # gated behind a token
sidepage serve notebook.ipynb --name demo         # editable Jupyter Lab, live kernel

sidepage secrets set MY_KEY                       # inject a secret, expose publicly
sidepage serve app.py --env MY_KEY --anon

sidepage pull hf:kalpi314/tiny_notes              # pull a huggingface space and register as app
sidepage proxy --port 5173 --name my-vite-app     # wrap `npm run dev`
sidepage serve app.py --anon --pwa --qr           # installable, with a QR to scan

--type is auto-detected, and within code so is the framework — Streamlit/FastAPI/MCP/Gradio each recognized by import and started with their real launcher. That's why several lines above are an identical sidepage serve app.py: dispatch reads content, not filenames. Both commands block until Ctrl+C or sidepage stop <app-name>; --detach backgrounds them (below).

How it works

  • A local reverse proxy in front of the app's real port: enforces --auth, counts usage, shows a holding page while the app boots, and proxies HTTP + WebSockets. The wrapped app needs zero sidepage-specific code.
  • A tunnel, per call: --anon for a free, no-account *.trycloudflare.com URL, or --domain <domain> for your own Cloudflare domain. Neither flag means 127.0.0.1 only.

Commands

Command What it does
serve <target> Wrap and host a static dir, script, or app.
proxy --port <n> Wrap an already-running local service.
stop <app-name> Tear down a running app (serve or proxy).
ls / status / usage List apps, check one, read its request counts.
inspect [<app-name>] Interactive HTTP console against a running app.
secrets set|list|remove Encrypted local vault for standing credentials.
account domain set / new <name> Provision a BYO Cloudflare domain / scaffold a static site.
app register|list|show|unregister|delete Save and manage serve invocations.
pull <source> Fetch a Hugging Face Space and register it, without running it.
promote, login, account status Not built yet; they say so.
sidepage serve <target> [--type auto|code|static|notebook] [--name <app-name>]
    [--auth open|token] [--anon | --domain <domain>] [--no-suffix] [--token <v>]
    [--env <SECRET_NAME>]... [--timeout <s>] [--idle-timeout <s>] [--qr]
    [--peer <role>=<app-name>]... [--pwa [--pwa-*]...] [--autoregister]
    [--detach] [--json]

--auth token gates the app behind a header, query param, or cookie set by a gate page. --env is repeatable and fails loud on an unknown name. --anon and --domain are mutually exclusive. sidepage <command> --help has the rest.

Guides

  • proxy.md — read before proxying anything public: forwarded headers, localhost-trust, per-framework fixes.
  • timeouts-and-peers.md — auto-teardown, lazy start, wiring apps together.
  • pwa.md — home-screen install and every --pwa-* flag.
  • registry.md — saving invocations, override and merge semantics.
  • byo-domain.md — your own Cloudflare domain, token scopes, --no-suffix.
  • pull.md — Hugging Face Spaces, and the gate before running downloaded code.

For agents and harnesses

serve and proxy block by default, which is right for a terminal and wrong for anything automated. Pass --detach --json and they return as soon as the app is genuinely serving — or has definitively failed — with one parseable line on stdout:

sidepage serve app.py --name demo --anon --detach --json
{"status":"running","app":"demo","pid":12345,"url":"https://random-words.trycloudflare.com","local_url":"http://127.0.0.1:8501","log":"~/.local/state/sidepage/logs/demo.log"}

Readiness is the registry entry the serving process writes once port, subprocess, and tunnel are all up — not a URL spotted in a log — so "running" means serving. A failed launch reports the real error and exits

  1. Under --json all prose moves to stderr, so stdout pipes into a parser.

This repo is also a plugin marketplace: in Claude Code, /plugin marketplace add dolphinsdotdev/sidepage then /plugin install sidepage@sidepage. That installs plugin/skills/sidepage-serve/, a Skill teaching an agent when to reach for serve vs proxy, which flags matter, and what to surface before pointing a tunnel at something. It bundles no executables, so it also installs cleanly under organization settings. For any other harness, copy that directory to wherever it looks for skills.

Development

uv sync                 # install runtime + dev deps
uv run ruff check .     # lint
uv run pytest           # full suite (~2 min; mostly first-run dependency resolves)

Layout and test-machine requirements: docs/DEVELOPMENT.md.

Project status

Real and tested end to end: serve/proxy for static, code, and notebook targets, open/token auth, --env secrets, --anon and BYO-domain tunneling, stop/ls/status/usage, inspect, the app registry, --timeout/--idle-timeout/--peer, --pwa/--qr, and --detach/--json.

Not implemented, and says so rather than silently no-op'ing: brokered tunneling, login/account status, the directory beyond this machine, --guardrail, --auth network/oauth, MCP tool browsing in inspect, and an OS-keychain vault backend. One known limitation, investigated not fixed: HMR for a Vite target proxied through --anon.

Full breakdown in docs/CHECKLIST.md; rationale in docs/OPEN_QUESTIONS.md.

Metadata

Release files for sidepage 0.2.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sidepage 0.2.4
File Size Uploaded
sidepage-0.2.4.tar.gz 144.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sidepage 0.2.4
File Interpreter ABI Platform
sidepage-0.2.4-py3-none-any.whl Python 3 none any Details

Total release size: 316.3 kB

Release files / sidepage-0.2.4.tar.gz

Download URL sidepage-0.2.4.tar.gz
Size 144.9 kB
Tags Source
SHA-256 checksum
How to use checksums
ba4e23c08e17c84caf8c45f8425f80cf59c2b3b4b2cf3c2a2c9dfe0a9cd6b3b4
BLAKE2b-256 checksum
How to use checksums
69d5f2e751195b5082335321f5fd7e4fee02a6ef68f70069ab9fcd4b25d6d300
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / sidepage-0.2.4-py3-none-any.whl

Download URL sidepage-0.2.4-py3-none-any.whl
Size 171.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e2dd04061c29f3d00127b1e7c1992faa35360b34751b08373c4ae77cb5fcd571
BLAKE2b-256 checksum
How to use checksums
facd87be009a8c281a8d54b34711b18fdca9b52a9154bc975227c22c9928e6a1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.2.4 This release

2 release files

0.2.3

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page