Publish HTML, Markdown and static mini apps to shareable Cloudflare Pages URLs from the terminal or coding agents.
$git clone https://github.com/amal-david/pagecastInstalls into the current project.
Install pagecast by running `git clone https://github.com/amal-david/pagecast`, then use it for the current task and follow its documentation at https://github.com/amal-david/pagecast.
| 1 | # Pagecast |
| 2 | |
| 3 | Preview local HTML reports, Markdown docs, and static mini apps, then publish |
| 4 | them to shareable Cloudflare Pages URLs — from the terminal or your coding agent. |
| 5 | |
| 6 | **Site:** <https://pagecasthq.pages.dev/> · |
| 7 | **Agent skill:** [`publish-report` on Skills.sh](https://www.skills.sh/amal-david/pagecast/publish-report) · |
| 8 | **Architecture:** [ARCHITECTURE.md](ARCHITECTURE.md) |
| 9 | |
| 10 | <p align="center"> |
| 11 | <img src="media/admin.png" alt="Pagecast admin UI: published reports with per-page password protection" width="900"> |
| 12 | </p> |
| 13 | |
| 14 | Pagecast is a local-first publishing tool for agent-generated reports and small |
| 15 | static web projects: preview files, publish, re-sync, rename links, |
| 16 | password-protect pages, and revoke URLs — from a local admin UI or headless |
| 17 | `pagecast` commands. Good fits: HTML reports and dashboards, Markdown docs and |
| 18 | plans, static mini apps from `dist`/`build`/`out`. Not a fit: server-rendered |
| 19 | apps that need a running backend (export static assets first). |
| 20 | |
| 21 | ## Quick Start |
| 22 | |
| 23 | Requires Node.js 20.19+ and a Cloudflare account (for publishing). No global install: |
| 24 | |
| 25 | ```sh |
| 26 | npx pagecast |
| 27 | ``` |
| 28 | |
| 29 | This starts the local app and opens the admin UI: |
| 30 | |
| 31 | - Admin UI — `http://pagecast.localhost:4173` |
| 32 | - Local preview/public origin — `http://pagecast.localhost:4174` |
| 33 | - Pagecast Home — `~/.pagecast/home/` (Cloudflare target, publication registry, settings) |
| 34 | - Workspace metadata — `.pagecast/` in the current directory |
| 35 | |
| 36 | One OS user profile owns one Pagecast Home and Cloudflare subdomain. Run the CLI |
| 37 | from the relevant project; use `--data-dir` only for an intentionally isolated |
| 38 | CI/container profile. If the default ports are busy, Pagecast falls forward to |
| 39 | the next free pair and remembers it. |
| 40 | |
| 41 | In the admin UI, confirm the suggested Home subdomain and click **Connect |
| 42 | Cloudflare** — Pagecast runs Wrangler's scoped browser OAuth flow (Cloudflare |
| 43 | labels the app **Wrangler**) and resumes setup after consent. From a source |
| 44 | checkout, run `npm start` instead. Prefer containers? See |
| 45 | [Run with Docker](#run-with-docker). |
| 46 | |
| 47 | Run in the background, or (macOS) install a login service plus a local-only |
| 48 | `http://pagecast.localhost` redirect: |
| 49 | |
| 50 | ```sh |
| 51 | npx pagecast background start && npx pagecast open |
| 52 | npx pagecast setup-local-url |
| 53 | # manage: pagecast local-url status|remove, pagecast background service status|uninstall |
| 54 | ``` |
| 55 | |
| 56 | Headless/advanced setup: |
| 57 | |
| 58 | ```sh |
| 59 | npx pagecast pages setup --project your-pagecast-home |
| 60 | # multiple accounts? add --account <account-id> |
| 61 | # automation? export CLOUDFLARE_API_TOKEN (scoped Pages:Edit) + CLOUDFLARE_ACCOUNT_ID |
| 62 | ``` |
| 63 | |
| 64 | **Upgrading from 0.5:** stop the old process (`npx pagecast@0.5.0 background stop`), |
| 65 | reinstall the macOS login service if you use it (`npx pagecast@0.6.1 background |
| 66 | service install`), and reload the unpacked Chrome extension from the matching |
| 67 | release. The first 0.6 launch creates `~/.pagecast/home/` and imports compatible |
| 68 | workspace publications without changing URLs; publications on other Cloudflare |
| 69 | projects remain legacy targets until you explicitly attach or move them. |
| 70 | |
| 71 | ## Publish From The Terminal |
| 72 | |
| 73 | ```sh |
| 74 | # An HTML or Markdown file → a memorable /p/<slug>/ link (source folder included) |
| 75 | npx pagecast publish "/absolute/path/report.html" --json |
| 76 | |
| 77 | # Set an expiry — 7d, 12h, or never (default 30d) |
| 78 | npx pagecast publish "/absolute/path/report.html" --expires 7d --json |
| 79 | |
| 80 | # Force a new URL, or explicitly update a known one |
| 81 | npx pagecast publish "/absolute/path/report.html" --new-link --json |
| 82 | npx pagecast publish "/absolute/path/report.html" --update <url-or-token> --json |
| 83 | |
| 84 | # A built static project → publish its entry file |
| 85 | npm run build && npx pagecast publish ./dist/index.html --json |
| 86 | |
| 87 | # A whole folder → replace a named Pages project directly (--branch defaults to main) |
| 88 | npx pagecast pages deploy ./dist --project my-static-site --json |
| 89 | ``` |
| 90 | |
| 91 | Things to know: |
| 92 | |
| 93 | - `publish` copies every non-hidden, non-symlink file under the source folder, |
| 94 | referenced or not — publish from a clean folder and keep secrets elsewhere. |
| 95 | - New links are **unlisted**: a memorable label plus a 128-bit suffix. Anyone |
| 96 | with the URL can view it — unlisted is not private. The admin UI's **Short |
| 97 | public link** toggle (or renaming to a vanity slug) makes a guessable public |
| 98 | drop instead. Password protection is the access-control option. |
| 99 | - Publishing is context-aware: repeating a publish for the same item in the same |
| 100 | agent context updates the existing URL. Context comes from `--context-id`, |
| 101 | `PAGECAST_CONTEXT_ID`, `CODEX_THREAD_ID`, `CLAUDE_SESSION_ID`, then a |
| 102 | workspace/source fallback; override matching with `--new-link` or `--update`. |
| 103 | - `pages deploy` is a separate, stateless whole-site operation on the named |
| 104 | project. It never changes the project used for managed `/p/...` links — |
| 105 | use a separate project unless replacing the managed site is intentional. |
| 106 | - `statusCode 401` → authentication required (interactive runs start Wrangler |
| 107 | auth automatically); `statusCode 409` → conflict, follow the returned message. |
| 108 | |
| 109 | ## Activity Analytics |
| 110 | |
| 111 | Optional, enabled in Settings: |