Deploy Jay Apps to Wix BaaS
Deploying to Wix BaaS
DevOps Agent Kit — documentation written for AI agents, readable by humans.
Overview
The wix-deploy plugin deploys Jay Framework apps to Wix BaaS (serverless). It bundles the server code into a single entry.mjs, uploads page data to a Wix data collection, and deploys to BaaS + CDN.
npm run build:production # build frontend + backend
npm run deploy # bundle + upload + deploy
Setup (First Time)
1. Create the Wix headless site
npm create @wix/new@latest init
Creates wix.config.json with appId and siteId. This is the deployment target — the BaaS worker and CDN assets go here.
2. Add Wix applications
In the Wix Business Manager, add the applications your project needs (e.g., Wix Stores, Wix Data). This is done on the backend services site — which may be the same site as the deployment target, or a different one in a headless setup.
3. Create an API key
In the Wix dashboard (API Keys section), create an API key with permissions for:
- Wix Data (read/write) — for the backend files data collection
- Any APIs your app uses (Stores, CMS, etc.)
4. Configure credentials
Add the API key to config/.wix.yaml. Running jay-stack-cli setup will fill in clientId and siteId from wix.config.json automatically — you only need to add the API key.
apiKeyStrategy:
apiKey: <your-api-key>
siteId: <auto-filled-from-wix-config>
oauthStrategy:
clientId: <auto-filled-from-wix-config>
5. Authenticate with Wix CLI
Run in your terminal:
npx @wix/cli login
Stores OAuth tokens in ~/.wix/auth/. The deploy command refreshes expired tokens automatically.
5b. Grant Velo deploy permissions to the headless application
Open the permissions dashboard for your headless application (appId from wix.config.json):
https://manage.wix.com/apps/<appId>/dev-center-permissions
Add:
| Permission | Required for |
|---|---|
VELO.APP_PROJECT_READ |
Reading app project before deploy |
VELO.APP_DEPLOYMENT_CREATE |
Creating and releasing deployments |
Site co-owner access is not enough — the headless application must have these permissions. Without them, deploy fails with 403 at "Creating deployment...".
After adding permissions, refresh the CLI session in your terminal:
npx @wix/cli logout
npx @wix/cli login
6. Create the data collection
Create a collection named jay-backend-files in the Wix dashboard (on the business site, where .wix.yaml points). Required fields:
| Field | Type | Description |
|---|---|---|
path |
Text | Relative file path |
content |
Text | File content |
fileType |
Text | File extension |
sizeBytes |
Number | Content byte length |
category |
Text | eager or lazy |
version |
Text | Build version (semver) |
7. Validate setup
jay-stack-cli setup
Should show all three plugins as configured:
wix-server-client— credentials verifiedwix-deploy— deploy target confirmedwix-stores— Stores API connected
Two Credential Files
The two config files serve different purposes and can point to different Wix sites:
| File | Purpose | Used At | Key Fields |
|---|---|---|---|
config/.wix.yaml |
Backend services — Wix SDK, data collections, Stores API | Build time + BaaS runtime | apiKey, clientId, siteId |
wix.config.json |
Deployment target — BaaS hosting + CDN | Deploy time only | appId, siteId |
Headless architecture: Deploy the BaaS worker to one site (the "app" site via wix.config.json) while accessing products, orders, and content on a different site (the "business" site via .wix.yaml).
Simple setup: Both files point to the same site. The clientId in .wix.yaml equals appId in wix.config.json.
Deploy Command
wix-deploy/deploy (recommended)
jay-stack-cli run wix-deploy/deploy --exclude-plugins aiditor
Internally:
- Bundle
entry.mjs(~2.5 MB) — plugins, server elements, framework code - Parallel:
- Upload backend data files → Wix data collection
- Deploy entry.mjs → BaaS + frontend assets → CDN
Options:
--exclude-plugins <names>— comma-separated plugins to exclude from the bundle--collection-id <name>— data collection name (default:jay-backend-files)--static-base-url <url>— CDN URL prefix for static assets--dry-run— preview without uploading
Individual commands (for debugging)
jay-stack-cli run wix-deploy/build-entry # bundle entry.mjs only
jay-stack-cli run wix-deploy/upload-backend # upload data files only
jay-stack-cli run wix-deploy/deploy-baas # deploy to BaaS + CDN only
Local Testing
node serve.mjs
Starts a local server at http://localhost:4000. Generated by wix-deploy/build-entry alongside dist/entry.mjs.
By default, uses WixDataArtifactStore (same as production) — lazy artifacts (page-parts.json, cache files) are fetched from the Wix data collection for the deployed build version. Deploy first, or set JAY_BACKEND_DIR=build/v*/backend to test a fresh local build offline.
See Troubleshooting → Local serve.mjs vs production below.
What Gets Deployed Where
┌─────────────────────────────────────────────────────────┐
│ entry.mjs (2.5 MB) → Wix BaaS │
│ │
│ Bundled by esbuild: │
│ ├── Framework serve code │
│ ├── Plugin code (wix-stores, wix-cart, etc.) │
│ ├── Server element modules (SSR render functions) │
│ ├── ssr-runtime (inlined) │
│ ├── Wix SDK (@wix/sdk, @wix/stores, etc.) │
│ ├── WixDataArtifactStore (data collection client) │
│ └── MODULE_REGISTRY (pre-imported module lookups) │
│ │
│ No node_modules on disk. No dynamic import() at runtime.│
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ Wix Data Collection (jay-backend-files) │
│ │
│ Eager (loaded on cold start): │
│ ├── route-manifest.json │
│ └── build-metadata.json │
│ │
│ Lazy (fetched per-route, cached in /tmp): │
│ ├── page-parts.json (per route) │
│ └── *.cache.json (per page instance) │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ Wix CDN │
│ │
│ ├── shared/*.js (framework client runtime) │
│ ├── pages/**/*.js (route client bundles + hydrate) │
│ └── pages/**/*.css (route stylesheets) │
└─────────────────────────────────────────────────────────┘
Updating After Data Changes
When products or CMS content changes, the renderer server updates page files in the data collection. The BaaS instance picks up changes on the next request for that page (cache miss triggers a fresh fetch).
To redeploy code changes: npm run build:production && npm run deploy.
Troubleshooting
Deploy fails with 403 (Velo permissions)
Symptom:
[deploy] baas | Creating deployment...
403 Forbidden — Permission 'VELO.APP_PROJECT_READ' denied for app with id '<appId>'
Cause: The headless application (appId in wix.config.json) is missing Velo deploy permissions. Site co-owner access does not grant deploy rights to the application.
Fix:
Open
https://manage.wix.com/apps/<appId>/dev-center-permissions(replace<appId>with the value fromwix.config.json)Add:
VELO.APP_PROJECT_READVELO.APP_DEPLOYMENT_CREATE
In your terminal, refresh the Wix CLI session:
npx @wix/cli logout npx @wix/cli loginRetry:
npm run deploy
Verify: npx @wix/cli whoami
Live site returns 500 after successful deploy
1. Regenerate entry.mjs after adding local modules
Symptom: Module not found in registry: server/components/...
Cause: Local server modules are not in MODULE_REGISTRY inside entry.mjs. npm run deploy runs build-entry internally, but if you test locally with an old dist/entry.mjs, modules may be missing.
Fix:
npm run build:production
jay-stack-cli run wix-deploy/build-entry
node serve.mjs # local smoke test
npm run deploy
For other runtime 500 causes (e.g. stale page-parts.json, fast-phase ViewState), see Jay design log #174 and agent-kit devops/production-build.md.
2. Move validators to devDependencies
Symptom: Deploy succeeds; runtime errors mention walkElements, resolveBinding, or parseTemplateParts stubs.
Cause: @jay-framework/wix-media, seo-validator, or a11y-validator in dependencies get bundled into entry.mjs. They are build-time only.
Fix: Move to devDependencies in package.json, then rebuild and redeploy.
Local serve.mjs vs production
| Mode | How | When to use |
|---|---|---|
| Default | node serve.mjs |
Production-like: WixDataArtifactStore, lazy files from data collection |
| Filesystem | JAY_BACKEND_DIR=build/v*/backend node serve.mjs |
Test a fresh local build without redeploying |
Note: Filesystem mode dynamic-imports server modules from disk. Service resolution can differ from the bundled entry.mjs on BaaS. Prefer default mode to match production, or redeploy first so the data collection has current artifacts.
Deploy checklist (quick)
jay-stack-cli setup
npx @wix/cli login
npm run build:production
npm run deploy
curl -s -o /dev/null -w "%{http_code}\n" https://<your-release-url>/
About this document
This page is part of the Jay Stack Agent Kit — documentation generated from the framework source and written primarily for AI agents. The language and structure are optimized for machine consumption — expect precise, specification-style prose rather than narrative documentation. Learn more about the Agent Kit →