Wix-Deploy-Pipeline
Design Log 22: Wix Deploy Pipeline
Written for AI agents. See Log Methodology Note below for details.
Status
Draft
Background
DL#20 and DL#21 established the technical architecture for deploying Jay Framework apps to Wix BaaS. The deployment works end-to-end (validated on store-light), but the developer experience is fragmented: four manual steps, two credential files, three different tools, and no site creation story.
Current Deployment Sequence
Step 1: npm run build:production
└─ jay-stack-cli build
└─ Produces: build/v1/frontend/ (CDN assets) + build/v1/backend/ (server artifacts)
Step 2: npm run deploy:upload-backend
└─ jay-stack-cli run wix-deploy/upload-backend
└─ Uploads: cache.json, page-parts.json, route-manifest.json → Wix Data Collection
└─ Credentials: config/.wix.yaml (API key + site ID for Wix SDK)
Step 3: npm run deploy:build-entry
└─ jay-stack-cli run wix-deploy/build-entry
└─ Bundles: entry.mjs (2.5 MB) with plugins, server elements, framework → dist/
└─ Also generates: serve.mjs (local testing), config/.wix.yaml copy
Step 4: npm run deploy:deploy
└─ jay-stack-cli run wix-deploy/deploy-baas
└─ Uploads: dist/entry.mjs → BaaS, build/v1/frontend/ → Wix CDN
└─ Credentials: wix.config.json (Wix CLI auth — separate from .wix.yaml)
What Goes Where
| Target | Content | Uploaded By | Credentials |
|---|---|---|---|
| Wix BaaS | entry.mjs (2.5 MB bundled server code) |
Wix CLI (step 4) | wix.config.json |
| Wix CDN | Frontend JS/CSS bundles | Wix CLI (step 4) | wix.config.json |
| Wix Data Collection | cache.json, page-parts.json, manifest | Wix SDK (step 2) | config/.wix.yaml |
| (bundled in entry) | Server elements, plugins, ssr-runtime | esbuild (step 3) | n/a |
Problem
P1: Too Many Steps
Four manual steps to deploy. Steps 2 and 3 are independent and could run in parallel. Steps 1→3→4 are sequential. A developer must remember the correct order.
P2: Two Credential Systems
config/.wix.yaml— Used by@jay-framework/wix-server-clientfor Wix SDK access (API key + site ID). Read at build time and at BaaS runtime. Copied intodist/config/for BaaS.wix.config.json— Used by the Wix CLI for deployment auth. Contains app ID and site reference. Read bywix preview/wix release.
These serve different purposes (SDK access vs deployment), but having two config files is confusing. Can they be unified? Or at least derived from one source?
P3: Setup Sequence
npm create @wix/new init creates a new Wix headless site and outputs wix.config.json. But there are several additional manual steps before deployment works:
- Add Wix applications — e.g., Wix Stores, Wix Data — done from the Wix Business Manager UI. Required for the site to have the APIs the app depends on.
- Create the data collection — the
jay-backend-filescollection used to store deployment JSON files (cache.json, page-parts.json, manifest). Done manually via the Wix dashboard or API. - Create API key and client ID — needed for
config/.wix.yamlso the Wix SDK can access data collections and APIs at runtime (both duringupload-backendand on BaaS). Done via Wix dashboard → API Keys. - Configure
config/.wix.yaml— manually enter the API key, client ID, and site ID.
Steps 1-4 are all done before the first deploy and are currently undocumented — the developer needs to know the Wix platform to complete them. Some could potentially be automated (e.g., creating the data collection via API, generating the API key).
P3.1: Setup Validation
The framework has a setup lifecycle (_serverSetup) that plugins can use to validate their prerequisites at dev/build time:
- wix-server-client already validates credentials — checks that API key and site ID are configured and can authenticate.
- wix-stores / wix-stores-v1 could validate that the Wix Stores application is installed on the site and is the expected version. Currently they don't — if Stores isn't installed, you get opaque API errors at runtime.
- wix-deploy could validate that the data collection exists and is accessible.
Adding setup validation to each plugin would catch misconfiguration early (at jay-stack dev / jay-stack build time) instead of at deploy or runtime.
P4: serve.mjs Confusion
build-entry generates serve.mjs alongside entry.mjs in dist/. The Wix CLI uploads everything in the server output directory. If BaaS picks up serve.mjs instead of entry.mjs, it sets JAY_BACKEND_DIR to a local Mac path, causing the WixDataArtifactStore to be bypassed.
Questions & Answers
Q1: Can we combine steps 2, 3, and 4 into a single deploy command?
A: Yes. Step 4 (deploy-baas) is already multi-step internally (bundles entry, uploads to BaaS, uploads frontend to CDN). All of steps 2-4 should be a single deploy command.
Q2: Can config/.wix.yaml and wix.config.json be unified?
A: Partially. wix.config.json has appId which equals clientId in .wix.yaml, and the site ID can be derived from it too. The only field that can't be derived is the API key — that requires manual creation in the Wix dashboard. So .wix.yaml generation only needs one manual input (the API key).
Q3: npm create @wix/new init creates the site + wix.config.json. Can we derive config/.wix.yaml from it?
A: Mostly — site ID and client ID (appId) can both be derived from wix.config.json. Only the API key requires manual creation in the Wix dashboard. The setup command needs just one manual input.
Q4: Should serve.mjs be generated outside dist/ to avoid accidental upload?
A: Yes. Generate it in the project root instead of dist/.
Q5: What's the minimal deploy experience we're targeting? A: Two commands for day-to-day work, plus a one-time setup:
# One-time setup (after npm create @wix/new init)
jay-stack-cli run wix-deploy/setup # guides through: create data collection, API key, .wix.yaml
# Day-to-day
yarn build # jay-stack-cli build
yarn deploy # jay-stack-cli run wix-deploy/deploy
P5: Two Credential Sets — By Design
The two credential files serve different purposes and intentionally can point to different Wix sites:
| File | Purpose | Used By | Key Fields |
|---|---|---|---|
config/.wix.yaml |
Backend services — Wix SDK access for data collections, Stores API, CMS, etc. | wix-server-client (build + BaaS runtime), upload-backend |
apiKey, clientId (= appId), siteId |
wix.config.json |
Deployment target — which BaaS app + CDN to deploy to | deploy-baas, Wix CLI |
appId, siteId |
Why they can differ: A headless Wix architecture may deploy the BaaS worker to one site (the "app" site) while accessing backend services (Stores, data collections) on a different site (the "business" site). For example:
wix.config.json→ the headless app site (BaaS + CDN hosting)config/.wix.yaml→ the business site (products, orders, CMS content)
For simple deployments where everything is on one site, both files reference the same site ID and app ID (= client ID).
Design
Target Command Structure
jay-stack-cli setup — Runs all plugins' setup hooks, including wix-deploy's
wix-deploy/deploy — Build + upload + deploy (replaces steps 2-4)
wix-deploy/serve — Generate serve.mjs for local testing
The framework already has a setup lifecycle (_serverSetup hook). The wix-deploy plugin registers its setup logic there — no separate CLI command needed. Running jay-stack-cli setup (or the first jay-stack-cli dev) triggers all plugins' setup hooks in order: wix-server-client validates credentials, then wix-deploy creates the data collection, etc.
Deploy Command Internal Flow
jay-stack-cli run wix-deploy/deploy
│
├─ 1. Read build/v1/backend/build-metadata.json
│ └─ Validate build exists, read current version N
│
├─ 2. Increment version to N+1
│ └─ Ensures running version N is not disturbed mid-deploy
│
├─ 3. Bundle entry.mjs with version N+1 baked in
│
├─ 4. Parallel:
│ ├─ Upload backend data files → Wix Data Collection (version N+1)
│ └─ Deploy dist/entry.mjs → BaaS + build/v1/frontend/ → CDN (via Wix CLI)
│
└─ 5. Done — BaaS cold-starts load version N+1 from data collection
Step 4 parallelizes the two upload targets: the data collection (cache.json, page-parts.json, manifest) and BaaS+CDN (entry.mjs, frontend assets). Both use version N+1. The running version N continues serving from the data collection until BaaS cold-starts pick up the new entry.mjs with version N+1.
Versioning
The deploy command owns version incrementing. Currently build-metadata.json has a version field (default 1). The deploy command:
- Reads current version N from
build-metadata.json - Uploads data collection items keyed as
v{N+1}__* - Bakes
N+1into entry.mjs (VERSIONconstant) - Deploys entry.mjs — new BaaS instances read version N+1 from the data collection
This means:
- Running instances serve version N until they cold-start with the new entry.mjs
- Data collection has both version N and N+1 items — no disruption
buildalways produces version 1;deployincrements on each deploy
Q: Should the version be stored in build-metadata.json (updated by deploy) or tracked separately (e.g., in the data collection itself, or in a deploy-state file)?
Setup Flow (via framework setup hook)
jay-stack-cli setup (triggers _serverSetup on all plugins)
│
│ wix-server-client setup (runs first):
├─ 1. Create config/.wix.yaml with placeholders if missing
├─ 2. Validate API key is configured (not placeholder)
│ └─ If missing: log instructions to create one at https://manage.wix.com/...
│
│ wix-deploy setup (runs after wix-server-client):
├─ 3. Validate wix.config.json exists
│ └─ If missing: log instructions to run npm create @wix/new init
├─ 4. Validate: authenticate with Wix SDK
└─ 5. Create data collection "jay-backend-files" via Wix SDK
(if not already exists)
serve.mjs
Separate command (wix-deploy/serve) rather than a side-effect of deploy. Generates serve.mjs in the project root (not dist/) to avoid BaaS uploading it.
Supports two modes:
- Local files (default):
JAY_BACKEND_DIRpoints atbuild/v1/backend/, usesFilesystemArtifactStore - Wix data: no
JAY_BACKEND_DIR, usesWixDataArtifactStore— tests the full BaaS code path locally
Implementation Results (2026-06-04)
Phase 1: Unified Deploy — DONE
Single wix-deploy/deploy command replaces the 3-step sequence. Internally:
- Bundles
entry.mjs(sequential — must complete before deploy) - Uploads backend data to Wix data collection + deploys to BaaS+CDN (parallel)
CLI output is clean with prefixed progress from each parallel step:
[deploy] Bundling entry.mjs...
[deploy] Bundled entry.mjs (2.5 MB) in 4.2s
[deploy] Uploading...
[deploy] data | 25 files (0.1 MB)
[deploy] data | 25/25 files uploaded
[deploy] baas | 28 client + 4 server files (3.6 MB)
[deploy] baas | Creating deployment...
[deploy] baas | Uploading server files...
[deploy] baas | Registering + releasing...
[deploy] baas | Released → https://example.wix-site-host.com
[deploy] Done in 17.8s (bundle 4.2s + deploy 13.6s)
[deploy] Entry: 2.5 MB | Backend files: 25
[deploy] URL: https://example.wix-site-host.com
Sub-commands (build-entry, upload-backend, deploy-baas) still exist for debugging.
serve.mjs moved to project root — no longer in dist/, so BaaS won't upload it.
wix.config.json simplified — only appId and siteId. No outputDirectory needed since we use ctx.build.frontend from the framework (version-aware) and don't use the Wix CLI for deployment.
Phase 2: Setup Hook — DONE
wix-deploy setup hook registered in plugin.yaml, runs during jay-stack-cli setup:
- Reads
appId(=clientId) andsiteIdfromwix.config.json - Updates
config/.wix.yamlonly if values are still placeholders — won't overwrite existing credentials - Validates API key is configured
- Reports deploy target and data collection name
Output:
📦 wix-deploy
✅ Services verified
Deploy target: wix.config.json (appId: 85dad238...). Data collection: jay-backend-files
Version Format Change
Version changed from number to string (semver). All code updated:
build-metadata.json:"version": "2.0.0"(was1)makeItemId: acceptsstringversionWixDataArtifactStore:version: string- Generated entry:
VERSION = '2.0.0'(wasparseInt(...)) - Data collection items keyed as
v2.0.0/pathin hash
Framework also updated: ctx.build.backend resolves to build/v2.0.0/backend (was hardcoded build/v1).
Per-Deploy Version Bump — DONE
The deploy command bumps the patch version in build-metadata.json before bundling:
- Build produces
2.0.0→ first deploy bumps to2.0.1, second to2.0.2, etc. - The bumped version is baked into entry.mjs and used for data collection item keys
- Running BaaS instances continue serving the previous version until cold-start with the new entry.mjs
- Data collection holds items for both versions — no disruption during deploy
Setup: Collection Validation — DONE
The wix-deploy setup hook now validates the data collection exists by querying it. If missing, reports the collection name and required fields. Uses the WIX_CLIENT_SERVICE from the global service registry (available after wix-server-client init).
Remaining Deviations
No wix-deploy/serve command — serve.mjs is still generated as a side-effect of build-entry. Could be separated later but low priority.
Data collection creation not automated — the setup hook validates the collection exists but doesn't auto-create it. Requires manual creation in the Wix dashboard.
Current Deploy Sequence
# One-time setup
npm create @wix/new@latest init # creates wix.config.json
# manually: add API key to config/.wix.yaml
# manually: create jay-backend-files collection
jay-stack-cli setup # validates everything
# Day-to-day
npm run build:production # jay-stack build
npm run deploy # jay-stack-cli run wix-deploy/deploy
Validated On
store-light— deployed to https://store-ligh-cecae80c-yoav68.wix-site-host.comstudio-store— deployed successfully with version 2.0.0
Log Methodology Note
Note: These design logs are written primarily for AI agents as part of the Design Log methodology and made accessible here for human readers. The language and structure are optimized for machine consumption — expect precise, specification-style prose rather than narrative documentation.