Skip to content

kit: deploy wires each vertical's route-rules.json into Wix CDN caching - #1761

Closed
aoded wants to merge 1 commit into
mainfrom
kit-cache-route-rules
Closed

aoded wants to merge 1 commit into
mainfrom
kit-cache-route-rules

Conversation

@aoded

@aoded aoded commented Oct 14, 2026 •

Copy link
Copy Markdown

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 /.
    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 return
    readFailureResponse and say which of the agent's pages to cache (Astro.cache.set or a
    routeRules entry). Validate on a page built from the skeleton on the test site.
  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 rest param ([...slug]) → 400; a single [slug] is always set, so keep
      Astro.params.slug! with no check. 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.

🤖 Generated with Claude Code

`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>
@aoded

aoded commented Oct 14, 2026

Copy link
Copy Markdown
Author

#skipreview

@aoded
aoded enabled auto-merge (squash) October 14, 2026 14:30
@aoded

aoded commented Oct 14, 2026

Copy link
Copy Markdown
Author

#skipreview

@aoded

aoded commented Oct 14, 2026

Copy link
Copy Markdown
Author

#forcemerge

@aoded

aoded commented Oct 15, 2026

Copy link
Copy Markdown
Author

Moved to wix-private/ax-skills#35: wix/skills is now a read-only mirror of wix-private/ax-skills.

@aoded aoded closed this Oct 15, 2026
auto-merge was automatically disabled October 15, 2026 12:49

Pull request was closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant