Skip to content

templates: the portfolio caches its public routes on Wix's CDN and answers 404/500 - #1763

Closed
aoded wants to merge 3 commits into
kit-cache-route-rulesfrom
templates-portfolio-caching
Closed

aoded wants to merge 3 commits into
kit-cache-route-rulesfrom
templates-portfolio-caching

Conversation

@aoded

@aoded aoded commented Oct 14, 2026 •

Copy link
Copy Markdown

The second template migrated with the kit's route-rules.json support (#1761; this PR is stacked
on it). It follows the blog (#1762).

What changed

  • Caching
    • portfolio/route-rules.json declares the cached routes (/portfolio, /portfolio/[slug],
      /projects/[slug]), each with maxAge: 3600 and no tags.
    • portfolio/project is recomposed. Its astro.config.mjs wires cacheWix() and the rules,
      and its package.json and lock pin @wix/astro-wix-hosting-adapter 3.0.2.
  • Errors
    • Not found → 404. Any other failed read → 500, and the error
      is logged.
    • The by-slug lookups are queries, and a query answers a missing slug with an empty 200 (checked
      live), so the miss is raised in portfolio-core.ts, which both transports share:
      visibleCollection/visibleProject throw PortfolioNotFoundError for a missing or hidden
      item, and isNotFound recognises it.
    • fetchCollectionBySlug/fetchProjectBySlug return the item itself, on the SDK and REST.
    • Each page's catch calls the template's own readFailureResponse (wix/portfolio/errors.ts).
    • The collection and project stores set notFound from isNotFound(e).
    • The gallery page no longer renders an empty state for a failed read. No
      Astro.cache.set(false) opt-outs: errors are never cached.
  • INSTRUCTIONS.md: the contract changes (errors.ts; notFound / isNotFound instead of
    null for a 404) and a rule describing the caching.

Validation

On a live site created and seeded from this template, released to Wix hosting:

  • Routes: 200 on every route; bogus and hidden collection and project slugs → 404.
  • Browser at desktop and phone width: gallery, collection and project pages work, with no
    console errors or failed requests.
  • Caching: with the conductor_override header, repeat requests are x-cache: HIT, age
    rises, and the server doesn't render again. 404s and / stay MISS.
  • Invalidation: each change below refreshed every page showing it within 3–16 s:
    • project title edited
    • project details row edited
    • project published
    • project hidden (its page → 404, gone from its collection)
    • collection renamed
    • collection hidden, and shown again
    • a release, which clears everything
  • Not refreshed: a gallery item added or edited through the API. See "DON'T MERGE" below.
  • No 400: a [slug] segment is never empty (Astro doesn't match one, and the host redirects
    /projects/ first), so the pages keep Astro.params.slug!.

DON'T MERGE: gallery item changes don't refresh the cache

Adding or editing a Portfolio project item (a gallery image) through the items API doesn't purge
the CDN cache. Project and collection writes do.

  • Checked on the test site: POST /portfolio/v1/items and PATCH /portfolio/v1/items/{id}. The
    project page kept serving its old gallery with age still climbing: twice for 240 s, once for 60 s.
  • Any project or collection write (/portfolio/v1/projects, /portfolio/v1/collections) purges
    every cached page on the site within 3–16 s, even a write that changes no data. After one, the
    new gallery item appeared.
  • The dashboard hides the bug. On every gallery save (add, edit or delete an image) it sends a
    PATCH of the project that re-sends the project unchanged, next to the item call. That PATCH
    bumps the revision, and the project event clears the cache.
  • So any code that writes items directly (an agent, the seed script, an integration) leaves
    project pages stale until the next project or collection change, a release, or maxAge (1 h).
  • Not known: whether Portfolio emits no event for items, or the cache invalidation doesn't
    listen to it. Either way the fix is on the platform side, not in this template.

Merge only after item changes purge the cache on their own.

🤖 Generated with Claude Code

aoded and others added 3 commits October 14, 2026 15:06
…swers 400/404/500

The second template migrated with the kit's `route-rules.json` support (#1761; this PR is stacked
on it). It follows the blog (#1762).

## What changed

- **Caching**
  - `portfolio/route-rules.json` declares the cached routes (`/portfolio`, `/portfolio/[slug]`,
    `/projects/[slug]`), each with `maxAge: 3600` and no tags.
  - `portfolio/project` is recomposed. Its `astro.config.mjs` wires `cacheWix()` and the rules,
    and its `package.json` and lock pin `@wix/astro-wix-hosting-adapter` 3.0.2.
- **Errors**
  - A missing route parameter → 400. Not found → 404. Any other failed read → 500, and the error
    is logged.
  - The by-slug lookups are queries, and a query answers a missing slug with an empty 200 (checked
    live), so the miss is raised in `portfolio-core.ts`, which both transports share:
    `visibleCollection`/`visibleProject` throw `PortfolioNotFoundError` for a missing or hidden
    item, and `isNotFound` recognises it.
  - `fetchCollectionBySlug`/`fetchProjectBySlug` return the item itself, on the SDK and REST.
  - Each page's `catch` calls the template's own `readFailureResponse` (`wix/portfolio/errors.ts`).
  - The collection and project stores set `notFound` from `isNotFound(e)`.
  - The gallery page no longer renders an empty state for a failed read. No
    `Astro.cache.set(false)` opt-outs: errors are never cached.
- **INSTRUCTIONS.md**: the contract changes (`errors.ts`; `notFound` / `isNotFound` instead of
  `null` for a 404) and a rule describing the caching.

## Validation

On a live site created and seeded from this template, released to Wix hosting:
- Routes: 200 on every route; bogus and hidden collection and project slugs → 404.
- Browser at desktop and phone width: gallery, collection and project pages work, with no
  console errors or failed requests.
- Caching: with the `conductor_override` header, repeat requests are `x-cache: HIT`, `age`
  rises, and the server doesn't render again. 404s and `/` stay MISS.
- Invalidation: each change below refreshed every page showing it within 3–16 s:
  - project title edited
  - project details row edited
  - project published
  - project hidden (its page → 404, gone from its collection)
  - collection renamed
  - collection hidden, and shown again
  - a release, which clears everything
- Not refreshed: a gallery item edited or added. No purge follows a project-item change, so the
  project page keeps its old gallery until the next collection or project change (any one purges
  every page), a release, or `maxAge`. INSTRUCTIONS.md says so.
- Not reachable: the 400. An empty `[slug]` redirects (301) before the page runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… gallery-item gap

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A single [slug] segment is never empty: Astro doesn't match an empty one, and the host
redirects the trailing-slash URL first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@aoded aoded changed the title templates: the portfolio caches its public routes on Wix's CDN and answers 400/404/500 templates: the portfolio caches its public routes on Wix's CDN and answers 404/500 Oct 15, 2026
@aoded

aoded commented Oct 15, 2026

Copy link
Copy Markdown
Author

Moved to wix-private/ax-skills#41

@aoded aoded closed this Oct 15, 2026
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