# thin.host: full documentation > thin.host is hosting for static and AI-generated sites, built to be driven by agents. Claude Code, Cursor, ChatGPT, Codex or any MCP client can publish a folder or zip and get a live URL in one tool call or one REST request, then map a custom domain with automatic TLS and send transactional email from a verified domain. This file concatenates the Markdown version of every docs, deploy-guide and comparison page listed in https://thin.host/llms.txt. ======================================================================== Source: https://thin.host/docs ======================================================================== # thin.host Documentation thin.host is the hosting and domain layer for the agent era. It provides an MCP server and REST API that lets AI agents publish the sites they generate straight to live hosting, provision custom domains end-to-end — including taking the user's payment and handling DNS configuration — and send transactional email. ## Quick Links - [Quickstart: MCP (5 minutes)](https://thin.host/docs/quickstart-mcp) — Add custom domains to your Claude Desktop agent - [Quickstart: REST API](https://thin.host/docs/quickstart-rest) — Integrate via HTTP from any language - [Get access to email](https://thin.host/docs/email) — Zero to sending: request access, approval, first send - [REST API Reference](https://thin.host/docs/api) — Full endpoint documentation - [MCP Tool Reference](https://thin.host/docs/mcp) — All 9 MCP tools explained ## How It Works 1. **Your agent calls thin.host** — via MCP tool or REST API — to provision a custom domain 2. **thin.host returns a claim URL** — your agent shows this to the end user 3. **The user claims & pays** — Stripe checkout, DNS instructions, live status on a hosted page 4. **Domain goes live** — SSL auto-provisions, webhook confirms to your platform ## Key Concepts - **Platform** — Your account. Has an API key, webhook URL, and plan tier. - **Domain** — A custom domain provisioned through your platform. Has a lifecycle: `pending_payment` → `pending_dns` → `pending_ssl` → `active` - **Claim Session** — A short-lived (24h) token/URL where end users complete payment and DNS setup - **Rev-Share** — End user pays $8/mo, split between thin.host and your platform ## Architecture thin.host is a managed layer that handles proxy and SSL, with [Stripe](https://stripe.com) for billing. Your agent never talks to the proxy or Stripe directly — thin.host handles the entire stack. ``` Agent (Claude, GPT, etc.) │ ├── MCP call ──→ thin.host MCP Server │ │ ├── REST call ──→ thin.host API (/v1/) │ │ │ ├── Proxy + SSL layer │ ├── Stripe (billing) │ └── PostgreSQL (state) │ └── claim_url ──→ Hosted Claim Page (end user) ``` --- Canonical page: https://thin.host/docs ======================================================================== Source: https://thin.host/docs/quickstart-mcp ======================================================================== # Quickstart: MCP Server Let any MCP-compatible agent (Claude Code, Claude Desktop, claude.ai, Cursor, VS Code, Windsurf, Codex, ChatGPT) publish the sites it generates straight to live hosting, provision custom domains for them, and send transactional email — in under 5 minutes. ## 1. Get a Platform API Key Sign up at [thin.host](https://thin.host/signup), then open [Email & API → Settings](https://thin.host/platform/settings) in your dashboard to create an API key (one per app or agent — each can be revoked on its own). For testing, you can use the free tier (3 domains, 100 API calls/day). > Sending email (the `send_email` tool) needs a separate, founder-approved access step beyond the API key. See [Get access to email](https://thin.host/docs/email). ## 2. Connect an agent The hosted MCP server runs at `https://thin.host/mcp` (Streamable HTTP). Clients that support OAuth register themselves, open a browser and show a thin.host consent page, so most setups need nothing but the URL. If a client cannot do OAuth, send an API key instead: `Authorization: Bearer th_live_…`. | Client | Fastest setup | |---|---| | Claude Code | `claude mcp add --transport http thin-host https://thin.host/mcp`, or the thin.host plugin | | Claude Desktop / claude.ai | Add a custom connector with the URL | | Cursor | `~/.cursor/mcp.json` or the install link | | VS Code (Copilot agent mode) | `code --add-mcp` or `.vscode/mcp.json` | | Windsurf (Devin Desktop) | `devin mcp add` or `mcp_config.json` | | Codex CLI and IDE extension | `codex mcp add thin-host --url https://thin.host/mcp` | | ChatGPT | Add a custom connector (developer mode) with the URL | ### Claude Code ```bash # OAuth: add the server, then in Claude Code run /mcp, pick thin-host and choose Authenticate claude mcp add --transport http thin-host https://thin.host/mcp # Available in every project, not just this one claude mcp add --transport http --scope user thin-host https://thin.host/mcp # With an API key instead of OAuth claude mcp add --transport http thin-host https://thin.host/mcp \ --header "Authorization: Bearer th_live_your_key" ``` **Or install the plugin**, which adds the hosted server together with the Docusaurus-deploy and email skills: ```bash /plugin marketplace add thinhost/thinhost-mcp /plugin install thin-host@thinhost ``` ### Claude Desktop and claude.ai Connectors added on claude.ai also work in Claude Desktop and on mobile (and in Claude Code when you sign in with the same account). 1. Open **Customize → Connectors** and choose **Add custom connector**. 2. Enter the URL `https://thin.host/mcp` exactly. If the dialog asks how to register the OAuth client, choose **Register automatically**. 3. Click **Add**, then **Connect**, sign in to thin.host and allow access. On Team and Enterprise plans an owner adds the connector once under **Organization settings → Connectors**, and each member then connects it from Customize → Connectors. The Free plan allows one custom connector. ### Cursor Add the server to `~/.cursor/mcp.json` (all projects) or `.cursor/mcp.json` (one project), then sign in when Cursor prompts for thin-host: ```json { "mcpServers": { "thin-host": { "url": "https://thin.host/mcp" } } } ``` One-click install link: [Add thin.host to Cursor](cursor://anysphere.cursor-deeplink/mcp/install?name=thin-host&config=eyJ1cmwiOiJodHRwczovL3RoaW4uaG9zdC9tY3AifQ==). ### VS Code (GitHub Copilot agent mode) ```bash code --add-mcp '{"name":"thin-host","type":"http","url":"https://thin.host/mcp"}' ``` Or commit it to a workspace in `.vscode/mcp.json`. VS Code registers itself with thin.host and opens a browser to sign in on first use. ```json { "servers": { "thin-host": { "type": "http", "url": "https://thin.host/mcp" } } } ``` The portable `.mcp.json` at the workspace root (and `~/.copilot/mcp-config.json`) uses the same entry under `"mcpServers"` instead of `"servers"`. ### Windsurf (Devin Desktop) Windsurf is now Devin Desktop. Add the server from a terminal and sign in: ```bash devin mcp add -s user thin-host https://thin.host/mcp devin mcp login thin-host ``` Or edit `~/.config/devin/mcp_config.json`. Builds that still read `~/.codeium/windsurf/mcp_config.json` use `"serverUrl"` in place of `"url"`. ```json { "mcpServers": { "thin-host": { "url": "https://thin.host/mcp" } } } ``` ### Codex CLI and IDE extension ```bash codex mcp add thin-host --url https://thin.host/mcp # detects OAuth and opens the browser codex mcp login thin-host # sign in again later ``` Both write to `~/.codex/config.toml`, which the CLI, the IDE extension and the desktop app share. To use an API key, point Codex at an environment variable: ```toml [mcp_servers.thin-host] url = "https://thin.host/mcp" bearer_token_env_var = "THINHOST_API_KEY" ``` ### ChatGPT 1. On chatgpt.com, open **Plugins**, click **+** and choose **Add custom MCP server**. 2. Name it thin.host, enter `https://thin.host/mcp` as the server URL and choose **OAuth** authentication. 3. Confirm, click **Create as a plugin**, install it and sign in to thin.host. 4. In a chat, type `@` and pick thin.host. Adding a custom MCP server is a ChatGPT web feature. Business, Enterprise and Edu workspaces get full access (on Business, admins create the plugin); OpenAI documents Pro accounts as limited to read and fetch actions, which rules out publishing. ### What the hosted server can and cannot do The hosted server cannot read your disk, so it publishes from a URL (`publish_website_from_url` / `update_website_from_url` — a .zip of the site or a single HTML page). Coding agents with a shell can instead upload a zip straight to the REST API with an API key: `curl -F file=@site.zip -F title="My Docs" https://thin.host/v1/websites/archive -H "Authorization: Bearer th_live_…"`. To publish a local build folder directly, use the local server below. ### Local server via uvx (reads your files) Runs the same server on your machine so `publish_website` can read a local folder or build directory directly — no zipping. Needs [uv](https://docs.astral.sh/uv/). ```bash claude mcp add thin-host \ -e THINHOST_API_URL=https://thin.host/v1 \ -e THIN_HOST_API_KEY=th_live_your_key \ -- uvx thinhost-mcp ``` The package is [thinhost-mcp on PyPI](https://pypi.org/project/thinhost-mcp/); the same wheel is also served at `https://thin.host/dl/thinhost-mcp/latest` if you would rather pin to the URL. ### Claude Desktop bundle (.mcpb) Download a ready-to-install bundle from the dashboard (Email & API → MCP package) and open it in Claude Desktop, or add the server by hand to `claude_desktop_config.json`: ```json { "mcpServers": { "thin-host": { "command": "uvx", "args": ["thinhost-mcp"], "env": { "THINHOST_API_URL": "https://thin.host/v1", "THIN_HOST_API_KEY": "th_live_your_key_here" } } } } ``` ## 3. Use It In a Claude conversation, ask Claude to build something and put it live: > "Build me a landing page for my bakery and publish it." Claude writes the site, calls `publish_website`, and hands you a live URL like `https://thin.host/s/sunrise-bakery/`. Iterate in the same conversation — "make the header green" — and Claude pushes the change with `update_website`. Custom domains work the same way: > "I just deployed my site to https://myapp.vercel.app. Can you set up myportfolio.com as a custom domain?" Claude will call `provision_domain`, get back a claim URL, and share it with you. You visit the claim page, pay, configure DNS, and the domain goes live. ## Available Tools | Tool | Description | |---|---| | `publish_website` | Publish a local HTML file, directory, or ZIP as a live hosted site | | `update_website` | Push updated pages/assets to an existing hosted site | | `list_websites` | List your hosted sites with their live URLs | | `provision_domain` | Create a new custom domain with payment/claim flow | | `check_domain_status` | Poll domain provisioning progress | | `update_origin` | Change the target URL for a domain | | `release_domain` | Tear down a provisioned domain | | `list_domains` | List all domains with optional filtering | | `send_email` | Send a transactional notification email (requires email access approval) | ## Example Flow ```python # Agent provisions a domain result = await mcp.call("provision_domain", { "domain": "mysite.com", "origin_url": "https://myapp.vercel.app", "user_email": "user@example.com" }) # → { provision_id, status: "pending_payment", claim_url, dns_instructions } # Agent shares the claim_url with the user # User pays and configures DNS # Agent checks status status = await mcp.call("check_domain_status", { "provision_id": result["provision_id"] }) # → { status: "active", ready: true } ``` See the [MCP Tool Reference](https://thin.host/docs/mcp) for full parameter and response documentation. --- Canonical page: https://thin.host/docs/quickstart-mcp ======================================================================== Source: https://thin.host/docs/quickstart-rest ======================================================================== # Quickstart: REST API Integrate thin.host website hosting and domain provisioning into any application using the REST API. ## 1. Get a Platform API Key Sign up at [thin.host](https://thin.host/signup), then open [Email & API → Settings](https://thin.host/platform/settings) in your dashboard to create an API key. Issue one key per app or agent that integrates with thin.host — each is labelled and can be revoked on its own. > Sending email (`POST /v1/emails`) needs a separate, founder-approved access step beyond the API key. See [Get access to email](https://thin.host/docs/email). ## 2. Publish a Website Send pages as HTML strings (assets go in `assets` as base64). The site is live at the returned `url` immediately. Requires a key created from the dashboard so it's linked to your account. ```bash curl -X POST https://thin.host/v1/websites \ -H "X-Platform-API-Key: th_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "title": "My Site", "slug": "my-site", "pages": [{"path": "/", "html": "

Hello

