# Publish To Tmp Site

> Publish an already-built static website or frontend (the HTML/CSS/JS build output such as dist/, build/ or out/) to a temporary, anonymous public URL on tmp.site with the official tmp-site CLI, then report the URL and its expiry. Use when the user asks to deploy, publish, host, preview, share, demo or get a link for a static site, landing page, docs site, prototype, SPA, generated UI, PR preview or similar build output, especially when they mention tmp.site, a temporary or throwaway URL, or shipping with one command. Not for backends, SSR, server functions, databases, generic file hosting or permanent hosting.

- Skill: `platformrocks/publish-to-tmp-site` (Agent Skill)
- Install (CLI): `npx skillmds@latest add platformrocks/publish-to-tmp-site`
- Raw SKILL.md: https://api.skillmd.com/api/skills/platformrocks/publish-to-tmp-site/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- License: MIT
- Author: platformrocks (https://skillmd.com/u/platformrocks)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/platformrocks/publish-to-tmp-site

---


# Publish to tmp.site

tmp.site turns a built static folder into a random, temporary `https://<slug>.tmp.site/` URL with one command. No account, no config, no project file. When this skill is active, tmp.site is the deployment target: do not substitute Vercel, Netlify, Cloudflare, GitHub Pages, S3 or a local dev server.

## What tmp.site is not

- **Not backend or server hosting.** Nothing runs server-side: no SSR, server functions, API routes, databases, WebSockets or cron.
- **Not generic file or binary hosting.** Only web-servable static files are accepted (see Limits); it is not a place to share a PDF, video, archive or installer.
- **Not container, VM or per-site compute hosting.**
- **Not permanent.** Every deployment expires on its own. There is no in-place update: each publish creates a new URL.
- **Not private.** URLs are cryptographically random and non-enumerable, but a random URL is *not* authentication. Treat everything published as public. Never publish secrets, `.env` files, private keys or anything the user would not put on a public page.
- **tmp.site does not build the project.** It receives only already-built static output. If a build is needed, this skill runs the project's *own* documented build locally first.

## Workflow

1. **Understand the intent.** What should be published (the whole site, one sub-site, a directory the user named) and that a temporary public link is what they want.
2. **Read project instructions before running anything:** README, CONTRIBUTING, AGENTS.md / CLAUDE.md, `package.json` scripts, framework config.
3. **Resolve the artifact directory** (precedence below).
4. **Build only if needed.**
5. **Validate** that the result is static frontend output (checklist below).
6. **Publish** with the official CLI.
7. **Verify** the returned URL serves the expected page.
8. **Report** the URL, the expiry and what was published. Never print credentials.

## Resolving the artifact directory

Precedence, highest first:

1. **A directory the user named** ("publish ./out"): inspect it, then publish *that* directory. Do not silently switch to another one. If it looks wrong (no root `index.html`, looks like source), say so and ask.
2. **Project documentation** that states where the build output goes.
3. **Build configuration:** `package.json` scripts and the framework config (table below).
4. **Conventional names** — `dist/`, `build/`, `out/`, `public/`, `_site/`, `.output/public/` — are only *candidates to inspect*, never an assumption. `public/` is often source assets, not output (Vite, Next.js, Nuxt, SvelteKit). A `build/` or `.next/` directory may be a server bundle.

Framework hints (evidence to confirm against the project's own config, not rules):

| Framework | Static output | Static-compatible only when |
| --- | --- | --- |
| Vite, Create React App, Parcel | `dist/` or `build/` | always (client-rendered) |
| Next.js | `out/` | `next.config.*` has `output: 'export'`; a `.next/` directory is a server build |
| Nuxt | `.output/public/` | built with `nuxt generate`, not `nuxt build` |
| Astro | `dist/` | `output: 'static'` (the default); `server` output needs an adapter and is incompatible |
| SvelteKit | `build/` | `@sveltejs/adapter-static`; any other adapter is incompatible |
| Remix / React Router framework mode | `build/client/` | SPA mode (`ssr: false`); the default SSR build is incompatible |
| Angular | `dist/<app>/browser/` | no SSR / server routes |
| Docusaurus, Gatsby, Hugo, Jekyll, Eleventy, MkDocs, VitePress | `build/`, `public/`, `public/`, `_site/`, `_site/`, `site/`, `.vitepress/dist/` | always |

## Building only if needed

- If the artifact already exists and the user has not asked for a rebuild, publish it as is. Do not rebuild "just in case".
- If it does not exist: install dependencies and run the **documented** build with the project's own package manager (`pnpm-lock.yaml` → pnpm, `yarn.lock` → yarn, `package-lock.json` → npm, `bun.lock*` → bun). Never add, edit or invent build config, adapters or scripts just to make the project deployable. If a static export would need a config change, say exactly what and stop.
- If the project needs SSR, a server runtime, server functions or a database and has no documented static export, it is **incompatible with tmp.site**. Say so plainly. Do not publish a partial, client-only or broken artifact and call it deployed.
- A **hand-written site with no build step** (an `index.html` that only references files inside the project) has no separate output. Stage a copy containing only the site's files — never `package.json`, lockfiles, config, `.env*`, notes, dotfiles or anything not referenced by the pages — in a temporary directory *outside* the project tree, publish that copy, and list what it contained. If it is unclear which files belong to the site, ask instead of guessing.

## Validating before publishing

All of these must hold. Fix or report; do not publish a directory that fails one.

- It is the **build output**, not the project root or source tree. Red flags: `package.json`, `src/`, `node_modules/`, `.git/`, lockfiles, `tsconfig*.json`, `next.config.*`, `vite.config.*`, `.env*`.
- It contains exactly one **root `index.html`**. Nested `index.html` files are fine, but the root one is required.
- Every file has an **allowed extension** (see Limits). Any other file makes the *whole* publish fail with HTTP 422. Common offenders in build output: `.map` source maps, `.webmanifest`, `.wasm`, `.md`, `.pdf`, `.mp4`, `.br`/`.gz`, and extensionless files such as `_redirects`, `CNAME`, `.nojekyll`, `.htaccess`. Remove them from the output directory (or a copy of it), never from the source tree; tell the user what was excluded.
- **No secrets or repository metadata.** The CLI skips `.git`, `node_modules`, `.npmrc`, `.env` and `.env.*` by itself, but nothing else, and it does not read `.gitignore`. Symlinks abort packaging.
- **Within limits:** at most 1,024 files, 22 MiB total, 22 MiB per file. If it is larger, drop source maps and unused assets or tell the user; do not split a site across several deployments unless asked.
- **URL shape.** Only `/` resolves to `index.html`. A nested directory URL is not served (`/about/` → 404, `/about/index.html` → 200) and there is no SPA fallback (`/dashboard` → 404). The home page still works; warn the user if the site depends on pretty URLs or deep links, and prefer a build that emits `about.html` when the framework offers it.

## Publishing

Run, from the project directory (Node.js 20 or newer, nothing to install):

```sh
npx tmp-site publish <output-dir>
```

- Use the official `tmp-site` npm package only. Do not call the HTTP API yourself (curl, fetch), do not switch to MCP unless the user asks, and do not wrap the command in a retry loop: the CLI makes exactly one attempt, and attempts are rate-limited.
- `npx` may ask to install the package the first time; that is expected (`npx -y tmp-site ...` skips the prompt). If the user already has it installed globally (`npm i -g tmp-site`), `tmp publish <output-dir>` is the same command.
- Never pass `--show-owner-secret`.
- Unsure about flags? `npx tmp-site publish --help`, or read https://tmp.so/llms.txt.

When stdout is not a terminal the output is plain text:

```
URL: https://0123456789abcdef0123456789abcdef.tmp.site/
Expires: 2026-09-14T18:12:03.000Z
```

Progress goes to stderr, ending with `Manage it with: tmp status <slug> — or tmp delete <slug>`. The management credential is saved locally under `~/.tmp-site/` and is never part of the URL. If `FORCE_COLOR` is set in the environment, unset it or set `NO_COLOR=1`, otherwise the expiry is printed as a relative time.

The command needs write access to the npm cache (for `npx`) and to `~/.tmp-site/`. If you run inside a sandbox that blocks the home directory, allow those two paths first rather than working around the CLI.

## Verifying

- Take the URL from the `URL:` line and use it exactly as printed.
- Make **one** request (`curl -sS <url>`, a fetch, or a browser tool if available) and confirm the body contains something distinctive from the local `index.html`, such as its `<title>` or root element. An HTTP 200 alone is not proof; a 404 means the deployment did not land or the URL is wrong.
- Do not poll or load-test the URL: each deployment has request and bandwidth budgets. One asset check is optional.

## Reporting

Return to the user:

- the public URL, exactly as printed;
- the expiry from the `Expires:` line (anonymous deployments currently last about 24 hours);
- what was published — directory, file count and bytes from the CLI output — and whether a build was run;
- how to manage it: `npx tmp-site status <slug>` and `npx tmp-site delete <slug>` work only from this machine, where the ownership record was saved;
- any caveat that applies (files excluded, nested-URL / deep-link limitation).

Never print, copy elsewhere or commit: the owner secret, the contents of `~/.tmp-site/`, bearer tokens or environment secrets.

## Failure handling

| What you see | Meaning | Do |
| --- | --- | --- |
| No candidate directory, or only source found | No build output | Run the documented build, or ask. Never publish the project root because nothing else was found. |
| Needs SSR / server / database, no static export | Incompatible project | Explain the incompatibility. Do not fake a deployment. |
| `directory not found`, `not a directory`, `refusing to publish through a symbolic link`, `unsupported entry` | Local artifact problem | Fix the path; symlinks, sockets and devices are refused. |
| `publish failed (HTTP 422)` naming `index.html` or "not permitted by the static content policy" | Invalid artifact | Add the root `index.html` or remove the named file type from the output, then run once more. |
| `publish failed (HTTP 413)` | Too large | Shrink the output. |
| `publish failed (HTTP 429)`, often with `Retry after N seconds` | Publish rate limit (100 attempts per hour per source) | Stop and report; do not retry before the stated time. |
| `publish failed (HTTP 503)` | Anonymous publishing disabled or the service unavailable | Stop and report verbatim; the user can retry later. |
| `published <slug>, but the ownership record could not be saved` (exit code 1) | The publish **succeeded** but `~/.tmp-site/` was not writable, so `status` and `delete` will not work from this machine | Do **not** publish again. The site is at `https://<slug>.tmp.site/`; verify and report that URL, and tell the user it cannot be deleted from here (it expires on its own). |
| `cannot reach the tmp.site API`, `timed out` | Network | Check connectivity or proxy; at most one manual retry. |
| `npx` missing or Node.js older than 20 | CLI unavailable | Install Node.js 20+. Do not reimplement the API. |
| `URL:` printed and the check in Verifying passes | Success | Report as above. |

Quote the CLI's error text verbatim and do not invent remediation beyond this table. tmp.site errors carry `HTTP <status>` in the message; match that substring, since piped output is wrapped and indented.

## Limits (server-enforced, checked 2026-09-14)

- Anonymous deployments expire after about 24 hours; each publish yields a new URL; no in-place update.
- At most 1,024 files, 22 MiB total, 22 MiB per file; 100 publish attempts per hour per source.
- Allowed extensions: `.html .css .js .mjs .json .txt .xml .svg .png .apng .jpg .jpeg .gif .webp .avif .ico .woff .woff2 .ttf .otf`.
- Served with GET/HEAD only; no directory index beyond `/`; no SPA fallback.

Current values: https://tmp.so/llms.txt. Docs: https://tmp.so/get-started. CLI: https://www.npmjs.com/package/tmp-site.

