Files
Native-Router-Vue/skills/integrate-native-vue-router/SKILL.md

9.8 KiB

name, description
name description
integrate-native-vue-router Integrate, migrate, configure, or debug Native Vue Router in new or existing Vue 3 applications. Use when adding @native-vue-router/core, converting a Vue Router app to native route surfaces, defining parent or sibling topology, adding gesture links and modal/sheet navigation, handling cached-view lifecycle, composing Vue built-ins with NativeRouterView, creating custom presentations, or wiring Capacitor and Electron adapters.

Integrate Native Vue Router

Implement Native Vue Router as a visual transaction layer around Vue Router. Keep Vue Router authoritative for committed URLs, history, guards, redirects, and route matching.

Read references/integration-reference.md before changing a project. Treat it as the API baseline for version 0.1.x. If the installed package version or local source differs, inspect that version's package.json, exported declarations, and source before editing.

Choose the adoption path

Determine whether the target is:

  • A new Vue application: establish the native route shell and topology while creating the router.
  • An existing Vue Router application: preserve its history mode, routes, guards, redirects, nested outlets, state, and deep links while migrating the visual root and selected navigation calls.
  • A host integration: add the core first, then add Capacitor or Electron as an adapter at the application boundary.
  • A targeted enhancement: adopt imperative animated navigation first and defer predictive gestures or sibling paging.

Do not widen the task into a framework upgrade without user authorization. If the project is below Vue 3.5 or Vue Router 5, report the compatibility gap and the exact upgrade it requires before changing dependencies.

Inspect the target

Before editing, identify:

  1. Package manager, workspace layout, Vue version, and Vue Router version.
  2. The router creation file, history implementation, route records, guards, redirects, scroll behavior, and lazy components.
  3. The app entry and plugin installation order.
  4. Every root and nested RouterView, plus wrappers such as KeepAlive, Transition, and Suspense.
  5. Calls to router.push, router.replace, router.back, RouterLink, tab controls, modal routing, and bespoke swipe handlers.
  6. Route-local side effects in setup/mount hooks, including analytics, subscriptions, polling, media, and mutations.
  7. Deep-linkable child routes, ordered peer routes, and routes whose local state can or cannot be evicted.
  8. Horizontal gesture owners such as carousels, maps, editors, and canvases.
  9. Browser/PWA, Capacitor, Electron, SSR, and accessibility requirements.

Summarize the route topology before implementation when it is non-trivial.

Install and bootstrap

Add @native-vue-router/core and its stylesheet. Add preset or platform packages only when needed. Match the project's package manager and formatting style.

Create exactly one native runtime for one authoritative root route surface:

  1. Create the Vue Router normally.
  2. Pass that router to createNativeRouter.
  3. Call app.use(router) before app.use(nativeRouter).
  4. Wait for router.isReady() when the application already does so or relies on deterministic initial rendering.
  5. Replace the root visual RouterView with NativeRouterView.
  6. Wrap it in NativeNavigator only when predictive Back or sibling paging is required.

Retain nested RouterView components inside route components. Do not add nested independent native runtimes without an explicit ownership design.

Model route topology

Add the smallest route metadata needed for the requested behavior:

  • Use presentation for a route's default visual treatment.
  • Add parent to directly addressable child or presented routes so a cold start has a predictive Back destination.
  • Add numeric siblingOrder to peer routes whose direction must be stable.
  • Choose siblingHistory: "replace" for tabs and other peers that should not grow Back history; use "push" only when Back should revisit peer selection.
  • Use cache: false for routes that must be destroyed when inactive and cache: "pin" only for deliberately retained views.
  • Use gesture: false to disable navigator gesture handling for a route.

Preserve params, query, and hash in dynamic parent functions whenever they are part of the logical parent location. Do not infer parentage from the mounted cache or route registration order.

navigator and siblingGroup are reserved labels in 0.1.x; do not claim that they automatically create navigator ownership. Pass sibling locations to NativeNavigator explicitly.

Migrate navigation intentionally

Use native runtime methods for navigation that needs preview-driven motion:

  • push or NativeLink for forward stack navigation.
  • replace for no-growth replacement.
  • sibling for ordered peers.
  • pop for Back.
  • present and dismiss for modal or sheet routes.
  • NativeSheet for safe-area-contained, content-height, or snapping sheet surfaces.
  • NativeGestureLink for component-originated horizontal dragging.
  • NativeDismissGesture for downward dismissal.

