Repository navigation
Conversation
`deploy.mjs` now lets a template cache its public routes on Wix's CDN, without the kit knowing the
template's routes:
- It merges the `route-rules.json` of every deployed vertical (Astro route pattern → rule, e.g.
`{ "maxAge": 3600 }`). A vertical without one isn't cached.
- When any rules were declared, it wires them into `astro.config.mjs`:
`import cacheWix from "@wix/astro-wix-hosting-adapter/cache"`, `cache: { provider: cacheWix() }`
and `routeRules`.
- This is fill-only: a config that already sets `cache` or `routeRules` is left alone.
- It reports `already_wired`, or lists only the routes still missing.
- It raises `@wix/astro-wix-hosting-adapter` to `^3.0.2` when the range's floor is lower. 3.0.2 is
the first release with `/cache`. This is the one scaffold-owned range deploy raises.
- A project without the hosting adapter (another host) isn't wired for Wix's cache at all.
This is a no-op for every template today: none ships a `route-rules.json` until its own PR adds
one. Astro needs no change: `^7.3.2` has stable top-level `cache`/`routeRules`, and the adapter's
peer is `^7.2.0`.
Checked:
- Composing a vertical with rules wires the config.
- A plain CLI scaffold at `^3.0.0` gets raised to `^3.0.2` and wired.
- Re-running reports `already_wired`.
- A vertical without rules (faq) leaves the config and adapter untouched.
## Migrating a template (one PR per template, after this one)
1. **Survey.** A route is cacheable only if its server render is public Wix data. Per-visitor
state must be a `client:load` island. Leave out pages that read the visitor on the server
(account, cart, flows) until the anonymous-identity safeguard ships. Never cache `/`.
2. **Declare the routes.** Add `<vertical>/route-rules.json` with
`{ "<route pattern>": { "maxAge": 3600 } }`, no `tags` and no `swr`.
3. **Errors: 400 / 404 / 500, no client fallback.**
- Readers: by-slug reads stop catching and return `T`. First check live that the endpoint
answers a missing item with 404 `NOT_FOUND`. Change the REST twin the same way.
- Helpers: `isNotFound` stays in the vertical's `*-core.ts`. Add `wix/<vertical>/errors.ts`
with `readFailureResponse`, copied from the blog. Nothing goes in `shared/`, because the
static stack flattens everything into one folder.
- Pages: a missing param → 400. One `try` around the reads, and its `catch` returns
`readFailureResponse(e, …)`. Remove the null checks and the empty-fallback renders.
- Stores keep fetching when unseeded, and set `notFound` via `isNotFound`.
- Non-fatal decoration reads keep their fallback.
4. **ETag.** Add one only when a single version value covers everything the route outputs. Never
on a detail page that also shows related data.
5. **INSTRUCTIONS.md.** Only the contract changes (`errors.ts`; `notFound` / `isNotFound` instead
of `null`) and one caching rule.
6. **Regenerate.**
- Run `node skills/wix-headless-templates/compose.mjs <vertical>`. The lock must have the
adapter at ≥3.0.2, with public npm URLs.
- In a scratch copy, run `npm ci`, `astro build` with dummy `WIX_CLIENT_*` values, and
`tsc --noEmit`.
- `deploy.mjs <vertical> --stack static` must report no error.
- Commit the source and `project/`.
7. **Validate live.**
- `install/setup.mjs --vertical <v> --plan plan.json --business-name …` creates and seeds the
site. Use local cover images.
- Build and release.
- curl every route, and run a browser check.
- With the `conductor_override` header, check HIT and MISS. Then, for every editable entity,
make one change through the API and time each affected page until it shows the change.
Finish with a release.
The blog is the first template migrated, in a PR stacked on this one.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 14, 2026
Author
|
#skipreview |
aoded
enabled auto-merge (squash)
October 14, 2026 14:30
Author
|
#skipreview |
Author
|
#forcemerge |
Author
|
Moved to wix-private/ax-skills#35: wix/skills is now a read-only mirror of wix-private/ax-skills. |
auto-merge was automatically disabled
October 15, 2026 12:49
Pull request was closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
deploy.mjsnow lets a template cache its public routes on Wix's CDN, without the kit knowing thetemplate's routes:
route-rules.jsonof every deployed vertical (Astro route pattern → rule, e.g.{ "maxAge": 3600 }). A vertical without one isn't cached.astro.config.mjs:import cacheWix from "@wix/astro-wix-hosting-adapter/cache",cache: { provider: cacheWix() }and
routeRules.cacheorrouteRulesis left alone.already_wired, or lists only the routes still missing.@wix/astro-wix-hosting-adapterto^3.0.2when the range's floor is lower. 3.0.2 isthe first release with
/cache. This is the one scaffold-owned range deploy raises.This is a no-op for every template today: none ships a
route-rules.jsonuntil its own PR addsone. Astro needs no change:
^7.3.2has stable top-levelcache/routeRules, and the adapter'speer is
^7.2.0.Checked:
^3.0.0gets raised to^3.0.2and wired.already_wired.Migrating a template (one PR per template, after this one)
state must be a
client:loadisland. Leave out pages that read the visitor on the server(account, cart, flows) until the anonymous-identity safeguard ships. Never cache
/.A template that ships no pages (storefront, cms, forms) skips step 2 and gets steps 3 and 5
only: its readers throw, it gains
errors.ts, and its INSTRUCTIONS.md page skeletons returnreadFailureResponseand say which of the agent's pages to cache (Astro.cache.setor arouteRulesentry). Validate on a page built from the skeleton on the test site.<vertical>/route-rules.jsonwith{ "<route pattern>": { "maxAge": 3600 } }, notagsand noswr.T. First check live that the endpointanswers a missing item with 404
NOT_FOUND. Change the REST twin the same way.isNotFoundstays in the vertical's*-core.ts. Addwix/<vertical>/errors.tswith
readFailureResponse, copied from the blog. Nothing goes inshared/, because thestatic stack flattens everything into one folder.
[...slug]) → 400; a single[slug]is always set, so keepAstro.params.slug!with no check. Onetryaround the reads, and itscatchreturnsreadFailureResponse(e, …). Remove the null checks and the empty-fallback renders.notFoundviaisNotFound.on a detail page that also shows related data.
errors.ts;notFound/isNotFoundinsteadof
null) and one caching rule.node skills/wix-headless-templates/compose.mjs <vertical>. The lock must have theadapter at ≥3.0.2, with public npm URLs.
npm ci,astro buildwith dummyWIX_CLIENT_*values, andtsc --noEmit.deploy.mjs <vertical> --stack staticmust report no error.project/.install/setup.mjs --vertical <v> --plan plan.json --business-name …creates and seeds thesite. Use local cover images.
conductor_overrideheader, check HIT and MISS. Then, for every editable entity,make one change through the API and time each affected page until it shows the change.
Finish with a release.
The blog is the first template migrated, in a PR stacked on this one.
🤖 Generated with Claude Code