@hostinger/mcp 3.3.0 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/gemini-extension.json +1 -1
  3. package/package.json +1 -1
  4. package/server.json +2 -2
  5. package/skills/headless/SKILL.md +68 -70
  6. package/skills/headless/connect/SKILL.md +1 -6
  7. package/skills/headless/steps/01-check-state/SKILL.md +24 -8
  8. package/skills/headless/steps/02-refine/SKILL.md +91 -24
  9. package/skills/headless/steps/03-provision/SKILL.md +63 -8
  10. package/skills/headless/steps/03-provision/ecommerce/SKILL.md +11 -2
  11. package/skills/headless/steps/03-provision/wordpress/SKILL.md +164 -15
  12. package/skills/headless/steps/04-content-model/SKILL.md +95 -17
  13. package/skills/headless/steps/04-content-model/wordpress/SKILL.md +66 -21
  14. package/skills/headless/steps/04-content-model/wordpress/woocommerce.md +153 -0
  15. package/skills/headless/steps/05-design/SKILL.md +9 -0
  16. package/skills/headless/steps/06-frontend/SKILL.md +31 -2
  17. package/skills/headless/steps/07-validate/SKILL.md +4 -1
  18. package/skills/headless/steps/08-deploy/SKILL.md +11 -3
  19. package/skills/headless/steps/09-done/SKILL.md +10 -4
  20. package/src/core/skills.js +49 -42
  21. package/src/core/skills.ts +49 -42
  22. package/src/servers/agency-hosting.js +1 -1
  23. package/src/servers/agency-hosting.ts +1 -1
  24. package/src/servers/agent-readiness.js +1 -1
  25. package/src/servers/agent-readiness.ts +1 -1
  26. package/src/servers/all.js +1 -1
  27. package/src/servers/all.ts +1 -1
  28. package/src/servers/billing.js +1 -1
  29. package/src/servers/billing.ts +1 -1
  30. package/src/servers/dns.js +1 -1
  31. package/src/servers/dns.ts +1 -1
  32. package/src/servers/domains.js +1 -1
  33. package/src/servers/domains.ts +1 -1
  34. package/src/servers/ecommerce.js +1 -1
  35. package/src/servers/ecommerce.ts +1 -1
  36. package/src/servers/horizons.js +1 -1
  37. package/src/servers/horizons.ts +1 -1
  38. package/src/servers/hosting.js +1 -1
  39. package/src/servers/hosting.ts +1 -1
  40. package/src/servers/mail.js +1 -1
  41. package/src/servers/mail.ts +1 -1
  42. package/src/servers/reach.js +1 -1
  43. package/src/servers/reach.ts +1 -1
  44. package/src/servers/vps.js +1 -1
  45. package/src/servers/vps.ts +1 -1
  46. package/src/servers/wordpress.js +1 -1
  47. package/src/servers/wordpress.ts +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,13 @@ Generated at release time from the diff between the previous and current
4
4
  build. Tool changes are listed individually; everything else is summarised
5
5
  by area.
6
6
 
7
+ ## v3.3.1 — 2026-10-19
8
+
9
+ ### Also in this release
10
+
11
+ - Bundled agent skills: 15 files
12
+ - Other files: `src/core/skills.js`, `src/core/skills.ts`
13
+
7
14
  ## v3.3.0 — 2026-10-19
8
15
 
9
16
  ### Also in this release
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hostinger-api-mcp",
3
- "version": "3.3.0",
3
+ "version": "3.3.1",
4
4
  "description": "Hostinger API — manage domains, DNS, hosting, VPS, billing and more from Gemini CLI.",
5
5
  "mcpServers": {
6
6
  "hostinger": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hostinger/mcp",
3
- "version": "3.3.0",
3
+ "version": "3.3.1",
4
4
  "mcpName": "io.github.hostinger/hostinger-api-mcp",
5
5
  "description": "MCP server for Hostinger API",
6
6
  "repository": {
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/hostinger/api-mcp-server",
7
7
  "source": "github"
8
8
  },
9
- "version": "3.3.0",
9
+ "version": "3.3.1",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "@hostinger/mcp",
14
- "version": "3.3.0",
14
+ "version": "3.3.1",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },
@@ -9,7 +9,7 @@ description: "Orchestrator for the Hostinger Headless build flow — build and d
9
9
 
10
10
  You are an AI coding agent. The user pasted a short prompt that points you here — something like:
11
11
 
12
- > Build a Headless site for `example.com` using hostinger.com/ai/skill.md
12
+ > Build a Headless site for `example.com` using hostinger.com/headless/skill.md
13
13
 
14
14
  Your job is to build and deploy a real website on the user's Hostinger account by following this
15
15
  recipe and the recipes it links to — nothing more, nothing less.
@@ -21,7 +21,7 @@ holds the flow, the state contract, the failure policy and the guardrails.
21
21
 
22
22
  The pasted prompt contains exactly two things that matter:
23
23
 
24
- - **This URL** — `hostinger.com/ai/skill.md`, the stable entry point.
24
+ - **This URL** — `hostinger.com/headless/skill.md`, the stable entry point.
25
25
  - **A domain** — e.g. `coral-pottery-1847.hostingersite.com` (a temporary Hostinger subdomain) or
26
26
  the user's own purchased domain. This is the single site you may touch.
27
27
 
@@ -37,47 +37,48 @@ Hostinger connector's OAuth token. **This recipe is not a security boundary.**
37
37
  ## The flow stages - STEPS TO FOLLOW
38
38
 
39
39
  Work through the steps in the order below, each reading its recipe and writing its artifact into the