"}] }' # Response includes: "url": "https://thin.host/s/my-site/" ``` Update it later with `PATCH /v1/websites/my-site` — pages upsert by path. ## 3. Provision a Domain ### curl ```bash curl -X POST https://thin.host/v1/domains \ -H "X-Platform-API-Key: th_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "domain": "mysite.com", "origin_url": "https://myapp.vercel.app", "end_user_email": "user@example.com" }' ``` ### Python ```python import requests resp = requests.post( "https://thin.host/v1/domains", headers={"X-Platform-API-Key": "th_live_your_key"}, json={ "domain": "mysite.com", "origin_url": "https://myapp.vercel.app", "end_user_email": "user@example.com", }, ) data = resp.json() print(data["claim_url"]) # Send this to the user ``` ### Node.js ```javascript const resp = await fetch("https://thin.host/v1/domains", { method: "POST", headers: { "X-Platform-API-Key": "th_live_your_key", "Content-Type": "application/json", }, body: JSON.stringify({ domain: "mysite.com", origin_url: "https://myapp.vercel.app", end_user_email: "user@example.com", }), }); const data = await resp.json(); console.log(data.claim_url); // Send this to the user ``` ## 4. Check Status ```bash curl https://thin.host/v1/domains/{id} \ -H "X-Platform-API-Key: th_live_your_key" # Response: # { # "id": "...", # "hostname": "mysite.com", # "status": "active", # "dns_status": "resolved", # "ssl_status": "active", # "payment_status": "paid", # "ready": true # } ``` ## 5. Update Origin ```bash curl -X PATCH https://thin.host/v1/domains/{id} \ -H "X-Platform-API-Key: th_live_your_key" \ -H "Content-Type: application/json" \ -d '{"origin_url": "https://new-deploy.vercel.app"}' ``` See the [REST API Reference](https://thin.host/docs/api) for full endpoint documentation. --- Canonical page: https://thin.host/docs/quickstart-rest ======================================================================== Source: https://thin.host/docs/email ======================================================================== # Get access to email Transactional email is **allowlist-gated and founder-approved** — it is not instant self-serve. This page walks you from zero to your first sent message, including the approval step. > Email is for transactional messages only — sign-in links, receipts, password resets, alerts. Not marketing, not bulk. ## The onboarding flow at a glance 1. **Create an account & API key** — sign up and grab your platform API key. 2. **Request email access** — one click in the dashboard records your request. 3. **Founder approval** — a thin.host admin reviews and enables sending (a deliverability / anti-abuse check). 4. **Verified sending domain** — send from the shared `mail.thin.host` sender immediately, or verify your own domain. 5. **Send** — via the REST API, SMTP relay, or the `send_email` MCP tool. ## 1. Create an account & API key Sign up at [thin.host](https://thin.host/auth/signup). API keys live in the dashboard under **Settings → API keys**. Issue one key per app that sends email; each is labelled and can be revoked without affecting the others. A key (`th_live_…`) authenticates every email send, so keep it secret. The free tier is enough to get started. ## 2. Request email access Email is off by default. In the dashboard, open **Email** (or **Settings → Transactional Email → How to request access**) and click **Request email access**. This records the request — *no email or support ticket is required*. Once requested, the dashboard shows an **Awaiting approval** badge with the time you applied. Your request appears in the founder's review queue. ## 3. Founder approval A thin.host admin reviews each request — this keeps shared sending reputation clean. Approval is quick for legitimate transactional use; we email your account address when sending goes live. Until then, any send attempt returns `email_not_enabled`. You can check your status any time on the dashboard **Email** page — the badge flips from **Not enabled** to **Email enabled** once you're approved. ## 4. Verified sending domain Your `from` address must use a verified domain: - **Shared domain (works immediately after approval)** — omit `from` and messages go out as `no-reply@mail.thin.host`. DKIM, SPF, and DMARC are already configured. - **Your own domain** — add it in platform settings and publish every DNS row we show. Targets are thin.host-branded (DKIM + return-path CNAMEs under `dns.thin.host`, apex SPF `include:_spf.dns.thin.host` merged into any existing SPF, and a DMARC TXT). Inbox providers look at SPF/DMARC on the From domain, not only DKIM. A `from` address that doesn't match a verified domain returns `invalid_from_domain` — surface it to the user, don't retry. ## 5. Send your first email Once approved, pick any of the three transports — the same allowlist, domain, suppression, and rate-limit gates apply to all of them. ### REST API ```bash curl -X POST https://thin.host/v1/emails \ -H "X-Platform-API-Key: th_live_your_key" \ -H "Content-Type: application/json" \ -d '{ "to": "user@example.com", "subject": "Your sign-in link", "text": "Click here: https://app.example.com/login?token=..." }' # → 202 { "id": "...", "status": "sent", "to": "user@example.com", # "from": "no-reply@mail.thin.host" } ``` ### SMTP relay Issue per-app SMTP credentials from the dashboard (**Email → SMTP credentials** — only available after approval). The password is shown once at issue time. ```python import smtplib smtp = smtplib.SMTP("smtp.thin.host", 587) # STARTTLS smtp.login("your_smtp_username", "your_smtp_password") smtp.sendmail(from_addr, [to_addr], message) ``` ### MCP tool (`send_email`) Download the ready-to-install `.mcpb` package from the dashboard (**Email → Claude Desktop MCP package**) and open it with Claude Desktop. Your agent can then call `send_email` directly. See the [MCP Tool Reference](https://thin.host/docs/mcp) for parameters and error codes. ## Why the approval gate? Deliverability is a shared resource. Founder approval and the suppression/rate-limit gates keep the sending pool healthy for everyone — which is what keeps your messages landing in the inbox. The gates you'll encounter: | Error code | Meaning | What to do | |---|---|---| | `email_not_enabled` | Account not yet approved for email | Request access in the dashboard; wait for approval | | `invalid_from_domain` | `from` isn't a verified domain | Omit `from`, or verify your domain — don't retry | | `recipient_suppressed` | Recipient previously bounced/complained | Don't retry; surface to the user | | `rate_limited` | Daily send cap reached | Retry after the 24h window resets | Want a marketing-level overview? See the [transactional email use-case page](https://thin.host/use-cases/email). There's also a drop-in [Claude skill](https://github.com/thinhost/thinhost-mcp/blob/main/skills/thin-host-email/SKILL.md) that wraps the precondition check and the send call. --- Canonical page: https://thin.host/docs/email ======================================================================== Source: https://thin.host/docs/static-sites ======================================================================== # Docusaurus & static builds thin.host hosts the output of any static-site generator — Docusaurus, Astro, Vite, VitePress, Hugo, Next `output: 'export'` — and an agent can deploy it in one tool call. This page is the Docusaurus recipe; the same flow works for the others. Prefer to hand this to Claude Code? Install the [thin-host-docusaurus skill](https://thin.host/skills/thin-host-docusaurus/SKILL.md) (`curl -o ~/.claude/skills/thin-host-docusaurus/SKILL.md --create-dirs https://thin.host/skills/thin-host-docusaurus/SKILL.md`) and say "deploy my docs". ## What you get - **One call to publish.** `publish_website(source_path="…/build", title, slug)` uploads the whole folder — hundreds of files are batched across requests automatically. - **Clean redeploys.** `update_website(…, sync=true)` uploads the new build and deletes every file the old one left behind, so renamed hashed chunks never pile up. - **Custom domain with TLS**, plus generated `robots.txt`, `sitemap.xml`, and canonical tags on it. - **Your own 404.** The build's `404.html` becomes the site's not-found page and is served with a real 404 status. - **Password or email gating** for the whole site or single pages, set in the dashboard and kept across redeploys. - **Redirects that survive.** Redirect pages you author in the dashboard are never pruned by a sync. ## 1. Decide the baseUrl Docusaurus bakes `baseUrl` into every asset URL. Where the site will be viewed decides the value: | Where readers will look | baseUrl | Notes | |---|---|---| | A custom domain, e.g. `docs.example.com` | `/` | The normal case. The thin.host preview URL renders unstyled until the domain is mapped — expected, not a bug. | | The preview URL `https://thin.host/s//` | `/s//` | Pick the slug first and pass it to `publish_website`. | Make it switchable so both builds come from one repo: ```typescript // docusaurus.config.ts url: 'https://docs.example.com', baseUrl: process.env.DOCUSAURUS_BASE_URL ?? '/', ``` ```bash # custom-domain build (default) npm run build # preview build for the shared thin.host origin DOCUSAURUS_BASE_URL=/s/example-docs/ npx docusaurus build --out-dir build-preview ``` The publish tools detect Docusaurus and report `base_url`. When it will not resolve at the returned URL the response carries a `warning` that says exactly this — an agent should relay it rather than debug a "blank" site. ## 2. Publish ```python publish_website( source_path="/abs/path/to/repo/build", title="Example Docs", slug="example-docs", # needed if you built with baseUrl '/s/example-docs/' ) # → { url: "https://thin.host/s/example-docs/", page_count: 277, asset_count: 400, # requests: 5, framework: "docusaurus", base_url: "/", warning: "…" } ``` Or from Claude Code, in words: *"Build the docs and publish the build folder to thin.host as example-docs."* ## 3. Redeploy with sync ```python update_website( website="example-docs", # slug, id, or live URL source_path="/abs/path/to/repo/build", sync=True, ) # → { removed_assets: ["/assets/js/main.0a1b2c3d.js", …], kept_redirects: [], … } ``` Always pass `sync=true` for a build folder. Without it the site keeps working, but every previous build's chunks stay forever. Sync is safe to re-run; a deploy that fails partway says which request failed, and running it again finishes the job. ## No local server? Publish a zip Through the hosted endpoint (`https://thin.host/mcp`, or any agent without a local MCP server) the build travels as a zip. Either upload it directly: ```bash cd build && zip -qr ../site.zip . && cd .. curl -X POST https://thin.host/v1/websites/example-docs/archive \ -H "Authorization: Bearer $THIN_HOST_API_KEY" -F file=@site.zip # sync=true by default ``` …or put the zip somewhere public and let the agent call `publish_website_from_url` / `update_website_from_url` with that link. Both apply the same mapping, baseUrl detection and sync rules as the local tools. ## 4. Map the domain Dashboard → the website → Domains → add `docs.example.com` and create the CNAME shown. TLS provisions automatically, secondary hostnames 301 to the primary, and `robots.txt` / `sitemap.xml` are generated for the domain. An agent can instead call `provision_domain` and hand the user the claim URL. ## Protecting the docs Password- or email-gate the whole site, or single pages, from the dashboard. Gating is stored on the page, and a redeploy updates pages in place, so it survives. Leave `/404` unprotected — a gated 404 page is not used for misses. ## REST, for CI Everything above is three endpoints. Split the build into batches of at most 20MB, 200 pages, and 500 assets each: ```bash # create (first batch) → note the slug curl -X POST https://thin.host/v1/websites -H "X-Platform-API-Key: $THIN_HOST_API_KEY" \ -H "Content-Type: application/json" -d @batch-0.json # remaining batches — assets first, then pages curl -X PATCH https://thin.host/v1/websites/example-docs -H "X-Platform-API-Key: $THIN_HOST_API_KEY" \ -H "Content-Type: application/json" -d @batch-1.json # prune with the full manifest curl -X POST https://thin.host/v1/websites/example-docs/sync -H "X-Platform-API-Key: $THIN_HOST_API_KEY" \ -H "Content-Type: application/json" \ -d '{"keep": {"pages": ["/", "/docs/intro", "/404"], "assets": ["/assets/js/main.e7f12ca1.js", "…"]}}' ``` Full field reference: [REST API](https://thin.host/docs/api#post-v1websitesid_or_slugsync) · [MCP tools](https://thin.host/docs/mcp). ## Supported files `.html` files become pages (`docs/intro/index.html` → `/docs/intro`, `404.html` → `/404`). Assets: css, js, mjs, map, png, jpg, jpeg, gif, svg, ico, webp, avif, mp4, webm, mp3, woff, woff2, ttf, otf, eot, wasm, json, xml, txt, csv, md, yaml, yml, pdf, webmanifest. Anything else (for example `.nojekyll`) is skipped and listed in `skipped_files`. Single files over ~15MB do not fit a request — compress or drop them. --- Canonical page: https://thin.host/docs/static-sites ======================================================================== Source: https://thin.host/docs/api ======================================================================== # REST API Reference All endpoints are under `/v1/`. Authenticate with `X-Platform-API-Key` header. ## Authentication Every request must include your platform API key: ```http X-Platform-API-Key: th_live_your_key_here ``` Every endpoint also accepts the key as `Authorization: Bearer th_live_…`, and accepts an OAuth access token issued by `/oauth/token` (the hosted MCP endpoint's sign-in flow) in the same header — both resolve to the same account. ## Error Format All errors return a structured JSON body: ```json { "error": { "code": "domain_taken", "message": "The domain mysite.com is already provisioned", "next_action": "Choose a different domain or check if you own this domain", "retryable": false } } ``` ## Rate Limits Rate limits are per-platform and vary by plan tier. Headers included on every response: | Header | Description | |---|---| | `X-Rate-Limit-Limit` | Max requests per day | | `X-Rate-Limit-Remaining` | Requests remaining today | | `X-Rate-Limit-Reset` | Seconds until limit resets | ## POST /v1/domains Provision a new custom domain. ### Request | Field | Type | Required | Description | |---|---|---|---| | `domain` | string | yes | Custom domain to provision (e.g. "mysite.com") | | `origin_url` | string | yes | Origin URL to proxy to | | `end_user_email` | string | yes | End user's email for billing | | `idempotency_key` | string | no | Prevent duplicate provisions on retry | ### Response (201) ```json { "id": "uuid", "domain": "mysite.com", "status": "pending_payment", "dns_instructions": { "type": "CNAME", "name": "mysite.com", "value": "cname.thin.host", "human_readable": "Set a CNAME record for mysite.com pointing to cname.thin.host" }, "claim_url": "https://thin.host/claim/abc123...", "next_action": "Direct the user to the claim_url to complete payment and DNS setup", "expected_completion_seconds": 300 } ``` ## GET /v1/domains/:id Get full domain status. ### Response (200) ```json { "id": "uuid", "hostname": "mysite.com", "origin_url": "https://myapp.vercel.app", "status": "active", "dns_status": "resolved", "ssl_status": "active", "payment_status": "paid", "ready": true, "created_at": "2026-04-25T00:00:00Z", "updated_at": "2026-04-25T01:00:00Z" } ``` ## PATCH /v1/domains/:id Update the origin URL for an existing domain. ### Request ```json { "origin_url": "https://new-deploy.vercel.app" } ``` ### Response (200) ```json { "id": "uuid", "domain": "mysite.com", "origin_url": "https://new-deploy.vercel.app", "status": "active", "updated_at": "2026-04-25T02:00:00Z" } ``` ## DELETE /v1/domains/:id Release a domain. Removes proxy config and marks as released. Not reversible. ### Response (200) ```json { "id": "uuid", "domain": "mysite.com", "status": "released", "released_at": "2026-04-25T03:00:00Z" } ``` ## GET /v1/domains List domains with pagination and filtering. ### Query Parameters | Param | Default | Description | |---|---|---| | `status` | all | Filter by status enum | | `page` | 1 | Page number | | `limit` | 50 | Results per page (max 100) | ### Response (200) ```json { "domains": [ ... ], "total": 42, "page": 1, "per_page": 50, "has_more": false } ``` ## POST /v1/websites Publish a new hosted website from JSON — the endpoint behind the MCP `publish_website` tool. Requires an API key created from the dashboard (linked to your account); unlinked platform keys get `account_not_linked`. The site is live at the returned `url` immediately. ### Request | Field | Type | Required | Description | |---|---|---|---| | `title` | string | yes | Site title | | `slug` | string | no | URL slug (site lives at /s//); auto-generated if omitted | | `pages` | array | yes | `[{path, html}]` — e.g. `{"path": "/", "html": "..."}` | | `assets` | array | no | `[{path, content_base64, content_type?}]` — css/js/images/fonts, base64-encoded | Limits: 20MB per request, 200 pages, 500 assets — a larger site is published as one `POST` followed by `PATCH` batches (the MCP tools do this automatically). Asset types: css, js, mjs, map, png, jpg, jpeg, gif, svg, ico, webp, avif, mp4, webm, mp3, woff, woff2, ttf, otf, eot, wasm, json, xml, txt, csv, md, yaml, yml, pdf, webmanifest. A site with no `/` page gets a placeholder root. A page at `/404` is served, with a 404 status, for any path the site does not have. ### Response (201) ```json { "id": "uuid", "slug": "my-site", "title": "My Site", "url": "https://thin.host/s/my-site/", "pages": ["/", "/about"], "assets": ["/css/style.css"], "page_count": 2, "asset_count": 1, "custom_domains": [], "next_action": "The site is live at ... — share that URL." } ``` ## POST /v1/websites/archive Publish a new site from one multipart upload instead of JSON batches — the shell-friendly path (and the hosted MCP endpoint's alternative to a public zip URL). Form fields: `file` (a `.zip` of the site/build folder, or a single `.html`), `title`, optional `slug`. Same page/asset mapping as the MCP tools; limit 30MB per upload. ```bash cd build && zip -qr ../site.zip . && cd .. curl -X POST https://thin.host/v1/websites/archive \ -H "Authorization: Bearer th_live_your_key" \ -F file=@site.zip -F title="My Docs" -F slug=my-docs ``` ### Response (201) As `POST /v1/websites`, plus `skipped_files`. ## POST /v1/websites/:id_or_slug/archive Redeploy from one multipart upload. Form fields: `file`, optional `title`, `sync` (default `true`: everything the archive does not contain is removed afterwards, exactly like `/sync` with the archive's manifest). ```bash curl -X POST https://thin.host/v1/websites/my-docs/archive \ -H "Authorization: Bearer th_live_your_key" -F file=@site.zip ``` ### Response (200) ```json { "url": "https://thin.host/s/my-docs/", "updated_pages": ["/", "/docs/intro"], "updated_assets": ["…"], "removed_pages": [], "removed_assets": ["/assets/js/main.0a1b2c3d.js"], "kept_redirects": [] } ``` ## PATCH /v1/websites/:id_or_slug Update a website — upserts pages/assets by path and can retitle. Paths not included are left untouched. ### Request ```json { "title": "My Site v2", "pages": [{ "path": "/", "html": "

Updated

