Page and Route Skill
This skill helps create and configure pages and routes in the OneKey app-monorepo.
⚠️ WARNING: Page Deletion Policy
DO NOT DELETE PAGES unless you have confirmed there are NO external links to the page.
External links include:
-
Deep links / Universal links
-
QR code handlers
-
Banner click handlers
-
Web URLs shared externally
-
Third-party integrations
-
Marketing materials / Documentation
If you need to remove a page's functionality:
Instead of deleting the route, keep the route registered and modify the page component:
import { Page } from '@onekeyhq/components';
/**
- @deprecated This page has been deprecated since v5.0.0
- New location: packages/kit/src/views/NewFeature/pages/NewPage.tsx
- New route: EModalRoutes.NewFeatureModal -> ENewFeatureRoutes.NewPage
- This page is kept for backward compatibility with external deep links.
- DO NOT DELETE - external links may still reference this route.
*/
function DeprecatedPage() {
return (
<Page
shouldRedirect={() => true} // Always redirect
onRedirected={() => {
// Navigate to replacement page or home
navigation.switchTab(ETabRoutes.Home);
// Or show a toast explaining the change
Toast.info({ title: 'This feature has been moved' });
}}
{null} // Render nothing </Page> ); }
export default DeprecatedPage;
This approach ensures:
-
Users accessing via old deep links are gracefully redirected
-
No broken links or blank screens
-
Analytics can track deprecated route access
-
Backward compatibility is maintained
Page Types
The page types are defined in packages/components/src/hocs/PageType/pageType.ts :
Type Description Animation Behavior
modal
Modal route pages iOS: First page slides from bottom, subsequent pages slide from right. Android: No animation. Web/Desktop/Extension/iPad: Same as iOS but displays as floating popup
stack
Tab route pages (will be renamed from "stack") On small screens, first page shows in bottom tab bar; on large screens, tab shows in sidebar. Subsequent pages slide from right. Android: No animation
fullScreen
Full screen overlay (deprecated) Layer is lower than modal, avoid adding new pages
onboarding
OnboardingV2 full screen pages Full screen overlay on all platforms, layer is below modal
Creating Routes
- Modal Route
Modal routes are configured in packages/kit/src/routes/Modal/router.tsx .
Example: Creating a NotificationsModal route
Step 1: Define Route Enum and Param Types
Create route file packages/shared/src/routes/notifications.ts :
export enum EModalNotificationsRoutes { NotificationList = 'NotificationList', NotificationIntroduction = 'NotificationIntroduction', }
export type IModalNotificationsParamList = { [EModalNotificationsRoutes.NotificationList]: undefined; [EModalNotificationsRoutes.NotificationIntroduction]: undefined; };
Step 2: Add to EModalRoutes Enum
In packages/shared/src/routes/modal.ts :
export enum EModalRoutes { // ... existing routes NotificationsModal = 'NotificationsModal', }
export type IModalParamList = { // ... existing types [EModalRoutes.NotificationsModal]: IModalNotificationsParamList; };
Step 3: Create Router Configuration
Create packages/kit/src/views/Notifications/router/index.ts :
import type { IModalFlowNavigatorConfig } from '@onekeyhq/components'; import { LazyLoadPage } from '@onekeyhq/kit/src/components/LazyLoadPage'; import type { IModalNotificationsParamList } from '@onekeyhq/shared/src/routes/notifications'; import { EModalNotificationsRoutes } from '@onekeyhq/shared/src/routes/notifications';
const NotificationList = LazyLoadPage( () => import('@onekeyhq/kit/src/views/Notifications/pages/NotificationList'), );
const NotificationIntroduction = LazyLoadPage( () => import('@onekeyhq/kit/src/views/Notifications/pages/NotificationIntroduction'), );
export const ModalNotificationsRouter: IModalFlowNavigatorConfig< EModalNotificationsRoutes, IModalNotificationsParamList
[] = [ { name: EModalNotificationsRoutes.NotificationList, component: NotificationList, }, { name: EModalNotificationsRoutes.NotificationIntroduction, component: NotificationIntroduction, }, ];
Step 4: Register in Modal Router
In packages/kit/src/routes/Modal/router.tsx :
import { ModalNotificationsRouter } from '../../views/Notifications/router';
const router: IModalRootNavigatorConfig<EModalRoutes>[] = [ // ... existing routes { name: EModalRoutes.NotificationsModal, children: ModalNotificationsRouter, }, ];
Step 5: Create Page Component
Create packages/kit/src/views/Notifications/pages/NotificationList.tsx :
import { Page } from '@onekeyhq/components';
function NotificationList() { return ( <Page safeAreaEnabled={false}> <Page.Body> {/* Page content */} </Page.Body> </Page> ); }
export default NotificationList;
- Onboarding Route
Onboarding routes are configured in packages/kit/src/views/Onboardingv2/router/index.tsx .
Example: Creating AddExistingWallet page
Step 1: Define Route Enum
In packages/shared/src/routes/onboarding.ts :
export enum EOnboardingPagesV2 { GetStarted = 'GetStarted', AddExistingWallet = 'AddExistingWallet', // ... more pages }
Step 2: Add to Router
In packages/kit/src/views/Onboardingv2/router/index.tsx :
const AddExistingWallet = LazyLoadPage( () => import('../pages/AddExistingWallet'), undefined, false, <OnboardingLayoutFallback />, );
export const OnboardingRouterV2: IModalFlowNavigatorConfig< EOnboardingPagesV2, IOnboardingParamListV2
[] = [ // ... other routes { name: EOnboardingPagesV2.AddExistingWallet, component: AddExistingWallet, options: hiddenHeaderOptions, }, ];
- Tab Route
Tab routes are configured in packages/kit/src/routes/Tab/router.ts .
Example: Creating Market tab with sub-pages
Step 1: Define Route Enum and Params
In packages/shared/src/routes/tabMarket.ts :
export enum ETabMarketRoutes { TabMarket = 'TabMarket', MarketDetail = 'MarketDetail', MarketDetailV2 = 'MarketDetailV2', MarketNativeDetail = 'MarketNativeDetail', MarketBannerDetail = 'MarketBannerDetail', }
export type ITabMarketParamList = { [ETabMarketRoutes.TabMarket]: { from?: EEnterWay } | undefined; [ETabMarketRoutes.MarketDetail]: { token: string }; [ETabMarketRoutes.MarketDetailV2]: { tokenAddress: string; network: string; isNative?: boolean; }; // ... more params };
Step 2: Create Sub-Router
Create packages/kit/src/routes/Tab/Marktet/router.ts :
import type { ITabSubNavigatorConfig } from '@onekeyhq/components'; import { ETabMarketRoutes } from '@onekeyhq/shared/src/routes'; import { LazyLoadRootTabPage, LazyLoadPage } from '../../../components/LazyLoadPage';
const MarketHome = LazyLoadRootTabPage(() => import('../../../views/Market/MarketHome')); const MarketDetail = LazyLoadPage(() => import('../../../views/Market/MarketDetail'));
export const marketRouters: ITabSubNavigatorConfig<any, any>[] = [ { rewrite: '/', name: ETabMarketRoutes.TabMarket, headerShown: !platformEnv.isNative, component: MarketHome, }, { name: ETabMarketRoutes.MarketDetail, component: MarketDetail, rewrite: '/tokens/:token', }, ];
Step 3: Register in Tab Router
In packages/kit/src/routes/Tab/router.ts :
import { marketRouters } from './Marktet/router';
export const useTabRouterConfig = () => { return useMemo(() => { const tabs = [ { name: ETabRoutes.Market, tabBarIcon: (focused?: boolean) => focused ? 'ChartTrendingUp2Solid' : 'ChartTrendingUp2Outline', translationId: ETranslations.global_market, rewrite: '/market', exact: true, children: marketRouters, // Control visibility per platform hiddenIcon: platformEnv.isNative, // Hide on mobile }, // ... other tabs ]; return tabs; }, []); };
Tab Configuration Options:
-
hiddenIcon : Hide tab icon on certain platforms
-
hideOnTabBar : Hide from tab bar but keep route accessible
-
inMoreAction : Show in "More" menu instead of main tab bar
-
freezeOnBlur : Keep tab state when switching tabs
Configuring Page Paths
⚠️ WARNING: Route Paths Must Be Unique
Route paths MUST NOT be duplicated. Each route path must be unique across the entire application.
If duplicate paths are detected, the application will throw an error at startup:
Found conflicting screens with the same pattern. The pattern '/market/tokens/.' resolves to both 'Main > Market > MarketDetail' and 'Main > Market > MarketDetailV2'. Patterns must be unique and cannot resolve to more than one screen.
Common causes of duplicate paths:
-
Two routes using the same rewrite value
-
Forgetting to update path when copying route configuration
-
Child routes with identical path segments
How to avoid:
-
Always use unique rewrite values for each route
-
When adding similar routes, differentiate paths (e.g., /token/:network vs /token/:network/:tokenAddress )
-
Run the app locally to verify no path conflicts before committing
URL Path Configuration
Route paths are calculated in packages/kit/src/routes/config/index.ts via resolveScreens .
resolveScreens Function
interface IScreenRouterConfig { name: string; // Route name (used as default path segment) rewrite?: string; // Override path segment exact?: boolean; // If true, ignores parent paths and uses only rewrite children?: IScreenRouterConfig[]; }
// resolveScreens transforms route config into path config const resolveScreens = (routes: IScreenRouterConfig[]) => routes.reduce((prev, route) => { prev[route.name] = { path: route.rewrite ? route.rewrite : route.name, // Use rewrite or name as path exact: !!route.exact, }; if (route.children) { prev[route.name].screens = resolveScreens(route.children); // Recursive for children } return prev; }, {});
How it works:
-
Each route's name becomes its key in the config
-
The path is either rewrite value (if provided) or name
-
exact flag determines if parent paths are included
-
Children routes are processed recursively
Path Calculation Rules
Rule 1: Default path accumulation Without any configuration, paths accumulate based on route hierarchy:
Route: Main -> Market -> MarketDetail Path: /Main/Market/MarketDetail
Rule 2: rewrite replaces current segment only
// Tab router config { name: ETabRoutes.Market, rewrite: '/market', // Replaces 'Market' with 'market' children: marketRouters, }
// Result: /Main/market/... (only current segment changed)
Rule 3: exact: true truncates all parent paths
{ name: EModalRoutes.SettingModal, children: ModalSettingStack, rewrite: '/settings', exact: true, // Ignores /Modal prefix }
// Without exact: /Modal/settings/... // With exact: /settings/...
Rule 4: Path params with /:param syntax
// In marketRouters { name: ETabMarketRoutes.MarketDetail, component: MarketDetail, rewrite: '/tokens/:token', // :token is a path parameter }
// Result path pattern: /market/tokens/:token // Actual URL example: /market/tokens/bitcoin
Complete Examples
Example 1: Tab Route with rewrite + exact
// Tab router (packages/kit/src/routes/Tab/router.ts) { name: ETabRoutes.Market, rewrite: '/market', exact: true, // Path starts from /market, not /Main/Market children: marketRouters, }
// Sub-router (packages/kit/src/routes/Tab/Marktet/router.ts) export const marketRouters = [ { name: ETabMarketRoutes.TabMarket, rewrite: '/', // Root of /market component: MarketHome, }, { name: ETabMarketRoutes.MarketDetail, rewrite: '/tokens/:token', component: MarketDetail, }, ];
// Resulting paths: // TabMarket: /market/ // MarketDetail: /market/tokens/:token (e.g., /market/tokens/bitcoin)
Example 2: Modal Route with exact
// Modal router (packages/kit/src/routes/Modal/router.tsx) { name: EModalRoutes.SettingModal, children: ModalSettingStack, rewrite: '/settings', exact: true, }
// Resulting path: /settings/... (not /Modal/settings/...)
Example 3: Onboarding Route
// Onboarding router config { name: EOnboardingV2Routes.OnboardingV2, rewrite: '/onboarding', exact: true, children: OnboardingRouterV2, }
// Sub-routes { name: EOnboardingPagesV2.GetStarted, rewrite: '/get-started', component: GetStarted, }
// Resulting path: /onboarding/get-started
Example 4: Native token detail (no tokenAddress in path)
{ name: ETabMarketRoutes.MarketNativeDetail, component: MarketDetailV2, rewrite: '/token/:network', // Only network, no token address }
// URL example: /market/token/eth
Example 5: Non-native token detail (with tokenAddress)
{ name: ETabMarketRoutes.MarketDetailV2, component: MarketDetailV2, rewrite: '/token/:network/:tokenAddress', }
// URL example: /market/token/eth/0x1234...
Path Calculation in buildAllowList
The pagePath template function in routeUtils.ts calculates full paths:
function pagePath(_: TemplateStringsArray, ...screenNames: string[]): string {
const path = screenNames.reduce((prev, screenName) => {
const screen = screenConfig[screenName];
const paths = screen.path.split('/:');
const rawPath = removeExtraSlash(paths[0]);
const screenPath = paths.length > 1 ? ${rawPath}/. : rawPath;
// If exact, use only current path; otherwise, accumulate
return screen.exact ? screenPath : addPath(prev, screenPath);
}, '');
return /${path};
}
// Usage:
pagePath${ERootRoutes.Main}${ETabRoutes.Market}${ETabMarketRoutes.MarketDetail}
// Result: /market/tokens/. (the /. indicates path params follow)
URL Allow List (Browser Display)
By default, routes don't display in the browser URL bar. To enable URL display, configure in packages/shared/src/utils/routeUtils.ts :
export const buildAllowList = (screens, perpDisabled, perpTabShowWeb) => {
const rules = {
// Show URL with parameters
[pagePath${ERootRoutes.Main}${ETabRoutes.Market}${ETabMarketRoutes.MarketDetailV2}]: {
showUrl: true, // Enable URL display
showParams: true, // Show query parameters
},
// Show URL without parameters
[pagePath${ERootRoutes.Main}${ETabRoutes.Swap}${ETabSwapRoutes.TabSwap}]: {
showUrl: true,
showParams: false, // Hide query parameters
},
};
return rules;
};
Note: When adding new pages that need browser URL display, configure them in buildAllowList .
Platform-Specific Routing: Web vs Extension
The routing implementation differs between web/native platforms and browser extension:
Web/Native: Standard Path Routing
File: packages/kit/src/routes/config/getStateFromPath.ts
// Simply re-exports from React Navigation export { getStateFromPath } from '@react-navigation/core';
URL format: https://app.onekey.so/market/tokens/bitcoin
Extension: Hash Routing
File: packages/kit/src/routes/config/getStateFromPath.ext.ts
The extension uses a custom implementation copied from @react-navigation/core with hash routing modifications. The file is marked with // ---CHANGED Begin---- and // ---CHANGED end---- comments to indicate customizations.
Why custom implementation is needed:
-
Browser extensions load from local HTML files (e.g., ui-expand-tab.html )
-
Standard path routing doesn't work with extension URL scheme
-
Hash routing allows navigation without page reload
Key customizations in getStateFromPath.ext.ts :
// 1. Store initial pathname for later use (line 98-100) // ---CHANGED Begin----: initial path from url let initialPath: string | undefined = globalThis.location.pathname; // ---CHANGED end----
// 2. Extract path from hash instead of pathname (line 107-109) export function getStateFromPath<ParamList extends {}>( path: string, options?: Options<ParamList> ): ResultState | undefined { // ---CHANGED Begin----: support hash router path = globalThis.location.hash.split('#').pop() || '/'; // ---CHANGED end---- // ... rest of function }
// 3. Rewrite initial path for focused route (line 731-736) // In createNestedStateObject function: route = findFocusedRoute(state) as ParsedRoute; // ---CHANGED Begin----: rewrite hash path to initial path if (initialPath) { route.path = initialPath; initialPath = undefined; } // ---CHANGED end----
URL format returned (in index.ts line 139):
return ${extHtmlFileUrl}#${newPath};
// Example: /ui-expand-tab.html#/market/tokens/bitcoin
URL format comparison:
Platform URL Format
Web https://app.onekey.so/market/tokens/bitcoin
Extension chrome-extension://xxx/ui-expand-tab.html#/market/tokens/bitcoin
Important notes for extension routing:
-
The # symbol separates the HTML file from the route path
-
Windows Chrome has specific requirements (line 131-137 in index.ts): // /ui-expand-tab.html/#/ NOT working for Windows Chrome // /ui-expand-tab.html#/ works fine
-
When developing extension-specific routes, test on both Mac and Windows Chrome
Extension Routing Modifications Summary
The getStateFromPath.ext.ts file contains 4 key modifications from the original @react-navigation/core implementation:
Location Modification Functional Impact
1 Lines 33-37 Import changes Uses OneKeyLocalError instead of native Error; imports utilities from @react-navigation/core
2 Lines 98-100 let initialPath = globalThis.location.pathname
Stores HTML file path (e.g., /ui-expand-tab.html ) for later use in route state
3 Lines 107-109 path = globalThis.location.hash.split('#').pop()
Core change: Extracts route path from URL hash instead of using passed parameter
4 Lines 731-736 Rewrite route.path with initialPath
Sets focused route's path to initial HTML file path for proper state management
Why these modifications are necessary:
-
Browser extensions run from local HTML files, not a web server
-
Standard path routing (/market/tokens/btc ) doesn't work with chrome-extension:// URLs
-
Hash routing (#/market/tokens/btc ) allows client-side navigation without server requests
-
The initial path storage ensures the extension knows its base HTML file location
Route Path Output by Platform
In packages/kit/src/routes/config/index.ts , the getPathFromState function handles platform differences:
getPathFromState(state, options) { // ... calculate path ...
if (platformEnv.isExtension) {
// Extension: return hash-based URL
if (newPath === '/' && globalThis.location.href.endsWith('#/')) {
return extHtmlFileUrl; // e.g., /ui-expand-tab.html
}
return ${extHtmlFileUrl}#${newPath}; // e.g., /ui-expand-tab.html#/market
}
// Web/Desktop: return standard path return newPath; // e.g., /market }
Page Lifecycle
The Page component supports lifecycle callbacks defined in packages/components/src/layouts/Page/type.ts :
interface IPageLifeCycle { onMounted?: () => void; // Called after page transition completes onUnmounted?: () => void; // Called after page unmount transition completes onCancel?: () => void; // Called when page closed without confirm onConfirm?: () => void; // Called when page closed with confirm onClose?: (extra?: { flag?: string }) => void; // Called on any close onRedirected?: () => void; // Called after redirect completes shouldRedirect?: () => boolean; // Return true to redirect immediately }
Usage in Page Component:
import { Page } from '@onekeyhq/components';
function MyPage() { return ( <Page onMounted={() => console.log('Page mounted')} onUnmounted={() => console.log('Page unmounted')} shouldRedirect={() => !hasPermission} onRedirected={() => navigation.navigate('Login')} > <Page.Body>{/* content */}</Page.Body> </Page> ); }
Use Cases:
Callback Use Case
onMounted
Load data, start animations, track page views
onUnmounted
Cleanup resources, cancel requests
onClose
Save draft, confirm unsaved changes
onCancel
Track cancel actions, cleanup form state
onConfirm
Track confirm actions, submit data
shouldRedirect
Auth guards, permission checks
onRedirected
Navigate to login, show toast
Redirect Pattern:
<Page shouldRedirect={() => { // Return true to immediately go back and trigger onRedirected return !isUserAuthenticated; }} onRedirected={() => { // Called after going back, navigate to appropriate screen navigation.pushModal(EModalRoutes.OnboardingModal, { screen: EOnboardingPages.Login, }); }}
Deep Link / Universal Link Configuration
Configure in packages/kit/src/routes/config/deeplink/index.ts :
Example: Adding invite_share deep link
Step 1: Define Deep Link Path
In packages/shared/src/consts/deeplinkConsts.tsx :
export enum EOneKeyDeepLinkPath { url_account = 'url_account', market_detail = 'market_detail', invite_share = 'invite_share', // Add new path }
export type IEOneKeyDeepLinkParams = { [EOneKeyDeepLinkPath.invite_share]: { utm_source: string; code: string; }; };
Step 2: Handle Deep Link
In packages/kit/src/routes/config/deeplink/index.ts :
async function processDeepLinkUrlAccount(params, times = 0) { const { parsedUrl } = params; const { hostname, queryParams, scheme, path } = parsedUrl;
if (scheme === ONEKEY_APP_DEEP_LINK || scheme === ONEKEY_APP_DEEP_LINK_NAME) { switch (hostname ?? path?.slice(1)) { case EOneKeyDeepLinkPath.invite_share: { const { utm_source: utmSource, code } = queryParams as IEOneKeyDeepLinkParams[EOneKeyDeepLinkPath.invite_share]; if (navigation) { navigation.switchTab(ETabRoutes.ReferFriends, { screen: ETabReferFriendsRoutes.TabReferAFriend, params: { utmSource, code }, }); } break; } } } }
Deep Link Format:
-
onekey-wallet://invite_share?utm_source=twitter&code=ABC123
-
https://app.onekey.so/wc/connect/wc?uri=... (Universal Link)
QR Code / Banner Click Navigation
Configure QR code handlers for scanning and banner clicks.
Example: MARKET_DETAIL handler
Step 1: Define Handler Type
In packages/shared/types/qrCode.ts :
export enum EQRCodeHandlerType { MARKET_DETAIL = 'MARKET_DETAIL', // ... other types }
export enum EQRCodeHandlerNames { marketDetail = 'marketDetail', // ... other names }
export const PARSE_HANDLER_NAMES = { all: [ EQRCodeHandlerNames.marketDetail, // ... other handlers ], };
Step 2: Create Handler
Create packages/kit-bg/src/services/ServiceScanQRCode/utils/parseQRCode/handlers/marketDetail.ts :
import { WEB_APP_URL, WEB_APP_URL_DEV, WEB_APP_URL_SHORT } from '@onekeyhq/shared/src/config/appConfig'; import { EQRCodeHandlerType } from '@onekeyhq/shared/types/qrCode'; import type { IMarketDetailValue, IQRCodeHandler } from '../type';
const marketDetail: IQRCodeHandler<IMarketDetailValue> = async (value, options) => { const urlValue = options?.urlResult; if (urlValue?.data?.urlParamList) { const origin = urlValue?.data?.origin; // Check if URL matches OneKey web app if ( [WEB_APP_URL, WEB_APP_URL_DEV, WEB_APP_URL_SHORT].includes(origin) && urlValue?.data?.pathname.startsWith('/market/tokens/') ) { const coinGeckoId = urlValue?.data?.pathname.split('/market/tokens/').pop(); return { type: EQRCodeHandlerType.MARKET_DETAIL, data: { origin, coinGeckoId }, }; } } return null; };
export default marketDetail;
Step 3: Register Handler
In packages/kit-bg/src/services/ServiceScanQRCode/utils/parseQRCode/handlers/index.ts :
import marketDetail from './marketDetail';
export const PARSE_HANDLERS = { [EQRCodeHandlerNames.marketDetail]: marketDetail, // ... other handlers };
Step 4: Handle Result in UI
In packages/kit/src/views/ScanQrCode/hooks/useParseQRCode.tsx :
const parse = useCallback(async (value, params) => { const result = await backgroundApiProxy.serviceScanQRCode.parse(value, options);
switch (result.type) { case EQRCodeHandlerType.MARKET_DETAIL: { const { coinGeckoId } = result.data as IMarketDetailValue; if (coinGeckoId) { await closeScanPage(); void marketNavigation.pushDetailPageFromDeeplink(navigation, { coinGeckoId }); } break; } } }, [navigation]);
Navigation Methods
// Push modal navigation.pushModal(EModalRoutes.NotificationsModal, { screen: EModalNotificationsRoutes.NotificationList, params: { /* page params */ }, });
// Switch tab navigation.switchTab(ETabRoutes.Market);
// Navigate within tab navigation.navigate(ERootRoutes.Main, { screen: ETabRoutes.Market, params: { screen: ETabMarketRoutes.MarketDetail, params: { token: 'bitcoin' }, }, }, { pop: true, });
// Go back navigation.goBack();
⚠️ IMPORTANT: Always Use pop: true with navigation.navigate
When using navigation.navigate , ALWAYS include the pop: true option to ensure proper navigation stack management:
// ✅ Correct - with pop: true navigation.navigate(ERootRoutes.Main, undefined, { pop: true, });
navigation.navigate(ERootRoutes.Main, { screen: ETabRoutes.Market, params: { screen: ETabMarketRoutes.MarketDetail, params: { token: 'bitcoin' }, }, }, { pop: true, });
// ❌ Wrong - missing pop: true navigation.navigate(ERootRoutes.Main, { screen: ETabRoutes.Market, });
Why pop: true is required:
-
Prevents navigation stack from growing indefinitely
-
Ensures proper back button behavior
-
Avoids memory leaks from accumulated screens
-
Maintains consistent navigation state across platforms
Files Reference
Purpose Location
Page type enum packages/components/src/hocs/PageType/pageType.ts
Modal routes packages/kit/src/routes/Modal/router.tsx
Tab routes packages/kit/src/routes/Tab/router.ts
Onboarding routes packages/kit/src/views/Onboardingv2/router/index.tsx
Route enums packages/shared/src/routes/
URL allow list packages/shared/src/utils/routeUtils.ts
Route config (linking) packages/kit/src/routes/config/index.ts
Web/Native path parser packages/kit/src/routes/config/getStateFromPath.ts
Extension path parser packages/kit/src/routes/config/getStateFromPath.ext.ts
Deep link config packages/kit/src/routes/config/deeplink/index.ts
Deep link consts packages/shared/src/consts/deeplinkConsts.tsx
QR handlers packages/kit-bg/src/services/ServiceScanQRCode/utils/parseQRCode/handlers/
Page component packages/components/src/layouts/Page/index.tsx
Page lifecycle packages/components/src/layouts/Page/hooks.ts