Deploy to hosting
Ship a project that already exists — on disk or in a Git repository — to a Hostinger website. Building a new site from a prompt (design, store, blog) is the
skill; this one takes code as it is.
Calling the operations
- Read the that returns before the first call of each operation. If a name below is rejected as unknown, for what the step does (e.g. "deploy static").
- Batch reads with ; values pass between steps as . Batches chain operations from one server only — the Hostinger Connector runs , and as separate servers.
- Every deploy overwrites the website's current contents. Confirm the target domain with the user before the first deploy to a site that already has content.
1. Pick the target website
- in the project: reuse its and (or ).
- Otherwise look the domain up with (Shared and Cloud; substring match — take the exact entry) and
agency-hosting_websites_list-plan
(Agency; keep ).
- No website yet:
- Shared and Cloud: take a domain (the user's own, or
hosting_domains_generate-free-subdomain
) and an from , then . is needed only for the first website on a new plan (first entry of ). Poll hosting_websites_list-setups
with every 10–15 s until — uploads and deploys return 404 or 409 before that.
- Agency:
agency-hosting_website-setups_create
with (plus for built frontends), from agency-hosting_php_list-versions-for-order
and from agency-hosting_datacenters_list
. Poll agency-hosting_website-setups_status
until ; it returns the .
- Node.js apps run on Business and Cloud plans (, in ). On other plans, build locally and deploy the output as a static site.
2. Choose the deploy
Shared and Cloud, on the local server: one operation does every deploy —
with
and either
(a directory on this machine) or
git: { repository: "owner/name", branch }
. Given a directory it detects what the project is, packs it itself (it skips
,
and
files, listing the
ones as
so you can set their values with
hosting_nodejs_replace-environment-variables
; it does not read
, so keep build output out of the directory) and does the upload, build and Git setup. Do not archive the directory or call upload and build operations by hand.
| Project | treats it as |
|---|
| Plain HTML/CSS/JS, or a framework's static build output | — extracts as-is |
| with a build script, a start script or a server dependency (Next.js, Nuxt, Express, Vite…) | — starts a build, returns |
| PHP code, no build step | |
| WordPress plugin folder (a header) or theme folder ( in ) | / ; activates a theme |
| A whole WordPress site from elsewhere | , with — see the skill |
- Pass to override detection. It is required for an archive (an archive cannot be inspected) and when a directory matches more than one WordPress type, which rejects as ambiguous.
- Node.js build settings come from the project; detection covers the framework and the build script. Set , , , , (default 22), or when it is wrong. A TypeScript or other compiled server app always needs set to the built file (for example ): detection only guesses a root-level file, and the build fails with "Entry file not found". The entry file is relative to the root directory for express, fastify, hono, react-router and other, and to the output directory for nest, nuxt, nitro, astro and svelte-kit (, not ); Next.js ignores it. Per-framework values are in the Hostinger docs under Node.js (Supported Frameworks, Build Settings).
- Static, PHP, plugin and theme deploys are live when the call returns. A WordPress site import only starts () and finishes extracting a few minutes later; do not report it complete or verify it before then. Node.js builds run on the server: see step 3.
Agency: the website's type decides (
agency-hosting_websites_get
): sites created as
take
agency-hosting_deploy-node-static-website
, which runs the build when the project has one; every other site takes
agency-hosting_deploy-php-application
, which extracts the archive as-is. They deploy archives, synchronously: the site is live when the call returns. WordPress plugins and themes on Agency sites are installed from wp-admin.
Archive rules for Agency (name archives
) and for archives you build yourself:
- Static: build locally first. must be at the archive root, not inside a folder:
cd dist && zip -r ../site_20260101_120000.zip .
- Node.js source: no , no build output (, , ), no , nothing matched by ; 50 MB at most.
git archive --format=zip -o app_20260101_120000.zip HEAD
produces exactly the committed files — mention that uncommitted changes are left out.
and the
operations read files from this machine, so only the local server has them. On the hosted server (
)
does not find them — upload the files yourself as below.
Without the local deploy operations (hosted server; on the local server only for Agency)
- Get upload credentials:
hosting_files_generate-upload-url
(, ); Agency: agency-hosting_files_generate-upload-url
(). Both return , and , which authenticate the upload instead of the API token.
- Upload each file with TUS, where is its path in the website's storage:
bash
SIZE=$(wc -c < "$FILE" | tr -d ' ')
curl -sS -X POST "$URL/$DEST?override=true" -H "X-Auth: $AUTH_KEY" -H "X-Auth-Rest: $REST_AUTH_KEY" -H "Tus-Resumable: 1.0.0" -H "Upload-Length: $SIZE" -H "Upload-Offset: 0"
curl -sS -X PATCH "$URL/$DEST?override=true" -H "X-Auth: $AUTH_KEY" -H "X-Auth-Rest: $REST_AUTH_KEY" -H "Tus-Resumable: 1.0.0" -H "Content-Type: application/offset+octet-stream" -H "Upload-Offset: 0" --data-binary "@$FILE"
The first call returns
, the second
with an
header equal to the file size.
makes a retry safe.
3. Deploy from the uploaded files (
is any fresh 8-character string, e.g.
$(LC_ALL=C tr -dc 'a-z0-9' < /dev/urandom | head -c 8)
):
| Project | | Then |
|---|
| Static or PHP | | hosting_websites_deploy-static-site-archive
with |
| Node.js | | hosting_nodejs_build-settings-from-archive
with , then hosting_nodejs_start-build
with those settings, and source_options.archive_path: "app.zip"
|
| WordPress plugin | every file, as wp-content/plugins/SLUG-RANDOM8/<path in the plugin>
| with and plugin_path: "SLUG-RANDOM8"
|
| WordPress theme | every file, as wp-content/themes/SLUG-RANDOM8/<path in the theme>
| with , theme_path: "SLUG-RANDOM8"
and optional |
| Agency, extracted as-is | | agency-hosting_files_import-website-from-archive
with |
| Agency | | agency-hosting_websites_build-nodejs-assets
with archive_path: ".h5g/RANDOM8"
— the directory, not the file |
3. Node.js builds
returns a
at once; the build runs on the server and takes minutes. Track it with
(
, optionally
; the latest build by default), polling every 10–20 s until
is
or
. It returns the build, its log and the stored build settings; pass the previous
as
to read only new output.
- Failed build: the response already carries (fetched once per build; the API allows 5 a minute).
- Wrong detection (framework, , or an entry file inside the build output, such as for a compiled app): deploy again with , , or set. An archive deploy sends its settings with the request and leaves the stored ones alone; a Git deploy also stores these values, so later pushes build with them.
On the hosted server, which has no
or
:
- After the upload steps below, start the build and track it with
hosting_nodejs_list-builds
and (by ), polling every 10–20 s.
- Failed build:
hosting_nodejs_analyse-failed-build
once per build (5 calls a minute), then hosting_nodejs_build-logs
if the analysis is empty.
- Wrong detection: run
hosting_nodejs_start-build
with explicit values, and source_options.archive_path
set to the archive's file name in the document root (check it is there with hosting_files_list-website-and-directories
). Store the same values with hosting_nodejs_update-build-settings
.
- To review detected settings before any build: upload the archive with
hosting_files_generate-upload-url
(the TUS steps are in its description), then hosting_nodejs_build-settings-from-archive
.
4. Auto-deploy from Git
On the local server,
with
git: { repository: "owner/name", branch }
does all of it: it finds the Git installation that can reach the repository and deploys it as the
you give. Always pass
or
unless the site already runs a Node.js app (or you pass Node.js settings such as
): a new site is not detected as Node.js, and a Node.js repository deployed as static would publish its source. Then:
- PHP and static sites: saves the auto-deployment settings, which deploys the branch immediately and again on every push;
- Node.js sites: starts a build of the branch with the stored build settings; later pushes build the same way. A Git deploy has nothing to detect from, so when none are stored pass and (from in ), plus and if the app has a build step; they are stored for those pushes.
With no active installation it stops and says so: the user connects GitHub or GitLab once in hPanel under Websites → Manage → Advanced → Git; there is no API for that step. Confirm with
, which returns the stored
.
On the hosted server, by hand:
hosting_git_list-installations
. With no installation (check and too), the user connects GitHub or GitLab once in hPanel, as above.
hosting_git_list-installation-repositories
with the installation gives , and (10 calls a minute).
hosting_git_update-auto-deployment-settings
with , , , and optional .
- PHP and static sites deploy the branch immediately and again on every push.
- Node.js sites clone nothing on save: start the first build with
hosting_nodejs_start-build
, and the same . Later pushes build with the stored settings, so keep hosting_nodejs_update-build-settings
correct.
- Confirm with
hosting_git_auto-deployment-settings
.
Agency Plan sites have no Git operations; deploy archives.
5. Environment variables (Node.js)
hosting_nodejs_replace-environment-variables
replaces the whole set — anything not sent is deleted.
hosting_nodejs_list-environment-variables
for the current keys. Values come back as ; never send those back.
- Build the full set: every current key plus the new ones, with real values from the project's or the user. When the real value of an existing key is unknown, ask — do not drop it.
- Send it once; the app restarts. Values baked in at build time (Next.js , Vite ) need a new
hosting_nodejs_start-build
.
Keys use uppercase letters, digits and underscores. Never commit
files or repeat secret values back to the user.
6. Database
- Node.js:
hosting_databases_setup-website
creates a MySQL database and writes , , , , and into the environment, then restarts the app. The password is generated and never returned. It fails with 422 when any of those keys exists — remove them first with the step 5 replace.
- PHP: with , , a strong generated and ; read the prefixed full name back from . The app reads credentials from a config file on the server that stays out of Git, and connects to or .
- Agency:
agency-hosting_databases_create-website
; the app connects to .
- The host from is only for connections from outside Hostinger — never put it in the deployed app.
7. Verify and record
bash
curl -s -o /dev/null -w "%{http_code}\n" https://DOMAIN/
curl -s https://DOMAIN/ | grep -o "TEXT THE PROJECT RENDERS"
A
alone can be a placeholder page; match real copy. A new site may serve a default page briefly — clear it with
hosting_cache_clear-website
and retry before calling the deploy failed.
Write
in the project so later runs reuse the target:
{ "domain", "username" or "website_uid", "type": "static" | "nodejs" | "php" }
, keeping any fields already there.