40
- site workspace `~/.hostinger/<domain>/`. The order is a **dependency order, not a strict lockstep**:
41
- **provision runs as a background task** and the prepare work of the stages around it overlaps the wait
42
- (see *Background provision & the instance barrier* below). Never skip a stage — **except validate**
43
- (optional) **and content model for a `webapp` brief** (there is no CMS or store to seed — see step 4):
44
- every other stage self-verifies and deploy verifies the live result, so validate is a
45
- quick instance+API confirmation and its rebuild/preview/approval run only when a person is signing off
46
- (see its recipe). State files are only hints; the truth is what the Hostinger connector reports, so
47
- verify a "done" marker against reality before acting on it. If a step's `SKILL.md` is missing from the installed skill folder, stop and tell
48
- the user rather than improvising the stage from its description.
40
+ site workspace `~/.hostinger/<domain>/`.
41
+
42
+
43
+ The order is sequencial run and check the whole headless flow:
44
+
45
+ | # | Stage | Skill / source | Writes | Instance? |
46
+ |---|--------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------|---|---|
47
+ | — | **connect** — connect the Hostinger connector, auth, get active plan | `connect/SKILL.md` → `connect/tools/<tool>.md` | `connect.json` | no |
48
+ | 1 | **check state** — where does this domain stand? resume / switch / start over | `steps/01-check-state/SKILL.md` | `state.json` | no |
49
+ | 2 | **refine** — discover what the user wants, in conversation | `steps/02-refine/SKILL.md` | `brief.md` | no |
50
+ | 3 | **provision** — choose the backend from the brief, then provision it | `steps/03-provision/<backend>/SKILL.md` | `site.json` | **bg** — fire, then poll in the background |
51
+ | 4 | **content model** — define + create content/images, then push to the backend | `steps/04-content-model/<backend>/SKILL.md` | `content-model.md` | prepare: no · **push: yes** |
52
+ | 5 | **design** — derive design directions from the brief, pick one, write the `design.md` contract + logo | `steps/05-design/SKILL.md` | `design.md`, `brand/` | no |
53
+ | 6 | **frontend** — pick/confirm the framework (default Next.js SSR), implement `design.md` against the backend | `steps/06-frontend/SKILL.md` | source in `<workspace>/src/` | shell: no · **data: yes** |
54
+ | 7 | **validate** *(optional)* — quick instance+API confirmation; rebuild/preview/approval only when a person signs off | `steps/07-validate/SKILL.md` | — | no (local) |
55
+ | 8 | **deploy** — upload source, trigger the build | `steps/08-deploy/SKILL.md` | `deploy.json` | **yes** |
56
+ | 9 | **done** — hand over URLs, dashboard, summary, next steps (the **final report**) | `steps/09-done/SKILL.md` | — | no |
49
57
 
50
- **The one concurrency rule:** two *independent* stages in a single session may run at once, but never
58
+ **The most important is that connect stage runs first and always**
59
+ It's fetched from the public URL and runs *before* the Hostinger MCP Server
60
+ is loaded, the main goal of this is to have the Hostinger MCP Server.
61
+
62
+ You can find those connect skills under `connect/`.
63
+ The main skill lives in `connect/SKILL.md`.
64
+ There are also specific tools under `connect/tools/`.
65
+
66
+ The other 9 numbered steps live under `steps/` and are read from the installed skill folder (this will be guided in connect step).
67
+
68
+ **One concurrency rule:** two *independent* stages in a single session may run at once, but never
51
69
  two writers of the same artifact, and never two agents/windows on the same domain — the `.lock`
52
70
  (Step 1) guards that. Parallelism is always *optional*: an agent that can't interleave work runs the
53
- steps serially and is still correct.
54
-
55
- The **Instance?** column says whether a stage touches the live backend: `no` = pure prepare work that
56
- can run during the provision wait; `push`/`data`/`yes` = a commit phase that joins the instance
57
- barrier; `bg` = provision itself, the background task.
58
-
59
- | # | Stage | Skill / source | Writes | Instance? |
60
- |---|---|---|---|---|
61
- | — | **connect** — connect the Hostinger connector, auth, active plan | `connect/SKILL.md` → `connect/tools/<tool>.md` | `connect.json` | no |
62
- | 1 | **check state** — where does this domain stand? resume / switch / start over | `steps/01-check-state/SKILL.md` | `state.json` | no |
63
- | 2 | **refine** — discover what the user wants, in conversation | `steps/02-refine/SKILL.md` | `brief.md` | no |
64
- | 3 | **provision** — choose the backend from the brief, then provision it | `steps/03-provision/<backend>/SKILL.md` | `site.json` | **bg** — fire, then poll in the background |
65
- | 4 | **content model** — define + create content/images, then push to the backend | `steps/04-content-model/<backend>/SKILL.md` | `content-model.md` | prepare: no · **push: yes** |
66
- | 5 | **design** — derive design directions from the brief, pick one, write the `design.md` contract + logo | `steps/05-design/SKILL.md` | `design.md`, `brand/` | no |
67
- | 6 | **frontend** — pick/confirm the framework (default Next.js SSR), implement `design.md` against the backend | `steps/06-frontend/SKILL.md` | source in `<workspace>/src/` | shell: no · **data: yes** |
68
- | 7 | **validate** *(optional)* — quick instance+API confirmation; rebuild/preview/approval only when a person signs off | `steps/07-validate/SKILL.md` | — | no (local) |
69
- | 8 | **deploy** — upload source, trigger the build | `steps/08-deploy/SKILL.md` | `deploy.json` | **yes** |
70
- | 9 | **done** — hand over URLs, dashboard, summary, next steps (the **final report**) | `steps/09-done/SKILL.md` | — | no |
71
-
72
- **connect** runs first — it's fetched from the public URL and runs *before* the Hostinger connector
73
- exists. The nine numbered steps live under `steps/` and are read from the installed skill folder.
74
- **provision** and **content model** route to a per-backend subfolder (`<backend>` = `wordpress` |
75
- `ecommerce` | `webapp`), chosen from the brief. **`webapp`** is a plain Node.js app host (an empty
76
- website — no CMS, no store, no `/cms`) for any app/SPA that brings its own code and data; it **skips the
77
- content-model stage entirely** (there is nothing to seed — the app owns its own data) and never installs
78
- WordPress. **design** turns the brief into a chosen look and writes the `design.md` contract;
79
- **frontend** is a single generic step that picks the framework (guess → default Next.js SSR → confirm)
80
- and implements `design.md`.
71
+ steps serially and is still correct. Saying this, Always that you consider, you can run the steps
72
+ in parallel using different threads or processes to save time, but always ensure the right output.
73
+
74
+ Steps can generate **State files** those files are only hints; the truth is what the Hostinger connector reports, so
75
+ verify a "done" marker against reality before acting on it. If a step's `SKILL.md` is missing from the installed skill folder, stop and tell
76
+ the user rather than improvising the stage from its description.
77
+
78
+ The **Instance?** column says whether a stage touches the live backend:
79
+ `no` = pure prepare work that can run during the provision wait;
80
+ `push`/`data`/`yes` = a commit phase that joins the instance barrier;
81
+ `bg` = provision itself, the background task.
81
82
 
