Cette page est publiée en anglais et en ukrainien ; la version anglaise figure ci-dessous.
Single-page apps (React, Vue, Angular)
For developers, in code: nothing is required; what to add when your router should handle navigation, and when the URL cannot name the screen.
Install the script as on any other site. The widget survives route changes because the page never reloads, and it reads the browser’s URL every time a message is sent — so an in-app route change is picked up without you telling it anything.
Three things are worth adding, each a few lines.
Let your router navigate
When the assistant opens a page it dispatches shukai:action:navigate on window before it
acts, and the event is cancelable. Claim it and route yourself; a full page load in an SPA is a
worse experience than your router.
window.addEventListener("shukai:action:navigate", (e) => {
e.preventDefault(); // ours now — the widget will not navigate
router.push(new URL(e.detail.url).pathname);
});
The event fires whether or not you cancel it, and the analytics beacon that counts the follow
fires either way, so the owner’s «offered → followed» numbers do not depend on who navigated.
Events lists every action event and what preventDefault() does on each.
When the URL cannot name the screen
The assistant knows which screen the user is on by matching the URL against the route patterns the
owner wrote into each screen’s source in the panel (/orders/{id} matches /orders/482 and
yields {id: "482"}). Two cases defeat that: hash routing (/#/orders/42 — the pathname is just
/), and one path serving two different screens. Then declare the route yourself:
router.afterEach((to) => {
Shukai.setContext({ route: to.matched.at(-1).path, params: to.params });
});
Your app already knows its own pattern (Angular route.routeConfig.path, React Router path,
Vue matched[].path). setContext is state, not an action: safe to call before the widget
has mounted, expected on every route change, and a declared route always beats the one matched
from the URL. Limits: a route of up to 255 characters, up to 20 params, values strings or
numbers.
Scroll your own container
«Scroll down» moves the page. If your app’s body does not scroll — an app shell with an inner
scroller — the widget finds the largest scrolling element itself, or you name one with
data-sa-scroll on it. To take over entirely, cancel shukai:action:scroll and scroll your
container:
window.addEventListener("shukai:action:scroll", (e) => {
e.preventDefault();
myScroller.scrollBy({ top: e.detail.direction === "down" ? 600 : -600 });
});
Two things that need no code
- The proactive finding (the raised hand) watches the URL once a second to notice a route
change — it does not patch
history.pushStateon your page. - Page actions read the screen again whenever the assistant needs it; an automatic id lasts
only as long as its element, so give your controls a
data-sa-idand ids survive re-renders (Marking up controls).
Logged-in users
For an app, hand the widget the user’s own token after login and clear it on logout, so the assistant can call your API as that user: User identity.