Prefer to chat? Query the API with natural language using our AI Skill →
Give your AI tool live Cito endpoint context before you write integration code.
Public docs assistant
Tell Cito API what you are building.
Get endpoint recommendations, exact requests, code snippets, and a free-key CTA without digging through every page.
Leaderboard Systems
Build ranked leaderboards with pagination and filters
Fetching Leaderboard Data
// Get regional leaderboard
const { data, pagination } = await cito.fortnite.leaderboards.get('NA-EAST', {
limit: 100,
page: 1
});
// Response
{
"data": [
{
"rank": 1,
"username": "Bugha",
"points": 45200,
"wins": 23,
"eliminations": 847,
"kd_ratio": 4.21,
"matches": 156,
"change": 2 // Rank change from yesterday
},
// ... more players
],
"pagination": {
"page": 1,
"total_pages": 50,
"total_results": 5000
}
}Leaderboard Component
Leaderboard.tsx
function RankChange({ change }: { change: number }) {
if (change > 0) return <span className="text-green-500">▲ {change}</span>;
if (change < 0) return <span className="text-red-500">▼ {Math.abs(change)}</span>;
return <span className="text-gray-500">—</span>;
}
export function Leaderboard({ region, game }: Props) {
const [page, setPage] = useState(1);
const { data, isLoading } = useQuery({
queryKey: ['leaderboard', game, region, page],
queryFn: () => cito[game].leaderboards.get(region, { page, limit: 50 })
});
return (
<div>
<div className="flex items-center justify-between mb-4">
<h2>{region} Leaderboard</h2>
<RegionSelector value={region} onChange={setRegion} />
</div>
<table className="w-full">
<thead>
<tr>
<th className="text-left">Rank</th>
<th className="text-left">Player</th>
<th className="text-right">Points</th>
<th className="text-right">Wins</th>
<th className="text-right">K/D</th>
<th className="text-right">Change</th>
</tr>
</thead>
<tbody>
{data?.data.map((player) => (
<tr key={player.username}>
<td className="font-bold">
{player.rank <= 3 ? ['🥇', '🥈', '🥉'][player.rank - 1] : player.rank}
</td>
<td>
<Link href={`/player/${player.username}`}>
{player.username}
</Link>
</td>
<td className="text-right">{player.points.toLocaleString()}</td>
<td className="text-right">{player.wins}</td>
<td className="text-right">{player.kd_ratio.toFixed(2)}</td>
<td className="text-right">
<RankChange change={player.change} />
</td>
</tr>
))}
</tbody>
</table>
<Pagination
page={page}
totalPages={data?.pagination.total_pages}
onChange={setPage}
/>
</div>
);
}Player Search
Find a specific player's rank:
// Search for player in leaderboard
const { data } = await cito.fortnite.leaderboards.search('NA-EAST', {
username: 'Bugha'
});
// Response
{
"rank": 1,
"username": "Bugha",
"points": 45200,
"percentile": 0.01 // Top 0.01%
}
// Component
function PlayerRankSearch({ region }) {
const [search, setSearch] = useState('');
const [result, setResult] = useState(null);
const handleSearch = async () => {
const { data } = await cito.fortnite.leaderboards.search(region, {
username: search
});
setResult(data);
};
return (
<div>
<input
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="Search player..."
/>
<button onClick={handleSearch}>Search</button>
{result && (
<div className="mt-4 p-4 bg-secondary">
<p>
{result.username} is ranked <strong>#{result.rank}</strong>
</p>
<p className="text-muted">
Top {(result.percentile * 100).toFixed(2)}%
</p>
</div>
)}
</div>
);
}Performance: Virtual Scrolling
For large leaderboards, use virtual scrolling:
import { useVirtualizer } from '@tanstack/react-virtual';
function VirtualLeaderboard({ players }) {
const parentRef = useRef(null);
const virtualizer = useVirtualizer({
count: players.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 48, // Row height
});
return (
<div ref={parentRef} className="h-[600px] overflow-auto">
<div style={{ height: virtualizer.getTotalSize() }}>
{virtualizer.getVirtualItems().map((virtualRow) => {
const player = players[virtualRow.index];
return (
<div
key={player.username}
style={{
position: 'absolute',
top: virtualRow.start,
height: virtualRow.size,
}}
>
<LeaderboardRow player={player} />
</div>
);
})}
</div>
</div>
);
}