Intelligent Routing
Navigation shouldn't be hard. pp.redirect(url) acts as a smart traffic controller. It automatically detects if a link is internal or external and chooses the most performant navigation strategy.
Internal Routes
If the domain matches the current origin:
- Uses Soft Navigation (SPA)
-
•Fetches content via AJAX
-
•Updates DOM with View Transitions
External Links
If the domain is different (e.g., google.com):
- Uses Hard Navigation
-
•Sets
window.location.href -
•Full browser refresh
Usage Patterns
// 1. Internal: Smoothly transitions to the settings page
// Triggers loading states and view transitions automatically.
pp.redirect('/account/settings');
// 2. External: Standard browser redirect
// Automatically detects the different origin.
pp.redirect('https://stripe.com/checkout');
// 3. Query Params: Works perfectly with URL construction
const params = new URLSearchParams({ source: 'dashboard' });
pp.redirect(`/users?${params.toString()}`);
Decision Logic
The function uses the native URL API to parse the destination string relative to the current window origin.
| Input URL | Detected Type | Action Taken |
|---|---|---|
| /dashboard | Internal | SPA navigation + push state |
| https://mysite.com/home | Internal (Same Origin) | SPA navigation + push state |
| https://google.com | External |
window.location.href
|
| #top | Anchor | Smooth scroll to element ID |
Navigation lifecycle
SPA link interception is on by default once the runtime mounts — there is no body-level opt-in attribute.
The only opt-out is a[pp-spa="false"], and it disables interception for that single link.
Each navigation dispatches document-level CustomEvents you can listen to from any component script.
| Event | detail |
|---|---|
| pp:navigation:start | { url } |
| pp:navigation:complete | { url } |
| pp:navigation:error | { url, error } |
<script>
const [navigating, setNavigating] = pp.state(false);
pp.effect(() => {
const start = () => setNavigating(true);
const done = () => setNavigating(false);
document.addEventListener('pp:navigation:start', start);
document.addEventListener('pp:navigation:complete', done);
document.addEventListener('pp:navigation:error', done);
return () => {
document.removeEventListener('pp:navigation:start', start);
document.removeEventListener('pp:navigation:complete', done);
document.removeEventListener('pp:navigation:error', done);
};
}, []);
</script>
Swapped region
pp-loading-content="true" marks the region replaced during
navigation. pp-loading-url selects route-specific loading states and
pp-loading-transition takes JSON with fadeIn and
fadeOut values (250 ms default).
Scroll behaviour
pp-reset-scroll="true" controls scroll reset, and
pp-scroll-key sets an author-defined key for per-element scroll restoration across navigations.
Automatic Backend Handling
You rarely need to call this manually after a pp.rpc(...). When an exposed function calls
PP\Request::redirect($url), the server answers 200 plus the
X-PP-Redirect, X-PP-Redirect-Status and
X-PP-Redirect-Replace headers. PulsePoint performs the navigation for you and the call resolves with
{ redirected: true, to }.
Redirects are same-origin only — a cross-origin target is discarded with a console warning.