Leave raw Vue Router navigation in place when it is an intentional redirect, non-animated control flow, or external integration. The runtime reconciles such navigation, but it cannot preview it before commit.

Preserve standard link semantics. Prefer NativeLink when a true anchor is needed. If using NativeGestureLink, select a semantic as element and retain keyboard activation and accessible naming.

Make preview mounts safe

Assume a destination can run setup and mount before its route guard approves the navigation, and can then unmount without becoming current.

Move committed-screen side effects from unconditional setup/mount code to useNativeViewActiveEffect, onNativeViewActivate, or explicit user actions. Use useNativeViewVisibleEffect only for work needed while the route is active or participating in a transition. Keep durable data in a store or persistence layer because the bounded native cache may evict component instances.

Do not replace the native multi-route cache with a single Vue KeepAlive. KeepAlive, Transition, Teleport, and Suspense may still be composed inside the NativeRouterView slot. Gate teleported overlays on native view visibility because teleported DOM is outside the inactive layer's inert and aria-hidden boundary.

For partial sheets, use NativeSheet rather than styling a route component with an arbitrary viewport height. Use no breakpoints for content height, or fractional breakpoints for snap points. Keep presentation: "sheet" in route metadata so direct entries retain safe-area and underlay behavior. Preserve the built-in scroll body unless replacing its gesture arbitration: normal content scrolling owns interior positions, while top/down and bottom/up overscroll started at a boundary hands off to sheet resizing. Keep one owner for the complete physical gesture; never reinterpret accumulated content-scroll distance as sheet movement after an edge is reached or direction reverses.

Use scoped useRoute() or Options API $route inside route trees. During a preview, do not substitute router.currentRoute: it intentionally remains the committed source location until navigation succeeds.

Add gesture ownership safely

Wrap only the intended route surface in NativeNavigator. Give the container a definite height and import core CSS.

Mark nested horizontal interaction regions with data-native-gesture="ignore". Confirm vertical scrolling, controls, text selection, RTL behavior, reduced motion, keyboard navigation, focus, and screen reader isolation after adding gestures.

Do not promise deterministic browser-edge ownership. Recommend Capacitor when a product requires native-level suppression of host Back gestures.

Add host adapters at the boundary

For Capacitor, install the adapter in createNativeRouter and configure hardware Back, haptics, deep-link mapping, background cache trimming, and root exit. Do not assume Universal Links or App Links are configured by JavaScript alone.

For Electron, call disableElectronHistoryGestures(app.commandLine) before app.whenReady() in the main process. Expose only the renderer callbacks needed by createElectronRendererAdapter through a secure preload. Preserve hash or custom-protocol history behavior used by packaged applications.

Keep host detection and host APIs out of route components unless the product experience genuinely differs.

Verify the integration

Run the target project's formatter, type checker, unit tests, build, and relevant end-to-end tests. Add tests or manual verification for the changed behavior:

  • Direct entry and reload on deep child URLs.
  • Params, query, hash, redirects, and nested route injection.
  • Both routes remain live during a held gesture while the URL stays unchanged.
  • Gesture cancellation preserves the source URL and state.
  • Accepted and rejected guards settle correctly.
  • Browser Back/Forward and cold-start parent Back.
  • Sibling direction and replace/push history behavior.
  • Cached state, eviction, unload, and active/visible effects.
  • Vue built-ins, provide/inject, Options API $route, and lifecycle hooks used by the application.
  • Teleported overlay cleanup and inactive-route focus isolation.
  • Gesture conflicts, RTL, reduced motion, keyboard behavior, and target hosts.

Use runtime.entries, activeKey, transaction, canGoBack, cacheStats, and onDiagnostic for focused diagnostics. Use the profiler only when measuring frame behavior; it is opt-in and should be stopped/disposed after capture.

Report the result

State which routes and navigation paths became native-aware, which raw Vue Router paths remain intentionally unchanged, what lifecycle work moved, and what was verified. Call out unresolved host limitations, missing parent topology, or dependency incompatibility explicitly.