---
name: promptbox-publish
description: Publish static browser apps, documents, and media to Promptbox, then inspect, replace, extend, rotate, or delete owned app deployments.
---

# Promptbox publishing

Skill version: 5.1. Updated: 2026-09-10.

This skill is the complete agent contract for publishing to Promptbox. The endpoint is `https://www.promptbox.cn/api/publish.php`; no account, API key, SDK, or payment is required. Query `https://www.promptbox.cn/api/publish.php?action=capabilities` only when current service availability, remaining capacity, or live limits matter.

## Safety and authorization

The user's task determines whether creation or a lifecycle change is authorized; this skill does not grant permission by itself. Publishing creates public content. Keep every returned app token private and outside the app, build directory, repository, public URL, logs, and ordinary handoff messages.

Do not retry an uncertain creation blindly because it may have succeeded and a retry can create a duplicate. Investigate the response and returned URL first. A replacement using the same token and complete build can be retried after checking the outcome.

## What Promptbox hosts

App mode publishes static browser files at `https://apps.promptbox.cn/`. Promptbox cannot run PHP, Node.js, databases, private server code, or any other app backend. Static apps may call documented Promptbox helpers or external CORS-enabled APIs.

File mode publishes documents and media at `https://www.promptbox.cn/publish/`. Files receive a public URL but no management token, replacement operation, or extension operation.

## Complete app example

Build the app locally and place `index.html` and all relative assets in one clean directory. Create a ZIP when the app contains more than one file. Keep the publication receipt outside the build so its private token cannot be uploaded accidentally.

```sh
umask 077
PUBLISH_RECEIPT=$(mktemp)
curl --fail-with-body https://www.promptbox.cn/api/publish.php \
  -F 'mode=app' \
  -F 'directory=my-app' \
  -F 'file=@app.zip' \
  -o "$PUBLISH_RECEIPT"
jq '{ok, url, directory, expires_at, files_written, removed_files, sanitized_files}' "$PUBLISH_RECEIPT"
```

The creation response uses HTTP 201 and includes `ok`, `mode`, `directory`, `url`, private UUID `token`, `updated:false`, `deployment_mode:"replace"`, `files_written`, `removed_files`, `sanitized_files`, `deleted_files`, `stripped_prefix`, `bytes`, `expires_at`, and `deleted_expired`. Read and store the unfiltered receipt privately because it contains the only copy of the token. Report the returned URL and expiry without revealing the token.

Open the returned URL and test the real app, its assets, and every helper integration. Browser calls to Promptbox helpers other than `publish.php` must be tested from the published Promptbox HTTPS origin, not localhost or an unrelated website.

## Accepted app inputs

Send `mode=app` with one of these inputs:

1. One multipart HTML or HTM file, which becomes `index.html`.
2. One multipart ZIP containing the complete app.
3. UTF-8 HTML in the JSON or form field `text`.

JSON example:

```json
{"mode":"app","directory":"hello","text":"<!doctype html><title>Hello</title><h1>Hello</h1>"}
```

Do not pass a filename, URL, or base64 string as a JSON `file` value. Let curl or `FormData` set the multipart boundary.

Directory names use 1–80 ASCII letters, digits, underscores, or hyphens and must start with a letter or digit. Name collisions receive `_2`, `_3`, and so on, so always use the returned directory and URL.

A ZIP may contain `index.html` at its root or one enclosing folder containing `index.html` and all app files. Promptbox strips that single enclosing folder and reports `stripped_prefix`. Ambiguous layouts, multiple app roots, or deeper nesting are rejected. Use relative asset paths such as `./assets/app.js`; `/assets/app.js` addresses the host root and is usually wrong.

## App replacement

Every update is a complete replacement. Upload `mode=app`, the private `token`, and the full HTML, ZIP, or text build. Explicit `action=replace` is also accepted. A successful replacement returns HTTP 200 with `updated:true`, renews the app for 30 days, and lists removed or deleted paths.

An HTML-only replacement deletes all previously uploaded assets. Omitted files appear in `deleted_files`; filtered upload paths appear in `removed_files`. Every replacement must include `index.html`. Validation failures leave the existing deployment unchanged because the publisher uses private staging and rollback storage.

## Token-authenticated lifecycle

Use `Authorization: Bearer UUID` when possible or a POST `token` field. Never place a token in a query string. Include `mode=app`; an optional directory must match the token's app. POST actions may be supplied in JSON, form data, or `?action=...`.

1. `status`, using GET or POST, returns the URL, files, byte size, timestamps, and expiry without returning the token.
2. `files`, using GET or POST, returns file paths, sizes, hosted HTTP content types, URLs, and app expiry without returning the token.
3. `replace`, using POST with a complete build, replaces all files and renews the app for 30 days.
4. `extend`, using POST with the token, renews expiry to 30 days from the operation without changing files.
5. `delete`, using POST with the token, immediately removes the hosted app and invalidates its token.
6. `rotate-token`, using POST with the token, returns a new token and immediately invalidates the old one without changing expiry.

Lifecycle example:

