Skip to content

Agentic UI: Recover the site preview from cached cross-site redirects - #4505

Merged
bcotrim merged 1 commit into
trunkfrom
stu-2217-fix-preview-frontend-port-redirect-cache
Aug 12, 2026
Merged

Agentic UI: Recover the site preview from cached cross-site redirects#4505
bcotrim merged 1 commit into
trunkfrom
stu-2217-fix-preview-frontend-port-redirect-cache

Conversation

@bcotrim

@bcotrim bcotrim commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Related issues

How AI was used in this PR

Claude Code traced the root cause and wrote the change. Diagnosis was driven by a deterministic repro (below) rather than inspection — three plausible causes were ruled out by experiment first.
Manually validated the fix and reviewed the code

Proposed Changes

Site ports are recycled between sites, and every preview shares one persistent webview session. So a permanent redirect cached while a port belonged to one site later hijacks whichever site inherits that port: the frontend tab renders someone else's site while wp-admin and phpMyAdmin look correct.

Users had no way out. Restarting the site, the reload button, switching sites, and restarting the app all fail — Chrome keeps cached 301s through every reload variant, and the redirect leaves the webview parked on the other site's URL, so reloading just reloads that.

The preview now notices when a load it started settles on a different origin and recovers itself, so this heals without the user knowing a cache exists. A Hard refresh item in the ⋮ menu (⌘⇧R) does the same on demand, covering stale caching we can't detect automatically — same-origin cached redirects, stale theme assets. Only the HTTP cache is dropped, so preview logins survive.

Testing Instructions

  1. Create two sites and note their ports (below: A on 8931, B on 8932).
  2. Give B a wp-content/mu-plugins/redirect.php that 301s the front end to A:
    <?php
    add_action( 'template_redirect', function () {
        wp_redirect( 'http://localhost:8931/', 301 );
        exit;
    } );
  3. Open B's preview — it shows A.
  4. Delete the mu-plugin. Confirm the server is clean: curl -sI http://localhost:8932/ returns 200 with no Location.
  5. Switch to A and back to B. B recovers on its own (before this PR it stayed on A permanently).
  6. Check ⋮ → Hard refresh and ⌘⇧R, with focus both inside the preview and in its chrome.
  7. Confirm wp-admin still auto-logs in — the cache clear must not drop cookies.

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?

@bcotrim
bcotrim requested a review from sejas August 11, 2026 12:49
@bcotrim bcotrim changed the title Recover the site preview from cached cross-site redirects Agentic UI: Recover the site preview from cached cross-site redirects Aug 11, 2026
@wpmobilebot

Copy link
Copy Markdown
Collaborator

📊 Performance Test Results

Comparing d0b3eeb vs trunk

app-size

Metric trunk d0b3eeb Diff Change
App Size (Mac) 1406.29 MB 1406.29 MB +0.00 MB ⚪ 0.0%

site-editor

Metric trunk d0b3eeb Diff Change
load 1062 ms 1034 ms 28 ms ⚪ 0.0%

site-startup

Metric trunk d0b3eeb Diff Change
siteCreation 7495 ms 7592 ms +97 ms 🔴 1.3%
siteStartup 2868 ms 2870 ms +2 ms ⚪ 0.0%

Results are median values from multiple test runs.

Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff)

@sejas sejas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bcotrim, what do you think about simplifying the logic and always performing a hard refresh? I didn’t notice any slowness when triggering a hard refresh on my test sites, probably because they’re local and network latency is negligible.

I tested the app, and confirmed there is a new button to produce the hard refresh and it solves the redirection issue. Thanks!

Image

@bcotrim

bcotrim commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

@bcotrim, what do you think about simplifying the logic and always performing a hard refresh? I didn’t notice any slowness when triggering a hard refresh on my test sites, probably because they’re local and network latency is negligible.

Do you mean removing the origin check? I think it's a cheap validation that prevents unnecessary hard reloads, if we do it every time, it means loading —> clear cache —> reload always. Locally it's probably ok, but it's unnecessary.
If this was not what you mean let me know, I'm merging this one to try and include in the release, but happy to do follow-up with your suggestion.

Thanks for the review! 🙇

@bcotrim
bcotrim merged commit 0c6ef38 into trunk Aug 12, 2026
16 checks passed
@bcotrim
bcotrim deleted the stu-2217-fix-preview-frontend-port-redirect-cache branch August 12, 2026 14:01

sejas commented Aug 12, 2026

Copy link
Copy Markdown
Member

All good. Thanks for merging it. It was just a thought that maybe the regular refresh button could clear the cash in all cases, so we wouldn't need a hard refresh option there, and users could easily hard refresh even without knowing. We can reconsider that option in the future based on user feedback. It could also help with some cached CSS and JS when developing a site.

bcotrim added a commit that referenced this pull request Aug 13, 2026
## Related issues

- Follow-up to #4505 /
[STU-2217](https://linear.app/a8c/issue/STU-2217/preview-pane-shows-the-previous-sites-port-on-the-frontend-tab-due-to),
implementing @sejas's review suggestion.

## How AI was used in this PR

Claude Code made the change. It's a net deletion of the surface added in
#4505.

## Proposed Changes

#4505 added a separate "Hard refresh" option so users could shake loose
a stale cached redirect. @sejas pointed out that the regular refresh
button could just do this in all cases — then there's nothing extra to
discover, and it also fixes the everyday annoyance of edited CSS/JS
being served stale during development.

Reloading the preview now always drops the HTTP cache. Cost is limited
to an explicit user action, and previews are local, so a refresh is
cheap. Cookies live in a separate store, so preview logins are
unaffected.

One thing had to come along: clearing the cache isn't enough on its own,
because a cached redirect moves the webview's current entry onto the
other site and `reload()` would reload *that*. Reload now re-navigates
to the site's own URL when it detects it's sitting off-origin, and
reloads normally otherwise.

The dedicated menu item is gone, ⌘⇧R stays as an alias for reload so the
browser habit isn't a dead key, and the automatic recovery from #4505 is
unchanged.

Trade-off: you can no longer reload the preview with a warm cache, so
you can't observe how your site behaves for a returning visitor.

## Testing Instructions

1. With a site running, edit a file its theme loads directly (e.g. add
`body { background: red }` to the active theme's `style.css`).
2. Press ⟳ in the preview — the change shows without any manual cache
clear. Confirm ⌘⇧R does the same.
3. Redirect recovery still works. Create a second site, give the first a
`wp-content/mu-plugins/redirect.php` that 301s its front end to the
second's port:
   ```php
   <?php
   add_action( 'template_redirect', function () {
       wp_redirect( 'http://localhost:<other-port>/', 301 );
       exit;
   } );
   ```
Open its preview (shows the other site), delete the mu-plugin, confirm
`curl -sI` returns `200` with no `Location`, then press ⟳ — it returns
to the right site.
4. Switching away and back should still self-heal without pressing
anything.
5. Confirm wp-admin still auto-logs in after a reload — the cache clear
must not drop cookies.

## Pre-merge Checklist

- [x] Have you checked for TypeScript, React or other console errors?
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.

3 participants