About orderly-sdk-page-components
A guide to prebuilt page components and routing for developers building DEX applications with the Orderly SDK. Its components cover trading, portfolios, markets, leaderboards, points, vaults, and affiliate pages, with responsive layouts.
Key features
- 01Prebuilt trading and portfolio pages
- 02Market listings and funding comparisons
- 03Leaderboard, points, and vault pages
- 04Affiliate dashboard component
- 05Lazy-loaded pages and Scaffold layouts
- 06Responsive desktop and mobile layouts
Use cases
- 01Assembling DEX pages quickly
- 02Adding positions, orders, and asset pages
- 03Building markets, leaderboard, or points pages
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ orderlynetwork/ skills --skill orderly-sdk-page-componentsAfter installing, type/orderly-sdk-page-componentsin Claude Code to confirm it loaded.
Details
From the project READMEOrderly Network: SDK Page Components
Pre-built, full-featured page components for building a complete DEX. Each page handles responsive design (desktop/mobile), state, and UI. In the reference template every page is lazy-loaded from app/pages/... and wrapped in a shared Scaffold layout.
When to Use
- Building a complete DEX quickly
- Using pre-built, production-ready pages
- Implementing standard DEX pages (trading, portfolio, markets, leaderboard)
Prerequisites
- Orderly SDK packages installed (see
orderly-sdk-install-dependency) - Providers configured (see
orderly-sdk-dex-architecture) - React Router v7 (
react-router-dom)
Overview
| Component | Package | Description |
|---|---|---|
TradingPage | @orderly.network/trading | Full trading interface (chart, orderbook, order entry) |
OverviewModule.OverviewPage | @orderly.network/portfolio | Portfolio dashboard |
PositionsModule.PositionsPage | @orderly.network/portfolio | Positions + history |
OrdersModule.OrdersPage | @orderly.network/portfolio | Orders (open, pending, filled) |
AssetsModule.AssetsPage | @orderly.network/portfolio | Balances, deposit/withdraw |
HistoryModule.HistoryPage | @orderly.network/portfolio | Trade / funding / settlement history |
APIManagerModule.APIManagerPage | @orderly.network/portfolio | API key management |
FeeTierModule.FeeTierPage | @orderly.network/portfolio | Fee tier overview |
SettingModule.SettingPage | @orderly.network/portfolio | Account settings |
MarketsHomePage | @orderly.network/markets | Markets listing + funding comparison |
GeneralLeaderboardWidget | @orderly.network/trading-leaderboard | Trading competition leaderboard |
PointSystemPage | @orderly.network/trading-points | Points/merits program |
VaultsPage | @orderly.network/vaults | Vault/Earn products |
Dashboard.DashboardPage | @orderly.network/affiliate | Affiliate/referral dashboard (inside ReferralProvider) |
Names matter.
GeneralLeaderboardWidget(notLeaderboardPage),PointSystemPage(notTradingRewardsPage; there is notrading-rewardspackage), andVaultsPage. The affiliate page isDashboard.DashboardPage, not a bareDashboard.
The Scaffold Wrapper Pattern
Every route layout in the reference template wraps its <Outlet/> in <Scaffold> from @orderly.network/ui-scaffold, passing nav/footer config (built once in useOrderlyConfig()) and a routerAdapter.
// app/pages/perp/Layout.tsx
import { Outlet } from 'react-router-dom';
import { Scaffold } from '@orderly.network/ui-scaffold';
import { useOrderlyConfig } from '@/utils/config';
import { useNav } from '@/hooks/useNav';
export default function PerpLayout() {
const config = useOrderlyConfig();
const { onRouteChange } = useNav();
return (
<Scaffold
mainNavProps={config.scaffold.mainNavProps}
footerProps={config.scaffold.footerProps}
bottomNavProps={config.scaffold.bottomNavProps}
routerAdapter={{ onRouteChange, currentPath: '/' }}
>
<Outlet />
</Scaffold>
);
}
Each section (perp, portfolio, markets, leaderboard, rewards, vaults, swap, points) has its own Layout.tsx using this pattern.
1. TradingPage
Rendered by app/pages/perp/Symbol.tsx (route /perp/:symbol). tradingViewConfig and sharePnLConfig come from useOrderlyConfig() (which builds them from the active theme + .env config).
// app/pages/perp/Symbol.tsx
import { useCallback, useState } from 'react';
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
import { API } from '@orderly.network/types';
import { TradingPage } from '@orderly.network/trading';
import { useOrderlyConfig } from '@/utils/config';
export default function PerpSymbol() {
const params = useParams();
const [symbol, setSymbol] = useState(params.symbol!);
const config = useOrderlyConfig();
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const onSymbolChange = useCallback(
(data: API.Symbol) => {
setSymbol(data.symbol);
const qs = searchParams.toString();
navigate(`/perp/${data.symbol}${qs ? `?${qs}` : ''}`);
},
[navigate, searchParams]
);
return (
<div className="h-full">
<TradingPage
symbol={symbol}
onSymbolChange={onSymbolChange}
tradingViewConfig={config.tradingPage.tradingViewConfig}
sharePnLConfig={config.tradingPage.sharePnLConfig}
/>
</div>
);
}
tradingViewConfig
tradingViewConfig: {
scriptSRC: string; // /tradingview/charting_library/charting_library.js
library_path: string; // /tradingview/charting_library/
customCssUrl?: string; // /tradingview/chart.css
colorConfig?: Partial<TradingViewColorConfig>; // only in legacy mode
}
Build it with createTradingViewConfig(themeSource) (see orderly-sdk-theming). TradingView library files must be placed in public/tradingview/charting_library/.
Route is
/perp/:symbol, not/trade. The index route/perpredirects to a default symbol.
2. Portfolio Pages
Portfolio is organized into modules, each with a …Page export. The template routes: portfolio (index), positions, orders, assets, api-key, fee, history, setting.
import {
OverviewModule, PositionsModule, OrdersModule, AssetsModule,
HistoryModule, APIManagerModule, FeeTierModule, SettingModule,
} from '@orderly.network/portfolio';
<OverviewModule.OverviewPage />
<PositionsModule.PositionsPage />
<OrdersModule.OrdersPage sharePnLConfig={config.tradingPage.sharePnLConfig} />
<AssetsModule.AssetsPage />
<HistoryModule.HistoryPage />
<APIManagerModule.APIManagerPage />
<FeeTierModule.FeeTierPage />
<SettingModule.SettingPage />
Portfolio routes (lazy-loaded page components, wrapped by a shared PortfolioLayout using Scaffold):
{
path: 'portfolio',
element: <PortfolioLayout />,
children: [
{ index: true, element: <PortfolioIndex /> }, // OverviewModule.OverviewPage
{ path: 'positions', element: <PortfolioPositions /> },
{ path: 'orders', element: <PortfolioOrders /> },
{ path: 'assets', element: <PortfolioAssets /> },
{ path: 'api-key', element: <PortfolioApiKey /> }, // APIManagerModule.APIManagerPage
{ path: 'fee', element: <PortfolioFee /> }, // FeeTierModule.FeeTierPage
{ path: 'history', element: <PortfolioHistory /> },
{ path: 'setting', element: <PortfolioSetting /> }, // SettingModule.SettingPage
],
}
3. MarketsHomePage
import { MarketsHomePage } from '@orderly.network/markets';
<MarketsHomePage
comparisonProps={{
// name + icon shown in the funding-comparison list (NOT an exchanges array)
exchangesName: import.meta.env.VITE_ORDERLY_BROKER_NAME,
exchangesIconSrc: '/logo-secondary.webp', // optional
}}
onSymbolChange={(symbol) => navigate(`/perp/${symbol.symbol}`)}
/>;
comparisonPropstakesexchangesNameandexchangesIconSrc(both optional), not anexchanges: string[]array.
4. Leaderboard
import { GeneralLeaderboardWidget } from '@orderly.network/trading-leaderboard';
export default function LeaderboardIndex() {
return (
<div className="oui-py-6 oui-px-4 lg:oui-px-6">
<GeneralLeaderboardWidget />
</div>
);
}
5. Points / Rewards
import { PointSystemPage } from '@orderly.network/trading-points';
import { RouteOption } from '@orderly.network/types';
export default function PointsIndex() {
const navigate = useNavigate();
const onRouteChange = (p: RouteOption) => {
if (p.href === '/perp') navigate(`/perp/${getSymbol()}`);
};
return <PointSystemPage onRouteChange={onRouteChange} />;
}
6. Vaults
import { VaultsPage as VaultsPageComponent } from '@orderly.network/vaults';
<VaultsPageComponent />;
7. Affiliate / Referral
Render Dashboard.DashboardPage inside <ReferralProvider>:
import { Dashboard, ReferralProvider } from '@orderly.network/affiliate';
export default function AffiliateIndex() {
return (
<ReferralProvider>
<Dashboard.DashboardPage />
</ReferralProvider>
);
}
Routing
Routes are defined in app/main.tsx with createBrowserRouter and a basename of import.meta.env.BASE_URL. All pages are lazy-loaded.
const router = createBrowserRouter(
[
{
path: '/',
element: <App />,
errorElement: <ErrorBoundary />,
children: [
{ index: true, element: <IndexPage /> },
{
path: 'perp',
element: <PerpLayout />,
children: [
{ index: true, element: <PerpIndex /> },
{ path: ':symbol', element: <PerpSymbol /> },
],
},
{
path: 'portfolio',
element: <PortfolioLayout />,
children: [
/* …see above… */
],
},
{
path: 'markets',
element: <MarketsLayout />,
children: [{ index: true, element: <MarketsIndex /> }],
},
{
path: 'leaderboard',
element: <LeaderboardLayout />,
children: [{ index: true, element: <LeaderboardIndex /> }],
},
{
path: 'rewards',
element: <RewardsLayout />,
children: [
{ index: true, element: <RewardsIndex /> },
{ path: 'affiliate', element: <RewardsAffiliate /> },
],
},
{
path: 'vaults',
element: <VaultsLayout />,
children: [{ index: true, element: <VaultsIndex /> }],
},
{
path: 'swap',
element: <SwapLayout />,
children: [{ index: true, element: <SwapIndex /> }],
},
{
path: 'points',
element: <PointsLayout />,
children: [{ index: true, element: <PointsIndex /> }],
},
],
},
],
{ basename: basePath }
);
Responsive Design
Page components handle desktop/mobile internally. Use useScreen() (from @orderly.network/ui) for your own layout decisions:
import { useScreen } from '@orderly.network/ui';
const { isMobile } = useScreen();
Best Practices
- Lazy-load every page (the template imports
app/pages/...lazily inmain.tsx). - Wrap routes in
Scaffoldso nav/footer/account menu are consistent. - Persist the symbol (the template calls
updateSymbol(symbol)on change) so deep links and the index route restore it. - Drive
tradingViewConfig/sharePnLConfigfromuseOrderlyConfig()so they follow the active theme. - Use
onSymbolChangeto update the URL for bookmarkable trading pages.
Related Skills
- orderly-sdk-dex-architecture - Project structure, providers, routing entry point
- orderly-sdk-theming - Theme config behind
tradingViewConfig - orderly-sdk-trading-workflows - Trading functionality details
- orderly-ui-components - Granular widgets vs. these high-level pages