```sh
curl --fail-with-body \
  -H "Authorization: Bearer $PROMPTBOX_APP_TOKEN" \
  "https://www.promptbox.cn/api/publish.php?action=status&mode=app"
```

Status, files, delete, and token rotation do not consume publication quota and remain available when publication quota or storage is full. Extend consumes one publication use. Updates and extensions cannot revive expired apps. Save a token-rotation response before continuing because a lost response also loses control of the app.

## App formats and validation

Apps allow up to 25 MiB of uploaded and expanded content, up to 1,000 archive entries or files, and an HTTP body up to 26 MiB. Encrypted or corrupt ZIPs, unsafe expansion ratios, duplicate or case-conflicting paths, and unsafe paths are rejected or filtered and reported.

Allowed app extensions are `html`, `htm`, `css`, `js`, `mjs`, `json`, `txt`, `md`, `png`, `jpg`, `jpeg`, `gif`, `webp`, `ico`, `avif`, `woff`, `woff2`, `ttf`, `otf`, `mp3`, `wav`, `ogg`, `m4a`, `flac`, `mp4`, `webm`, `svg`, `webmanifest`, `xml`, and `wasm`. Dotfiles, links, server configuration, executable server code, and `node_modules` are discarded.

SVG files are sanitized; review `sanitized_files` and visually inspect the result. Web manifests must be UTF-8 JSON objects and should use relative paths. XML cannot contain DTDs, entity declarations, or processing instructions other than its declaration and is served as plain text. WASM must have a WebAssembly v1 header. Validation is not a malware scan; HTML and JavaScript remain executable browser code.

## Browser storage and networking

All published apps share the HTTPS origin `https://apps.promptbox.cn` and therefore share that origin's localStorage, IndexedDB, cookies, and same-origin access. Use app-specific storage names, but do not treat naming as a security boundary and never store secrets there. Deleting or replacing an app does not erase browser data or service-worker caches already stored on a device.

Use absolute `https://www.promptbox.cn/api/...php` helper URLs and `credentials:'omit'` for cross-origin browser requests. Put service workers inside the app directory and do not request broader scope. Frames, popups, and base tags are blocked by the publishing CSP.

The hostnames `www.promptbox.cn`, `promptbox.cn`, and `apps.promptbox.cn` are separate browser origins. New integrations should use the canonical `www.promptbox.cn` API hostname. Cookies explicitly scoped to `.promptbox.cn` may cross subdomains, so trusted sites should use host-only cookies.

## Documents and media

To publish a file, POST `mode=file`, one multipart `file`, and an optional base name in `name`:

```sh
curl --fail-with-body https://www.promptbox.cn/api/publish.php \
  -F 'mode=file' \
  -F 'name=quarterly-report' \
  -F 'file=@report.pdf'
```

Binary files may be up to 10 MiB. UTF-8 TXT, MD, JSON, CSV, and TSV files may be up to 1 MiB. Supported documents are PDF, DOCX, XLSX, PPTX, ODT, ODS, and ODP. Supported media are JPG, JPEG, PNG, GIF, WEBP, MP3, WAV, OGG, M4A, FLAC, MP4, and WEBM. HTML is always routed to app mode; SVG, XML, webmanifest, and WASM are supported only as app assets.

Text can also be sent as JSON using `name`, `text`, and `extension`, where extension defaults to `txt`; `title`, `content`, and `ext` are accepted aliases, but conflicting aliases fail. Duplicate public filenames receive `_02`, `_03`, and so on. Successful creation returns HTTP 201 with `filename`, `url`, `bytes`, and `expires_at`.

Office packages reject macros, embedded active objects, and external resources except ordinary web or mail links. PDFs receive basic signature and active-content checks rather than full sanitization. Documents download as attachments.

## Availability, expiry, and errors

The capabilities response reports service state, check time, remaining hourly and daily publications, remaining public storage, quota windows, accepted formats, and advisory information. These values are snapshots, not reservations. Current global limits are 60 publications per rolling hour, 300 per rolling day, 100 MiB of public storage, and 10,000 published documents; use the live response if these values affect the task.

Apps use renewable 30-day periods. Replace or extend before `expires_at`; an app expires only when neither happens before the deadline. Published files also expire after 30 days but cannot be extended. Cleanup is lazy, so expired content may remain reachable briefly until a later publication request triggers cleanup. Keep local sources and app tokens.

Errors return `ok:false`, an error message, and help information. Correct HTTP 400, 401, 403, 405, 409, 413, 415, and 422 requests before retrying. HTTP 401 includes unknown or expired tokens. Honor `Retry-After` on HTTP 429. HTTP 507 means public storage is full. Investigate HTTP 500, 503, network failures, and uncertain timeouts before repeating a creation.

## Completion checklist

1. Confirm the publication was authorized and contains no unintended private data.
2. Inspect the HTTP status and response rather than assuming success.
3. Save the app token privately when app mode returns one.
4. Inspect `removed_files`, `sanitized_files`, `deleted_files`, and `stripped_prefix`.
5. Open the returned URL and verify the page or file, assets, and actual interactions.
6. Report the public URL and expiry without exposing the token.