82
83
  **Always end with the final report.** Whenever a run ends, give the user the final report defined
83
84
  in `steps/09-done/SKILL.md`: an outcome paragraph, a *Steps completed* table (one row per stage that
@@ -97,38 +98,35 @@ Validation before deploy, always — nothing reaches the live domain unseen.
97
98
 
98
99
  ### Background provision & the instance barrier
99
100
 
100
- Provisioning is mostly *waiting*: `hosting_websites_create` returns "queued" immediately, then it's a
101
- `hosting_websites_list-setups` poll every ~15 s for a few minutes. Don't block on that poll. The
101
+ **Provision always runs — what it does depends on what the domain already has.** Often onboarding on
102
+ hostinger.com has already created the website before you run, so the domain *has* a headless instance;
103
+ but an instance existing does **not** mean provision is done or can be skipped. `check_state` works out
104
+ which of these cases applies and records it, then provision takes the matching path:
105
+
106
+ 1. **An empty headless shell already exists for the domain (the common onboarding case).** Onboarding
107
+ creates the website first — an **empty headless shell** (`hosting_websites_start-setup { type:
108
+ "headless_empty" }`): `website_type` is `headless`, but **no backend is installed** (no WordPress at
109
+ `/cms`, no store). This still goes through provision, which **adopts the shell and swaps it to the
110
+ chosen backend** (the backend is picked in refine first): WordPress is installed into the shell's
111
+ `/cms` with `wordpress_installations_install { type: "headless" }`, or the shell is adopted as the
112
+ Ecommerce storefront host. **Never skip provision for a shell, and never create a second site.** See
113
+ the provision router's *Onboarding handoff*.
114
+ 2. **No instance exists at all** (the user ran the headless flow without onboarding provisioning
115
+ anything). Provision creates a fresh headless instance with `hosting_websites_start-setup` using the
116
+ chosen backend's own `type`.
117
+ 3. **User wants a webapp.** Provision is a plain Node.js app host, not headless — `webapp` ignores
118
+ headless shells entirely and is only reached by experimental actions, never the onboarding flow.
119
+
120
+ Either way the create/install is asynchronous and returns `queued` immediately, then it's polled
121
+ every ~15 s for a few minutes — **what you poll depends on the path**: a fresh
122
+ `hosting_websites_start-setup` is polled with `hosting_websites_list-setups` until `completed`, while a
123
+ shell swap (`wordpress_installations_install`) creates no new setup, so it's polled with
124
+ `wordpress_installations_list` until the `/cms` row is `is_valid`. Don't block on that poll. The
102
125
  single rule that makes the overlap safe:
103
126
 
104
127
  > **Fire provision as a background task, then do every stage's prepare work while it settles. The
105
- > moment a step must write to the live instance, it waits for provision to report `completed`
106
- > (verified against `hosting_websites_list-setups`). That wait is the *instance barrier*.**
107
-
108
- Once `brief.md` exists (it already fixes the backend choice), the lanes are:
109
-
110
- ```
111
- refine ──▶ brief.md
112
- ├─▶ provision: FIRE create, record provision.in_progress ─────────┐ (bg poll)
113
- ├─▶ content-model PREPARE: define entities, write copy, │
114
- │ generate images │
115
- ├─▶ design: directions → design.md + logo (from the brief) │
116
- └─▶ frontend SHELL: pick framework, scaffold, implement design.md │
117
- │
118
- ══════════════════════ instance barrier: provision.status == completed ═════╪═════
119
- ▼
120
- ├─▶ content-model PUSH: send content/media via the connector (needs the instance)
121
- └─▶ frontend DATA: wire fetch/bind against the backend API URL from site.json
122
- │
123
- ▼
124
- validate ──▶ deploy (needs the provisioned target) ──▶ done
125
- ```
126
-
127
- Nothing before the barrier touches the backend, so it's safe to run in any order the agent can manage
128
- — sequentially if it can't interleave. Nothing after the barrier may start until provision is
129
- verifiably `completed`. If provision **fails** at the barrier (quota, `422`, a changed free
130
- subdomain), the prepare artifacts (drafted content, generated images, the `src/` shell) stay valid —
131
- only the commit phases wait or retry; re-run provision, then cross the barrier.
128
+ > moment a step must write to the live instance, it waits for provision to report ready (via the
129
+ > backend step's readiness poll — see above). That wait is the *instance barrier*.**
132
130
 
133
131
  ---
134
132
 
@@ -264,4 +262,4 @@ result:
264
262
 
265
263
  Never edit the JSON before sending, never add account details (the connector's login identifies the
266
264
  account), and never let a failed send block, delay or change the run. Check-state sends any
267
- reports still unsent (abandoned runs, earlier failures) with `unsent`.
265
+ reports still unsent (abandoned runs, earlier failures) with `unsent`.
@@ -89,13 +89,8 @@ for that tool, or drive `npx --yes --package=@hostinger/mcp@latest hostinger-api
89
89
 
90
90
  ## Phase 3 - Continue to Headless Hosting steps
91
91
 
92
- After evrything is verified then you can go back to `headless/SKILL.md` and follow the steps section to start the process.
92
+ After evrything is verified and you have access to the Hostinger MCP Server and the skills then you can go back to `headless/SKILL.md` and follow the steps section to start the process.
93
93
 
94
- > **Backend-specific MCP groups.** The base connector covers hosting + WordPress. An **Ecommerce** build
95
- > also needs the separate **`hostinger-ecommerce`** MCP group (`ecommerce_*` ops) — it is not loaded by
96
- > default. The provision step adds it when the brief chooses Ecommerce (see
97
- > `steps/03-provision/ecommerce/SKILL.md`); adding an MCP server needs a session restart/reconnect to
98
- > take effect.
99
94
 
100
95
  ## Reference Sources
101
96
 
@@ -5,7 +5,7 @@ description: "First build step of the Hostinger Headless flow, run right after c
5
5
 
6
6
  # headless-step-check-state
7
7
 
8
- The first build step of the Hostinger Headless flow (orchestrated by `hostinger.com/ai/skill.md`),
8
+ The first build step of the Hostinger Headless flow (orchestrated by `hostinger.com/headless/skill.md`),
9
9
  run right after connect. Connect has already connected the Hostinger connector and confirmed the
10
10
  account can build. Your job here is to
11
11
  **figure out where this domain stands and agree the route with the user** before any new work begins.
@@ -116,6 +116,17 @@ Query the Hostinger connector — the local files are never trusted on their own
116
116
  - `status: completed` → provisioned; then, depending on backend, check whether a build has succeeded.
117
117
  - `status: running` → still provisioning (see Step 1).
118
118
  - `status: failed` → provisioning stopped before finishing → route to **provision** to self-heal.
119
+ - **Is it an empty headless shell from onboarding?** A `headless` site whose setup is `completed` is
120
+ **not necessarily finished** — onboarding now creates the website *before* the build runs, as an
121
+ **empty headless shell** (`hosting_websites_start-setup { type: "headless_empty" }`): `website_type`
122
+ is `headless` but **no backend is installed** (no WordPress at `/cms`, no store). Tell a shell from a
123
+ real backend the same way provision does: within 24 h the setup `type` is `headless_empty`; otherwise
124
+ `wordpress_installations_list { username, domain, ownership: "all" }` returns **no** `/cms` row and
125
+ there is no `site.json` recording a backend. An empty shell means **provision has not chosen or
126
+ installed a backend yet** — this is a **new build** that happens to already own its website, not a
127
+ finished or resumable one. Route it to **refine** (choose the backend), then **provision** adopts the
128
+ shell and swaps it to that backend (see the provision router's *Onboarding handoff*). Never create a
129
+ second site, and never skip provision for it.
119
130
 
120
131
  Reconcile with the local state. **When they disagree, reality wins** and the local `stage` is
121
132
  corrected.
@@ -132,7 +143,8 @@ yet** (`brief.md`, `site.json`, …).
132
143
  | Local state | Reality (domain) | Position |
133
144
  |---|---|---|
134
145
  | none (connect only) | free | **new build** — start from refine |
135
- | none (connect only) | site exists | **adopt / resume** — never create a second site; route to the first unfinished stage |
146
+ | none (connect only) | empty headless shell (onboarding) | **new build on an existing shell** — start from refine; provision adopts the shell and swaps it to the chosen backend. Never create a second site, never skip provision |
147
+ | none (connect only) | site exists with a real backend | **adopt / resume** — never create a second site; route to the first unfinished stage |
136
148
  | build artifacts present, incomplete | matches | **resume** at `state.json`'s `stage` |
137
149
  | build artifacts present | disagrees | **reality wins** — recompute the stage from what actually exists |
138
150
  | build artifacts present, all done | live site exists | **finished** — this is now an *iterate* request, not a build |
@@ -145,12 +157,16 @@ The question to ask depends on whether there is actually **something to resume**
145
157
  artifacts** (`brief.md`, `site.json`, …) or a **live site** for this domain. A stray `.lock` or
146
158
  connect-only files are *not* something to resume.
147
159
 
148
- - **New build** (no build artifacts and the domain is free) → just proceed to refine. **Don't ask
149
- resume vs start over** — there's nothing to resume; both would land in the same place. If a leftover
150
- `.lock` is lying around, silently take it over and continue (optionally mention it in one line).
151
- - **Something to resume** (build artifacts exist, or a site exists for the domain) → tell the user
152
- plainly what's there and **ask them to choose**, regardless of how old it is (don't guess from
153
- timestamps):
160
+ - **New build** (no build artifacts and either the domain is free **or** it holds only an empty
161
+ headless shell from onboarding) → just proceed to refine. **Don't ask resume vs start over** —
162
+ there's nothing to resume; both would land in the same place. An empty headless shell is not
163
+ "something to resume": it has no backend and no content yet, so it's a fresh build that already owns
164
+ its website — provision will adopt and swap it. Mention it in one line ("Using the headless site
165
+ onboarding already created for this domain."). If a leftover `.lock` is lying around, silently take
166
+ it over and continue (optionally mention it in one line).
167
+ - **Something to resume** (build artifacts exist, or a site exists for the domain **with a real backend
168
+ installed** — WordPress at `/cms`, a store, or a deployed app) → tell the user plainly what's there
169
+ and **ask them to choose**, regardless of how old it is (don't guess from timestamps):
154
170
 
155
171
  - **Resume** — pick up at the computed stage. (If a `.lock` is present in this case, also confirm no
156
172
  other window is actively building this domain right now.)
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: headless-step-refine
3
- description: "Step 2 (refine) of the Hostinger Headless flow. Turns the user's seed — often just a domain — into a brief through conversation: asks what they want to build (purpose, audience, tone, pages, products, must-haves; images, local files, links all welcome), recommends the backend that fits (WordPress, Ecommerce, WordPress + Ecommerce, or Webapp for a custom app/SPA), lets the user confirm it, then writes brief.md."
3
+ description: "Step 2 (refine) of the Hostinger Headless flow. Turns the user's seed — often just a domain — into a brief through conversation: asks what they want to build (purpose, audience, tone, pages, products, must-haves; images, local files, links all welcome), then *infers* the backend that fits (WordPress, Ecommerce, WordPress + Ecommerce, WordPress + WooCommerce for a one-site content+store, or Webapp for a custom app/SPA) — it never asks the user to pick a backend or a technology; the user confirms the plan in plain language, then it writes brief.md. Hostinger Ecommerce stays the default for selling; WooCommerce is chosen only when the user explicitly asks for it or wants content and a store on one WordPress site."
4
4
  ---
5
5
 
6
6
  # headless-step-refine
@@ -13,6 +13,14 @@ the site comes from talking to the user.
13
13
  backend. Every other question is skippable: the more the user gives, the better the site, but never
14
14
  hold the build hostage to refinement. Fill gaps with sensible defaults and say so in the brief.
15
15
 
16
+ > **Never ask the user to choose a backend or a technology.** Don't ask "WordPress or Ecommerce?",
17
+ > don't present WordPress/Ecommerce/WooCommerce/Webapp as options, and don't surface the backend in a
18
+ > multiple-choice UI. Open with **"What do you want to build?"** and infer the backend yourself in
19
+ > Step 4 from what they describe (and whether they sell). The backend is a technical decision the flow
20
+ > makes *for* the user — they confirm the **plan** (what the site is and does), not the plumbing. The
21
+ > only exception is when the user *volunteers* a backend ("build it on WordPress", "use WooCommerce"):
22
+ > then honour their choice and note it in the brief.
23
+
16
24
  **In:** the domain (the workspace directory name), plus anything the user already shared.
17
25
  **Out:** `~/.hostinger/<domain>/brief.md`.
18
26
 
@@ -36,21 +44,38 @@ Suggested backend on a provisioned site. Explain that switching backends means a
36
44
 
37
45
  Before asking anything, collect what the user has already given you, so you don't ask for it again:
38
46
 
47
+ - **Inspect the directory the command was run in** — this is the biggest signal for the build mode
48
+ (Step 3). Look for an existing **frontend / webapp / commerce project**: a `package.json`, a
49
+ framework config (`next.config.*`, `astro.config.*`, `vite.config.*`, `svelte.config.*`, `nuxt.*`),
50
+ a `src/` or `app/` tree, `index.html`, a storefront/cart, etc. A real project here usually means the
51
+ user **already has their own frontend** and mainly needs a Hostinger backend to wire it to — lean
52
+ toward "bring your own frontend" in Step 3. If the folder has nothing site-like, assume they don't
53
+ and lean toward "agent builds it".
39
54
  - Anything in the pasted prompt beyond the domain (a sentence, a link, a screenshot).
40
55
  - Files in the current project that look like site material (copy, logos, product lists, images).
41
- - What the agent already knows about the user from local memory or this conversation.
56
+ - What the agent already knows about the user from local memory or this conversation (a prior build,
57
+ stack preferences, a frontend they always use).
42
58
  - The domain name itself — a hint only (`coral-pottery.com` suggests pottery), never a conclusion.
43
59
 
44
60
  ## Step 3 — Ask
45
61
 
46
- If Step 2 already answers *what are you building* and *will they sell*, skip straight to Step 4.
62
+ If Step 2 already answers *what are you building* and *will they sell*, skip the Round 1–3 questions
63
+ below, but still ask **Build mode** before moving on.
64
+
65
+ Otherwise open with one line and **wait for the user's answer**: *"Tell me what you want to build — a
66
+ sentence is enough. Links, screenshots or files help too. Skip anything you don't want to answer."*
47
67
 
48
- Otherwise open with one line: *"Tell me what you want to build — a sentence is enough. Links,
49
- screenshots or files help too. Skip anything you don't want to answer."*
68
+ > **"What do you want to build?" is an OPEN question — ask it in plain prose and wait.** Never turn it
69
+ > into a multiple-choice list of pre-baked site ideas ("Coffee shop / Travel blog / Portfolio …"):
70
+ > that puts words in the user's mouth and defeats the point of asking. Let them describe it in their
71
+ > own words. The structured question UI is only for genuinely *choice-shaped* follow-ups (selling
72
+ > yes/no, which pages, tone adjectives, the build mode) — not for the opening question, and never for
73
+ > the backend.
50
74
 
51
75
  Ask in **short rounds of 2–3 questions**, and adapt each round to the previous answers. If your tool
52
76
  has a structured question UI (multiple choice with an "other" field), use it for the choice-shaped
53
- questions. **At most 3 rounds**, and stop early as soon as you can guess the backend and the user
77
+ follow-up questions (pages, selling yes/no, tone) — **never for the opening "what do you want to
78
+ build?" and never for the backend** (that's your decision, not theirs). **At most 3 rounds**, and stop early as soon as you can guess the backend and the user
54
79
  seems done — "just build it", "you decide", or a skipped question means *use defaults*, not *ask
55
80
  again*.
56
81
 
@@ -84,15 +109,38 @@ If the user asks for something outside the scope (user accounts, member areas, b
84
109
  calendar backend, user-generated content), say plainly that the headless flow doesn't support it yet
85
110
  and record it under **Out of scope** — don't promise it.
86
111
 
87
- ## Step 4 — Recommend the backend
112
+ ### Build mode — ask once (this one *is* a user choice)
113
+
114
+ The backend is your call, but **how the frontend gets built is the user's** — because most of the time
115
+ the user already has their own frontend and just needs a Hostinger backend to wire it to. After the
116
+ folder + memory inspection (Step 2), ask **one** question (a structured choice is ideal here), seeding
117
+ the default from what you found:
118
+
119
+ - **Bring your own frontend** *(default when Step 2 found a real project in the folder)* — "I already
120
+ have a frontend / I'll drive the design and we vibe-code it together." The agent **uses the user's
121
+ existing project in the current folder as the source**, collaborates on design/code at the user's
122
+ direction, and wires it to the provisioned backend. There is **no agent-generated design** — the
123
+ design step defers to the user (see the Build mode box at the top of the design step), and the frontend step builds on their project
124
+ rather than scaffolding a new one.
125
+ - **Agent designs and builds it** *(default when the folder has nothing site-like)* — "Give me ideas
126
+ — you design and code it." Today's flow: the design step proposes directions and the frontend step
127
+ scaffolds and implements them.
88
128
 
89
- Pick the backend that fits what the user told you:
129
+ Record the answer as the brief's **Build mode**. This is the one frontend/technology question you *do*
130
+ put to the user; everything else about the stack (framework, SSR/SSG) is still inferred. The deliverable
131
+ is the same either way — a working site on the backend; only *who drives the frontend* changes.
132
+
133
+ ## Step 4 — Decide the backend (your call, from the brief — not a question)
134
+
135
+ From what the user described, **you** pick the backend that fits — this is an internal decision, never
136
+ a question put back to the user. Pick the backend that fits what the user told you:
90
137
 
91
138
  | Backend | Choose when | What it gives the owner |
92
139
  |---|---|---|
93
140
  | **WordPress** | No selling. The owner publishes and edits content: pages, blog, articles, portfolio. | Headless WordPress at `/cms` — write and edit content in wp-admin. |
94
141
  | **Ecommerce** | Selling is the point, and the rest is a few static pages (About, Contact, FAQ, policies). No ongoing blog. | Hostinger Ecommerce store — products, collections, checkout, payments, shipping, orders. |
95
- | **WordPress + Ecommerce** | Selling **and** regular editorial content (a blog, guides, lookbooks, recipes) the owner keeps adding to. | Both: WordPress for content, the Ecommerce store for products and checkout. |
142
+ | **WordPress + Ecommerce** | Selling **and** regular editorial content (a blog, guides, lookbooks, recipes) the owner keeps adding to, run as **two** backends (WordPress site + separate Hostinger Ecommerce store). | Both: WordPress for content, the Ecommerce store for products and checkout. |
143
+ | **WordPress + WooCommerce** | **Only** when the user explicitly names WooCommerce, or explicitly wants content **and** a store on **one** WordPress site (one admin, one domain). The one-site alternative to WordPress + Ecommerce. | A single headless WordPress at `/cms` with the WooCommerce plugin — products, cart, coupons and checkout (Cash on Delivery) over the WooCommerce Store API, plus WP posts/pages on the same site. |
96
144
  | **Webapp** | A custom **app, SPA or web application** that brings its own code and data — a dashboard, tool, calculator, booking app, a project the user is deploying — **not** a content site or a store. No CMS and no store engine. | A plain Node.js app host (an empty website, no `/cms`), with a MySQL database when the app needs one. The app owns all its routes and data. |
97
145
 
98
146
  Rules of thumb:
@@ -104,6 +152,12 @@ Rules of thumb:
104
152
  WordPress + Ecommerce.
105
153
  - **Then the content.** Selling plus only a few fixed pages → Ecommerce. Selling plus content the
106
154
  owner will keep publishing → WordPress + Ecommerce.
155
+ - **Hostinger Ecommerce is the default for selling — WooCommerce is never the default and is never
156
+ recommended on its own.** Choose **WordPress + WooCommerce** only when the user explicitly names
157
+ WooCommerce, or explicitly wants content **and** a store on one WordPress site (one admin, one
158
+ domain — the one-site alternative to WordPress + Ecommerce). For every other selling case, keep
159
+ Hostinger Ecommerce. If the user wants both content and a store but hasn't said "one site" or
160
+ "WooCommerce", offer it as an option — don't switch to it silently.
107
161
  - **Don't add WordPress "just in case".** A second backend is a second admin to learn. Recommend the
108
162
  combination only when the user described ongoing content.
109
163
  - Selling a single service by enquiry (no checkout, no cart) is **not** commerce → WordPress with a
@@ -114,22 +168,26 @@ Rules of thumb:
114
168
 
115
169
  **Then set rendering** (write it in the brief's **Rendering** section): **Ecommerce → SSR required**
116
170
  (carts/search need per-request rendering — any SSR framework works; Next.js is the default, not a
117
- requirement); **WordPress → SSG (Astro)** if the site is mostly static and the owner is fine rebuilding
171
+ requirement); **WordPress + WooCommerce → SSR required** (same reason — cart/checkout need per-request
172
+ rendering); **WordPress → SSG (Astro)** if the site is mostly static and the owner is fine rebuilding
118
173
  to publish, otherwise **SSR**; **Webapp → whatever the app is** (SSR for a server app, SPA for a
119
174
  client-only app) — it deploys as a Node.js app either way. When unsure, default to **Next.js SSR**.
120
175
 
121
- ## Step 5 — Confirm in one message
176
+ ## Step 5 — Confirm the plan in one message
122
177
 
123
- Send **one** message that carries both the recommendation and the brief summary:
178
+ Send **one** message that confirms **what you'll build** — the plan, not the plumbing. Lead with the
179
+ site, not the backend:
124
180
 
125
- - **Backend** — the choice, the one-line reason, and what it means day to day (where they'll edit
126
- content and products). Name the alternative if it was a close call.
127
- - **Brief** — what it is, audience, pages, products (if any), tone. Mark anything you defaulted
181
+ - **The plan** — what it is, audience, pages, products (if any), tone. Mark anything you defaulted
128
182
  (*"assumed: warm, minimal look"*) so the user sees what they skipped.
183
+ - **How it's built** — state the backend as a *consequence* in one plain line, focused on what it
184
+ means for them day to day ("I'll build this on WordPress, so you edit pages and posts in a normal
185
+ WordPress admin"), **not** as a choice you're asking them to make. Don't ask "is WordPress OK?" or
186
+ offer alternatives unless it was a genuine close call *and* the difference matters to the user.
129
187
 
130
188
  End with *"Good to go, or anything to change?"* A yes (or silence-equivalent like "go") → write
131
- `brief.md`. Changes → apply them and write it; don't loop back into questions. If they pick a
132
- different backend, use theirs and note it in the brief.
189
+ `brief.md`. Changes → apply them and write it; don't loop back into questions. If the user
190
+ *volunteers* a different backend, use theirs and note it in the brief.
133
191
 
134
192
  ## Step 6 — Write `brief.md` and hand off
135
193
 
@@ -139,8 +197,10 @@ user's own words where you can. Then update `state.json`:
139
197
  `"stage": "provision"`, fresh `updated_at`.
140
198
 
141
199
  The **Suggested backend** section is the contract with `03-provision/SKILL.md`, which routes on it.
142
- Its first line must be exactly one of `**WordPress**`, `**Ecommerce**`, `**WordPress + Ecommerce**` or
143
- `**Webapp**`, followed by an em dash and the one-line reason.
200
+ Its first line must be exactly one of `**WordPress**`, `**Ecommerce**`, `**WordPress + Ecommerce**`,
201
+ `**WordPress + WooCommerce**` or `**Webapp**`, followed by an em dash and the one-line reason.
202
+ `**WordPress + WooCommerce**` is the WordPress backend with the WooCommerce store turned on — provision
203
+ routes it to the `wordpress` subfolder with the store enabled (it is **not** a separate backend).
144
204
 
145
205
  ## `brief.md` template
146
206
 
@@ -184,14 +244,21 @@ user didn't specify.>
184
244
  <logo, colours, photos, copy the user provided and where they are; "None yet" if none>
185
245
 
186
246
  ## Suggested backend
187
- **<WordPress | Ecommerce | WordPress + Ecommerce | Webapp>** — <one-line reason>.
247
+ **<WordPress | Ecommerce | WordPress + Ecommerce | WordPress + WooCommerce | Webapp>** — <one-line reason>.
188
248
  <"Confirmed by the user." or "User chose this over the recommended <X> because <reason>.">
189
249
 
250
+ ## Build mode
251
+ **<Bring your own frontend | Agent designs and builds>** — <one line>. <When "Bring your own frontend":
252
+ the path to the user's existing project in the current folder (the frontend source), and how they want
253
+ to drive design/code. When "Agent designs and builds": leave the design + frontend steps to run as
254
+ normal.> The design step and the frontend step both read this: **Bring your own frontend** → design
255
+ defers to the user and frontend builds on their project; **Agent designs and builds** → both run as normal.
256
+
190
257
  ## Rendering
191
- **<SSR | SSG>** — <reason>. Rules: **Ecommerce requires SSR** (carts/search need per-request
192
- rendering — any SSR framework works; Next.js is the default, not a requirement); **WordPress may be
193
- SSG (Astro)** when the site is mostly static and rarely changes, otherwise **SSR**. Default when
194
- unsure: **Next.js SSR**.
258
+ **<SSR | SSG>** — <reason>. Rules: **Ecommerce requires SSR** and **WordPress + WooCommerce requires
259
+ SSR** (carts/checkout need per-request rendering — any SSR framework works; Next.js is the default, not
260
+ a requirement); **WordPress may be SSG (Astro)** when the site is mostly static and rarely changes,
261
+ otherwise **SSR**. Default when unsure: **Next.js SSR**.
195
262
  ```
196
263
 
197
264
  ## Example — WordPress + Ecommerce
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: headless-step-provision
3
- description: "Step 3 (provision) of the Hostinger Headless flow. Chooses the backend from brief.md (wordpress | ecommerce | webapp), then routes to the matching subfolder to provision it; writes site.json."
3
+ description: "Step 3 (provision) of the Hostinger Headless flow. Chooses the backend from brief.md (wordpress | ecommerce | webapp), then routes to the matching subfolder to provision it; writes site.json. WordPress + WooCommerce routes to the wordpress subfolder with the WooCommerce store turned on — it is not a separate backend."
4
4
  ---
5
5
 
6
6
  # headless-step-provision
@@ -25,19 +25,74 @@ Read the brief's **Suggested backend** section:
25
25
  | Suggested backend | Follow |
26
26
  |---|---|
27
27
  | WordPress | `wordpress/SKILL.md` |
28
+ | WordPress + WooCommerce | `wordpress/SKILL.md` **with the WooCommerce store on** (see below) |
28
29
  | Ecommerce | `ecommerce/SKILL.md` |
29
30
  | Webapp | `webapp/SKILL.md` |
30
31
 
31
32
  If the section is missing or names something else, go back to **refine** — don't pick one here.
32
33
  Tell the user the backend and its one-line reason before provisioning.
33
34
 
34
- > **Supported backends: `wordpress`, `ecommerce` and `webapp`.** `webapp` is a plain Node.js app host
35
- > (an empty website — no CMS, no store, no `/cms`) for any app/SPA that brings its own code and data; it
36
- > never installs WordPress. PocketBase is not available in this version — refine never proposes it, and
37
- > there is no `pocketbase/` subfolder; if a brief somehow names it, stop and tell the user rather than
38
- > improvising it. A **WordPress + Ecommerce** brief has no single combined `start-setup` type yet: stop,
39
- > tell the user it isn't supported as one site, and offer to continue with just WordPress or just
40
- > Ecommerce — then route to that one subfolder.
35
+ > **WordPress + WooCommerce is the WordPress backend with a store — not a new backend.** Route it to
36
+ > `wordpress/SKILL.md` and follow that recipe's **optional WooCommerce tail** (install + activate the
37
+ > `woocommerce` plugin and verify the store endpoints; the catalog is seeded later through the per-site WP
38
+ > MCP's native `wc-*` abilities — no custom plugin, no consumer key). `site.json → backend` stays
39
+ > `"wordpress"`; the store is recorded under `site.json → woocommerce` (`enabled: true`). Everything else
40
+ > downstream that routes on
41
+ > `wordpress` (content-model push, deploy's `/cms` preservation, done's wp-admin login) then works
42
+ > unchanged.
43
+
44
+ > **Supported backends: `wordpress` (optionally with a WooCommerce store), `ecommerce` and `webapp`.**
45
+ > `webapp` is a plain Node.js app host (an empty website — no CMS, no store, no `/cms`) for any app/SPA
46
+ > that brings its own code and data; it never installs WordPress. PocketBase is not available in this
47
+ > version — refine never proposes it, and there is no `pocketbase/` subfolder; if a brief somehow names
48
+ > it, stop and tell the user rather than improvising it. A **WordPress + Ecommerce** brief (two separate
49
+ > backends — a WordPress site **and** a Hostinger Ecommerce store) has no single combined `start-setup`
50
+ > type yet: stop, tell the user it isn't supported as one site, and offer either to continue with just
51
+ > WordPress or just Ecommerce (route to that one subfolder), **or**, if they want content and a store on
52
+ > **one** site, to switch the brief to **WordPress + WooCommerce** — the one-site path, which routes to
53
+ > `wordpress/SKILL.md` with the store on.
54
+
55
+ ## Onboarding handoff — swap an existing empty headless shell (do this before creating anything)
56
+
57
+ Onboarding can create the website **before** you ever run, then paste the build prompt into this agent.
58
+ When it does, the domain already has an **empty headless shell**: a website set up with
59
+ `hosting_websites_start-setup { type: "headless_empty" }` — `website_type` is `headless`, but **nothing
60
+ is installed** (no WordPress at `/cms`, no store). It is the hosting slot only, waiting for a backend.
61
+
62
+ So provision has **two entry shapes**, and each subfolder's *detect* step picks between them:
63
+
64
+ - **An empty headless shell already exists for the domain → adopt it and *swap* it to the chosen
65
+ backend. Never call `start-setup` again, never create a second site.** The swap is backend-specific:
66
+ - **WordPress** → install WordPress **into the existing shell's `/cms`** with
67
+ `wordpress_installations_install { type: "headless" }` (it rewrites the root `.htaccess` and marks
68
+ the site headless-WordPress). Do **not** use `start-setup { type: "headless_wordpress" }` — that is
69
+ only for creating a fresh site.
70
+ - **Ecommerce** → the empty headless shell **is** the storefront host already (a `headless_ecommerce`
71
+ website installs no store engine either). Adopt it as the frontend host and go straight to creating
72
+ the store + custom sales channel.
73
+ - **No site exists for the domain at all → create it fresh, exactly as each subfolder defines today**
74
+ (`start-setup` with the backend's own `type`).
75
+
76
+ > **Webapp is not part of this handoff at all.** `webapp` is **not** reached on the usual onboarding
77
+ > flow — it is only triggered by experimental actions — so it **ignores headless instances entirely**:
78
+ > it never detects, adopts or swaps an empty headless shell, and provisions its own **Node.js app host**
79
+ > exactly as `webapp/SKILL.md` defines today. The swap below is **WordPress and Ecommerce only**.
80
+
81
+ **How to tell an empty shell from an already-provisioned backend** (both read `website_type: headless`):
82
+
83
+ 1. Exact-match the domain row in `hosting_websites_list` — if there is **no** row, nothing exists → create fresh.
84
+ 2. Within 24 h of onboarding, `hosting_websites_list-setups` still shows the setup `type`
85
+ (`headless_empty` = empty shell; `headless_wordpress` = WordPress already; `headless_ecommerce` = an
86
+ ecommerce host). Beyond 24 h the setup drops off — fall back to the backend probe:
87
+ 3. `wordpress_installations_list { username, domain, ownership: "all" }` — a row with `directory: "cms"`
88
+ and `is_valid: true` means WordPress is **already** installed (adopt, don't swap); **no** such row on
89
+ a `headless` site means the shell is still empty and WordPress must be swapped in. A local `site.json`
90
+ with a recorded backend means a previous run already provisioned — trust reality over it, but it tells
91
+ you not to expect an empty shell.
92
+
93
+ This only changes *detect*. Everything after the swap (verify, `site.json`, the WooCommerce tail, the
94
+ background fire/join split) is identical to a fresh provision. A swap that installs WordPress is still
95
+ asynchronous — fire it, record `provision.in_progress`, and join at the barrier just like a fresh create.
41
96
 
42
97
  ## Step 2 — Fire (don't block)
43
98