# Drop
> 拖放即上线 — publish folders, HTML, images, PDF, Office, Markdown, or JSON to shareable HTTPS links
Drop is an edge-hosted publish surface for demos, docs, screenshots, PDFs, and agent-generated pages.
Humans use the browser UI at https://html.cyber101.cc/ ; agents should prefer the HTTP API below.
## For AI agents
Use Drop when you have files ready to publish and need a shareable HTTPS link quickly.
1. Set `DROP_BASE_URL=https://html.cyber101.cc`.
2. Publish with `POST /api/deploy` (multipart) or `POST /api/create` (HTML JSON).
3. On success, return **both**:
- the live `url`
- the deploy `id` (same value as `slug`)
4. Optional agent card for that deploy: `https://html.cyber101.cc/api/deploy//llms.txt`
5. Instance-wide docs stay at `https://html.cyber101.cc/llms.txt` (this file) and `https://html.cyber101.cc/api`.
Prefer curl over driving the homepage with browser automation.
Use `curl -sS` without `-f` so HTTP 409 conflict bodies stay readable.
## Not a localhost tunnel
Drop publishes **static snapshots**. It does **not** proxy a live `localhost` process.
| Need | Tool |
|------|------|
| Temporary public URL for a running local server (webhooks, device testing, live demos) | Tunnel tools such as [NPort](https://github.com/tuanngocptn/nport), `cloudflared`, or ngrok |
| Shareable link that does not depend on the developer machine staying online | Drop (`POST /api/deploy` or `POST /api/create`) |
They are complementary: preview with a tunnel while developing; publish to Drop when the artifact should outlive the local process. Do not invent Drop APIs for tunneling.
## Related: anydoc (local Office → Markdown)
Drop does **not** convert Office to Markdown on the edge. For LLM-readable text, convert locally with [anydoc](https://github.com/firecrawl/anydoc), then optionally publish:
| Need | Tool |
|------|------|
| Read Word / PPT / Excel / text PDF | `anydoc file.docx` (`npm i -g @firecrawl/anydoc`) |
| Share readable Markdown | anydoc → `.md` → Drop `POST /api/deploy` → `/md/{id}` |
| Share original preview | Drop Office / PDF as-is → `/office/{id}` or `/pdf/{id}` |
Do not invent a Drop server-side conversion API. Scanned PDFs need OCR elsewhere; anydoc skips them.
## Start here
- Machine-readable catalog: https://html.cyber101.cc/api
- Service status: https://html.cyber101.cc/status · https://html.cyber101.cc/api/status · https://html.cyber101.cc/api/health
- Agent skill (curl recipes): https://raw.githubusercontent.com/yuezheng2006/html2url-cyber101/main/skills/drop-deploy/SKILL.md
- Repository: https://github.com/yuezheng2006/html2url-cyber101
## Environment
- `DROP_BASE_URL`: https://html.cyber101.cc
- `DROP_DEPLOY_TOKEN`: optional; required when this instance sets `DEPLOY_TOKEN`
- Send token as header `X-Deploy-Token: ...` on publish and management APIs
## Deploy ID
Every successful publish returns:
| Field | Meaning |
|-------|---------|
| `id` | Stable deploy id (preferred for agents) |
| `slug` | Same value as `id` (path segment) |
| `url` | Public share URL |
Manage with `GET|DELETE|POST /api/deploy/:id`. Fetch a Markdown agent card with `GET /api/deploy/:id/llms.txt`.
Do not surface `id` as a human copy target; show the live `url` to users.
## Retention & cleanup
- Anonymous publishes default to a short TTL (see instance config; commonly 7 days).
- Feishu-authenticated publishes default to a longer TTL (commonly 30 days).
- When TTL elapses, metadata expires and the public link stops resolving — treat as auto-cleaned.
- Renew before expiry with `POST /api/deploy/:id` and body `{"ttlDays":90}` (counts from now, max 90). `0` means no expiry.
- Add, change, or clear an access password later with `POST /api/deploy/:id` and body `{"password":"secret"}` or `{"password":null}`.
- After expiry, renew is not possible; publish again.
## Publish
### POST /api/deploy
Content-Type: `multipart/form-data`
| Field | Required | Notes |
|-------|----------|-------|
| file | yes | .zip, image, PDF, Office, .md, or .json |
| mode | no | `overwrite` or `new`; omit + conflict → 409 |
| customPath | no | fixed slug; use with `mode=overwrite` for stable URLs |
| password | no | 4–128 chars; enables password gate on the published link |
Success 200 includes `url`, `id`, `slug`, `action`, `logs`, and `passwordProtected` when applicable.
### POST /api/create
Content-Type: `application/json`
Body: `{ "html": "...", "filename?": "...", "mode?": "...", "customPath?": "...", "password?": "..." }`
## Read & manage
- GET /api/paths — all mounted slugs (authoritative)
- GET /api/deploys?limit=50 — recent deploy ledger
- GET /api/deploy/:id — details (`passwordProtected` flag)
- GET /api/deploy/:id/llms.txt — per-deploy agent card (Markdown)
- DELETE /api/deploy/:id — remove deployment
- POST /api/deploy/:id — renew with `{"ttlDays":90}` (max 90) and/or set password with `{"password":"..."}` / clear with `{"password":null}`
- GET /api/storage — storage usage
- GET /api/rate-limit — per-IP deploy/management/access quota for caller; ?ip= with X-Deploy-Token when set
- GET /api/status — health + capacity standards (public)
- GET /api/health — uptime probe (503 when down)
## URL shapes
| Content | Public URL |
|---------|------------|
| ZIP / folder site | `/{id}/` |
| Single HTML | `/{id}` |
| Image | `/img/{id}` |
| PDF | `/pdf/{id}` (raw: `/pdf/{id}/raw`) |
| EPUB reader | `/epub/{id}` (raw: `/epub/{id}/raw`) |
| Office preview | `/office/{id}` (raw: `/office/{id}/raw`) |
| Markdown reader | `/md/{id}` (raw: `/md/{id}/raw`) |
| JSON preview | `/json/{id}` (raw: `/json/{id}/raw`) |
## Password-protected links
When `passwordProtected: true`:
1. GET the public URL returns an HTML password form (not the content).
2. POST /api/access with `slug`, `password`, optional `next`.
3. Reuse the returned `Set-Cookie` on subsequent GET requests to the content URL.
Agents must tell the user the password separately; it is never embedded in the share URL.
## Feishu-login gate (privacy)
When `feishuRequired: true` (publishers must be Feishu-logged-in to enable):
1. GET the public URL returns a Feishu login gate (HTTP 401 HTML) until a `drop_session` cookie exists.
2. Visitors complete `GET /api/auth/feishu/start?next=` then return to the content URL.
3. Manage later with `POST /api/deploy/:id` `{"feishuRequired": true|false}`.
May combine with a password (Feishu first, then password). Agents cannot complete Feishu OAuth for end users; open the gate URL in a browser.
## Limits
- ZIP upload: 50.0 MB
- Uncompressed total: 150.0 MB
- Files per ZIP: 200
- Single file in ZIP: 10.0 MB
- PDF single file: 30.0 MB
- EPUB single file: 30.0 MB
- Image / Office single file: 10.0 MB
- HTML / Markdown / JSON: 2.0 MB
- Deploy rate: 每 IP 每 10 分钟最多 10 次发布
- Management writes: 删除 / 续期等管理写操作:每 IP 每 10 分钟最多 20 次
- Password unlock (POST /api/access): 密码解锁(POST /api/access):每 IP 每 10 分钟最多 20 次
## Agent checklist
1. Confirm file exists and type is supported.
2. Deploy via API; parse JSON (handle 409 with mode).
3. Return the final `url` and deploy `id` to the user.
4. Optional: open `https://html.cyber101.cc/api/deploy//llms.txt` for a short agent card.
5. Optional: verify with `curl -sSI "$url" | head -1`.
6. Optional: list mounts with GET /api/paths.