Your static page works on localhost, but the reviewer needs a link—not a development setup. A screenshot hides the layout, while a new URL for every revision makes the current draft unclear.
The goal: one viewable draft, one review question, and a controlled update. We'll use two versions of a fictional studio invitation.
Disclosure: this HTMLtoURL Pro team tutorial was prepared with AI assistance. On September 8, 2026, we verified a production single-HTML studio publish and same-URL update in a separate viewing tab. ZIP files were checked offline only; the API code below is a documented, unexecuted alternative. No customer visit, payment or mobile test is claimed.
What we actually verified
After publishing demo-v1.html in the studio, a separate public tab showed Review Version 1 and Saturday, 2–5 pm.
We then uploaded demo-v2.html, selected Update same URL, and refreshed that tab. The same link showed Review Version 2, Saturday, 3–6 pm, and the revised question.
The temporary sample displayed an expiry of September 15, 2026, 10:38 AM, Asia/Shanghai. Use the repository and dated evidence as the long-lived reference. We did not read or export a management token during this UI check.
Get the practice files
The kit includes two single-file HTML versions, matching ZIPs, editable sources, validate.py, checksums and recorded checks. The fictional invitation contains no real address, forms, remote assets, tracking, customer data or secrets.
git clone https://github.com/weidacn/ai-creative-practice-kits.git
cd ai-creative-practice-kits/html-review
python3 validate.py
The standard-library validator checks archive paths, local references, source/archive agreement, version changes and checksums—without a network request. Also open demo-v1.html locally: structural validation is not visual review.
1. Choose the right kind of handoff
Use single HTML for a self-contained mockup, or a ZIP for separate assets. This kit's archive contains:
index.html
styles.css
illustration.svg
Keep relative paths intact. Static hosting does not run a backend or database. A public URL is not access control: don't upload confidential material merely because you plan to share with one person.
2. Keep private publishing data outside the project
The API docs separate the public URL from its private manageToken. Reviewers need only the URL. Keep edit data outside the repository:
set -e
umask 077
REVIEW_WORK="$(mktemp -d /tmp/html-review.XXXXXX)"
export REVIEW_WORK
Keep the same terminal open for the remaining commands. Files in this directory may contain the edit key. Do not commit, upload or show them in a recording.
3. Publish the first HTML version intentionally
The tested UI path is: upload version one, review retention/quota details, publish, then upload version two and choose Update same URL.
For the unexecuted API alternative, review the current studio and docs first. This request chooses seven-day retention, not permanent or unlimited hosting:
python3 - <<'PY'
import json
import os
from pathlib import Path
work = Path(os.environ["REVIEW_WORK"])
payload = {
"html": Path("demo-v1.html").read_text(encoding="utf-8"),
"title": "Fictional studio review",
"retentionDays": 7,
}
(work / "request-v1.json").write_text(json.dumps(payload), encoding="utf-8")
PY
curl --disable --retry 0 --fail-with-body --silent --show-error --max-time 60 \
https://htmltourl.pro/push \
-H 'Content-Type: application/json' \
--data-binary "@$REVIEW_WORK/request-v1.json" \
-o "$REVIEW_WORK/response-v1.private.json"
Running this performs a real upload. --disable ignores personal curl configuration; --retry 0 prevents automatic retries. A timeout is ambiguous: stop and check whether it completed before another POST. A quota/rate rejection is not success.
Print only viewing information—not the response or edit key:
python3 - <<'PY'
import json
import os
from pathlib import Path
work = Path(os.environ["REVIEW_WORK"])
result = json.loads((work / "response-v1.private.json").read_text())
print("Public review URL:", result["url"])
print("Confirmed expiry:", result["expiresAt"])
PY
Use the actual response; no success output is invented here.
If you choose the ZIP instead
Start a separate ZIP test rather than assuming it shares the HTML test's management key:
curl --disable --retry 0 --fail-with-body --silent --show-error --max-time 60 \
https://htmltourl.pro/api/site-packages \
-F 'archive=@demo-v1.zip' \
-F 'title=Fictional packaged studio review' \
-F 'retentionDays=7' \
-o "$REVIEW_WORK/zip-response-v1.private.json"
Let curl set the multipart boundary, and check both compressed and extracted-size limits. The remaining code updates HTML. A ZIP update instead needs its own original slug/token and the whole replacement archive.
4. Verify the review experience, not just the response
Open the returned public URL separately. Check the heading, time, review question and expiry; for a ZIP, check CSS/SVG loading too. Test the intended device before promising compatibility.
Your QA visit is not a customer's visit. Ask a real reviewer to confirm loading and answer one question. Send only the view URL and actual expiry, never its edit key.
5. Update the HTML without losing track of the URL
The documented update sends replacement HTML with the original slug and management token. Stop rather than guess if the returned domain format differs:
python3 - <<'PY'
import json
import os
from pathlib import Path
from urllib.parse import urlsplit
work = Path(os.environ["REVIEW_WORK"])
first = json.loads((work / "response-v1.private.json").read_text())
host = urlsplit(first["url"]).hostname or ""
suffix = ".htmltourl.online"
if not host.endswith(suffix):
raise SystemExit("Unexpected hosted URL. Check the current docs before updating.")
slug = host[:-len(suffix)]
if not slug or "." in slug:
raise SystemExit("Unexpected slug format. Do not guess an edit target.")
payload = {
"html": Path("demo-v2.html").read_text(encoding="utf-8"),
"slug": slug,
"manageToken": first["manageToken"],
"retentionDays": 7,
}
(work / "request-v2.private.json").write_text(json.dumps(payload), encoding="utf-8")
PY
curl --disable --retry 0 --fail-with-body --silent --show-error --max-time 60 \
https://htmltourl.pro/push \
-H 'Content-Type: application/json' \
--data-binary "@$REVIEW_WORK/request-v2.private.json" \
-o "$REVIEW_WORK/response-v2.private.json"
python3 - <<'PY'
import json
import os
from pathlib import Path
work = Path(os.environ["REVIEW_WORK"])
first = json.loads((work / "response-v1.private.json").read_text())
second = json.loads((work / "response-v2.private.json").read_text())
if first["url"] != second["url"]:
raise SystemExit("The returned URL changed. Stop and investigate before sharing.")
print("Public review URL:", second["url"])
print("Confirmed expiry after update:", second["expiresAt"])
PY
Then reload the public URL and inspect the new time and question. A matching URL in JSON is useful, but it is not proof of changed visitor-visible content.
The public documentation describes renewing the expiry on update. Record the actual returned value rather than calculating or promising one yourself.
6. Finish the handoff with clear boundaries
Temporary links expire; the docs describe noindex, not SEO backlinks. Keep management data in secure project storage only while needed—a temporary directory is not a durable backup. Never paste it into GitHub or a support issue.
The useful outcome is a reviewer opening the right draft, answering the right question, and finding the revision. Report the failure point if that breaks, without private tokens or client content.


Top comments (0)