audit-hosting
Audit a Hostinger web hosting account (Shared, Cloud and Agency plans) and report what needs attention: every plan and website,…
Step 8 (deploy) of the Hostinger Headless flow. Archives the frontend source, then deploys through the connector's one-shot hosting_deploy (type nodejs — it uploads the source, runs npm install and the build on the server) with the chosen framework's build settings (appType +
$ npx -y skills add hostinger/api-mcp-server --skill 08-deploy --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/08-deployContext preview
The summary Claude sees to decide when to auto-load this skill.
Step 8 (deploy) of the Hostinger Headless flow. Archives the frontend source, then deploys through the connector's one-shot hosting_deploy (type nodejs — it uploads the source, runs npm install and the build on the server) with the chosen framework's build settings (appType +
name: headless-step-deploy description: "Step 8 (deploy) of the Hostinger Headless flow. Archives the frontend source, then deploys through the connector's one-shot hosting_deploy (type nodejs — it uploads the source, runs npm install and the build on the server) with the chosen framework's build settings (appType + output dir) passed explicitly, polls to completion with hosting_get-deployment, verifies the live site and that the backend survived, then writes deploy.json."
Ship the frontend to the live domain through the Hostinger connector. You hand the connector a zip of the project **source** and it uploads it, runs `npm install` + the build script on the server, and serves the result. **Out:** `deploy.json`.
This is an **instance-barrier** step: run it only after `provision.status == "completed"` and validate (if run) has passed. All operations go through the connector (`execute`).
**In:** the project in `~/.hostinger/<domain>/src/`, `site.json` (`username`, `urls`), `state.json` (`frontend.framework`, `frontend.rendering`).
> ## ⚠️ The one rule that makes this work: pass build settings explicitly > If you let `hosting_deploy` **auto-detect** build settings, for a headless site that detection returns > **null** (`appType:null`, `outputDirectory:null`, Node 20) — the build "completes" but the **root > serves 403** (no `appType`/output → the vhost serves a directory with no entry). This is reproducible. > **Always pass `appType`, `outputDirectory`, `nodeVersion`, `buildScript`, `packageManager` and > `rootDirectory` on the `hosting_deploy` call** with the framework's values; the deploy then resolves > them and serves correctly, and `/cms` is preserved.
Map `frontend.framework` (from `state.json`) to its `appType` + build output directory, and pass those on the `hosting_deploy` call. `appType` is the framework's value, e.g. `next`, `nuxt`, `astro`, `svelte-kit`, `nest`, `express`, `fastify`, `react`, `create-react-app`, `gatsby`, `vite`, `vue`, `angular`, `parcel`, `svelte`, `other`.
Common cases (all `nodeVersion: 22`, `buildScript: "build"`, `packageManager: "npm"`, `rootDirectory: "."`):
| Framework / mode | Local config | `appType` | `outputDirectory` | |---|---|---|---| | **Next.js — SSR** *(default)* | `output: 'standalone'` | `next` | `.next` | | **Nuxt — SSR** | default | `nuxt` | `.output` | | **SvelteKit — SSR** | node adapter | `svelte-kit` | `build` | | **Astro — static** | `output: 'static'` | `astro` | `dist` | | **Vite / React / Vue — static (SPA)** | — | `vite` (or `react`/`vue`) | `dist` | | **Express / NestJS / Fastify — server** | — | `express`/`nest`/`fastify` | build output dir |
SSR/server frameworks run a persistent Node process (root sends `x-powered-by` / `cache-control: no-store`); static frameworks serve their output dir as files. If unsure of a framework's output dir, check the framework's own build output, but **always pass `appType`/`outputDirectory` on the deploy call with the framework's correct values** — don't rely on auto-detection (it returns null → 403).
1. **Instance live.** `provision.status == "completed"`, re-verified with `hosting_websites_list-setups { "domain": "<domain>" }`. 2. **Build output exists locally** (the framework's output dir — e.g. `.next/`, `dist/`, `.output/`) and the project builds clean (frontend/validate already did this). If not, go back. 3. **Env vars (only if used).** Build-time vars (e.g. `NEXT_PUBLIC_*`) must be set **before** the build with `hosting_nodejs_replace-environment-variables` (full replace). Never put secrets in the repo or the archive. **Webapp with a database:** that full replace wipes the `DB_*`/`DATABASE_URL` that `hosting_databases_setup-website` injected (the generated password reads back masked), so set all app vars in the same replace and, if you can't, first reset the password with `hosting_databases_change-password` and resend every `DB_*`/`DATABASE_URL` — see `../03-provision/webapp/SKILL.md` Step 3.
Zip the project **source** with `package.json` at the archive root. **Include** the app/source, `public/`, the framework config (`next.config.mjs` / `astro.config.mjs`), `tsconfig.json`, `package.json`, `package-lock.json`, `.nvmrc`. **Exclude** `node_modules/`, the build output (`.next/`, `dist/`, `out/`), `.git/`, and any `.htaccess` — the server installs and builds from source.
cd ~/.hostinger/<domain>/src zip -r -X ../app.zip . -x 'node_modules/*' '.next/*' 'dist/*' 'out/*' '.git/*' '**/.htaccess'
Pass the framework's build settings **inline** on the deploy call — there is no separate settings step. `path` is the archive from Step 2 (or the source directory itself; `hosting_deploy` archives a directory for you, skipping `node_modules/`, `.git/` and `.env`, but it does **not** read `.gitignore`, so the build output must already be absent).
{ "operation": "hosting_deploy",
"params": {
"domain": "<domain>",
"path": "/absolute/path/to/.hostinger/<domain>/app.zip",
"type": "nodejs",
"appType": "<framework appType, e.g. next>",
"outputDirectory": "<framework output dir, e.g. .next>",
"nodeVersion": 22,
"buildScript": "build",
"packageManager": "npm",
"rootDirectory": "." } }`hosting_deploy` uploads the source and triggers `npm install` + the build **end-to-end** — do not call any upload or build operation yourself. It returns a build `buildUuid` at once. This **overwrites the website root** (expected) and keeps `/cms` intact. Passing `appType`/`outputDirectory` explicitly is what keeps the root from serving 403 (see the rule above).
Poll `hosting_get-deployment { "domain": "<domain>", "buildUuid": "<buildUuid>" }` with backoff until `build.state` is `completed`. On `failed`, the same response carries the
Audit a Hostinger web hosting account (Shared, Cloud and Agency plans) and report what needs attention: every plan and website,…
Connect a custom domain to a website on Hostinger web hosting (Shared, Cloud or Agency plans) end to end: attach the domain to…
Deploy an existing project to a website on Hostinger web hosting (Shared, Cloud or Agency plans) and keep it deployed: picks the…
Orchestrator for the Hostinger Headless build flow — build and deploy a real website on the user's Hostinger account from a…
Connect step for the Hostinger Headless flow — verify Node, run the bootstrap (reach the Hostinger MCP server + OAuth sign-in),…
First build step of the Hostinger Headless flow, run right after connect. Works out where a given domain's build stands — is a…