" }], "assets": [{ "path": "/css/style.css", "content_base64": "..." }] } ``` ### Response (200) ```json { "url": "https://thin.host/s/my-site/", "updated_pages": ["/"], "updated_assets": ["/css/style.css"] } ``` ## POST /v1/websites/:id_or_slug/sync Finalize a build-output deploy: delete every page and asset the site has that the manifest does not list. Static-site generators (Docusaurus, Astro, Vite, Next export) rename their hashed chunks on every build, and `PATCH` only upserts — upload the new build in batches (assets first, then pages), then post the full manifest here and the leftovers are removed. Pages with a dashboard-authored `redirect_to` are kept and reported in `kept_redirects`. See [Docusaurus & static builds](https://thin.host/docs/static-sites). ### Request ```json { "keep": { "pages": ["/", "/docs/intro", "/404"], "assets": ["/assets/js/main.e7f12ca1.js", "/assets/css/styles.be7ce4c6.css", "/img/logo.svg"] } } ``` `keep.pages` must be non-empty (`empty_manifest` otherwise) — to remove a whole site use `DELETE`. ### Response (200) ```json { "url": "https://thin.host/s/my-docs/", "page_count": 3, "asset_count": 3, "removed_pages": ["/docs/old-page"], "removed_assets": ["/assets/js/main.0a1b2c3d.js"], "kept_redirects": ["/guide/moved"] } ``` ## GET /v1/websites List your hosted websites, newest first. Supports `page` and `limit` (max 100) query parameters. ### Response (200) ```json { "websites": [ { "id": "...", "slug": "my-site", "url": "https://thin.host/s/my-site/", "page_count": 2 } ], "total": 1, "page": 1, "per_page": 50, "has_more": false } ``` ## GET /v1/websites/:id_or_slug Get one website, including its page paths and asset paths. ## DELETE /v1/websites/:id_or_slug Delete a website and all its pages and assets. Not reversible. ### Response (200) ```json { "deleted": true, "slug": "my-site" } ``` ## Domain Status Enum | Status | Meaning | |---|---| | `pending_payment` | Waiting for end user to pay via claim page | | `pending_dns` | Paid, waiting for DNS records to propagate | | `pending_ssl` | DNS verified, SSL certificate provisioning | | `active` | Domain is live with SSL | | `failed` | Provisioning failed or expired | | `released` | Domain was released/deleted | --- Canonical page: https://thin.host/docs/api ======================================================================== Source: https://thin.host/docs/mcp ======================================================================== # MCP Tool Reference The thin.host MCP server exposes 9 tools — 3 for website hosting, 5 for domain provisioning, and `send_email` for transactional email. All tool descriptions are written for agent reasoning — status fields are enums, not prose. ## Connecting Same tools, three transports — see the [MCP quickstart](https://thin.host/docs/quickstart-mcp) for the commands: | Transport | Where | Auth | Publish path | |---|---|---|---| | Hosted (Streamable HTTP) | `https://thin.host/mcp` | Bearer API key, or OAuth (PKCE; discovery at `/.well-known/oauth-authorization-server`) | `publish_website_from_url` / `update_website_from_url`, or `POST /v1/websites/archive` | | Local (stdio) via `uvx` | your machine | `THIN_HOST_API_KEY` env | `publish_website` / `update_website` read local folders directly | | Claude Desktop bundle | your machine | key embedded at download | as local | The hosted endpoint is stateless JSON-RPC over `POST` (no sessions, no SSE). `publish_website` and `update_website` are hidden there because "local" would mean the server's disk. ## publish_website *Local server only.* Publish a local HTML file, directory, ZIP, or static build folder (a Docusaurus `build/`, Astro/Vite `dist/`, Next `out/`) as a live hosted website. Use right after generating a site so the user gets a shareable URL instead of loose files. HTML files become pages (`index.html` → `/`, `about.html` → `/about`, `docs/intro/index.html` → `/docs/intro`, `404.html` → the site's not-found page); css/js/images/fonts become assets served relative to the site root. Big builds are uploaded in several requests automatically. Docusaurus builds are detected and their `base_url` reported — a `warning` comes back when it will not resolve at the returned URL (see [Docusaurus & static builds](https://thin.host/docs/static-sites)). **Precondition:** the API key must be created from the thin.host dashboard so it is linked to an account — an unlinked key gets `account_not_linked`. ### Parameters | Name | Type | Required | Description | |---|---|---|---| | `source_path` | string | yes | Absolute path to an .html file, a site/build directory, or a .zip | | `title` | string | yes | Site title (shown in the dashboard) | | `slug` | string | no | URL slug (site lives at /s//); auto-generated if omitted | ### Returns ```json { "url": "https://thin.host/s/my-site/", "id": "uuid", "slug": "my-site", "title": "My Site", "page_count": 2, "asset_count": 1, "pages": ["/", "/about"], "assets": ["/css/style.css"], "requests": 1, "skipped_files": [], "framework": "docusaurus", "base_url": "/", "warning": "This Docusaurus build uses baseUrl '/' … (only when it will not resolve at url)", "next_action": "The site is live at ... — share that URL." } ``` ## update_website *Local server only.* Push updated pages/assets to an existing hosted site (upsert by path). Local files replace the same paths on the site. With `sync=false` (default) site files not in the upload are left untouched; with `sync=true` the upload is the whole site and everything else is deleted afterwards — use it whenever you redeploy a generator build folder, or each build's renamed chunks accumulate. Redirect pages authored in the dashboard are never pruned (`kept_redirects`), and page-level protection survives because pages are updated in place. See [Docusaurus & static builds](https://thin.host/docs/static-sites). ### Parameters | Name | Type | Required | Description | |---|---|---|---| | `website` | string | yes | The site's id, slug, or live URL | | `source_path` | string | yes | Absolute path to an .html file, a site directory, or a .zip | | `title` | string | no | New site title | | `sync` | boolean | no | Treat the upload as the complete site and remove everything else (default false) | ### Returns ```json { "url": "https://thin.host/s/my-docs/", "updated_page_count": 277, "updated_asset_count": 400, "updated_pages": ["/", "/404", "/docs/intro", "… 274 more"], "removed_assets": ["/assets/js/main.0a1b2c3d.js"], "removed_pages": [], "kept_redirects": [], "requests": 5, "framework": "docusaurus", "base_url": "/" } ``` ## publish_website_from_url Publish a site from a public URL — a `.zip` of the site or build folder (`cd build && zip -r ../site.zip .`), or a single `.html` page. Everything else matches `publish_website`: page/asset mapping, batching, Docusaurus baseUrl detection and its `warning`. Private, loopback and cloud-metadata addresses are refused; the limit is 150MB. ### Parameters | Name | Type | Required | Description | |---|---|---|---| | `source_url` | string | yes | Public http(s) URL of a .zip archive or an .html file | | `title` | string | yes | Site title | | `slug` | string | no | URL slug (site lives at /s//) | ### Returns Same shape as `publish_website`. ## update_website_from_url Redeploy an existing site from a URL. `sync` defaults to **true** here — a zipped build is the whole site — so files the archive does not contain are removed afterwards (dashboard redirect pages are kept). Pass `sync=false` to upsert only. ### Parameters | Name | Type | Required | Description | |---|---|---|---| | `website` | string | yes | The site's id, slug, or live URL | | `source_url` | string | yes | Public http(s) URL of a .zip archive or an .html file | | `title` | string | no | New site title | | `sync` | boolean | no | Treat the archive as the whole site (default true) | ### Returns Same shape as `update_website`. ## list_websites List the account's hosted websites with their live URLs, newest first. ### Parameters | Name | Type | Required | Default | |---|---|---|---| | `limit` | int | no | 50 | ### Returns ```json { "websites": [ { "slug": "my-site", "url": "https://thin.host/s/my-site/", "page_count": 2, "custom_domains": [] } ], "total": 1 } ``` ## provision_domain Provision a new custom domain for an AI-generated site or app. ### Parameters | Name | Type | Required | Description | |---|---|---|---| | `domain` | string | yes | Custom domain (e.g. "mysite.com") | | `origin_url` | string | yes | Current URL where the site is hosted | | `user_email` | string | yes | End user's email for billing | | `idempotency_key` | string | no | Prevent duplicate provisions on retry | ### Returns ```json { "provision_id": "uuid", "status": "pending_payment", "dns_instructions": { "type": "CNAME", "name": "mysite.com", "value": "cname.thin.host", "human_readable": "Set a CNAME record for mysite.com pointing to cname.thin.host" }, "claim_url": "https://thin.host/claim/abc123...", "expected_completion_seconds": 300 } ``` ## check_domain_status Check current provisioning status. Call this to poll until `ready: true`. ### Parameters | Name | Type | Required | |---|---|---| | `provision_id` | string | yes | ### Returns ```json { "status": "active", "dns_status": "resolved", "ssl_status": "active", "payment_status": "paid", "ready": true } ``` ## update_origin Change where a domain points to. Use when the user redeploys to a new URL. ### Parameters | Name | Type | Required | |---|---|---| | `provision_id` | string | yes | | `new_origin_url` | string | yes | ### Returns ```json { "status": "active", "updated_at": "2026-04-25T02:00:00Z" } ``` ## release_domain Tear down a provisioned domain. Not reversible. ### Parameters | Name | Type | Required | |---|---|---| | `provision_id` | string | yes | ### Returns ```json { "status": "released", "released_at": "2026-04-25T03:00:00Z" } ``` ## list_domains List all domains provisioned through your platform. ### Parameters | Name | Type | Required | Default | |---|---|---|---| | `status_filter` | string | no | all | | `limit` | int | no | 50 | ### Returns ```json { "domains": [ { "id": "...", "hostname": "...", "status": "...", "ready": true }, ... ], "total": 42, "has_more": false } ``` ## send_email Send a single transactional notification email (sign-in link, receipt, alert). **Precondition:** the account must be allowlisted for email *and* the `from` address must use a verified sending domain — omit `from` to use the default verified sender. Unapproved accounts get `email_not_enabled`; a bad sender gets `invalid_from_domain`. Surface those errors to the user instead of retrying. Transactional only — not for marketing or bulk. ### Parameters | Name | Type | Required | Description | |---|---|---|---| | `to` | string | yes | Recipient email address | | `subject` | string | yes | Subject line | | `text` | string | one of text/html | Plain-text body | | `html` | string | one of text/html | HTML body | | `from_address` | string | no | Sender on a verified domain; omit for the default | | `reply_to` | string | no | Reply-To header | ### Returns ```json { "id": "", "status": "sent", "to": "user@example.com", "from_address": "no-reply@mail.thin.host" } ``` Common failure `error_code`s: `email_not_enabled`, `invalid_from_domain`, `recipient_suppressed` (prior bounce/complaint — do not retry), `rate_limited` (retryable after the window resets), `invalid_to`, `missing_subject`, `empty_body`. There is also a drop-in [Claude skill](https://github.com/thinhost/thinhost-mcp/blob/main/skills/thin-host-email/SKILL.md) wrapping this tool + the REST endpoint. ## Error Format All tools return structured errors when something goes wrong: ```json { "error_code": "domain_taken", "error_message": "The domain mysite.com is already provisioned", "agent_should_retry": false, "suggested_next_tool_call": "Choose a different domain" } ``` --- Canonical page: https://thin.host/docs/mcp ======================================================================== Source: https://thin.host/docs/concepts ======================================================================== # Concepts ## Platforms A platform is your thin.host account. It represents an agent product or SaaS that integrates thin.host for custom domain provisioning. Each platform gets: - An API key for authentication - A webhook URL for status change notifications - A plan tier (Free, Indie, Platform, Enterprise) with usage limits - Optional white-label settings for the claim page ## Domains A domain represents a custom domain provisioned through your platform. Domains go through a lifecycle: ``` pending_payment → pending_dns → pending_ssl → active ↓ released (via DELETE) ``` Each domain is tied to a platform, has an origin URL (where traffic is proxied to), and has billing state (Stripe subscription). ## Claim Sessions When a domain is provisioned, thin.host creates a claim session — a short-lived (24h) URL that the end user visits to: 1. Complete Stripe payment ($8/mo default) 2. View DNS configuration instructions 3. Monitor DNS propagation and SSL provisioning in real-time The claim page is hosted by thin.host, so your agent product never needs to build billing or DNS UX. ## Webhooks Configure a webhook URL in your platform settings to receive notifications when domain status changes: ```json { "event": "payment_completed", "domain_id": "uuid", "hostname": "mysite.com", "status": "pending_dns" } ``` Events: `payment_completed`, `domain_active`, `subscription_cancelled` ## Idempotency All write endpoints support idempotency keys (via the `idempotency_key` body field or `Idempotency-Key` header). If you retry a provision with the same key, thin.host returns the existing domain instead of creating a duplicate. This is critical for agent calling patterns where retries are common. ## DNS thin.host manages proxy and SSL for you. The end user needs to set one DNS record: ``` Type: CNAME Name: mysite.com Value: cname.thin.host ``` For apex domains (no www), an A or ALIAS record may be needed depending on the registrar. The claim page provides registrar-specific instructions. --- Canonical page: https://thin.host/docs/concepts ======================================================================== Source: https://thin.host/docs/billing ======================================================================== # Billing & Rev-Share ## How Billing Works thin.host uses a three-party billing model: 1. **End user pays** — via Stripe on the claim page. Default: $8/mo per domain. 2. **Revenue splits** — thin.host keeps $4/mo, your platform keeps $4/mo (default). 3. **Platform pays thin.host** — a separate monthly invoice for your platform tier subscription. ## Default Pricing | Component | Amount | |---|---| | End user retail price | $8.00/mo per domain | | thin.host take | $4.00/mo per domain | | Platform revenue share | $4.00/mo per domain | ## Custom Pricing (Platform Tier) Platform-tier customers can customize: - **Retail price** — Set any price above $4/mo floor - **Revenue split** — Custom splits negotiated per platform Example: Set retail to $12/mo with a 70/30 split → you keep $8.40, thin.host keeps $3.60. ## Platform Tier Pricing | Tier | Monthly Fee | Domains | API Calls/Day | |---|---|---|---| | Free | $0 | 3 | 100 | | Indie ($29/mo) | $29 | 25 | 10,000 | | Platform ($199/mo) | $199 + $1/domain after 50 | Unlimited | Unlimited | | Enterprise | Custom | Unlimited | Unlimited | ## Subscription Lifecycle - **Payment** — Stripe Checkout on the claim page. Subscription starts on payment. - **Renewal** — Monthly auto-renewal via Stripe. - **Cancellation** — When a subscription is cancelled, the domain transitions to `released` after a grace period. - **Failed payment** — Stripe retries per its dunning schedule. If ultimately unpaid, domain is released. ## Webhooks for Billing Events Your platform webhook receives: - `payment_completed` — end user paid, domain moves to `pending_dns` - `subscription_cancelled` — domain released --- Canonical page: https://thin.host/docs/billing ======================================================================== Source: https://thin.host/docs/recipes ======================================================================== # Recipes Integration patterns for common agent frameworks and platforms. ## Claude Desktop (MCP) See [Quickstart: MCP](https://thin.host/docs/quickstart-mcp) for the full setup. Once configured, Claude can provision domains directly in conversation. ## LangChain (Python) ```python from langchain.tools import StructuredTool import requests API_KEY = "th_live_your_key" API_URL = "https://thin.host/v1" def provision_domain(domain: str, origin_url: str, user_email: str) -> dict: """Provision a custom domain via thin.host.""" resp = requests.post( f"{API_URL}/domains", headers={"X-Platform-API-Key": API_KEY}, json={"domain": domain, "origin_url": origin_url, "end_user_email": user_email}, ) return resp.json() tool = StructuredTool.from_function( func=provision_domain, name="provision_domain", description="Provision a custom domain for a deployed site. Returns a claim_url for the user.", ) ``` ## Vercel AI SDK (TypeScript) ```typescript import { tool } from "ai"; import { z } from "zod"; const provisionDomain = tool({ description: "Provision a custom domain via thin.host", parameters: z.object({ domain: z.string().describe("Custom domain to provision"), origin_url: z.string().describe("Origin URL to proxy to"), user_email: z.string().describe("End user email for billing"), }), execute: async ({ domain, origin_url, user_email }) => { const resp = await fetch("https://thin.host/v1/domains", { method: "POST", headers: { "X-Platform-API-Key": process.env.THIN_HOST_API_KEY!, "Content-Type": "application/json", }, body: JSON.stringify({ domain, origin_url, end_user_email: user_email }), }); return resp.json(); }, }); ``` ## OpenAI Agents SDK (Python) ```python from agents import function_tool import requests API_KEY = "th_live_your_key" @function_tool def provision_domain(domain: str, origin_url: str, user_email: str) -> dict: """Provision a custom domain. Returns claim_url for the user to pay and configure DNS.""" resp = requests.post( "https://thin.host/v1/domains", headers={"X-Platform-API-Key": API_KEY}, json={"domain": domain, "origin_url": origin_url, "end_user_email": user_email}, ) return resp.json() ``` ## Webhook Integration ```python # Flask webhook handler @app.route("/webhooks/thinhost", methods=["POST"]) def thinhost_webhook(): data = request.json if data["event"] == "payment_completed": # User paid — domain moving to DNS setup notify_user(data["domain_id"], "Payment received! Configure DNS next.") elif data["event"] == "domain_active": # Domain is fully live notify_user(data["domain_id"], f"Your domain {data['hostname']} is live!") return "", 200 ``` --- Canonical page: https://thin.host/docs/recipes ======================================================================== Source: https://thin.host/guides ======================================================================== # Deploy guides Step-by-step guides for putting a static site live on thin.host, one per framework. Each covers the build command, the folder to deploy, the base-path setting for the `/s//` preview URL, a prompt for your agent (Claude Code, Cursor, ChatGPT and other MCP clients), the equivalent `curl` call, and the custom-domain step. | Guide | Build | Deploy this folder | |---|---|---| | [Astro](https://thin.host/guides/deploy-astro) | `npm run build` | `dist/` | | [Vite (React)](https://thin.host/guides/deploy-vite-react) | `npm run build` | `dist/` | | [Vue](https://thin.host/guides/deploy-vue) | `npm run build` | `dist/` | | [SvelteKit](https://thin.host/guides/deploy-sveltekit) | `npm run build` | `build/` | | [Next.js (static export)](https://thin.host/guides/deploy-nextjs) | `npm run build` | `out/` | | [Nuxt (generate)](https://thin.host/guides/deploy-nuxt) | `npx nuxt generate` | `.output/public/` | | [Gatsby](https://thin.host/guides/deploy-gatsby) | `npm run build` | `public/` | | [Hugo](https://thin.host/guides/deploy-hugo) | `hugo --cleanDestinationDir --minify` | `public/` | | [Jekyll](https://thin.host/guides/deploy-jekyll) | `JEKYLL_ENV=production bundle exec jekyll build` | `_site/` | | [Eleventy (11ty)](https://thin.host/guides/deploy-eleventy) | `npx @11ty/eleventy` | `_site/` | | [MkDocs](https://thin.host/guides/deploy-mkdocs) | `mkdocs build` | `site/` | | [VitePress](https://thin.host/guides/deploy-vitepress) | `npm run docs:build` | `docs/.vitepress/dist/` | | [Docusaurus](https://thin.host/guides/deploy-docusaurus) | `npm run build` | `build/` | | [Plain HTML](https://thin.host/guides/deploy-html) | none | the folder with `index.html` | | [An HTML page from a Claude or ChatGPT chat](https://thin.host/guides/deploy-ai-chat-html) | none | the folder with `index.html` | ## The same three steps for every framework 1. **Build static files** with the base path set for where the site will be read: `/s//` for the thin.host preview URL, `/` for a custom domain. 2. **Deploy the output folder**: ask your agent to publish it through the thin.host MCP server, or zip it and `POST` it to `/v1/websites/archive`. 3. **Map a domain** from the dashboard (CNAME to `cname.thin.host`, automatic TLS), then rebuild with base `/`. New to the MCP server? Start with [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). Moving from another host? See [thin.host compared](https://thin.host/compare). --- Canonical page: https://thin.host/guides ======================================================================== Source: https://thin.host/guides/deploy-astro ======================================================================== # Deploy Astro to thin.host Build an Astro site to dist/ and publish it from Claude Code, Cursor or one curl call. thin.host serves the static files and gives you a live URL right away. Your agent can do every step for you through the thin.host MCP server, or you can run one `curl` command. ## At a glance | Step | Astro | |---|---| | Build command | `npm run build` | | Folder to deploy | `dist/` | | Preview build (served at `/s/my-site/`) | `npx astro build --base /s/my-site` | | Deploy | `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive` | | Live URL | `https://thin.host/s/my-site/`, or your own domain | ## Before you start - **Requires:** Node.js 22.12 or later (Astro does not support odd-numbered Node releases). - **A thin.host account.** [Sign up](https://thin.host/signup), then create an API key under Settings (for `curl` and the local MCP server), or connect your agent with OAuth as shown in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## Create a project (skip if you have one) ```bash npm create astro@latest ``` ## Set the base path Until a domain points at it, a thin.host site lives under a sub-path: `https://thin.host/s//`. Astro prefixes its bundled assets with the base option, but not your own links: write internal links with import.meta.env.BASE_URL. Pass the base on the command line for the preview build and leave it out for a custom domain, so the config only names your real domain. ```javascript // astro.config.mjs import { defineConfig } from 'astro/config'; export default defineConfig({ site: 'https://www.example.com', }); ``` | Where readers will look | Build with | |---|---| | The preview URL `https://thin.host/s/my-site/` | `npx astro build --base /s/my-site` | | A custom domain, or a free `.thin.host` subdomain | `npm run build` (base path `/`) | Pick the slug (`my-site` here) before you build the preview, and pass the same slug when you deploy. ## Build ```bash npm run build ``` The finished site is in `dist/`. That folder is what you deploy. ## Deploy from your agent (MCP) Connect thin.host to Claude Code, Claude Desktop, Cursor, VS Code, Windsurf, Codex or ChatGPT once ([setup for each client](https://thin.host/docs/quickstart-mcp)), then ask: > Build this Astro project for thin.host with the slug my-site and publish the dist/ folder. With the local server (`uvx thinhost-mcp`) the agent runs the build and calls `publish_website` with the absolute path of `dist/`; large builds are split across requests automatically. Later changes go out with `update_website` and `sync=true`, which also removes files the new build dropped. The hosted connector (`https://thin.host/mcp`, used by claude.ai and ChatGPT) cannot read your disk. From a coding agent it uploads with the REST call below; otherwise it publishes from a public link to a zip or HTML file with `publish_website_from_url`. ## Deploy with curl ```bash cd dist && zip -r ../site.zip . && cd - curl -F file=@site.zip -F title="My Astro site" -F slug=my-site \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/archive ``` The JSON response includes `url`, the live address (`https://thin.host/s/my-site/`). To redeploy, upload the new zip to the site's archive endpoint; pages and assets missing from it are removed: ```bash curl -F file=@site.zip \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/my-site/archive ``` A single upload can be up to 30 MB. See the [REST API reference](https://thin.host/docs/api) for every field. ## Add a custom domain 1. Open the site in the [dashboard](https://thin.host/dashboard) and add your hostname under **Custom Domains**, for example `www.example.com`. A `.thin.host` subdomain is free and works immediately. 2. Create the DNS record the dashboard shows: a `CNAME` pointing at `cname.thin.host`. TLS is issued automatically once DNS resolves. 3. Rebuild with the base path `/` (`npm run build`) and redeploy. Pages on a custom domain get a canonical tag, a generated `robots.txt` and a `sitemap.xml`. ## Astro notes - Static output is Astro's default. A project that added an SSR adapter or output: 'server' needs the default static output (or prerendered pages) to produce a folder thin.host can serve. - Files in public/ referenced as /file.png are not prefixed with the base; build those URLs from import.meta.env.BASE_URL too. ## FAQ **Does Astro's server output work on thin.host?** No. thin.host serves static files, so keep Astro's default static output. Pages that need a server at request time have to be prerendered or moved to an API hosted elsewhere. **Why does the preview URL load without styles or scripts?** The site is served under /s// until a custom domain points at it, so a build that references /assets/... asks the thin.host root for files that live under the sub-path. Build with the base path set to /s// for the preview, or map a domain (a free .thin.host subdomain works) and build with base /. **How do I redeploy?** Rebuild, zip the output folder again and POST it to /v1/websites//archive, or ask your agent to run update_website with sync=true. Sync removes files the new build no longer contains, so old hashed bundles do not pile up. **How large can a site be?** A single archive upload can be up to 30 MB. The local MCP server (uvx thinhost-mcp) reads the build folder directly and splits large sites across requests, up to 150 MB. ## Sources Commands and options checked against the official Astro docs on 2026-10-14: - [Astro: Deploy your Astro site](https://docs.astro.build/en/guides/deploy/) - [Astro configuration reference: base](https://docs.astro.build/en/reference/configuration-reference/#base) - [Astro CLI reference](https://docs.astro.build/en/reference/cli-reference/) - [Astro: Install and set up](https://docs.astro.build/en/install-and-setup/) Other frameworks: [all deploy guides](https://thin.host/guides). Coming from another host? [Compare thin.host](https://thin.host/compare). --- Canonical page: https://thin.host/guides/deploy-astro ======================================================================== Source: https://thin.host/guides/deploy-vite-react ======================================================================== # Deploy Vite (React) to thin.host Build a Vite + React app to dist/ and put it live on thin.host from your agent or a curl call. thin.host serves the static files and gives you a live URL right away. Your agent can do every step for you through the thin.host MCP server, or you can run one `curl` command. ## At a glance | Step | Vite (React) | |---|---| | Build command | `npm run build` | | Folder to deploy | `dist/` | | Preview build (served at `/s/my-site/`) | `npm run build -- --base=/s/my-site/` | | Deploy | `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive` | | Live URL | `https://thin.host/s/my-site/`, or your own domain | ## Before you start - **Requires:** A current Node.js LTS release. - **A thin.host account.** [Sign up](https://thin.host/signup), then create an API key under Settings (for `curl` and the local MCP server), or connect your agent with OAuth as shown in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## Create a project (skip if you have one) ```bash npm create vite@latest my-app -- --template react ``` ## Set the base path Until a domain points at it, a thin.host site lives under a sub-path: `https://thin.host/s//`. Vite rewrites asset URLs with its base option, which you can pass on the command line, so no config change is needed. If you use React Router, give the router the same base so routes resolve under the preview path. ```javascript // src/main.jsx ``` | Where readers will look | Build with | |---|---| | The preview URL `https://thin.host/s/my-site/` | `npm run build -- --base=/s/my-site/` | | A custom domain, or a free `.thin.host` subdomain | `npm run build` (base path `/`) | Pick the slug (`my-site` here) before you build the preview, and pass the same slug when you deploy. ## Build ```bash npm run build ``` The finished site is in `dist/`. That folder is what you deploy. ## Deploy from your agent (MCP) Connect thin.host to Claude Code, Claude Desktop, Cursor, VS Code, Windsurf, Codex or ChatGPT once ([setup for each client](https://thin.host/docs/quickstart-mcp)), then ask: > Build this Vite (React) project for thin.host with the slug my-site and publish the dist/ folder. With the local server (`uvx thinhost-mcp`) the agent runs the build and calls `publish_website` with the absolute path of `dist/`; large builds are split across requests automatically. Later changes go out with `update_website` and `sync=true`, which also removes files the new build dropped. The hosted connector (`https://thin.host/mcp`, used by claude.ai and ChatGPT) cannot read your disk. From a coding agent it uploads with the REST call below; otherwise it publishes from a public link to a zip or HTML file with `publish_website_from_url`. ## Deploy with curl ```bash cd dist && zip -r ../site.zip . && cd - curl -F file=@site.zip -F title="My Vite (React) site" -F slug=my-site \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/archive ``` The JSON response includes `url`, the live address (`https://thin.host/s/my-site/`). To redeploy, upload the new zip to the site's archive endpoint; pages and assets missing from it are removed: ```bash curl -F file=@site.zip \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/my-site/archive ``` A single upload can be up to 30 MB. See the [REST API reference](https://thin.host/docs/api) for every field. ## Add a custom domain 1. Open the site in the [dashboard](https://thin.host/dashboard) and add your hostname under **Custom Domains**, for example `www.example.com`. A `.thin.host` subdomain is free and works immediately. 2. Create the DNS record the dashboard shows: a `CNAME` pointing at `cname.thin.host`. TLS is issued automatically once DNS resolves. 3. Rebuild with the base path `/` (`npm run build`) and redeploy. Pages on a custom domain get a canonical tag, a generated `robots.txt` and a `sitemap.xml`. ## Vite (React) notes - Hard-coded '/logo.png' strings in JSX are not rewritten; build runtime URLs from import.meta.env.BASE_URL. - Client-side routes are not files. thin.host serves your 404.html for unknown paths, so copying dist/index.html to dist/404.html makes deep links load the app (with a 404 status), or use hash routing. ## FAQ **Deep links to my React routes return a 404 page. What do I do?** Copy dist/index.html to dist/404.html before zipping. thin.host serves 404.html for any path that is not a file, so the app boots and the router takes over. The response status stays 404, which matters only for crawlers; prerender pages you want indexed. **Why does the preview URL load without styles or scripts?** The site is served under /s// until a custom domain points at it, so a build that references /assets/... asks the thin.host root for files that live under the sub-path. Build with the base path set to /s// for the preview, or map a domain (a free .thin.host subdomain works) and build with base /. **How do I redeploy?** Rebuild, zip the output folder again and POST it to /v1/websites//archive, or ask your agent to run update_website with sync=true. Sync removes files the new build no longer contains, so old hashed bundles do not pile up. **How large can a site be?** A single archive upload can be up to 30 MB. The local MCP server (uvx thinhost-mcp) reads the build folder directly and splits large sites across requests, up to 150 MB. ## Sources Commands and options checked against the official Vite (React) docs on 2026-10-14: - [Vite: Deploying a static site](https://vite.dev/guide/static-deploy) - [Vite: Public base path](https://vite.dev/guide/build#public-base-path) - [React Router: BrowserRouter basename](https://reactrouter.com/api/declarative-routers/BrowserRouter) Other frameworks: [all deploy guides](https://thin.host/guides). Coming from another host? [Compare thin.host](https://thin.host/compare). --- Canonical page: https://thin.host/guides/deploy-vite-react ======================================================================== Source: https://thin.host/guides/deploy-vue ======================================================================== # Deploy Vue to thin.host Build a create-vue (Vite) app to dist/ and deploy it to thin.host from your agent or curl. thin.host serves the static files and gives you a live URL right away. Your agent can do every step for you through the thin.host MCP server, or you can run one `curl` command. ## At a glance | Step | Vue | |---|---| | Build command | `npm run build` | | Folder to deploy | `dist/` | | Preview build (served at `/s/my-site/`) | `npm run build -- --base=/s/my-site/` | | Deploy | `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive` | | Live URL | `https://thin.host/s/my-site/`, or your own domain | ## Before you start - **Requires:** Node.js 22.18+ or 24.12+ (create-vue's current requirement). - **A thin.host account.** [Sign up](https://thin.host/signup), then create an API key under Settings (for `curl` and the local MCP server), or connect your agent with OAuth as shown in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## Create a project (skip if you have one) ```bash npm create vue@latest ``` ## Set the base path Until a domain points at it, a thin.host site lives under a sub-path: `https://thin.host/s//`. create-vue projects build with Vite, so the base can be passed on the command line. The generated router already follows it: ```javascript // src/router/index.js const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes, }); ``` | Where readers will look | Build with | |---|---| | The preview URL `https://thin.host/s/my-site/` | `npm run build -- --base=/s/my-site/` | | A custom domain, or a free `.thin.host` subdomain | `npm run build` (base path `/`) | Pick the slug (`my-site` here) before you build the preview, and pass the same slug when you deploy. ## Build ```bash npm run build ``` The finished site is in `dist/`. That folder is what you deploy. ## Deploy from your agent (MCP) Connect thin.host to Claude Code, Claude Desktop, Cursor, VS Code, Windsurf, Codex or ChatGPT once ([setup for each client](https://thin.host/docs/quickstart-mcp)), then ask: > Build this Vue project for thin.host with the slug my-site and publish the dist/ folder. With the local server (`uvx thinhost-mcp`) the agent runs the build and calls `publish_website` with the absolute path of `dist/`; large builds are split across requests automatically. Later changes go out with `update_website` and `sync=true`, which also removes files the new build dropped. The hosted connector (`https://thin.host/mcp`, used by claude.ai and ChatGPT) cannot read your disk. From a coding agent it uploads with the REST call below; otherwise it publishes from a public link to a zip or HTML file with `publish_website_from_url`. ## Deploy with curl ```bash cd dist && zip -r ../site.zip . && cd - curl -F file=@site.zip -F title="My Vue site" -F slug=my-site \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/archive ``` The JSON response includes `url`, the live address (`https://thin.host/s/my-site/`). To redeploy, upload the new zip to the site's archive endpoint; pages and assets missing from it are removed: ```bash curl -F file=@site.zip \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/my-site/archive ``` A single upload can be up to 30 MB. See the [REST API reference](https://thin.host/docs/api) for every field. ## Add a custom domain 1. Open the site in the [dashboard](https://thin.host/dashboard) and add your hostname under **Custom Domains**, for example `www.example.com`. A `.thin.host` subdomain is free and works immediately. 2. Create the DNS record the dashboard shows: a `CNAME` pointing at `cname.thin.host`. TLS is issued automatically once DNS resolves. 3. Rebuild with the base path `/` (`npm run build`) and redeploy. Pages on a custom domain get a canonical tag, a generated `robots.txt` and a `sitemap.xml`. ## Vue notes - Vue Router's HTML5 history mode needs a fallback for deep links: copy dist/index.html to dist/404.html before deploying, or use createWebHashHistory(). ## FAQ **Do I need Nuxt to host a Vue app on thin.host?** No. A create-vue app builds to plain static files in dist/. Use Nuxt's generate command only if the project is a Nuxt app (see the Nuxt guide). **Why does the preview URL load without styles or scripts?** The site is served under /s// until a custom domain points at it, so a build that references /assets/... asks the thin.host root for files that live under the sub-path. Build with the base path set to /s// for the preview, or map a domain (a free .thin.host subdomain works) and build with base /. **How do I redeploy?** Rebuild, zip the output folder again and POST it to /v1/websites//archive, or ask your agent to run update_website with sync=true. Sync removes files the new build no longer contains, so old hashed bundles do not pile up. **How large can a site be?** A single archive upload can be up to 30 MB. The local MCP server (uvx thinhost-mcp) reads the build folder directly and splits large sites across requests, up to 150 MB. ## Sources Commands and options checked against the official Vue docs on 2026-10-14: - [Vue: Quick start](https://vuejs.org/guide/quick-start) - [Vue Router: Different history modes](https://router.vuejs.org/guide/essentials/history-mode.html) - [Vite: shared options, base](https://vite.dev/config/shared-options#base) Other frameworks: [all deploy guides](https://thin.host/guides). Coming from another host? [Compare thin.host](https://thin.host/compare). --- Canonical page: https://thin.host/guides/deploy-vue ======================================================================== Source: https://thin.host/guides/deploy-sveltekit ======================================================================== # Deploy SvelteKit to thin.host Prerender a SvelteKit app with adapter-static and publish the build/ folder to thin.host. thin.host serves the static files and gives you a live URL right away. Your agent can do every step for you through the thin.host MCP server, or you can run one `curl` command. ## At a glance | Step | SvelteKit | |---|---| | Build command | `npm run build` | | Folder to deploy | `build/` | | Preview build (served at `/s/my-site/`) | `BASE_PATH=/s/my-site npm run build` | | Deploy | `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive` | | Live URL | `https://thin.host/s/my-site/`, or your own domain | ## Before you start - **Requires:** Node.js 22.17 or later for SvelteKit 3. - **A thin.host account.** [Sign up](https://thin.host/signup), then create an API key under Settings (for `curl` and the local MCP server), or connect your agent with OAuth as shown in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## Create a project (skip if you have one) ```bash npx sv create my-app ``` ## Make the build fully static Install adapter-static, pass it to the sveltekit() Vite plugin, and prerender every page from the root layout. SvelteKit 3 (October 2026) reads this from vite.config.js; on SvelteKit 2 the same adapter and paths options go under kit in svelte.config.js. ```javascript // vite.config.js // npm i -D @sveltejs/adapter-static import { sveltekit } from '@sveltejs/kit/vite'; import adapter from '@sveltejs/adapter-static'; import { defineConfig } from 'vite'; export default defineConfig({ plugins: [ sveltekit({ adapter: adapter(), paths: { base: process.env.BASE_PATH ?? '' }, }), ], }); // src/routes/+layout.js export const prerender = true; ``` ## Set the base path Until a domain points at it, a thin.host site lives under a sub-path: `https://thin.host/s//`. The paths.base option must be empty or start with a slash, and must not end with one. Build links with resolve() from $app/paths so they follow it (SvelteKit 3 removed the base export). ```html About ``` | Where readers will look | Build with | |---|---| | The preview URL `https://thin.host/s/my-site/` | `BASE_PATH=/s/my-site npm run build` | | A custom domain, or a free `.thin.host` subdomain | `npm run build` (base path `/`) | Pick the slug (`my-site` here) before you build the preview, and pass the same slug when you deploy. ## Build ```bash npm run build ``` The finished site is in `build/`. That folder is what you deploy. ## Deploy from your agent (MCP) Connect thin.host to Claude Code, Claude Desktop, Cursor, VS Code, Windsurf, Codex or ChatGPT once ([setup for each client](https://thin.host/docs/quickstart-mcp)), then ask: > Build this SvelteKit project for thin.host with the slug my-site and publish the build/ folder. With the local server (`uvx thinhost-mcp`) the agent runs the build and calls `publish_website` with the absolute path of `build/`; large builds are split across requests automatically. Later changes go out with `update_website` and `sync=true`, which also removes files the new build dropped. The hosted connector (`https://thin.host/mcp`, used by claude.ai and ChatGPT) cannot read your disk. From a coding agent it uploads with the REST call below; otherwise it publishes from a public link to a zip or HTML file with `publish_website_from_url`. ## Deploy with curl ```bash cd build && zip -r ../site.zip . && cd - curl -F file=@site.zip -F title="My SvelteKit site" -F slug=my-site \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/archive ``` The JSON response includes `url`, the live address (`https://thin.host/s/my-site/`). To redeploy, upload the new zip to the site's archive endpoint; pages and assets missing from it are removed: ```bash curl -F file=@site.zip \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/my-site/archive ``` A single upload can be up to 30 MB. See the [REST API reference](https://thin.host/docs/api) for every field. ## Add a custom domain 1. Open the site in the [dashboard](https://thin.host/dashboard) and add your hostname under **Custom Domains**, for example `www.example.com`. A `.thin.host` subdomain is free and works immediately. 2. Create the DNS record the dashboard shows: a `CNAME` pointing at `cname.thin.host`. TLS is issued automatically once DNS resolves. 3. Rebuild with the base path `/` (`npm run build`) and redeploy. Pages on a custom domain get a canonical tag, a generated `robots.txt` and a `sitemap.xml`. ## SvelteKit notes - Every route must be prerenderable. Dynamic routes no link reaches need entries (export const entries), or the build stops with "marked as prerenderable, but were not prerendered". ## FAQ **Can I ship a client-side fallback page?** Yes. adapter({ fallback: '404.html' }) writes an SPA shell as 404.html, and thin.host serves 404.html for paths that are not files, so unprerendered routes render in the browser (with a 404 status). The SvelteKit docs warn that SPA mode costs performance and SEO, so prerender what you can. **Why does the preview URL load without styles or scripts?** The site is served under /s// until a custom domain points at it, so a build that references /assets/... asks the thin.host root for files that live under the sub-path. Build with the base path set to /s// for the preview, or map a domain (a free .thin.host subdomain works) and build with base /. **How do I redeploy?** Rebuild, zip the output folder again and POST it to /v1/websites//archive, or ask your agent to run update_website with sync=true. Sync removes files the new build no longer contains, so old hashed bundles do not pile up. **How large can a site be?** A single archive upload can be up to 30 MB. The local MCP server (uvx thinhost-mcp) reads the build folder directly and splits large sites across requests, up to 150 MB. ## Sources Commands and options checked against the official SvelteKit docs on 2026-10-14: - [SvelteKit: Static site generation (adapter-static)](https://svelte.dev/docs/kit/adapter-static) - [SvelteKit configuration: paths](https://svelte.dev/docs/kit/configuration#paths) - [SvelteKit: Migrating to SvelteKit 3](https://svelte.dev/docs/kit/migrating-to-sveltekit-3) Other frameworks: [all deploy guides](https://thin.host/guides). Coming from another host? [Compare thin.host](https://thin.host/compare). --- Canonical page: https://thin.host/guides/deploy-sveltekit ======================================================================== Source: https://thin.host/guides/deploy-nextjs ======================================================================== # Deploy Next.js (static export) to thin.host Turn on output: 'export', build Next.js to out/, and deploy the static site to thin.host. thin.host serves the static files and gives you a live URL right away. Your agent can do every step for you through the thin.host MCP server, or you can run one `curl` command. ## At a glance | Step | Next.js (static export) | |---|---| | Build command | `npm run build` | | Folder to deploy | `out/` | | Preview build (served at `/s/my-site/`) | `BASE_PATH=/s/my-site npm run build` | | Deploy | `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive` | | Live URL | `https://thin.host/s/my-site/`, or your own domain | ## Before you start - **Requires:** Node.js 20.9 or later. - **A thin.host account.** [Sign up](https://thin.host/signup), then create an API key under Settings (for `curl` and the local MCP server), or connect your agent with OAuth as shown in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## Create a project (skip if you have one) ```bash npx create-next-app@latest ``` ## Make the build fully static Static export is opt-in. Set output to 'export'; with the default image loader, also set images.unoptimized because there is no image server. ```javascript // next.config.mjs /** @type {import('next').NextConfig} */ const nextConfig = { output: 'export', images: { unoptimized: true }, basePath: process.env.BASE_PATH ?? '', }; export default nextConfig; ``` ## Set the base path Until a domain points at it, a thin.host site lives under a sub-path: `https://thin.host/s//`. The basePath option prefixes routes and assets. It must start with a slash and must not end with one; leave it empty for a custom domain. next/link adds it for you, but next/image src values and files in public/ need the prefix written in. ```javascript // next.config.mjs basePath: process.env.BASE_PATH ?? '', ``` | Where readers will look | Build with | |---|---| | The preview URL `https://thin.host/s/my-site/` | `BASE_PATH=/s/my-site npm run build` | | A custom domain, or a free `.thin.host` subdomain | `npm run build` (base path `/`) | Pick the slug (`my-site` here) before you build the preview, and pass the same slug when you deploy. ## Build ```bash npm run build ``` The finished site is in `out/`. That folder is what you deploy. ## Deploy from your agent (MCP) Connect thin.host to Claude Code, Claude Desktop, Cursor, VS Code, Windsurf, Codex or ChatGPT once ([setup for each client](https://thin.host/docs/quickstart-mcp)), then ask: > Build this Next.js (static export) project for thin.host with the slug my-site and publish the out/ folder. With the local server (`uvx thinhost-mcp`) the agent runs the build and calls `publish_website` with the absolute path of `out/`; large builds are split across requests automatically. Later changes go out with `update_website` and `sync=true`, which also removes files the new build dropped. The hosted connector (`https://thin.host/mcp`, used by claude.ai and ChatGPT) cannot read your disk. From a coding agent it uploads with the REST call below; otherwise it publishes from a public link to a zip or HTML file with `publish_website_from_url`. ## Deploy with curl ```bash cd out && zip -r ../site.zip . && cd - curl -F file=@site.zip -F title="My Next.js (static export) site" -F slug=my-site \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/archive ``` The JSON response includes `url`, the live address (`https://thin.host/s/my-site/`). To redeploy, upload the new zip to the site's archive endpoint; pages and assets missing from it are removed: ```bash curl -F file=@site.zip \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/my-site/archive ``` A single upload can be up to 30 MB. See the [REST API reference](https://thin.host/docs/api) for every field. ## Add a custom domain 1. Open the site in the [dashboard](https://thin.host/dashboard) and add your hostname under **Custom Domains**, for example `www.example.com`. A `.thin.host` subdomain is free and works immediately. 2. Create the DNS record the dashboard shows: a `CNAME` pointing at `cname.thin.host`. TLS is issued automatically once DNS resolves. 3. Rebuild with the base path `/` (`npm run build`) and redeploy. Pages on a custom domain get a canonical tag, a generated `robots.txt` and a `sitemap.xml`. ## Next.js (static export) notes - Static export has no server: Route Handlers that read the request, Proxy (formerly middleware), rewrites/redirects/headers in next.config, ISR, Server Actions, cookies and dynamic routes without generateStaticParams are not available. - Each route becomes route.html (or route/index.html with trailingSlash: true); thin.host serves both at /route. ## FAQ **Do API routes and middleware work with a Next.js static export?** No. output: 'export' produces only static files, so anything that needs a server at request time is unavailable. Keep those parts on a server platform and host the static front end on thin.host. **Why are my next/image images broken after export?** The default image loader needs a server. Set images: { unoptimized: true } or configure a custom loader. **Why does the preview URL load without styles or scripts?** The site is served under /s// until a custom domain points at it, so a build that references /assets/... asks the thin.host root for files that live under the sub-path. Build with the base path set to /s// for the preview, or map a domain (a free .thin.host subdomain works) and build with base /. **How do I redeploy?** Rebuild, zip the output folder again and POST it to /v1/websites//archive, or ask your agent to run update_website with sync=true. Sync removes files the new build no longer contains, so old hashed bundles do not pile up. **How large can a site be?** A single archive upload can be up to 30 MB. The local MCP server (uvx thinhost-mcp) reads the build folder directly and splits large sites across requests, up to 150 MB. ## Sources Commands and options checked against the official Next.js (static export) docs on 2026-10-14: - [Next.js: Static exports](https://nextjs.org/docs/app/guides/static-exports) - [Next.js config: basePath](https://nextjs.org/docs/app/api-reference/config/next-config-js/basePath) - [Next.js config: trailingSlash](https://nextjs.org/docs/app/api-reference/config/next-config-js/trailingSlash) Other frameworks: [all deploy guides](https://thin.host/guides). Coming from another host? [Compare thin.host](https://thin.host/compare). --- Canonical page: https://thin.host/guides/deploy-nextjs ======================================================================== Source: https://thin.host/guides/deploy-nuxt ======================================================================== # Deploy Nuxt (generate) to thin.host Prerender a Nuxt app with nuxt generate and publish .output/public to thin.host. thin.host serves the static files and gives you a live URL right away. Your agent can do every step for you through the thin.host MCP server, or you can run one `curl` command. ## At a glance | Step | Nuxt (generate) | |---|---| | Build command | `npx nuxt generate` | | Folder to deploy | `.output/public/` | | Preview build (served at `/s/my-site/`) | `NUXT_APP_BASE_URL=/s/my-site/ npx nuxt generate` | | Deploy | `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive` | | Live URL | `https://thin.host/s/my-site/`, or your own domain | ## Before you start - **Requires:** Node.js 22 or later. - **A thin.host account.** [Sign up](https://thin.host/signup), then create an API key under Settings (for `curl` and the local MCP server), or connect your agent with OAuth as shown in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## Create a project (skip if you have one) ```bash npm create nuxt@latest my-app ``` ## Set the base path Until a domain points at it, a thin.host site lives under a sub-path: `https://thin.host/s//`. The app.baseURL option sets the path prefix. Nuxt also reads NUXT_APP_BASE_URL at build time, so the preview build needs no config change. ```typescript // nuxt.config.ts export default defineNuxtConfig({ app: { baseURL: '/' }, }); ``` | Where readers will look | Build with | |---|---| | The preview URL `https://thin.host/s/my-site/` | `NUXT_APP_BASE_URL=/s/my-site/ npx nuxt generate` | | A custom domain, or a free `.thin.host` subdomain | `npx nuxt generate` (base path `/`) | Pick the slug (`my-site` here) before you build the preview, and pass the same slug when you deploy. ## Build ```bash npx nuxt generate ``` The finished site is in `.output/public/`. That folder is what you deploy. ## Deploy from your agent (MCP) Connect thin.host to Claude Code, Claude Desktop, Cursor, VS Code, Windsurf, Codex or ChatGPT once ([setup for each client](https://thin.host/docs/quickstart-mcp)), then ask: > Build this Nuxt (generate) project for thin.host with the slug my-site and publish the .output/public/ folder. With the local server (`uvx thinhost-mcp`) the agent runs the build and calls `publish_website` with the absolute path of `.output/public/`; large builds are split across requests automatically. Later changes go out with `update_website` and `sync=true`, which also removes files the new build dropped. The hosted connector (`https://thin.host/mcp`, used by claude.ai and ChatGPT) cannot read your disk. From a coding agent it uploads with the REST call below; otherwise it publishes from a public link to a zip or HTML file with `publish_website_from_url`. ## Deploy with curl ```bash cd .output/public && zip -r ../../site.zip . && cd - curl -F file=@site.zip -F title="My Nuxt (generate) site" -F slug=my-site \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/archive ``` The JSON response includes `url`, the live address (`https://thin.host/s/my-site/`). To redeploy, upload the new zip to the site's archive endpoint; pages and assets missing from it are removed: ```bash curl -F file=@site.zip \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/my-site/archive ``` A single upload can be up to 30 MB. See the [REST API reference](https://thin.host/docs/api) for every field. ## Add a custom domain 1. Open the site in the [dashboard](https://thin.host/dashboard) and add your hostname under **Custom Domains**, for example `www.example.com`. A `.thin.host` subdomain is free and works immediately. 2. Create the DNS record the dashboard shows: a `CNAME` pointing at `cname.thin.host`. TLS is issued automatically once DNS resolves. 3. Rebuild with the base path `/` (`npx nuxt generate`) and redeploy. Pages on a custom domain get a canonical tag, a generated `robots.txt` and a `sitemap.xml`. ## Nuxt (generate) notes - nuxt generate prerenders every route it can reach by following links from /. Add unlinked routes to prerender.routes. - Paths built at runtime (for example `/img/${name}.png`) do not get the base URL; prefix them with useRuntimeConfig().app.baseURL. ## FAQ **Should I use nuxt build or nuxt generate for thin.host?** nuxt generate. nuxt build produces a Node server, which thin.host does not run; generate writes static HTML for every route to .output/public. **Why does the preview URL load without styles or scripts?** The site is served under /s// until a custom domain points at it, so a build that references /assets/... asks the thin.host root for files that live under the sub-path. Build with the base path set to /s// for the preview, or map a domain (a free .thin.host subdomain works) and build with base /. **How do I redeploy?** Rebuild, zip the output folder again and POST it to /v1/websites//archive, or ask your agent to run update_website with sync=true. Sync removes files the new build no longer contains, so old hashed bundles do not pile up. **How large can a site be?** A single archive upload can be up to 30 MB. The local MCP server (uvx thinhost-mcp) reads the build folder directly and splits large sites across requests, up to 150 MB. ## Sources Commands and options checked against the official Nuxt (generate) docs on 2026-10-14: - [Nuxt: nuxt generate](https://nuxt.com/docs/4.x/api/commands/generate) - [Nuxt: Deployment, static hosting](https://nuxt.com/docs/4.x/getting-started/deployment#static-hosting) - [Nuxt configuration: app.baseURL](https://nuxt.com/docs/4.x/api/nuxt-config#baseurl) Other frameworks: [all deploy guides](https://thin.host/guides). Coming from another host? [Compare thin.host](https://thin.host/compare). --- Canonical page: https://thin.host/guides/deploy-nuxt ======================================================================== Source: https://thin.host/guides/deploy-gatsby ======================================================================== # Deploy Gatsby to thin.host Build a Gatsby site to public/ (with --prefix-paths for the preview) and deploy it to thin.host. thin.host serves the static files and gives you a live URL right away. Your agent can do every step for you through the thin.host MCP server, or you can run one `curl` command. ## At a glance | Step | Gatsby | |---|---| | Build command | `npm run build` | | Folder to deploy | `public/` | | Preview build (served at `/s/my-site/`) | `npx gatsby build --prefix-paths` | | Deploy | `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive` | | Live URL | `https://thin.host/s/my-site/`, or your own domain | ## Before you start - **Requires:** Node.js 18 or later. - **A thin.host account.** [Sign up](https://thin.host/signup), then create an API key under Settings (for `curl` and the local MCP server), or connect your agent with OAuth as shown in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## Create a project (skip if you have one) ```bash npm init gatsby ``` ## Set the base path Until a domain points at it, a thin.host site lives under a sub-path: `https://thin.host/s//`. Gatsby applies pathPrefix only when you build with --prefix-paths, so the plain build stays correct for a custom domain. ```javascript // gatsby-config.js module.exports = { pathPrefix: '/s/my-site', }; ``` | Where readers will look | Build with | |---|---| | The preview URL `https://thin.host/s/my-site/` | `npx gatsby build --prefix-paths` | | A custom domain, or a free `.thin.host` subdomain | `npm run build` (base path `/`) | Pick the slug (`my-site` here) before you build the preview, and pass the same slug when you deploy. ## Build ```bash npm run build ``` The finished site is in `public/`. That folder is what you deploy. ## Deploy from your agent (MCP) Connect thin.host to Claude Code, Claude Desktop, Cursor, VS Code, Windsurf, Codex or ChatGPT once ([setup for each client](https://thin.host/docs/quickstart-mcp)), then ask: > Build this Gatsby project for thin.host with the slug my-site and publish the public/ folder. With the local server (`uvx thinhost-mcp`) the agent runs the build and calls `publish_website` with the absolute path of `public/`; large builds are split across requests automatically. Later changes go out with `update_website` and `sync=true`, which also removes files the new build dropped. The hosted connector (`https://thin.host/mcp`, used by claude.ai and ChatGPT) cannot read your disk. From a coding agent it uploads with the REST call below; otherwise it publishes from a public link to a zip or HTML file with `publish_website_from_url`. ## Deploy with curl ```bash cd public && zip -r ../site.zip . && cd - curl -F file=@site.zip -F title="My Gatsby site" -F slug=my-site \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/archive ``` The JSON response includes `url`, the live address (`https://thin.host/s/my-site/`). To redeploy, upload the new zip to the site's archive endpoint; pages and assets missing from it are removed: ```bash curl -F file=@site.zip \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/my-site/archive ``` A single upload can be up to 30 MB. See the [REST API reference](https://thin.host/docs/api) for every field. ## Add a custom domain 1. Open the site in the [dashboard](https://thin.host/dashboard) and add your hostname under **Custom Domains**, for example `www.example.com`. A `.thin.host` subdomain is free and works immediately. 2. Create the DNS record the dashboard shows: a `CNAME` pointing at `cname.thin.host`. TLS is issued automatically once DNS resolves. 3. Rebuild with the base path `/` (`npm run build`) and redeploy. Pages on a custom domain get a canonical tag, a generated `robots.txt` and a `sitemap.xml`. ## Gatsby notes - Only Link, navigate and withPrefix() add the prefix. Hard-coded or break under the preview path. ## FAQ **Do Gatsby Functions or SSR pages work on thin.host?** No. thin.host serves the static files in public/. Pages using getServerData or Gatsby Functions need a server platform. **Why does the preview URL load without styles or scripts?** The site is served under /s// until a custom domain points at it, so a build that references /assets/... asks the thin.host root for files that live under the sub-path. Build with the base path set to /s// for the preview, or map a domain (a free .thin.host subdomain works) and build with base /. **How do I redeploy?** Rebuild, zip the output folder again and POST it to /v1/websites//archive, or ask your agent to run update_website with sync=true. Sync removes files the new build no longer contains, so old hashed bundles do not pile up. **How large can a site be?** A single archive upload can be up to 30 MB. The local MCP server (uvx thinhost-mcp) reads the build folder directly and splits large sites across requests, up to 150 MB. ## Sources Commands and options checked against the official Gatsby docs on 2026-10-14: - [Gatsby: Adding a path prefix](https://www.gatsbyjs.com/docs/how-to/previews-deploys-hosting/path-prefix/) - [Gatsby CLI reference](https://www.gatsbyjs.com/docs/reference/gatsby-cli/) Other frameworks: [all deploy guides](https://thin.host/guides). Coming from another host? [Compare thin.host](https://thin.host/compare). --- Canonical page: https://thin.host/guides/deploy-gatsby ======================================================================== Source: https://thin.host/guides/deploy-hugo ======================================================================== # Deploy Hugo to thin.host Build a Hugo site to public/ with the right baseURL and publish it to thin.host. thin.host serves the static files and gives you a live URL right away. Your agent can do every step for you through the thin.host MCP server, or you can run one `curl` command. ## At a glance | Step | Hugo | |---|---| | Build command | `hugo --cleanDestinationDir --minify` | | Folder to deploy | `public/` | | Preview build (served at `/s/my-site/`) | `hugo --cleanDestinationDir --minify --baseURL https://thin.host/s/my-site/` | | Deploy | `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive` | | Live URL | `https://thin.host/s/my-site/`, or your own domain | ## Before you start - **Requires:** A recent Hugo release (the quick start asks for v0.158.0 or later). - **A thin.host account.** [Sign up](https://thin.host/signup), then create an API key under Settings (for `curl` and the local MCP server), or connect your agent with OAuth as shown in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## Create a project (skip if you have one) ```bash hugo new project my-site ``` ## Set the base path Until a domain points at it, a thin.host site lives under a sub-path: `https://thin.host/s//`. Hugo builds links from baseURL, which must include the protocol and end with a slash. Keep your custom domain in the config and override it on the command line for the preview build. ```toml # hugo.toml baseURL = 'https://www.example.com/' ``` | Where readers will look | Build with | |---|---| | The preview URL `https://thin.host/s/my-site/` | `hugo --cleanDestinationDir --minify --baseURL https://thin.host/s/my-site/` | | A custom domain, or a free `.thin.host` subdomain | `hugo --cleanDestinationDir --minify` (base path `/`) | Pick the slug (`my-site` here) before you build the preview, and pass the same slug when you deploy. ## Build ```bash hugo --cleanDestinationDir --minify ``` The finished site is in `public/`. That folder is what you deploy. ## Deploy from your agent (MCP) Connect thin.host to Claude Code, Claude Desktop, Cursor, VS Code, Windsurf, Codex or ChatGPT once ([setup for each client](https://thin.host/docs/quickstart-mcp)), then ask: > Build this Hugo project for thin.host with the slug my-site and publish the public/ folder. With the local server (`uvx thinhost-mcp`) the agent runs the build and calls `publish_website` with the absolute path of `public/`; large builds are split across requests automatically. Later changes go out with `update_website` and `sync=true`, which also removes files the new build dropped. The hosted connector (`https://thin.host/mcp`, used by claude.ai and ChatGPT) cannot read your disk. From a coding agent it uploads with the REST call below; otherwise it publishes from a public link to a zip or HTML file with `publish_website_from_url`. ## Deploy with curl ```bash cd public && zip -r ../site.zip . && cd - curl -F file=@site.zip -F title="My Hugo site" -F slug=my-site \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/archive ``` The JSON response includes `url`, the live address (`https://thin.host/s/my-site/`). To redeploy, upload the new zip to the site's archive endpoint; pages and assets missing from it are removed: ```bash curl -F file=@site.zip \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/my-site/archive ``` A single upload can be up to 30 MB. See the [REST API reference](https://thin.host/docs/api) for every field. ## Add a custom domain 1. Open the site in the [dashboard](https://thin.host/dashboard) and add your hostname under **Custom Domains**, for example `www.example.com`. A `.thin.host` subdomain is free and works immediately. 2. Create the DNS record the dashboard shows: a `CNAME` pointing at `cname.thin.host`. TLS is issued automatically once DNS resolves. 3. Rebuild with the base path `/` (`hugo --cleanDestinationDir --minify`) and redeploy. Pages on a custom domain get a canonical tag, a generated `robots.txt` and a `sitemap.xml`. ## Hugo notes - In templates, call relURL and absURL without a leading slash: relURL "style.css" keeps the sub-path, relURL "/style.css" drops it. - Hugo does not empty public/ before building; --cleanDestinationDir keeps old pages out of the zip. ## FAQ **Do I need Hugo extended?** Only for the embedded LibSass compiler, which Hugo deprecated in v0.153.0. Dart Sass works with any edition. **Why does the preview URL load without styles or scripts?** The site is served under /s// until a custom domain points at it, so a build that references /assets/... asks the thin.host root for files that live under the sub-path. Build with the base path set to /s// for the preview, or map a domain (a free .thin.host subdomain works) and build with base /. **How do I redeploy?** Rebuild, zip the output folder again and POST it to /v1/websites//archive, or ask your agent to run update_website with sync=true. Sync removes files the new build no longer contains, so old hashed bundles do not pile up. **How large can a site be?** A single archive upload can be up to 30 MB. The local MCP server (uvx thinhost-mcp) reads the build folder directly and splits large sites across requests, up to 150 MB. ## Sources Commands and options checked against the official Hugo docs on 2026-10-14: - [Hugo: Host and deploy](https://gohugo.io/host-and-deploy/) - [Hugo: Configuration (baseURL)](https://gohugo.io/configuration/all/) - [Hugo: hugo command](https://gohugo.io/commands/hugo/) - [Hugo: relURL](https://gohugo.io/functions/urls/relurl/) Other frameworks: [all deploy guides](https://thin.host/guides). Coming from another host? [Compare thin.host](https://thin.host/compare). --- Canonical page: https://thin.host/guides/deploy-hugo ======================================================================== Source: https://thin.host/guides/deploy-jekyll ======================================================================== # Deploy Jekyll to thin.host Build a Jekyll site to _site/ with the right baseurl and deploy it to thin.host. thin.host serves the static files and gives you a live URL right away. Your agent can do every step for you through the thin.host MCP server, or you can run one `curl` command. ## At a glance | Step | Jekyll | |---|---| | Build command | `JEKYLL_ENV=production bundle exec jekyll build` | | Folder to deploy | `_site/` | | Preview build (served at `/s/my-site/`) | `JEKYLL_ENV=production bundle exec jekyll build --baseurl /s/my-site` | | Deploy | `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive` | | Live URL | `https://thin.host/s/my-site/`, or your own domain | ## Before you start - **Requires:** Ruby (with RubyGems, GCC and Make) and Bundler. - **A thin.host account.** [Sign up](https://thin.host/signup), then create an API key under Settings (for `curl` and the local MCP server), or connect your agent with OAuth as shown in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## Create a project (skip if you have one) ```bash gem install jekyll bundler && jekyll new my-site ``` ## Set the base path Until a domain points at it, a thin.host site lives under a sub-path: `https://thin.host/s//`. Jekyll prefixes links with baseurl when templates use the relative_url filter. Override it on the command line for the preview build; it is empty for a custom domain and never "/". ```yaml # _config.yml url: "https://www.example.com" baseurl: "" ``` | Where readers will look | Build with | |---|---| | The preview URL `https://thin.host/s/my-site/` | `JEKYLL_ENV=production bundle exec jekyll build --baseurl /s/my-site` | | A custom domain, or a free `.thin.host` subdomain | `JEKYLL_ENV=production bundle exec jekyll build` (base path `/`) | Pick the slug (`my-site` here) before you build the preview, and pass the same slug when you deploy. ## Build ```bash JEKYLL_ENV=production bundle exec jekyll build ``` The finished site is in `_site/`. That folder is what you deploy. ## Deploy from your agent (MCP) Connect thin.host to Claude Code, Claude Desktop, Cursor, VS Code, Windsurf, Codex or ChatGPT once ([setup for each client](https://thin.host/docs/quickstart-mcp)), then ask: > Build this Jekyll project for thin.host with the slug my-site and publish the _site/ folder. With the local server (`uvx thinhost-mcp`) the agent runs the build and calls `publish_website` with the absolute path of `_site/`; large builds are split across requests automatically. Later changes go out with `update_website` and `sync=true`, which also removes files the new build dropped. The hosted connector (`https://thin.host/mcp`, used by claude.ai and ChatGPT) cannot read your disk. From a coding agent it uploads with the REST call below; otherwise it publishes from a public link to a zip or HTML file with `publish_website_from_url`. ## Deploy with curl ```bash cd _site && zip -r ../site.zip . && cd - curl -F file=@site.zip -F title="My Jekyll site" -F slug=my-site \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/archive ``` The JSON response includes `url`, the live address (`https://thin.host/s/my-site/`). To redeploy, upload the new zip to the site's archive endpoint; pages and assets missing from it are removed: ```bash curl -F file=@site.zip \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/my-site/archive ``` A single upload can be up to 30 MB. See the [REST API reference](https://thin.host/docs/api) for every field. ## Add a custom domain 1. Open the site in the [dashboard](https://thin.host/dashboard) and add your hostname under **Custom Domains**, for example `www.example.com`. A `.thin.host` subdomain is free and works immediately. 2. Create the DNS record the dashboard shows: a `CNAME` pointing at `cname.thin.host`. TLS is issued automatically once DNS resolves. 3. Rebuild with the base path `/` (`JEKYLL_ENV=production bundle exec jekyll build`) and redeploy. Pages on a custom domain get a canonical tag, a generated `robots.txt` and a `sitemap.xml`. ## Jekyll notes - Write internal links as {{ '/about/' | relative_url }}; hard-coded /paths ignore baseurl. - GitHub Pages builds Jekyll for you; on thin.host you upload the built _site/ folder. ## FAQ **Can I keep my GitHub Pages Jekyll site and also deploy it to thin.host?** Yes. Build locally or in CI with bundle exec jekyll build and upload _site/. GitHub Pages' plugin allowlist does not apply, so any plugin your Gemfile installs works. **Why does the preview URL load without styles or scripts?** The site is served under /s// until a custom domain points at it, so a build that references /assets/... asks the thin.host root for files that live under the sub-path. Build with the base path set to /s// for the preview, or map a domain (a free .thin.host subdomain works) and build with base /. **How do I redeploy?** Rebuild, zip the output folder again and POST it to /v1/websites//archive, or ask your agent to run update_website with sync=true. Sync removes files the new build no longer contains, so old hashed bundles do not pile up. **How large can a site be?** A single archive upload can be up to 30 MB. The local MCP server (uvx thinhost-mcp) reads the build folder directly and splits large sites across requests, up to 150 MB. ## Sources Commands and options checked against the official Jekyll docs on 2026-10-14: - [Jekyll: Deployment](https://jekyllrb.com/docs/step-by-step/10-deployment/) - [Jekyll: Configuration options (baseurl)](https://jekyllrb.com/docs/configuration/options/) - [Jekyll: Liquid filters (relative_url)](https://jekyllrb.com/docs/liquid/filters/) Other frameworks: [all deploy guides](https://thin.host/guides). Coming from another host? [Compare thin.host](https://thin.host/compare). --- Canonical page: https://thin.host/guides/deploy-jekyll ======================================================================== Source: https://thin.host/guides/deploy-eleventy ======================================================================== # Deploy Eleventy (11ty) to thin.host Build an Eleventy site to _site/ with a path prefix and publish it to thin.host. thin.host serves the static files and gives you a live URL right away. Your agent can do every step for you through the thin.host MCP server, or you can run one `curl` command. ## At a glance | Step | Eleventy (11ty) | |---|---| | Build command | `npx @11ty/eleventy` | | Folder to deploy | `_site/` | | Preview build (served at `/s/my-site/`) | `npx @11ty/eleventy --pathprefix=/s/my-site/` | | Deploy | `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive` | | Live URL | `https://thin.host/s/my-site/`, or your own domain | ## Before you start - **Requires:** Node.js 18 or later. - **A thin.host account.** [Sign up](https://thin.host/signup), then create an API key under Settings (for `curl` and the local MCP server), or connect your agent with OAuth as shown in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## Create a project (skip if you have one) ```bash npm init -y && npm install @11ty/eleventy ``` ## Set the base path Until a domain points at it, a thin.host site lives under a sub-path: `https://thin.host/s//`. Eleventy's path prefix is applied by the bundled HTML base plugin, which rewrites root-relative URLs in the HTML it writes. Add the plugin once, then pass the prefix on the command line for the preview build. ```javascript // eleventy.config.js import { HtmlBasePlugin } from '@11ty/eleventy'; export default function (eleventyConfig) { eleventyConfig.addPlugin(HtmlBasePlugin); } ``` | Where readers will look | Build with | |---|---| | The preview URL `https://thin.host/s/my-site/` | `npx @11ty/eleventy --pathprefix=/s/my-site/` | | A custom domain, or a free `.thin.host` subdomain | `npx @11ty/eleventy` (base path `/`) | Pick the slug (`my-site` here) before you build the preview, and pass the same slug when you deploy. ## Build ```bash npx @11ty/eleventy ``` The finished site is in `_site/`. That folder is what you deploy. ## Deploy from your agent (MCP) Connect thin.host to Claude Code, Claude Desktop, Cursor, VS Code, Windsurf, Codex or ChatGPT once ([setup for each client](https://thin.host/docs/quickstart-mcp)), then ask: > Build this Eleventy (11ty) project for thin.host with the slug my-site and publish the _site/ folder. With the local server (`uvx thinhost-mcp`) the agent runs the build and calls `publish_website` with the absolute path of `_site/`; large builds are split across requests automatically. Later changes go out with `update_website` and `sync=true`, which also removes files the new build dropped. The hosted connector (`https://thin.host/mcp`, used by claude.ai and ChatGPT) cannot read your disk. From a coding agent it uploads with the REST call below; otherwise it publishes from a public link to a zip or HTML file with `publish_website_from_url`. ## Deploy with curl ```bash cd _site && zip -r ../site.zip . && cd - curl -F file=@site.zip -F title="My Eleventy (11ty) site" -F slug=my-site \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/archive ``` The JSON response includes `url`, the live address (`https://thin.host/s/my-site/`). To redeploy, upload the new zip to the site's archive endpoint; pages and assets missing from it are removed: ```bash curl -F file=@site.zip \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/my-site/archive ``` A single upload can be up to 30 MB. See the [REST API reference](https://thin.host/docs/api) for every field. ## Add a custom domain 1. Open the site in the [dashboard](https://thin.host/dashboard) and add your hostname under **Custom Domains**, for example `www.example.com`. A `.thin.host` subdomain is free and works immediately. 2. Create the DNS record the dashboard shows: a `CNAME` pointing at `cname.thin.host`. TLS is issued automatically once DNS resolves. 3. Rebuild with the base path `/` (`npx @11ty/eleventy`) and redeploy. Pages on a custom domain get a canonical tag, a generated `robots.txt` and a `sitemap.xml`. ## Eleventy (11ty) notes - The plugin rewrites URLs in .html output only. URLs inside CSS or JavaScript files are not prefixed; use the htmlBaseUrl filter for unusual spots. ## FAQ **Where does Eleventy put the built site?** In _site/ by default. Change it with --output or the dir.output option, and zip that folder. **Why does the preview URL load without styles or scripts?** The site is served under /s// until a custom domain points at it, so a build that references /assets/... asks the thin.host root for files that live under the sub-path. Build with the base path set to /s// for the preview, or map a domain (a free .thin.host subdomain works) and build with base /. **How do I redeploy?** Rebuild, zip the output folder again and POST it to /v1/websites//archive, or ask your agent to run update_website with sync=true. Sync removes files the new build no longer contains, so old hashed bundles do not pile up. **How large can a site be?** A single archive upload can be up to 30 MB. The local MCP server (uvx thinhost-mcp) reads the build folder directly and splits large sites across requests, up to 150 MB. ## Sources Commands and options checked against the official Eleventy (11ty) docs on 2026-10-14: - [Eleventy: Deploy to a subdirectory with a path prefix](https://www.11ty.dev/docs/config/#deploy-to-a-subdirectory-with-a-path-prefix) - [Eleventy: HTML plugin](https://www.11ty.dev/docs/plugins/html-base/) - [Eleventy: Get started](https://www.11ty.dev/docs/get-started/) Other frameworks: [all deploy guides](https://thin.host/guides). Coming from another host? [Compare thin.host](https://thin.host/compare). --- Canonical page: https://thin.host/guides/deploy-eleventy ======================================================================== Source: https://thin.host/guides/deploy-mkdocs ======================================================================== # Deploy MkDocs to thin.host Build MkDocs (or Material for MkDocs) to site/ and deploy the docs to thin.host. thin.host serves the static files and gives you a live URL right away. Your agent can do every step for you through the thin.host MCP server, or you can run one `curl` command. ## At a glance | Step | MkDocs | |---|---| | Build command | `mkdocs build` | | Folder to deploy | `site/` | | Preview build (served at `/s/my-site/`) | `SITE_URL=https://thin.host/s/my-site/ mkdocs build` | | Deploy | `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive` | | Live URL | `https://thin.host/s/my-site/`, or your own domain | ## Before you start - **Requires:** Python 3 and pip. - **A thin.host account.** [Sign up](https://thin.host/signup), then create an API key under Settings (for `curl` and the local MCP server), or connect your agent with OAuth as shown in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## Create a project (skip if you have one) ```bash pip install mkdocs && mkdocs new my-docs ``` ## Set the base path Until a domain points at it, a thin.host site lives under a sub-path: `https://thin.host/s//`. MkDocs writes relative links between pages, but site_url must name the real address, sub-path included: it drives canonical links, the sitemap and the 404 page. Read it from an environment variable so one config serves both builds. ```yaml # mkdocs.yml site_name: My Docs site_url: !ENV [SITE_URL, 'https://docs.example.com/'] ``` | Where readers will look | Build with | |---|---| | The preview URL `https://thin.host/s/my-site/` | `SITE_URL=https://thin.host/s/my-site/ mkdocs build` | | A custom domain, or a free `.thin.host` subdomain | `mkdocs build` (base path `/`) | Pick the slug (`my-site` here) before you build the preview, and pass the same slug when you deploy. ## Build ```bash mkdocs build ``` The finished site is in `site/`. That folder is what you deploy. ## Deploy from your agent (MCP) Connect thin.host to Claude Code, Claude Desktop, Cursor, VS Code, Windsurf, Codex or ChatGPT once ([setup for each client](https://thin.host/docs/quickstart-mcp)), then ask: > Build this MkDocs project for thin.host with the slug my-site and publish the site/ folder. With the local server (`uvx thinhost-mcp`) the agent runs the build and calls `publish_website` with the absolute path of `site/`; large builds are split across requests automatically. Later changes go out with `update_website` and `sync=true`, which also removes files the new build dropped. The hosted connector (`https://thin.host/mcp`, used by claude.ai and ChatGPT) cannot read your disk. From a coding agent it uploads with the REST call below; otherwise it publishes from a public link to a zip or HTML file with `publish_website_from_url`. ## Deploy with curl ```bash cd site && zip -r ../site.zip . && cd - curl -F file=@site.zip -F title="My MkDocs site" -F slug=my-site \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/archive ``` The JSON response includes `url`, the live address (`https://thin.host/s/my-site/`). To redeploy, upload the new zip to the site's archive endpoint; pages and assets missing from it are removed: ```bash curl -F file=@site.zip \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/my-site/archive ``` A single upload can be up to 30 MB. See the [REST API reference](https://thin.host/docs/api) for every field. ## Add a custom domain 1. Open the site in the [dashboard](https://thin.host/dashboard) and add your hostname under **Custom Domains**, for example `www.example.com`. A `.thin.host` subdomain is free and works immediately. 2. Create the DNS record the dashboard shows: a `CNAME` pointing at `cname.thin.host`. TLS is issued automatically once DNS resolves. 3. Rebuild with the base path `/` (`mkdocs build`) and redeploy. Pages on a custom domain get a canonical tag, a generated `robots.txt` and a `sitemap.xml`. ## MkDocs notes - Material for MkDocs builds the same way (pip install mkdocs-material, theme name material) and needs site_url for instant navigation. Material is in maintenance mode and does not support MkDocs 2.0, so pin mkdocs below 2. ## FAQ **Does mkdocs gh-deploy work with thin.host?** No, gh-deploy pushes to a GitHub Pages branch. Run mkdocs build and upload site/ instead. **Why does the preview URL load without styles or scripts?** The site is served under /s// until a custom domain points at it, so a build that references /assets/... asks the thin.host root for files that live under the sub-path. Build with the base path set to /s// for the preview, or map a domain (a free .thin.host subdomain works) and build with base /. **How do I redeploy?** Rebuild, zip the output folder again and POST it to /v1/websites//archive, or ask your agent to run update_website with sync=true. Sync removes files the new build no longer contains, so old hashed bundles do not pile up. **How large can a site be?** A single archive upload can be up to 30 MB. The local MCP server (uvx thinhost-mcp) reads the build folder directly and splits large sites across requests, up to 150 MB. ## Sources Commands and options checked against the official MkDocs docs on 2026-10-14: - [MkDocs: Getting started](https://www.mkdocs.org/getting-started/) - [MkDocs configuration (site_url)](https://www.mkdocs.org/user-guide/configuration/) - [Material for MkDocs: Creating your site](https://squidfunk.github.io/mkdocs-material/creating-your-site/) Other frameworks: [all deploy guides](https://thin.host/guides). Coming from another host? [Compare thin.host](https://thin.host/compare). --- Canonical page: https://thin.host/guides/deploy-mkdocs ======================================================================== Source: https://thin.host/guides/deploy-vitepress ======================================================================== # Deploy VitePress to thin.host Build a VitePress docs site to docs/.vitepress/dist and publish it to thin.host. thin.host serves the static files and gives you a live URL right away. Your agent can do every step for you through the thin.host MCP server, or you can run one `curl` command. ## At a glance | Step | VitePress | |---|---| | Build command | `npm run docs:build` | | Folder to deploy | `docs/.vitepress/dist/` | | Preview build (served at `/s/my-site/`) | `BASE_PATH=/s/my-site/ npm run docs:build` | | Deploy | `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive` | | Live URL | `https://thin.host/s/my-site/`, or your own domain | ## Before you start - **Requires:** Node.js 18 or later (VitePress 1.x). - **A thin.host account.** [Sign up](https://thin.host/signup), then create an API key under Settings (for `curl` and the local MCP server), or connect your agent with OAuth as shown in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## Create a project (skip if you have one) ```bash npm add -D vitepress && npx vitepress init ``` ## Set the base path Until a domain points at it, a thin.host site lives under a sub-path: `https://thin.host/s//`. The base option must start and end with a slash; VitePress applies it to links and Markdown asset references. Paths built in your own theme components need withBase(). ```typescript // docs/.vitepress/config.mts import { defineConfig } from 'vitepress'; export default defineConfig({ base: process.env.BASE_PATH ?? '/', }); ``` | Where readers will look | Build with | |---|---| | The preview URL `https://thin.host/s/my-site/` | `BASE_PATH=/s/my-site/ npm run docs:build` | | A custom domain, or a free `.thin.host` subdomain | `npm run docs:build` (base path `/`) | Pick the slug (`my-site` here) before you build the preview, and pass the same slug when you deploy. ## Build ```bash npm run docs:build ``` The finished site is in `docs/.vitepress/dist/`. That folder is what you deploy. ## Deploy from your agent (MCP) Connect thin.host to Claude Code, Claude Desktop, Cursor, VS Code, Windsurf, Codex or ChatGPT once ([setup for each client](https://thin.host/docs/quickstart-mcp)), then ask: > Build this VitePress project for thin.host with the slug my-site and publish the docs/.vitepress/dist/ folder. With the local server (`uvx thinhost-mcp`) the agent runs the build and calls `publish_website` with the absolute path of `docs/.vitepress/dist/`; large builds are split across requests automatically. Later changes go out with `update_website` and `sync=true`, which also removes files the new build dropped. The hosted connector (`https://thin.host/mcp`, used by claude.ai and ChatGPT) cannot read your disk. From a coding agent it uploads with the REST call below; otherwise it publishes from a public link to a zip or HTML file with `publish_website_from_url`. ## Deploy with curl ```bash cd docs/.vitepress/dist && zip -r ../../../site.zip . && cd - curl -F file=@site.zip -F title="My VitePress site" -F slug=my-site \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/archive ``` The JSON response includes `url`, the live address (`https://thin.host/s/my-site/`). To redeploy, upload the new zip to the site's archive endpoint; pages and assets missing from it are removed: ```bash curl -F file=@site.zip \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/my-site/archive ``` A single upload can be up to 30 MB. See the [REST API reference](https://thin.host/docs/api) for every field. ## Add a custom domain 1. Open the site in the [dashboard](https://thin.host/dashboard) and add your hostname under **Custom Domains**, for example `www.example.com`. A `.thin.host` subdomain is free and works immediately. 2. Create the DNS record the dashboard shows: a `CNAME` pointing at `cname.thin.host`. TLS is issued automatically once DNS resolves. 3. Rebuild with the base path `/` (`npm run docs:build`) and redeploy. Pages on a custom domain get a canonical tag, a generated `robots.txt` and a `sitemap.xml`. ## VitePress notes - The docs:build script comes from vitepress init and runs vitepress build docs. If your source folder is not docs/, the output is /.vitepress/dist. ## FAQ **Do clean URLs work?** Yes. thin.host serves about.html at /about, so cleanUrls: true works without extra config. **Why does the preview URL load without styles or scripts?** The site is served under /s// until a custom domain points at it, so a build that references /assets/... asks the thin.host root for files that live under the sub-path. Build with the base path set to /s// for the preview, or map a domain (a free .thin.host subdomain works) and build with base /. **How do I redeploy?** Rebuild, zip the output folder again and POST it to /v1/websites//archive, or ask your agent to run update_website with sync=true. Sync removes files the new build no longer contains, so old hashed bundles do not pile up. **How large can a site be?** A single archive upload can be up to 30 MB. The local MCP server (uvx thinhost-mcp) reads the build folder directly and splits large sites across requests, up to 150 MB. ## Sources Commands and options checked against the official VitePress docs on 2026-10-14: - [VitePress: Deploy your VitePress site](https://vitepress.dev/guide/deploy) - [VitePress site config: base](https://vitepress.dev/reference/site-config#base) - [VitePress: Getting started](https://vitepress.dev/guide/getting-started) Other frameworks: [all deploy guides](https://thin.host/guides). Coming from another host? [Compare thin.host](https://thin.host/compare). --- Canonical page: https://thin.host/guides/deploy-vitepress ======================================================================== Source: https://thin.host/guides/deploy-docusaurus ======================================================================== # Deploy Docusaurus to thin.host Build Docusaurus to build/ and deploy it from Claude Code with one tool call or one curl. thin.host serves the static files and gives you a live URL right away. Your agent can do every step for you through the thin.host MCP server, or you can run one `curl` command. ## At a glance | Step | Docusaurus | |---|---| | Build command | `npm run build` | | Folder to deploy | `build/` | | Preview build (served at `/s/my-site/`) | `DOCUSAURUS_BASE_URL=/s/my-site/ npm run build` | | Deploy | `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive` | | Live URL | `https://thin.host/s/my-site/`, or your own domain | ## Before you start - **Requires:** Node.js 20 or later. - **A thin.host account.** [Sign up](https://thin.host/signup), then create an API key under Settings (for `curl` and the local MCP server), or connect your agent with OAuth as shown in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## Create a project (skip if you have one) ```bash npx create-docusaurus@latest my-docs classic ``` ## Set the base path Until a domain points at it, a thin.host site lives under a sub-path: `https://thin.host/s//`. Docusaurus bakes baseUrl into every asset URL, and url plus baseUrl are both required. The publish tools detect Docusaurus and warn when the baseUrl will not resolve at the returned URL. ```typescript // docusaurus.config.ts url: 'https://docs.example.com', baseUrl: process.env.DOCUSAURUS_BASE_URL ?? '/', ``` | Where readers will look | Build with | |---|---| | The preview URL `https://thin.host/s/my-site/` | `DOCUSAURUS_BASE_URL=/s/my-site/ npm run build` | | A custom domain, or a free `.thin.host` subdomain | `npm run build` (base path `/`) | Pick the slug (`my-site` here) before you build the preview, and pass the same slug when you deploy. ## Build ```bash npm run build ``` The finished site is in `build/`. That folder is what you deploy. ## Deploy from your agent (MCP) Connect thin.host to Claude Code, Claude Desktop, Cursor, VS Code, Windsurf, Codex or ChatGPT once ([setup for each client](https://thin.host/docs/quickstart-mcp)), then ask: > Build this Docusaurus project for thin.host with the slug my-site and publish the build/ folder. With the local server (`uvx thinhost-mcp`) the agent runs the build and calls `publish_website` with the absolute path of `build/`; large builds are split across requests automatically. Later changes go out with `update_website` and `sync=true`, which also removes files the new build dropped. The hosted connector (`https://thin.host/mcp`, used by claude.ai and ChatGPT) cannot read your disk. From a coding agent it uploads with the REST call below; otherwise it publishes from a public link to a zip or HTML file with `publish_website_from_url`. ## Deploy with curl ```bash cd build && zip -r ../site.zip . && cd - curl -F file=@site.zip -F title="My Docusaurus site" -F slug=my-site \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/archive ``` The JSON response includes `url`, the live address (`https://thin.host/s/my-site/`). To redeploy, upload the new zip to the site's archive endpoint; pages and assets missing from it are removed: ```bash curl -F file=@site.zip \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/my-site/archive ``` A single upload can be up to 30 MB. See the [REST API reference](https://thin.host/docs/api) for every field. ## Add a custom domain 1. Open the site in the [dashboard](https://thin.host/dashboard) and add your hostname under **Custom Domains**, for example `www.example.com`. A `.thin.host` subdomain is free and works immediately. 2. Create the DNS record the dashboard shows: a `CNAME` pointing at `cname.thin.host`. TLS is issued automatically once DNS resolves. 3. Rebuild with the base path `/` (`npm run build`) and redeploy. Pages on a custom domain get a canonical tag, a generated `robots.txt` and a `sitemap.xml`. ## Docusaurus notes - In JSX, use useBaseUrl() for static files; a literal '/img/x.png' breaks under a baseUrl. - Docusaurus has a dedicated walkthrough, including the Claude Code skill. More on Docusaurus: [Docusaurus hosting walkthrough](https://thin.host/use-cases/docusaurus) · [Docusaurus & static builds (docs)](https://thin.host/docs/static-sites) ## FAQ **Is there a Claude Code skill for Docusaurus deploys?** Yes. Install thin-host-docusaurus from https://thin.host/skills/thin-host-docusaurus/SKILL.md (or the thin.host Claude Code plugin) and say "deploy my docs". **Why does the preview URL load without styles or scripts?** The site is served under /s// until a custom domain points at it, so a build that references /assets/... asks the thin.host root for files that live under the sub-path. Build with the base path set to /s// for the preview, or map a domain (a free .thin.host subdomain works) and build with base /. **How do I redeploy?** Rebuild, zip the output folder again and POST it to /v1/websites//archive, or ask your agent to run update_website with sync=true. Sync removes files the new build no longer contains, so old hashed bundles do not pile up. **How large can a site be?** A single archive upload can be up to 30 MB. The local MCP server (uvx thinhost-mcp) reads the build folder directly and splits large sites across requests, up to 150 MB. ## Sources Commands and options checked against the official Docusaurus docs on 2026-10-14: - [Docusaurus: Deployment](https://docusaurus.io/docs/deployment) - [Docusaurus config: baseUrl](https://docusaurus.io/docs/api/docusaurus-config) - [Docusaurus: Static assets](https://docusaurus.io/docs/static-assets) Other frameworks: [all deploy guides](https://thin.host/guides). Coming from another host? [Compare thin.host](https://thin.host/compare). --- Canonical page: https://thin.host/guides/deploy-docusaurus ======================================================================== Source: https://thin.host/guides/deploy-html ======================================================================== # Deploy plain HTML to thin.host Publish a folder of hand-written HTML, CSS and JS (or a single index.html) to thin.host. thin.host serves the static files and gives you a live URL right away. Your agent can do every step for you through the thin.host MCP server, or you can run one `curl` command. ## At a glance | Step | plain HTML | |---|---| | Folder to deploy | the folder that holds `index.html` | | Deploy | `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive` | | Live URL | `https://thin.host/s/my-site/`, or your own domain | ## Before you start - **Requires:** Nothing to install. - **A thin.host account.** [Sign up](https://thin.host/signup), then create an API key under Settings (for `curl` and the local MCP server), or connect your agent with OAuth as shown in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## Check your links Until a domain points at it, a thin.host site lives under a sub-path: `https://thin.host/s//`. Use relative paths (style.css, img/logo.png, about.html). Root-absolute paths such as /style.css only resolve once a custom domain points at the site. ```html About ``` ## Deploy from your agent (MCP) Connect thin.host to Claude Code, Claude Desktop, Cursor, VS Code, Windsurf, Codex or ChatGPT once ([setup for each client](https://thin.host/docs/quickstart-mcp)), then ask: > Save this page as index.html and publish it to thin.host with the slug my-site. With the local server (`uvx thinhost-mcp`) the agent writes the file and calls `publish_website` with its path. Ask for changes in the same conversation and it pushes them with `update_website`. The hosted connector (`https://thin.host/mcp`, used by claude.ai and ChatGPT) cannot read your disk. From a coding agent it uploads with the REST call below; otherwise it publishes from a public link to a zip or HTML file with `publish_website_from_url`. ## Deploy with curl ```bash zip -r site.zip . -x '.*' curl -F file=@site.zip -F title="My plain HTML site" -F slug=my-site \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/archive ``` The JSON response includes `url`, the live address (`https://thin.host/s/my-site/`). To redeploy, upload the new zip to the site's archive endpoint; pages and assets missing from it are removed: ```bash curl -F file=@site.zip \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/my-site/archive ``` A single upload can be up to 30 MB. See the [REST API reference](https://thin.host/docs/api) for every field. ## Add a custom domain 1. Open the site in the [dashboard](https://thin.host/dashboard) and add your hostname under **Custom Domains**, for example `www.example.com`. A `.thin.host` subdomain is free and works immediately. 2. Create the DNS record the dashboard shows: a `CNAME` pointing at `cname.thin.host`. TLS is issued automatically once DNS resolves. Pages on a custom domain get a canonical tag, a generated `robots.txt` and a `sitemap.xml`. ## Plain HTML notes - index.html becomes /, about.html becomes /about, blog/index.html becomes /blog, and 404.html becomes the site's not-found page. - A single file can be uploaded as-is: curl -F file=@index.html …/v1/websites/archive. ## FAQ **Can I upload without the command line?** Yes. Sign in and drop the files (or a zip) on the upload page at thin.host; you get the same live URL. **How large can a site be?** A single archive upload can be up to 30 MB. The local MCP server (uvx thinhost-mcp) reads the build folder directly and splits large sites across requests, up to 150 MB. Other frameworks: [all deploy guides](https://thin.host/guides). Coming from another host? [Compare thin.host](https://thin.host/compare). --- Canonical page: https://thin.host/guides/deploy-html ======================================================================== Source: https://thin.host/guides/deploy-ai-chat-html ======================================================================== # Deploy an HTML page from a Claude or ChatGPT chat to thin.host Take an HTML page that Claude or ChatGPT wrote in a chat and get a live, shareable URL for it. thin.host serves the static files and gives you a live URL right away. Your agent can do every step for you through the thin.host MCP server, or you can run one `curl` command. ## At a glance | Step | an HTML page from a Claude or ChatGPT chat | |---|---| | Folder to deploy | the folder that holds `index.html` | | Deploy | `curl -F file=@index.html -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive` | | Live URL | `https://thin.host/s/my-site/`, or your own domain | ## Before you start - **Requires:** The HTML from the chat (a Claude artifact or a ChatGPT canvas or code block). - **A thin.host account.** [Sign up](https://thin.host/signup), then create an API key under Settings (for `curl` and the local MCP server), or connect your agent with OAuth as shown in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## Check your links Until a domain points at it, a thin.host site lives under a sub-path: `https://thin.host/s//`. Chat-generated pages are usually a single self-contained file. Save it as index.html; if it loads images or scripts from relative paths, put those files next to it. ```html ``` ## Deploy from your agent (MCP) Connect thin.host to Claude Code, Claude Desktop, Cursor, VS Code, Windsurf, Codex or ChatGPT once ([setup for each client](https://thin.host/docs/quickstart-mcp)), then ask: > Save this page as index.html and publish it to thin.host with the slug my-site. With the local server (`uvx thinhost-mcp`) the agent writes the file and calls `publish_website` with its path. Ask for changes in the same conversation and it pushes them with `update_website`. The hosted connector (`https://thin.host/mcp`, used by claude.ai and ChatGPT) cannot read your disk. From a coding agent it uploads with the REST call below; otherwise it publishes from a public link to a zip or HTML file with `publish_website_from_url`. ## Deploy with curl ```bash curl -F file=@index.html -F title="My page" -F slug=my-site \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/archive ``` The JSON response includes `url`, the live address (`https://thin.host/s/my-site/`). To redeploy, upload the new file to the site's archive endpoint; pages and assets missing from it are removed: ```bash curl -F file=@index.html \ -H "Authorization: Bearer $THINHOST_API_KEY" \ https://thin.host/v1/websites/my-site/archive ``` A single upload can be up to 30 MB. See the [REST API reference](https://thin.host/docs/api) for every field. ## Add a custom domain 1. Open the site in the [dashboard](https://thin.host/dashboard) and add your hostname under **Custom Domains**, for example `www.example.com`. A `.thin.host` subdomain is free and works immediately. 2. Create the DNS record the dashboard shows: a `CNAME` pointing at `cname.thin.host`. TLS is issued automatically once DNS resolves. Pages on a custom domain get a canonical tag, a generated `robots.txt` and a `sitemap.xml`. ## An HTML page from a Claude or ChatGPT chat notes - In Claude, copy the artifact's code (or download it). In ChatGPT, copy the code block or the canvas contents. - Coding agents (Claude Code, Codex, Cursor) can write the file and publish it in one step: ask them to save the page as index.html and publish it to thin.host. ## FAQ **Can Claude publish the page straight from claude.ai?** The hosted thin.host connector publishes from a URL (publish_website_from_url), so the page needs to be reachable at a public link first. Otherwise save it as index.html and upload it with the dashboard or curl. **Will the page keep working after the chat ends?** Yes. The site stays live until you delete it, and you can edit the copy in place from the dashboard. **How large can a site be?** A single archive upload can be up to 30 MB. The local MCP server (uvx thinhost-mcp) reads the build folder directly and splits large sites across requests, up to 150 MB. Other frameworks: [all deploy guides](https://thin.host/guides). Coming from another host? [Compare thin.host](https://thin.host/compare). --- Canonical page: https://thin.host/guides/deploy-ai-chat-html ======================================================================== Source: https://thin.host/compare ======================================================================== # thin.host compared with other static hosts thin.host is built for sites that an AI agent creates and deploys: an MCP server and a one-call REST upload give the agent a live URL, and custom domains and transactional email come from the same account. The hosts below are all good at what they do. These pages say plainly where each one is the better fit and how to move a site over. Facts about other services are as of October 2026 and link to the vendor's own pages. | Compared with | Their free tier | Official MCP server | |---|---|---| | [thin.host vs Netlify](https://thin.host/compare/netlify) | 300 credits a month, spent on production deploys, bandwidth and requests; projects pause when they run out. Deploy previews and form submissions use no credits. | Official Netlify MCP server (remote or npm), with guides for Claude Code, Codex, Cursor and VS Code, plus Claude and ChatGPT apps. | | [thin.host vs Vercel](https://thin.host/compare/vercel) | Hobby: 100 GB data transfer and 1,000,000 CDN requests a month, for non-commercial, personal use only. | Official Vercel MCP server (OAuth) for Claude Code, claude.ai, ChatGPT, Codex, Cursor and VS Code; it can deploy. | | [thin.host vs GitHub Pages](https://thin.host/compare/github-pages) | Free for public repositories on GitHub Free: sites up to 1 GB, a soft 100 GB/month bandwidth limit, and not meant as free hosting for an online business, e-commerce or SaaS. | No Pages-specific MCP server. GitHub's official MCP server works with repositories and Actions. | | [thin.host vs Cloudflare Pages](https://thin.host/compare/cloudflare-pages) | Unlimited static-asset requests, 500 builds a month, 100 projects and 20,000 files per site. | Official Cloudflare MCP servers (API and docs), and temporary deploys for agents with wrangler deploy --temporary. | | [thin.host vs Surge](https://thin.host/compare/surge) | Unlimited publishing with no project caps, custom domains and basic SSL; no bandwidth figure is published. | No official MCP server found. | | [thin.host vs Neocities](https://thin.host/compare/neocities) | 1 GB storage, 200 GB bandwidth and one site on a neocities.org subdomain, with restricted file types and no ads. | No official MCP server found. | | [thin.host vs tiiny.host](https://thin.host/compare/tiiny-host) | 1 active project, 3 MB uploads, 5,000 visits and 5 GB bandwidth a month, with a tiiny.host banner and no custom domain. | Official MCP server (publish, update and delete projects) on Solo and above, authenticated with an API key. | | [thin.host vs Render](https://thin.host/compare/render) | Static sites are free to deploy; the Hobby workspace includes 5 GB bandwidth a month (then $0.15/GB), 500 build minutes and 2 custom domains. | Official Render MCP server (it can create static sites and trigger deploys) and plugins for Claude Code, Codex and Cursor. | ## What thin.host offers - **Free tier:** Free account: hosted sites at thin.host/s// and free .thin.host subdomains. The domain API's free platform tier covers 3 domains. - **Agent support:** Official hosted MCP server (thin.host/mcp, OAuth 2.1) plus a local server (uvx thinhost-mcp), a Claude Code plugin and a REST API. - **Custom domains:** Yes, several per site, added from the dashboard with a CNAME to cname.thin.host. - **Email:** Yes: transactional email over MCP, REST or SMTP from a verified sending domain (access is approved per account). - **Limits:** Static files only, plus built-in form capture and password or email gating. No serverless functions. --- Canonical page: https://thin.host/compare ======================================================================== Source: https://thin.host/compare/netlify ======================================================================== # thin.host vs Netlify Netlify is a mature web platform: Git-based deploys with previews, serverless and edge functions, forms and storage. thin.host is a smaller, static-only host built around agent deploys, where one MCP tool call or one zip upload returns a live URL, and custom domains and transactional email live in the same account. > Facts about Netlify are taken from Netlify's own pricing and documentation pages as of October 2026 (checked 2026-10-14) and listed under Sources. Plans change; check the vendor's page before you decide. ## Side by side | | thin.host | Netlify | |---|---|---| | **Free tier** | Free account: hosted sites at thin.host/s// and free .thin.host subdomains. The domain API's free platform tier covers 3 domains. | 300 credits a month, spent on production deploys, bandwidth and requests; projects pause when they run out. Deploy previews and form submissions use no credits. | | **Cheapest paid plan** | Domain API tiers: Indie $29/month, Platform $199/month. End users pay $8/month per domain provisioned through the claim flow. | Personal, $9/month (1,000 credits). Pro is $20/month (3,000 credits). | | **Custom domains** | Yes, several per site, added from the dashboard with a CNAME to cname.thin.host. | Yes, on the free plan. | | **HTTPS** | Automatic for custom domains and thin.host subdomains. | Automatic, included with custom domains on the free plan. | | **AI agent / MCP support** | Official hosted MCP server (thin.host/mcp, OAuth 2.1) plus a local server (uvx thinhost-mcp), a Claude Code plugin and a REST API. | Official Netlify MCP server (remote or npm), with guides for Claude Code, Codex, Cursor and VS Code, plus Claude and ChatGPT apps. | | **Transactional email** | Yes: transactional email over MCP, REST or SMTP from a verified sending domain (access is approved per account). | No sending service of its own. The Email Integration relays through your own Mailgun, Postmark or SendGrid account and has been closed to new teams since September 11, 2026. | | **How you deploy** | MCP tool call, one REST upload of a zip, or drag-and-drop in the dashboard. No Git integration: you build locally or in CI. | Git continuous deployment, the CLI (netlify deploy --prod --dir=dist), Netlify Drop drag-and-drop, and an API. | | **Deploy without an account** | No, an account is needed to deploy. | Yes. Netlify Drop works without signing in (password-protected until claimed), and netlify deploy --allow-anonymous must be claimed within an hour. | | **Server-side features** | Static files only, plus built-in form capture and password or email gating. No serverless functions. | Functions, Edge Functions, Forms, Blobs and a database. | ## When Netlify is the better choice - You deploy from Git and want deploy previews and branch deploys for every change. - The site needs server-side pieces such as Functions, Edge Functions or Netlify Forms. ## When thin.host is the better choice - An agent or a script deploys the site: one MCP call or one zip upload, no repository needed. - You want transactional email from a verified domain in the same account as the hosting. - You would rather not track a monthly credit budget for a static site. ## Moving from Netlify to thin.host 1. Get the built site: run your build locally with the same command Netlify runs, or download a successful deploy as a ZIP from its page in the Netlify UI (it holds the publish directory). 2. Publish the folder: ask your agent to publish it to thin.host (MCP), or zip it and run `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive`. Check the site at its `/s//` preview URL. 3. Plan for redirects: thin.host does not read `_redirects` or `netlify.toml`, and redirects are not yet self-serve. Keep URL paths the same where you can; for a page that moved, deploy a small HTML page with a `meta refresh` and a canonical link to the new address. 4. Point forms at thin.host's form capture: set each form's action to `/s//_forms`. Submissions appear under Leads. 5. Move the domain: add it to the site under Custom Domains in the thin.host dashboard, change its DNS record to the CNAME the dashboard shows (cname.thin.host), and remove it from Netlify once thin.host's certificate is live. ### What does not carry over - _redirects, _headers and netlify.toml - Netlify Functions and Edge Functions - Netlify Forms history, Blobs and Database - Deploy previews and branch deploys Deploy commands for your framework are in the [deploy guides](https://thin.host/guides); agent setup is in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## FAQ **Can I move a site that uses Netlify Functions?** Only the static part. thin.host does not run serverless functions, so keep them on Netlify (or another platform) and call them from the static site. **Can I deploy to thin.host without an account?** No. Sign up (free), then deploy with an API key, the MCP server or the dashboard's upload page. **Do I have to move my DNS provider?** No. Keep DNS where it is and create the record the dashboard shows, a CNAME to cname.thin.host. TLS is issued automatically once it resolves. ## Sources Netlify facts checked on 2026-10-14 against: - [Netlify pricing](https://www.netlify.com/pricing/) - [Netlify docs: How credits work](https://docs.netlify.com/manage/accounts-and-billing/billing/billing-for-credit-based-plans/how-credits-work/) - [Netlify docs: Netlify MCP server](https://docs.netlify.com/build/build-with-ai/netlify-mcp-server/) - [Netlify docs: Email Integration](https://docs.netlify.com/integrations/email-integration/) - [Netlify docs: Create deploys](https://docs.netlify.com/deploy/create-deploys/) - [Netlify CLI: deploy](https://cli.netlify.com/commands/deploy/) - [Netlify Drop quickstart](https://docs.netlify.com/start/quickstarts/netlify-drop-quickstart/) thin.host facts: [pricing](https://thin.host/docs/billing), [REST API](https://thin.host/docs/api), [MCP tools](https://thin.host/docs/mcp). --- Canonical page: https://thin.host/compare/netlify ======================================================================== Source: https://thin.host/compare/vercel ======================================================================== # thin.host vs Vercel Vercel is built around frontend frameworks, Next.js above all, with serverless and edge functions, previews for every push and a broad set of AI tools. thin.host hosts static output only and concentrates on letting an agent publish a folder, then attach a domain and email. > Facts about Vercel are taken from Vercel's own pricing and documentation pages as of October 2026 (checked 2026-10-14) and listed under Sources. Plans change; check the vendor's page before you decide. ## Side by side | | thin.host | Vercel | |---|---|---| | **Free tier** | Free account: hosted sites at thin.host/s// and free .thin.host subdomains. The domain API's free platform tier covers 3 domains. | Hobby: 100 GB data transfer and 1,000,000 CDN requests a month, for non-commercial, personal use only. | | **Cheapest paid plan** | Domain API tiers: Indie $29/month, Platform $199/month. End users pay $8/month per domain provisioned through the claim flow. | Pro, $20 per developer seat per month, including $20 of usage credit. | | **Custom domains** | Yes, several per site, added from the dashboard with a CNAME to cname.thin.host. | Yes, up to 50 per project on Hobby. | | **HTTPS** | Automatic for custom domains and thin.host subdomains. | Automatic certificates for every domain, on all plans. | | **AI agent / MCP support** | Official hosted MCP server (thin.host/mcp, OAuth 2.1) plus a local server (uvx thinhost-mcp), a Claude Code plugin and a REST API. | Official Vercel MCP server (OAuth) for Claude Code, claude.ai, ChatGPT, Codex, Cursor and VS Code; it can deploy. | | **Transactional email** | Yes: transactional email over MCP, REST or SMTP from a verified sending domain (access is approved per account). | No. Vercel does not send email and points to Resend on its Marketplace. | | **How you deploy** | MCP tool call, one REST upload of a zip, or drag-and-drop in the dashboard. No Git integration: you build locally or in CI. | Git integration, the CLI (vercel --prod), Vercel Drop (sign-in required) and a REST API. | | **Deploy without an account** | No, an account is needed to deploy. | Mostly no: vercel index.html --temporary publishes a single HTML file without logging in. | | **Server-side features** | Static files only, plus built-in form capture and password or email gating. No serverless functions. | Functions, Middleware, Image Optimization, ISR and more. | ## When Vercel is the better choice - Your Next.js app needs server rendering, ISR, middleware or image optimisation. - You want a preview deployment for every pull request, wired to your Git host. ## When thin.host is the better choice - The site is static output (including a Next.js static export) and an agent or a script deploys it. - You want transactional email and custom domains in the same account, without per-seat pricing. ## Moving from Vercel to thin.host 1. Produce static files: for Next.js set `output: 'export'` and build to `out/` (see the [Next.js guide](https://thin.host/guides/deploy-nextjs)); for other frameworks run the same build command locally. 2. Publish the folder: ask your agent to publish it to thin.host (MCP), or zip it and run `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive`. Check the site at its `/s//` preview URL. 3. Plan for redirects: thin.host does not read `vercel.json`, and redirects are not yet self-serve. Keep URL paths the same where you can; for a page that moved, deploy a small HTML page with a `meta refresh` and a canonical link to the new address. Rewrites and custom headers have no equivalent. 4. Move the domain: add it to the site under Custom Domains in the thin.host dashboard, change its DNS record to the CNAME the dashboard shows (cname.thin.host), and remove it from Vercel once thin.host's certificate is live. ### What does not carry over - vercel.json redirects, rewrites and headers - Serverless Functions, Edge Functions and Middleware - Image Optimization (set images.unoptimized for a static export) - Preview deployments and Deployment Protection (thin.host offers password or email gating) Deploy commands for your framework are in the [deploy guides](https://thin.host/guides); agent setup is in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## FAQ **Can I move a Next.js app from Vercel to thin.host?** If it can be statically exported, yes: set output: 'export', build, and deploy the out/ folder. Apps that rely on server rendering, API routes or middleware need a server platform. **Can I deploy to thin.host without an account?** No. Sign up (free), then deploy with an API key, the MCP server or the dashboard's upload page. **Do I have to move my DNS provider?** No. Keep DNS where it is and create the record the dashboard shows, a CNAME to cname.thin.host. TLS is issued automatically once it resolves. ## Sources Vercel facts checked on 2026-10-14 against: - [Vercel pricing](https://vercel.com/pricing) - [Vercel docs: Hobby plan](https://vercel.com/docs/plans/hobby) - [Vercel docs: SSL certificates](https://vercel.com/docs/domains/working-with-ssl) - [Vercel docs: Vercel MCP](https://vercel.com/docs/agent-resources/vercel-mcp) - [Vercel CLI: deploy](https://vercel.com/docs/cli/deploy) - [Vercel guide: email with your Vercel domain](https://vercel.com/kb/guide/set-up-email-with-your-vercel-domain) thin.host facts: [pricing](https://thin.host/docs/billing), [REST API](https://thin.host/docs/api), [MCP tools](https://thin.host/docs/mcp). --- Canonical page: https://thin.host/compare/vercel ======================================================================== Source: https://thin.host/compare/github-pages ======================================================================== # thin.host vs GitHub Pages GitHub Pages publishes a site straight from a GitHub repository and is free for public repositories. thin.host takes an uploaded build instead of a repository, so an agent can publish without Git, and adds access gating and transactional email. > Facts about GitHub Pages are taken from GitHub Pages's own pricing and documentation pages as of October 2026 (checked 2026-10-14) and listed under Sources. Plans change; check the vendor's page before you decide. ## Side by side | | thin.host | GitHub Pages | |---|---|---| | **Free tier** | Free account: hosted sites at thin.host/s// and free .thin.host subdomains. The domain API's free platform tier covers 3 domains. | Free for public repositories on GitHub Free: sites up to 1 GB, a soft 100 GB/month bandwidth limit, and not meant as free hosting for an online business, e-commerce or SaaS. | | **Cheapest paid plan** | Domain API tiers: Indie $29/month, Platform $199/month. End users pay $8/month per domain provisioned through the claim flow. | Publishing from private repositories needs GitHub Pro, Team (listed at $4 per user per month) or Enterprise. | | **Custom domains** | Yes, several per site, added from the dashboard with a CNAME to cname.thin.host. | Yes, apex domains and subdomains. | | **HTTPS** | Automatic for custom domains and thin.host subdomains. | A Let's Encrypt certificate once DNS is correct; Enforce HTTPS is a separate setting. | | **AI agent / MCP support** | Official hosted MCP server (thin.host/mcp, OAuth 2.1) plus a local server (uvx thinhost-mcp), a Claude Code plugin and a REST API. | No Pages-specific MCP server. GitHub's official MCP server works with repositories and Actions. | | **Transactional email** | Yes: transactional email over MCP, REST or SMTP from a verified sending domain (access is approved per account). | No. | | **How you deploy** | MCP tool call, one REST upload of a zip, or drag-and-drop in the dashboard. No Git integration: you build locally or in CI. | git push to a publishing branch (root or /docs), or a GitHub Actions workflow. | | **Deploy without an account** | No, an account is needed to deploy. | No, a GitHub account and repository are required. | | **Server-side features** | Static files only, plus built-in form capture and password or email gating. No serverless functions. | None. | ## When GitHub Pages is the better choice - The site is the docs or homepage of a repository and should live next to the code. - You want free hosting for an open-source project, built by GitHub Actions on every push. ## When thin.host is the better choice - An agent publishes the site from a folder or zip, with no repository involved. - Some pages need a password or an email allowlist, set from the dashboard. - The app also needs to send transactional email. ## Moving from GitHub Pages to thin.host 1. Build the site yourself: a branch-published site is built with Jekyll, so run `bundle exec jekyll build` and use `_site/` (see the [Jekyll guide](https://thin.host/guides/deploy-jekyll)); an Actions-built site runs the same build command locally. 2. Publish the folder: ask your agent to publish it to thin.host (MCP), or zip it and run `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive`. Check the site at its `/s//` preview URL. 3. Keep deploying on push if you like: add a workflow step that zips the build and POSTs it to `/v1/websites//archive`, with the API key in a repository secret. 4. Move the domain: add it to the site under Custom Domains in the thin.host dashboard, change its DNS record to the CNAME the dashboard shows (cname.thin.host), and remove it from the repository's Pages settings once thin.host's certificate is live. ### What does not carry over - Automatic builds on push (replace with a CI step that calls the archive API) - The CNAME file (the domain is set in the dashboard) - username.github.io addresses (update links that point at them) Deploy commands for your framework are in the [deploy guides](https://thin.host/guides); agent setup is in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## FAQ **Can I keep deploying on every git push?** Yes. Add a GitHub Actions step that zips the build output and POSTs it to /v1/websites//archive with an API key stored as a secret; files missing from the new zip are removed. **Can I deploy to thin.host without an account?** No. Sign up (free), then deploy with an API key, the MCP server or the dashboard's upload page. **Do I have to move my DNS provider?** No. Keep DNS where it is and create the record the dashboard shows, a CNAME to cname.thin.host. TLS is issued automatically once it resolves. ## Sources GitHub Pages facts checked on 2026-10-14 against: - [GitHub Pages limits](https://docs.github.com/en/pages/getting-started-with-github-pages/github-pages-limits) - [GitHub's plans](https://docs.github.com/en/get-started/learning-about-github/githubs-plans) - [GitHub pricing](https://github.com/pricing) - [Securing your GitHub Pages site with HTTPS](https://docs.github.com/en/pages/getting-started-with-github-pages/securing-your-github-pages-site-with-https) - [Configuring a publishing source](https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site) - [GitHub MCP server](https://github.com/github/github-mcp-server) thin.host facts: [pricing](https://thin.host/docs/billing), [REST API](https://thin.host/docs/api), [MCP tools](https://thin.host/docs/mcp). --- Canonical page: https://thin.host/compare/github-pages ======================================================================== Source: https://thin.host/compare/cloudflare-pages ======================================================================== # thin.host vs Cloudflare Pages Cloudflare Pages serves static sites from Cloudflare's network with unlimited free static requests, and grows into Workers when a site needs code; Cloudflare now suggests starting new projects on Workers static assets. thin.host is narrower: static hosting deployed by agents, with domains, access gating and email in one account. > Facts about Cloudflare Pages are taken from Cloudflare Pages's own pricing and documentation pages as of October 2026 (checked 2026-10-14) and listed under Sources. Plans change; check the vendor's page before you decide. ## Side by side | | thin.host | Cloudflare Pages | |---|---|---| | **Free tier** | Free account: hosted sites at thin.host/s// and free .thin.host subdomains. The domain API's free platform tier covers 3 domains. | Unlimited static-asset requests, 500 builds a month, 100 projects and 20,000 files per site. | | **Cheapest paid plan** | Domain API tiers: Indie $29/month, Platform $199/month. End users pay $8/month per domain provisioned through the claim flow. | Workers Paid, from $5 a month per account. | | **Custom domains** | Yes, several per site, added from the dashboard with a CNAME to cname.thin.host. | Yes, up to 100 per Pages project; an apex domain needs its DNS on Cloudflare. | | **HTTPS** | Automatic for custom domains and thin.host subdomains. | Automatic certificates for custom domains. | | **AI agent / MCP support** | Official hosted MCP server (thin.host/mcp, OAuth 2.1) plus a local server (uvx thinhost-mcp), a Claude Code plugin and a REST API. | Official Cloudflare MCP servers (API and docs), and temporary deploys for agents with wrangler deploy --temporary. | | **Transactional email** | Yes: transactional email over MCP, REST or SMTP from a verified sending domain (access is approved per account). | Yes: Email Sending (public beta since April 2026) on Workers Paid, 3,000 emails a month included. | | **How you deploy** | MCP tool call, one REST upload of a zip, or drag-and-drop in the dashboard. No Git integration: you build locally or in CI. | wrangler pages deploy , Git integration, dashboard upload (up to 1,000 files) and an API. | | **Deploy without an account** | No, an account is needed to deploy. | Yes: Cloudflare Drop and wrangler --temporary; claim within 60 minutes to keep the site. | | **Server-side features** | Static files only, plus built-in form capture and password or email gating. No serverless functions. | Pages Functions and the Workers platform (KV, R2, D1, Durable Objects). | ## When Cloudflare Pages is the better choice - High-traffic static sites: static requests are free and unlimited on a global network. - The site will need server logic, storage or queues later, all on the same platform. ## When thin.host is the better choice - You want a root domain without moving your DNS to Cloudflare. - An agent should publish with one MCP call, and hosting, domains and email should share one account. - Pages need a password or an email allowlist set from a dashboard. ## Moving from Cloudflare Pages to thin.host 1. Build locally with the project's build command and take its output directory. 2. Publish the folder: ask your agent to publish it to thin.host (MCP), or zip it and run `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive`. Check the site at its `/s//` preview URL. 3. Plan for redirects: thin.host does not read `_redirects`, and redirects are not yet self-serve. Keep URL paths the same where you can; for a page that moved, deploy a small HTML page with a `meta refresh` and a canonical link to the new address. `_headers` and `_routes.json` have no equivalent. 4. Move the domain: add it under Custom Domains in the thin.host dashboard. If its DNS stays on Cloudflare, change the record to a DNS-only (grey cloud) CNAME to cname.thin.host so thin.host can issue the certificate, then remove the domain from the Pages project. ### What does not carry over - _redirects, _headers and _routes.json - Pages Functions and Workers bindings - Preview deployments per branch Deploy commands for your framework are in the [deploy guides](https://thin.host/guides); agent setup is in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## FAQ **Do I have to move my DNS away from Cloudflare?** No. Keep DNS on Cloudflare and point a DNS-only CNAME record at cname.thin.host. **Can I deploy to thin.host without an account?** No. Sign up (free), then deploy with an API key, the MCP server or the dashboard's upload page. **Do I have to move my DNS provider?** No. Keep DNS where it is and create the record the dashboard shows, a CNAME to cname.thin.host. TLS is issued automatically once it resolves. ## Sources Cloudflare Pages facts checked on 2026-10-14 against: - [Cloudflare Pages docs](https://developers.cloudflare.com/pages/) - [Cloudflare Pages limits](https://developers.cloudflare.com/pages/platform/limits/) - [Cloudflare Pages Functions pricing](https://developers.cloudflare.com/pages/functions/pricing/) - [Cloudflare Workers pricing](https://developers.cloudflare.com/workers/platform/pricing/) - [Cloudflare Pages custom domains](https://developers.cloudflare.com/pages/configuration/custom-domains/) - [Cloudflare MCP servers](https://developers.cloudflare.com/agents/model-context-protocol/mcp-servers-for-cloudflare/) - [Cloudflare Drop changelog](https://developers.cloudflare.com/changelog/post/2026-07-08-cloudflare-drag-and-drop/) - [Cloudflare Email Service pricing](https://developers.cloudflare.com/email-service/platform/pricing/) thin.host facts: [pricing](https://thin.host/docs/billing), [REST API](https://thin.host/docs/api), [MCP tools](https://thin.host/docs/mcp). --- Canonical page: https://thin.host/compare/cloudflare-pages ======================================================================== Source: https://thin.host/compare/surge ======================================================================== # thin.host vs Surge Surge is a minimal CLI host: surge ./dist publishes a folder, with free custom domains and managed TLS. thin.host is just as quick to deploy to, and adds an MCP server for agents, a dashboard with editing and access gating, and transactional email. > Facts about Surge are taken from Surge's own pricing and documentation pages as of October 2026 (checked 2026-10-14) and listed under Sources. Plans change; check the vendor's page before you decide. ## Side by side | | thin.host | Surge | |---|---|---| | **Free tier** | Free account: hosted sites at thin.host/s// and free .thin.host subdomains. The domain API's free platform tier covers 3 domains. | Unlimited publishing with no project caps, custom domains and basic SSL; no bandwidth figure is published. | | **Cheapest paid plan** | Domain API tiers: Indie $29/month, Platform $199/month. End users pay $8/month per domain provisioned through the claim flow. | Surge Professional, $30/month. | | **Custom domains** | Yes, several per site, added from the dashboard with a CNAME to cname.thin.host. | Yes, on the free plan. | | **HTTPS** | Automatic for custom domains and thin.host subdomains. | Managed certificates for custom domains; *.surge.sh is HTTPS. The pricing page lists forced HTTPS under Professional. | | **AI agent / MCP support** | Official hosted MCP server (thin.host/mcp, OAuth 2.1) plus a local server (uvx thinhost-mcp), a Claude Code plugin and a REST API. | No official MCP server found. | | **Transactional email** | Yes: transactional email over MCP, REST or SMTP from a verified sending domain (access is approved per account). | No. | | **How you deploy** | MCP tool call, one REST upload of a zip, or drag-and-drop in the dashboard. No Git integration: you build locally or in CI. | CLI: surge ./dist example.com, with SURGE_TOKEN for CI. | | **Deploy without an account** | No, an account is needed to deploy. | No; the first CLI run creates an account in the terminal. | | **Server-side features** | Static files only, plus built-in form capture and password or email gating. No serverless functions. | None. Redirects, password protection and CORS are paid ROUTER, AUTH and CORS files. | ## When Surge is the better choice - You want one terminal command and nothing else to learn. - You publish many small projects with free custom domains. ## When thin.host is the better choice - Agents deploy for you through MCP tools in Claude Code, Cursor, ChatGPT and other clients. - Password or email-allowlist protection is part of the dashboard, not a paid file. - The app also needs transactional email. ## Moving from Surge to thin.host 1. Your local project folder is already the build. 2. Publish the folder: ask your agent to publish it to thin.host (MCP), or zip it and run `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive`. Check the site at its `/s//` preview URL. 3. Single-page apps: rename Surge's `200.html` fallback to `404.html`. thin.host serves it for any path that is not a file. 4. Move the domain: add it to the site under Custom Domains in the thin.host dashboard, change its DNS record to the CNAME the dashboard shows (cname.thin.host), and remove it from Surge (tear the project down with the Surge CLI) once thin.host's certificate is live. ### What does not carry over - The CNAME file (the domain is set in the dashboard) - 200.html (use 404.html) - ROUTER, AUTH and CORS files - .surgeignore (zip only what you want deployed) Deploy commands for your framework are in the [deploy guides](https://thin.host/guides); agent setup is in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## FAQ **What replaces Surge's 200.html?** Name the file 404.html. thin.host serves 404.html for any path that is not a file, so a single-page app boots on deep links; the response status is 404. **Can I deploy to thin.host without an account?** No. Sign up (free), then deploy with an API key, the MCP server or the dashboard's upload page. **Do I have to move my DNS provider?** No. Keep DNS where it is and create the record the dashboard shows, a CNAME to cname.thin.host. TLS is issued automatically once it resolves. ## Sources Surge facts checked on 2026-10-14 against: - [Surge pricing](https://surge.sh/pricing) - [Surge docs: Plans](https://surge.sh/docs/platform/plans) - [Surge docs: SSL](https://surge.sh/docs/platform/ssl) - [Surge docs: Getting started](https://surge.sh/docs/getting-started) - [Surge docs: Platform files](https://surge.sh/docs/platform/) thin.host facts: [pricing](https://thin.host/docs/billing), [REST API](https://thin.host/docs/api), [MCP tools](https://thin.host/docs/mcp). --- Canonical page: https://thin.host/compare/surge ======================================================================== Source: https://thin.host/compare/neocities ======================================================================== # thin.host vs Neocities Neocities hosts hand-made personal websites with a community around them (follows, tags and profiles) on an ad-free free plan. thin.host is aimed at developers and agents: deploys by API or MCP, framework build output, and a custom domain on a free account. > Facts about Neocities are taken from Neocities's own pricing and documentation pages as of October 2026 (checked 2026-10-14) and listed under Sources. Plans change; check the vendor's page before you decide. ## Side by side | | thin.host | Neocities | |---|---|---| | **Free tier** | Free account: hosted sites at thin.host/s// and free .thin.host subdomains. The domain API's free platform tier covers 3 domains. | 1 GB storage, 200 GB bandwidth and one site on a neocities.org subdomain, with restricted file types and no ads. | | **Cheapest paid plan** | Domain API tiers: Indie $29/month, Platform $199/month. End users pay $8/month per domain provisioned through the claim flow. | Supporter, $5/month: 50 GB storage, custom domains and multiple sites. | | **Custom domains** | Yes, several per site, added from the dashboard with a CNAME to cname.thin.host. | Supporter plan only. | | **HTTPS** | Automatic for custom domains and thin.host subdomains. | Yes on the free subdomain; custom-domain certificates come with Supporter. | | **AI agent / MCP support** | Official hosted MCP server (thin.host/mcp, OAuth 2.1) plus a local server (uvx thinhost-mcp), a Claude Code plugin and a REST API. | No official MCP server found. | | **Transactional email** | Yes: transactional email over MCP, REST or SMTP from a verified sending domain (access is approved per account). | No. | | **How you deploy** | MCP tool call, one REST upload of a zip, or drag-and-drop in the dashboard. No Git integration: you build locally or in CI. | Browser editor and uploads, the neocities CLI (neocities push ), an HTTP API, and WebDAV on Supporter. | | **Deploy without an account** | No, an account is needed to deploy. | No; sites are created by signing up (free). | | **Server-side features** | Static files only, plus built-in form capture and password or email gating. No serverless functions. | None. | ## When Neocities is the better choice - A personal site with a community around it: followers, tags and a profile. - Editing HTML in the browser on an ad-free free plan with generous bandwidth. ## When thin.host is the better choice - A custom domain on a free account, with TLS issued automatically. - Deploying framework builds from an agent, a script or CI with one upload. - Transactional email and access gating for the same site. ## Moving from Neocities to thin.host 1. Download your files from the Neocities dashboard (or a backup). 2. Publish the folder: ask your agent to publish it to thin.host (MCP), or zip it and run `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive`. Check the site at its `/s//` preview URL. 3. Move the domain: add it to the site under Custom Domains in the thin.host dashboard, change its DNS record to the CNAME the dashboard shows (cname.thin.host), and remove it from Neocities once thin.host's certificate is live. ### What does not carry over - Followers, tags and your Neocities profile - The yoursite.neocities.org address (update links that point at it) Deploy commands for your framework are in the [deploy guides](https://thin.host/guides); agent setup is in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## FAQ **Can I edit pages in the browser on thin.host?** Yes. The dashboard has an editor with a live preview and inline text editing. **Can I deploy to thin.host without an account?** No. Sign up (free), then deploy with an API key, the MCP server or the dashboard's upload page. **Do I have to move my DNS provider?** No. Keep DNS where it is and create the record the dashboard shows, a CNAME to cname.thin.host. TLS is issued automatically once it resolves. ## Sources Neocities facts checked on 2026-10-14 against: - [Neocities Supporter plan](https://neocities.org/supporter) - [Neocities: About](https://neocities.org/about) - [Neocities: Allowed file types](https://neocities.org/site_files/allowed_types) - [Neocities CLI](https://neocities.org/cli) - [Neocities API](https://neocities.org/api) thin.host facts: [pricing](https://thin.host/docs/billing), [REST API](https://thin.host/docs/api), [MCP tools](https://thin.host/docs/mcp). --- Canonical page: https://thin.host/compare/neocities ======================================================================== Source: https://thin.host/compare/tiiny-host ======================================================================== # thin.host vs tiiny.host tiiny.host makes sharing a single HTML file, zip or PDF quick for non-developers, with QR codes, passwords and analytics built in. thin.host covers quick sharing too, and adds build-folder deploys from agents, framework guides, and a custom domain on a free account. > Facts about tiiny.host are taken from tiiny.host's own pricing and documentation pages as of October 2026 (checked 2026-10-14) and listed under Sources. Plans change; check the vendor's page before you decide. ## Side by side | | thin.host | tiiny.host | |---|---|---| | **Free tier** | Free account: hosted sites at thin.host/s// and free .thin.host subdomains. The domain API's free platform tier covers 3 domains. | 1 active project, 3 MB uploads, 5,000 visits and 5 GB bandwidth a month, with a tiiny.host banner and no custom domain. | | **Cheapest paid plan** | Domain API tiers: Indie $29/month, Platform $199/month. End users pay $8/month per domain provisioned through the claim flow. | Tiny, $9/month (1 project, 25 MB uploads). Custom domains start with Solo, $18/month. | | **Custom domains** | Yes, several per site, added from the dashboard with a CNAME to cname.thin.host. | Solo plan and above. | | **HTTPS** | Automatic for custom domains and thin.host subdomains. | Included with custom domains on paid plans. | | **AI agent / MCP support** | Official hosted MCP server (thin.host/mcp, OAuth 2.1) plus a local server (uvx thinhost-mcp), a Claude Code plugin and a REST API. | Official MCP server (publish, update and delete projects) on Solo and above, authenticated with an API key. | | **Transactional email** | Yes: transactional email over MCP, REST or SMTP from a verified sending domain (access is approved per account). | No transactional email; the Pro plan can capture visitor emails. | | **How you deploy** | MCP tool call, one REST upload of a zip, or drag-and-drop in the dashboard. No Git integration: you build locally or in CI. | Drag and drop a zip or file, paste HTML, an API (Solo and above), MCP, Zapier and Make. | | **Deploy without an account** | No, an account is needed to deploy. | Unclear: tiiny.host's own pages disagree on whether you can upload without signing up. | | **Server-side features** | Static files only, plus built-in form capture and password or email gating. No serverless functions. | None. Password protection, analytics and email capture are built in. | ## When tiiny.host is the better choice - You share single files or PDFs and want QR codes, analytics and visitor email capture built in. - The simplest possible upload page for non-technical teammates. ## When thin.host is the better choice - Framework builds: up to 30 MB per upload, or 150 MB through the local MCP server. - A custom domain and MCP access on a free account. - Transactional email for the app behind the site. ## Moving from tiiny.host to thin.host 1. Use your local copy of the files, or download them from tiiny.host (archived projects offer a download). 2. Publish the folder: ask your agent to publish it to thin.host (MCP), or zip it and run `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive`. Check the site at its `/s//` preview URL. 3. Recreate password protection in the site's Access Protection settings. 4. Move the domain: add it to the site under Custom Domains in the thin.host dashboard, change its DNS record to the CNAME the dashboard shows (cname.thin.host), and remove it from tiiny.host once thin.host's certificate is live. ### What does not carry over - Analytics and link-tracking history - Captured email lists (thin.host's form capture collects new submissions) - QR codes Deploy commands for your framework are in the [deploy guides](https://thin.host/guides); agent setup is in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## FAQ **Can I password-protect a page like on tiiny.host?** Yes. Password or email-allowlist protection can be set for a whole site or a single page in the dashboard. **Can I deploy to thin.host without an account?** No. Sign up (free), then deploy with an API key, the MCP server or the dashboard's upload page. **Do I have to move my DNS provider?** No. Keep DNS where it is and create the record the dashboard shows, a CNAME to cname.thin.host. TLS is issued automatically once it resolves. ## Sources tiiny.host facts checked on 2026-10-14 against: - [tiiny.host pricing](https://tiiny.host/pricing) - [tiiny.host: Connect to Claude with MCP](https://helpdesk.tiiny.host/en/article/how-to-connect-tiiny-host-to-claude-with-mcp-14z1okp/) - [tiiny.host API docs](https://api-docs.tiiny.host) - [tiiny.host: Archive your projects](https://helpdesk.tiiny.host/en/article/how-to-archive-your-projects-cd4ftr/) - [tiiny.host: Share projects](https://tiiny.host/use-case/share-projects/) thin.host facts: [pricing](https://thin.host/docs/billing), [REST API](https://thin.host/docs/api), [MCP tools](https://thin.host/docs/mcp). --- Canonical page: https://thin.host/compare/tiiny-host ======================================================================== Source: https://thin.host/compare/render ======================================================================== # thin.host vs Render Render runs web services, background workers, databases and static sites from Git, with previews for pull requests. Its static sites are free to deploy within the Hobby workspace limits. thin.host only hosts static sites, deployed by upload rather than from a repository. > Facts about Render are taken from Render's own pricing and documentation pages as of October 2026 (checked 2026-10-14) and listed under Sources. Plans change; check the vendor's page before you decide. ## Side by side | | thin.host | Render | |---|---|---| | **Free tier** | Free account: hosted sites at thin.host/s// and free .thin.host subdomains. The domain API's free platform tier covers 3 domains. | Static sites are free to deploy; the Hobby workspace includes 5 GB bandwidth a month (then $0.15/GB), 500 build minutes and 2 custom domains. | | **Cheapest paid plan** | Domain API tiers: Indie $29/month, Platform $199/month. End users pay $8/month per domain provisioned through the claim flow. | Pro, $25/month plus compute: 25 GB bandwidth and 15 custom domains. | | **Custom domains** | Yes, several per site, added from the dashboard with a CNAME to cname.thin.host. | Yes: 2 on Hobby, then $0.25 per domain per month. | | **HTTPS** | Automatic for custom domains and thin.host subdomains. | Automatic managed certificates at no extra cost. | | **AI agent / MCP support** | Official hosted MCP server (thin.host/mcp, OAuth 2.1) plus a local server (uvx thinhost-mcp), a Claude Code plugin and a REST API. | Official Render MCP server (it can create static sites and trigger deploys) and plugins for Claude Code, Codex and Cursor. | | **Transactional email** | Yes: transactional email over MCP, REST or SMTP from a verified sending domain (access is approved per account). | No. | | **How you deploy** | MCP tool call, one REST upload of a zip, or drag-and-drop in the dashboard. No Git integration: you build locally or in CI. | Auto-deploy on git push with pull-request previews, deploy hooks, render.yaml Blueprints, a CLI, a REST API and MCP. | | **Deploy without an account** | No, an account is needed to deploy. | No; an account and a Git repository are required. | | **Server-side features** | Static files only, plus built-in form capture and password or email gating. No serverless functions. | Web services, background workers, cron jobs and Postgres next to the static site. | ## When Render is the better choice - The static front end sits next to APIs, workers and Postgres you also run on Render. - Git-driven deploys with a preview for every pull request. ## When thin.host is the better choice - Publishing without a Git repository: an agent or a script uploads the build. - Custom domains that are not metered per domain. - Transactional email from the same account. ## Moving from Render to thin.host 1. Run the static site's Build Command locally and take its Publish Directory. 2. Publish the folder: ask your agent to publish it to thin.host (MCP), or zip it and run `curl -F file=@site.zip -H "Authorization: Bearer $THINHOST_API_KEY" https://thin.host/v1/websites/archive`. Check the site at its `/s//` preview URL. 3. Plan for redirects: thin.host does not read Render's redirect rules, and redirects are not yet self-serve. Keep URL paths the same where you can; for a page that moved, deploy a small HTML page with a `meta refresh` and a canonical link to the new address. Rewrites and custom headers have no equivalent. 4. Move the domain: add it to the site under Custom Domains in the thin.host dashboard, change its DNS record to the CNAME the dashboard shows (cname.thin.host), and remove it from Render once thin.host's certificate is live. ### What does not carry over - Redirect and rewrite rules and custom headers - Pull-request previews and deploy hooks - Auto-deploy on git push (use a CI step that calls the archive API) Deploy commands for your framework are in the [deploy guides](https://thin.host/guides); agent setup is in [Quickstart (MCP)](https://thin.host/docs/quickstart-mcp). ## FAQ **Can thin.host also run my Render web service?** No. thin.host hosts static files only. Keep the service on Render and serve the static front end from either host. **Can I deploy to thin.host without an account?** No. Sign up (free), then deploy with an API key, the MCP server or the dashboard's upload page. **Do I have to move my DNS provider?** No. Keep DNS where it is and create the record the dashboard shows, a CNAME to cname.thin.host. TLS is issued automatically once it resolves. ## Sources Render facts checked on 2026-10-14 against: - [Render pricing](https://render.com/pricing) - [Render changelog: updated workspace plans](https://render.com/changelog/updated-plans-for-render-workspaces) - [Render docs: Static sites](https://render.com/docs/static-sites) - [Render docs: Redirects and rewrites](https://render.com/docs/redirects-rewrites) - [Render docs: MCP server](https://render.com/docs/mcp-server) thin.host facts: [pricing](https://thin.host/docs/billing), [REST API](https://thin.host/docs/api), [MCP tools](https://thin.host/docs/mcp). --- Canonical page: https://thin.host/compare/render