Everything you need to deploy, manage, and edit HTML sites from the browser, terminal, or API.
Get a live site in under 30 seconds. Sign in with Google, GitHub or an email link, then publish. Upgrade to Pro for more sites, longer TTLs, and custom domains.
Go to htmlhost.co, paste or drop an HTML file, pick a TTL, and hit Publish. Done.
bash# Install globally
npm i -g htmlhost-cli
# Authenticate — opens your browser to htmlhost.co/settings#keys
htmlhost login
# Deploy current directory (shows file list, asks for confirmation)
htmlhost deploy
# ✓ Live at https://bold-fern-x3k.htmlhost.co
# Linked → .htmlhost (future deploys update this site)bashcurl -X POST https://htmlhost.co/api/sites \
-H "Authorization: Bearer hh_live_your_token_here" \
-H "Content-Type: application/json" \
-d '{"html":"<h1>Hello World</h1>","ttl":"7d"}'The htmlhost CLI is a zero-dependency Node.js tool. Requires Node 18+.
bash# Install
npm i -g htmlhost-cli
# Update to the latest version
npm update -g htmlhost-cli
# Check your installed version
htmlhost --versionAuthenticate with an API token. Running this command automatically opens Settings → API keys in your browser. Paste the token back in the terminal when prompted. Credentials are saved to ~/.htmlhostrc.
Deploy an HTML file or directory and get a live URL. Passing a directory (or no argument) deploys the entire folder as a multi-page site — HTML pages and all other assets (images, CSS, JS, fonts) are packaged and uploaded together. Passing a single file deploys just that file with local assets auto-inlined.
--ttl <value>stringSet TTL: 1d, 7d, 30d, never--slug <slug>stringRe-deploy to a specific site--title <title>stringSet the site title--newflagForce a new site (ignore .htmlhost link)--no-assetsflagSkip asset inlining for single-file deploys--no-pull-checkflagSkip remote change detection before re-deploy--jsonflagOutput result as JSON (for CI/CD)--ttl <value>string--slug <slug>string--title <title>string--newflag--no-assetsflag--no-pull-checkflag--jsonflagDeploy a directory as a complete multi-page website — HTML pages and all other files (images, CSS, JS, fonts) are uploaded together. Point htmlhost deploy at a folder (or run it with no arguments from your project root). The CLI shows you a file tree and asks for confirmation before uploading. Each HTML file maps to a clean URL:
bash# Deploy current directory
htmlhost deploy
# Deploy a specific directory
htmlhost deploy ./my-project
# File mapping:
# index.html → /
# about.html → /about
# contact.html → /contact
# blog/index.html → /blog
# blog/post-1.html → /blog/post-1
# ✓ Live at https://bold-fern-x3k.htmlhost.co
# 3 pages · 5 assets · 30d TTLAdd a 404.html file to your project and it will be served automatically when visitors access a non-existent page. Page limits: Free plan supports 10 pages, Pro supports 100.
When you deploy, the CLI scans your HTML for local file references and makes the deployed site fully self-contained. CSS and JS files are inlined directly into the HTML, while binary assets (images, fonts, SVGs, PDFs) are uploaded to your media library with URLs rewritten automatically.
If a CSS file contains url() references (e.g. background images, font files), those assets are uploaded first and the URLs inside the CSS are rewritten before the stylesheet is inlined.
CSS/JS files ≥ 512 KB are uploaded to the media library instead of inlined, to avoid bloating the HTML. Files larger than 10 MB are skipped entirely. External URLs (https://, data:, etc.) are left untouched.
bash# Deploy with automatic asset processing (default)
htmlhost deploy
# ✓ Found 4 local assets to process
#
# ✓ styles.css (4.2 KB) → inlined as <style>
# ✓ hero.png (340 KB) → https://htmlhost.co/m/c9d0e1f2
# ✓ Inter.woff2 (92 KB) → https://htmlhost.co/m/d3e4f5a6
# ✓ app.js (12.1 KB) → inlined as <script>
# ✓ logo.svg (2.8 KB) → https://htmlhost.co/m/a1b2c3d4
#
# ✓ Inlined 2 files into HTML
# ✓ Uploaded 3 assets to media library
# Skip asset processing
htmlhost deploy --no-assetsHow each file type is handled:
<link href> — CSS files are inlined as <style> blocks (with nested url() assets uploaded first)<script src> — JS files are inlined as <script> blocks<img src>, <img srcset> — images uploaded to media library<video src>, <video poster>, <audio src> — media uploadedurl() in <style> blocks, inline styles, and external CSS files — assets uploaded, URLs rewrittenAfter the first deploy, the CLI saves the site slug to a .htmlhostfile in your project directory. On subsequent deploys, the CLI automatically re-deploys to the same site — no prompt needed for directory deploys. For single-file deploys, you'll be asked:
text? This project is linked to bold-fern-x3k.htmlhost.co
1. Overwrite existing site
2. Create a new site instead
3. Cancel
4. Always overwrite (remember for this project)
5. Always create new (remember for this project)
Enter choice (1-5):Choosing option 4 or 5 saves the preference to .htmlhost, so you won't be asked again. Use --new to skip the prompt and force a new site.
bash# First deploy — creates site and .htmlhost link
htmlhost deploy
# Second deploy — re-deploys to the same site (directory: Y/n confirm; file: menu)
htmlhost deploy
# Deploy a specific file
htmlhost deploy contact.html
# Force a new site (bypass .htmlhost)
htmlhost deploy --newBuilding with an AI coding tool (Claude Code, Codex, Cursor, Copilot…)? Run this once in your project. It writes htmlhost's instructions (hosting rules, the CLI, and how to build forms that deliver) into AGENTS.md and adds an @AGENTS.md import to CLAUDE.md, so your AI builds features that work on htmlhost. Only a marked block is managed, so your own notes in those files are kept. The instructions are added automatically by htmlhost cloneand kept up to date on each deploy. Agent files are never deployed.
bashhtmlhost agents # add or refresh the instructions
htmlhost agents --print # print them instead
htmlhost agents --no-claude # leave CLAUDE.md aloneTools that can browse can also read the guide directly at htmlhost.co/agents.md.
List all your sites in a formatted table showing slug, URL, size, TTL, and expiry.
Delete a site by slug. Use --force to skip the confirmation prompt.
Open a deployed site in your default browser.
bashhtmlhost open bold-fern-x3kShow the authenticated user's email, handle, and plan.
Remove saved credentials from ~/.htmlhostrc.
Manage form-notification recipients for a site. Without a subcommand, lists all recipients and their status. If no slug is given, the site is detected from the .htmlhost file in the current directory.
bashhtmlhost recipients my-site # list recipients
htmlhost recipients add my-site user@example.com # invite a recipient
htmlhost recipients remove my-site user@example.com # remove (prompts for confirmation)
htmlhost recipients resend my-site user@example.com # resend a pending invitationUse --force to skip the confirmation prompt on remove, and --json for machine-readable output.
List a site's published versions, newest first, with who published each one and what it changed. Every deploy and every save in the web editor is a version. Without a slug, the linked site is used.
Make an earlier version live again. Without a version number, it goes back to the version before the live one. The old version is published again as a new version, so the one you replaced stays in history and you can switch back. Restoring needs the site owner to be on Pro; collaborators who can publish can restore too. Run htmlhost pull afterwards so your local files match.
bashhtmlhost versions my-site # list versions
htmlhost rollback # linked site: back one version
htmlhost rollback my-site 12 # make v12 live again
htmlhost rollback my-site 12 -f # skip the confirmationThe CLI supports bidirectional sync with htmlhost.co. When you or a collaborator edits a site through the web editor, you can pull those changes back to your local project. The CLI also detects remote changes automatically before every re-deploy.
Like git status for a linked folder: shows which site it deploys to, whether the live site changed since your last deploy or pull, and what the next htmlhost deploy would add, modify, or remove. It never writes anything.
--jsonflagOutput the status as JSON--jsonflagbashhtmlhost status
# Example output:
# ● Linked to my-site.htmlhost.co (folder)
# ✓ Live site unchanged since your last sync (v5)
#
# Changes to deploy:
# + new: contact.html
# ~ modified: index.html
# - removed: old.html (only on the live site; deploy deletes it)Download remote changes from an htmlhost.co site to your local project. If the project is linked via .htmlhost, the slug is detected automatically. Otherwise, pass it as an argument.
--force, -fflagPull without confirmation prompt--dry-runflagShow what would change without writing files--force, -fflag--dry-runflagbash# Pull changes for the linked site
htmlhost pull
# Pull a specific site by slug
htmlhost pull my-site
# Show what would change without writing
htmlhost pull --dry-run
# Example output:
# ● Pulling from my-site.htmlhost.co…
# Version 5 · Updated 2h ago
#
# + New: about.html (1.2 KB)
# ~ Modified: index.html
# ~ Modified: css/style.css
#
# ● 1 new, 2 modified files to pull
# ? Pull these changes? (y/N)Pulled files overwrite local versions. Files that exist locally but not on the remote are left untouched — the CLI never deletes local files during a pull.
Clone a deployed site into a new local directory. This is useful for sites that were created through the web editor and haven't been deployed from the CLI before. After cloning, use htmlhost deploy to push changes and htmlhost pull to sync remote edits.
bash# Clone into a new directory named after the slug
htmlhost clone my-site
# → creates ./my-site/ with all files + .htmlhost link
# Clone into a specific directory
htmlhost clone my-site ./my-project
# After cloning:
cd my-site
htmlhost deploy # push changes
htmlhost pull # sync remote editsUse --force to overwrite an existing non-empty directory.
When re-deploying to a linked site, the CLI automatically checks if the remote site was modified since your last deploy or pull. If remote changes are detected, you'll be prompted before overwriting:
text! Remote changes detected — my-site.htmlhost.co was modified since your last deploy.
Remote version: 5 · Local version: 3
? What would you like to do?
1. Pull changes first, then deploy
2. Deploy anyway (overwrites remote changes)
3. Cancel
Enter choice (1-3):Use --no-pull-check to skip this check (useful for CI/CD pipelines where you always want to deploy).
Connect Claude, Cursor, VS Code, Windsurf, Codex or any other MCP client to your account, and your AI can deploy, list, pull and delete your sites for you. It uses the same token as htmlhost login.
bash# Claude Code
claude mcp add htmlhost -- npx -y htmlhost-mcpSetup for every client, the full tool reference and troubleshooting are in the MCP server guide.
All endpoints accept Authorization: Bearer <token> headers. Generate tokens at Settings → API keys.
Base URL: https://htmlhost.co
/api/sites/api/sites/api/sites?slug={slug}/api/sites/pull?slug={slug}/api/sites/{slug}/versions/api/sites/{slug}/versions/{n}/restore/api/media/api/media/api/media/api/tokens/api/tokens/api/tokens?id={id}/api/tokens/meCreate a new site or update an existing one. Supports both single-page and multi-page deploys.
htmlstringRequired. The HTML content to deploytitlestringOptional. Falls back to <title> tag or auto-generated namettlstringOptional. 1d, 7d, 30d, or never. Defaults to plan defaultslugstringOptional. If provided, re-deploys to that existing sitehtmlstringtitlestringttlstringslugstringpagesarrayRequired. Array of { path, html, title? } objectspages[].pathstringURL path for the page, e.g. "/" or "/about"pages[].htmlstringHTML content for this pagepages[].titlestringOptional. Page titletitlestringOptional. Site-level titlettlstringOptional. 1d, 7d, 30d, or neverslugstringOptional. Re-deploy to existing multi-page sitepagesarraypages[].pathstringpages[].htmlstringpages[].titlestringtitlestringttlstringslugstringjson// Multi-page deploy example
{
"pages": [
{ "path": "/", "html": "<html>Homepage</html>" },
{ "path": "/about", "html": "<html>About</html>" },
{ "path": "/contact", "html": "<html>Contact</html>" }
],
"title": "My Portfolio",
"ttl": "30d"
}json{
"ok": true,
"id": "550e8400-e29b-41d4-a716-446655440000",
"slug": "bold-fern-x3k",
"url": "bold-fern-x3k.htmlhost.co",
"version": 1,
"ttl": "7d",
"expiresAt": "2026-05-11T08:00:00.000Z"
}Returns all your sites and aggregate usage stats.
json{
"sites": [
{
"id": "...",
"slug": "bold-fern-x3k",
"title": "My Portfolio",
"url": "bold-fern-x3k.htmlhost.co",
"sizeBytes": 4200,
"size": "4.1 KB",
"ttl": "7d",
"expiresAt": "2026-05-11T08:00:00.000Z",
"createdAt": "2026-05-04T08:00:00.000Z",
"updatedAt": "2026-05-04T08:00:00.000Z"
}
],
"usage": {
"siteCount": 1,
"totalBytes": 4200,
"maxBytes": 524288000,
"plan": "free"
}
}Delete by slug or UUID.
bashcurl -X DELETE "https://htmlhost.co/api/sites?slug=bold-fern-x3k" \
-H "Authorization: Bearer hh_live_your_token"The site's versions, newest first, with what each one changed. Works for the owner and collaborators.usable: falsemeans the owner's plan can't restore them.
bashcurl https://htmlhost.co/api/sites/bold-fern-x3k/versions \
-H "Authorization: Bearer hh_live_your_token"Publishes version n again as a new version. The one it replaces stays in history. Anyone who can publish the site can restore it; if the owner's plan doesn't include restore, the response is 402 with requiresPro: true.
bashcurl -X POST https://htmlhost.co/api/sites/bold-fern-x3k/versions/12/restore \
-H "Authorization: Bearer hh_live_your_token"Every publish is saved as a version: each save in the editor, each deploy from the CLI, API or an AI agent, and each restore. You can see who published it, how, and which files it added, changed or removed. On Pro you can preview any earlier version, compare it with the live site, and make it live again.
htmlhost versions and htmlhost rollback (CLI).list_versions and restore_version tools (MCP).Restoring publishes the old version again as a new version, labelled “Restored from vN”. The version it replaces stays in history, so you can switch back the same way. A restore goes through the same checks as any publish, so it uses the owner's current plan limits.
A version holds your site's files: pages, CSS, JS and assets. Custom domains, form settings, the site password and the expiry date aren't part of a version, so a restore leaves them as they are. If you work from the CLI, run htmlhost pull after a restore so your local files match.
On a site with several pages, the header and footer can be shared: change them on any page and the editor asks whether to apply the change to every page, so you never have to repeat an edit page by page. Each page still highlights its own menu link.
Shared blocks carry their own styles and menu scripts where the editor can identify them, so a new page does not need matching CSS first. Keep embedded styles, font links and scripts inside the shared markers when editing code.
In Shared components, choose Edit header or Edit footer; you can also click the Shared badge in the outline, right-click it in the preview, or use Edit Shared Header (or Footer) when something inside it is selected. The preview shows just that block, with the rest of the page hidden, so it's easy to work on: click text to edit it, drag blocks in from the Library, or use + Add sectionto add a row inside it, such as an announcement bar above the menu. Everything you add goes inside the shared block. Your edits stay a draft: they don't count as unsaved changes to your site until you press Save to N pages, which updates every page that shares the block. Done returns to the whole page. With unsaved edits, Cancel asks whether to discard them. Switching pages or publishing with an unsaved draft asks you to save it first.
When you share a header or footer, the editor moves the CSS and JavaScript that only it uses out of your pages and into/shared/header.css and /shared/header.js (or footer), linked from inside the shared block. Every page that shares it then gets them, including new pages, and changing header.csschanges the header everywhere at once. It moves only what can't affect anything else: rules that can only match inside the block, and scripts that only touch it. Before anything changes, every page is rendered again; if one would look different, nothing moves and you're told which page. Styles you add while editing the header on its own move into its file when you press Save to N pages. For a block shared before this existed, openManage pages → Advanced and choose Extract styles & scripts into files.
Every page keeps a full copy of the header and footer, wrapped in two HTML comments. Your pages stay plain HTML, so they work anywhere, and the CLI, downloads and version history treat them like any other page.
html<!-- hh:shared header active-class="active" -->
<header>
<nav><a href="/">Home</a> <a href="/about" class="active">About</a></nav>
</header>
<!-- /hh:shared header -->active-class names the class that marks the current page's link (with active-on="parent"it goes on the link's parent, such as an <li>), and aria-current="page" means that link also getsaria-current. The editor works these out when you share; you don't need to write them. Remove the comments from a page to stop sharing on it. If you edit pages outside the editor, change shared blocks on every page: htmlhost deploy warns when the copies differ, and the guide for AI agents explains the same rules to your own AI tools.
Upload images, fonts, and other assets. Each file gets a permanent URL served from Cloudflare's edge CDN. Use these URLs in your HTML.
Tip: When you htmlhost deploy, local assets are automatically uploaded to your media library and the HTML references are rewritten — no manual upload step needed. See the CLI → Automatic asset uploading section for details.
bashcurl -X POST https://htmlhost.co/api/media \
-H "Authorization: Bearer hh_live_your_token" \
-F "file=@logo.png"When you run htmlhost deploy, local assets are automatically uploaded to your media library and HTML references are rewritten — no manual upload step needed. See the CLI → Automatic asset processing section for details.
Images (PNG, JPG, GIF, SVG, WebP, AVIF, ICO), fonts (WOFF, WOFF2, TTF, OTF), documents (PDF), video (MP4, WebM), and audio (MP3, OGG, WAV).
The browser editor includes an AI assistant that can edit your HTML visually. Click any element, describe the change in natural language, and watch it update live.
Free plan: 10 AI edits a day. Pro plan: 100 AI edits a day. Uses platform-managed API keys — no setup required. Once a Free account has used all the sites its plan allows, the built-in AI works only on its live sites, not on unpublished drafts. Your own API key works anywhere.
For unlimited edits, add your own API key from any supported provider. Keys are saved only in your browser's local storage. When you use one, it passes through our proxy to the provider and is never stored or logged.
sk-...sk-ant-...AIza...sk-...sk-ant-...AIza...Any form on your site can deliver straight to you, with no backend and no third-party form service. Visitors' messages land in your dashboard and your inbox, and you decide what visitors see after they send.
Point any form at /__hh/form with method="post" and give every field a name. A hidden _form field names the form, so one site can run several (a contact form and a newsletter signup, say).
html<form action="/__hh/form" method="post">
<input type="hidden" name="_form" value="Contact">
<input name="name" placeholder="Your name" required>
<input name="email" type="email" placeholder="you@example.com" required>
<textarea name="message" required></textarea>
<button type="submit">Send</button>
</form>Your published site adds a small script that sends the form in the background, so visitors stay on the page. Without JavaScript the form still works: it sends normally and shows a confirmation page.
For the same spam protection as Library forms, add this hidden trap field inside the form. People never see it; bots that fill it in are discarded:
html<div aria-hidden="true" style="position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden">
<label>Leave this field empty <input type="text" name="_hh_hp" tabindex="-1" autocomplete="off"></label>
</div>A form you pasted in or wrote yourself may not send anywhere yet. In the editor, click anything inside it: the AI panel shows This form doesn't send anywhere yet. Click Send to my inbox (or right-click the form → Send to my inbox). htmlhost points it at your inbox and names it for you. Publish, and it's live. Search boxes are left alone.
Once a form delivers, the same panel shows 📨, its name and how many messages it has received, with links to read them and to its settings. The 📨 also marks delivering forms in the breadcrumb and the Structure tab.
Open your site from the dashboard and go to Messages to read, mark as spam, or export messages to CSV. The Inbox tab on your dashboard shows messages from all your sites in one list. Each new message is also emailed to you, and replying to that email goes straight to the visitor.
In your site's Forms tab, under Who gets new messages, click Add recipient(1 extra person on Free, up to 10 on Pro). They get one email asking them to confirm; nothing else reaches them until they do, and every email has a link to stop. They don't need an htmlhost account.
By default everyone gets every form. To split them, for example Careers to your hiring manager and Contact to sales, click All forms under a person's name and choose Only these forms. You always get everything, and you can switch your own emails off once someone else is receiving them.
You can also manage recipients from the terminal with htmlhost recipients — see the CLI section above.
In the Forms tab, Email notifications has three options. Instantly (the default) sends an email for every message. Daily summarysends one email a day, around 08:00 UTC, listing the day's messages. Paused sends nothing. Messages are always saved on the Messages tab whichever you choose.
Collaborators can edit your site but can't see its messages unless you allow it. In the Forms tab, turn on Collaborators can read messages. They'll see the site in their Inbox and can read, mark and export messages; only you can delete them.
After a successful send, a visitor either sees a confirmation message under the form or is taken to another page on your site (a “thank you” page, for example). You set this in two places:
A form's own setting always wins over the site default. If a form has its own message, it shows that message even when the site default is to go to a page. Pages must be on your own site and start with /; sending visitors to other websites isn't allowed. The error message, if you set one, replaces the specific reason a message couldn't be sent.
Form Settings saves your choices in the form's HTML as hidden inputs, so you can also write them by hand:
_formnameThe form's name. Groups its messages in your dashboard._successmessageConfirmation shown under the form after sending._redirectpathPage on your site to open after sending, e.g. /thanks._errormessageShown instead of the specific reason when sending fails._formname_successmessage_redirectpath_errormessagehtml<form action="/__hh/form" method="post">
<input type="hidden" name="_form" value="Quote request">
<input type="hidden" name="_redirect" value="/thanks">
<input type="hidden" name="_error" value="Sorry, that didn't go through. Email us at hi@example.com.">
...
</form>The message appears in a <p data-hh-form-msg> added to the end of the form, withdata-state="success" or "error". It uses your page's font and colour unless you style it:
css[data-hh-form-msg] { padding: 12px 16px; border-radius: 8px; background: #ecfdf5; color: #065f46; }
[data-hh-form-msg][data-state="error"] { background: #fef2f2; color: #991b1b; }Drag File Upload from Library → Elements → Forms into a form; the form is set up for files automatically. Visitors can attach up to 3 files (images, PDFs, Office documents, text or CSV). Files are checked by their content, not just their name, and kept private: you download them from the message in your dashboard, and emails only list their names.
Keep a spreadsheet of your form messages that fills itself in. Your site's Forms tab → Integrations → Google Sheetsoffers two ways. You don't connect a Google account to htmlhost for either.
Instant (recommended): each message becomes a new row within seconds.
New fields become new columns, rows are only ever added (so your own notes beside them stay put), and a visitor can't sneak a formula into your sheet. The script checks a signature on every request, so only htmlhost can add rows. It uses your site's single webhook slot.
Hourly link: click Create Google Sheets link and paste the =IMPORTDATA("…") formula into cell A1. Google refreshes it about once an hour. It mirrors your dashboard (read-only, oldest first), so new messages appear at the bottom. The link is shown once and works like a password: make a new one if it leaks.
Send every message to your own server, or to tools like Zapier, Make or n8n. In the Forms tab → Integrations, paste an https:// URL and click Save, then Send test. Each message is POSTed as JSON a moment after it's received:
json{
"event": "form.submission",
"id": "5f0c…",
"site": { "slug": "bakery", "address": "bakery.htmlhost.co" },
"form": "Contact",
"page": "/contact",
"submittedAt": "2026-09-23T10:00:00.000Z",
"email": "ada@example.com",
"fields": [{ "name": "name", "value": "Ada" }, { "name": "message", "value": "Hi!" }],
"files": [{ "name": "brief.pdf", "size": 48213, "type": "application/pdf" }]
}To check a request really came from htmlhost, compare the X-Htmlhost-Signature header with an HMAC-SHA256 of the raw body, using the signing secret shown in the Forms tab:
jsconst expected = "sha256=" + crypto.createHmac("sha256", SECRET).update(rawBody).digest("hex");
const valid = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers["x-htmlhost-signature"]));Your endpoint should reply within 5 seconds. Redirects aren't followed, and only public addresses can be used. The Forms tab shows the result of the latest delivery. Attachments are listed by name only; download them from the dashboard.
If you build locally with an AI coding tool, run htmlhost agents in your project first. It tells your AI exactly how forms work here, so the forms it writes deliver to you.
The AI knows how forms work here. Try “after this form is sent, go to the thanks page”, “change the confirmation to ‘We'll reply within a day’”, or “make the form's success message green”. In Discuss mode you can also just ask how forms work.
Free accounts receive up to 50 messages a month across all sites; Pro receives up to 5,000. We email you once if you reach the limit. File attachments are a Pro feature: up to 3 files per message, 10 MB each and 25 MB in total (images, PDFs, Office documents, text and CSV), with 2 GB of attachments a month.
Serve any site from your own domain. Custom domains are included with Pro, or you can buy a domain add-on for a single domain, billed yearly. Go to Settings → Domains, enter the domain and choose the site it should show. You can also start from a site in your dashboard: ⋮ → Add custom domain.
After you add the domain, the Domains page shows the exact record to create. Copy it from there, because the value can differ from domain to domain. It will be one of these two:
example.comARoot (apex) domain. Name: @, value: the IP address shown (usually 76.76.21.21).www.example.comCNAMEAny subdomain. Name: the subdomain part (www, blog, shop.eu…), value: the hostname shown (usually cname.vercel-dns.com).example.comAwww.example.comCNAMEtext# Root domain (example.com)
Type: A
Name: @
Value: 76.76.21.21 ← use the value shown in Settings → Domains
# Subdomain (www.example.com)
Type: CNAME
Name: www
Value: cname.vercel-dns.com ← use the value shown in Settings → DomainsA, AAAA or CNAME records for the same name first (for example, your registrar's parking page). They conflict with the new record.A record for it.example.com and www.example.com? Add each as its own domain, one A record and one CNAME.The Domains page checks your DNS automatically and moves through Awaiting DNS → Provisioning TLS → DNS & TLS ready. The HTTPS certificate is issued for you, with nothing to upload. Most DNS changes are picked up within minutes, but some networks can take a few hours (rarely up to 24) to see the new record, so the domain may work on one connection before another.
A site on an active custom domain doesn't expire while the domain stays connected. Forms and password protection work on custom domains exactly as they do on your htmlhost.co address.
Tokens authenticate CLI and API requests. Generate them at Settings → API keys.
texthh_live_a91fc7b3d2e014c8f5a6b9d0e1f2a3b4c5d6e7f8Tokens start with hh_live_ and contain 48 hex characters. The raw token is shown once at creation. We store only the SHA-256 hash on our servers.
When a site's TTL elapses, the public URL goes offline (returns a 410). The site stays in your dashboard so you don't lose track of it.
Questions? Reach out at hey@htmlhost.co