feat: add ClientCard and ClientsList components to MDXComponents

This commit is contained in:
kastov
2025-10-10 18:09:37 +03:00
parent 917092db54
commit d349be4f3b
9 changed files with 1329 additions and 0 deletions

89
docs/clients.mdx Normal file
View File

@@ -0,0 +1,89 @@
---
sidebar_position: 8
title: 📱 Clients
hide_title: true
hide_table_of_contents: true
description: 'A comprehensive list of proxy clients that work with Remnawave across all platforms - Android, iOS, Windows, macOS, and Linux. Find the perfect client for your needs.'
---
<HeroSection
title="Clients"
subtitle="A comprehensive list of proxy clients that work with Remnawave. Choose the best client for your platform and preferred proxy core."
/>
<CategoryNav
categories={[
{ id: 'android', icon: '📱', title: 'Android' },
{ id: 'windows', icon: '💻', title: 'Windows' },
{ id: 'ios', icon: '🍎', title: 'iOS' },
{ id: 'macos', icon: '👛', title: 'macOS' },
{ id: 'linux', icon: '🐧', title: 'Linux' }
]}
/>
<CategorySection
id="android"
title="Android"
description="Proxy clients for Android devices"
icon="📱"
columns={3}
>
<ClientsList platform="android" />
</CategorySection>
<CategorySection
id="ios"
title="iOS"
description="Proxy clients for iOS devices"
icon="🍎"
columns={3}
>
<ClientsList platform="ios" />
</CategorySection>
<CategorySection
id="windows"
title="Windows"
description="Proxy clients for Windows"
icon="💻"
columns={3}
>
<ClientsList platform="windows" />
</CategorySection>
<CategorySection
id="macos"
title="macOS"
description="Proxy clients for macOS"
icon="👛"
columns={3}
>
<ClientsList platform="macos" />
</CategorySection>
<CategorySection
id="linux"
title="Linux"
description="Proxy clients for Linux"
icon="🐧"
columns={3}
>
<ClientsList platform="linux" />
</CategorySection>
---
<div
style={{
textAlign: 'center',
marginTop: '4rem',
padding: '2rem',
borderRadius: '12px'
}}
>
<h3> Notice</h3>
<p>
This list is community-maintained. If you find any broken links or want to add a client,
please open a PR on GitHub.
</p>
</div>

View File

@@ -0,0 +1,210 @@
import GitHubStars from '@site/src/components/GitHubStars'
import Link from '@docusaurus/Link'
import React from 'react'
import clsx from 'clsx'
import styles from './styles.module.css'
type CoreType = 'mihomo' | 'other' | 'singbox' | 'xray'
interface ClientCardProps {
author?: string
authorLink?: string
core: CoreType
coreIcon?: string // SVG icon URL
description: string
featured?: boolean
githubRepo?: string
hwidSupported?: boolean
id?: string
links?: {
docs?: string
download?: string
github?: string
telegram?: string
website?: string
}
platform?: string
title: string
}
const CORE_CONFIG: Record<
CoreType,
{ color: string; darkColor: string; iconSvg?: string; label: string }
> = {
mihomo: {
label: 'Mihomo',
iconSvg: '/clients/mihomo_black.svg',
color: '#3a4f66',
darkColor: '#2a3847'
},
xray: {
label: 'X-Ray',
iconSvg: '/clients/xray_black.svg',
color: '#4a3d5a',
darkColor: '#3a2d4a'
},
singbox: {
label: 'Sing-Box',
iconSvg: '/clients/sb_black.svg',
color: '#2d4a3d',
darkColor: '#1d3a2d'
},
other: {
label: 'Other',
color: '#3d4349',
darkColor: '#2d3339'
}
}
export default function ClientCard({
title,
description,
author,
authorLink,
links,
core,
coreIcon,
featured = false,
hwidSupported = false,
githubRepo,
id,
platform
}: ClientCardProps) {
const clientId =
id ||
title
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '')
const coreConfig = CORE_CONFIG[core] || CORE_CONFIG.other
return (
<div
className={clsx(styles.clientCard, featured && styles.featured)}
data-core={core}
id={clientId}
>
{/* Content */}
<div className={styles.cardContent}>
{/* Badges Row - Always render to maintain consistent spacing */}
<div className={styles.badgesRow}>
{featured && <span className={styles.featuredBadge}></span>}
{hwidSupported && (
<div
className={styles.hwidBadge}
data-tooltip="This client supports sending HWID"
>
<svg fill="currentColor" height="14" viewBox="0 0 16 16" width="14">
<path d="M13.485 1.431a1.473 1.473 0 0 1 2.104 2.062l-7.84 9.801a1.473 1.473 0 0 1-2.12.04L.431 8.138a1.473 1.473 0 0 1 2.084-2.083l4.111 4.112 6.82-8.69a.486.486 0 0 1 .04-.045z" />
</svg>
<span>HWID</span>
</div>
)}
{githubRepo && links?.github && (
<Link className={styles.starsBadge} to={links.github}>
<GitHubStars repo={githubRepo} />
</Link>
)}
</div>
<div className={styles.cardHeader}>
<div className={styles.titleWrapper}>
<h3 className={styles.clientTitle}>
<a className={styles.clientAnchor} href={`#${clientId}`}>
{title}
</a>
</h3>
{author && (
<div className={styles.authorInfo}>
<span className={styles.byText}>by</span>
{authorLink ? (
<Link className={styles.authorLink} to={authorLink}>
{author}
</Link>
) : (
<span className={styles.authorName}>{author}</span>
)}
</div>
)}
{platform && <div className={styles.platformBadge}>{platform}</div>}
</div>
</div>
<p className={styles.description}>{description}</p>
{links && (
<div className={styles.links}>
{links?.download && (
<Link
className={clsx(styles.link, styles.downloadLink)}
to={links.download}
>
<svg fill="currentColor" height="14" viewBox="0 0 16 16" width="14">
<path d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z" />
<path d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3z" />
</svg>
Download
</Link>
)}
{links?.github && (
<Link
className={clsx(styles.link, styles.githubLink)}
to={links.github}
>
<svg fill="currentColor" height="14" viewBox="0 0 16 16" width="14">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z" />
</svg>
GitHub
</Link>
)}
{links?.docs && (
<Link className={clsx(styles.link, styles.docsLink)} to={links.docs}>
<svg fill="currentColor" height="14" viewBox="0 0 16 16" width="14">
<path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v13.5a.5.5 0 0 1-.777.416L8 13.101l-5.223 2.815A.5.5 0 0 1 2 15.5V2zm2-1a1 1 0 0 0-1 1v12.566l4.723-2.482a.5.5 0 0 1 .554 0L13 14.566V2a1 1 0 0 0-1-1H4z" />
</svg>
Docs
</Link>
)}
{links?.telegram && (
<Link
className={clsx(styles.link, styles.telegramLink)}
to={links.telegram}
>
<svg fill="currentColor" height="14" viewBox="0 0 16 16" width="14">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8.287 5.906c-.778.324-2.334.994-4.666 2.01-.378.15-.577.298-.595.442-.03.243.275.339.69.47l.175.055c.408.133.958.288 1.243.294.26.006.549-.1.868-.32 2.179-1.471 3.304-2.214 3.374-2.23.05-.012.12-.026.166.016.047.041.042.12.037.141-.03.129-1.227 1.241-1.846 1.817-.193.18-.33.307-.358.336a8.154 8.154 0 0 1-.188.186c-.38.366-.664.64.015 1.088.327.216.589.393.85.571.284.194.568.387.936.629.093.06.183.125.27.187.331.236.63.448.997.414.214-.02.435-.22.547-.82.265-1.417.786-4.486.906-5.751a1.426 1.426 0 0 0-.013-.315.337.337 0 0 0-.114-.217.526.526 0 0 0-.31-.093c-.3.005-.763.166-2.984 1.09z" />
</svg>
Telegram
</Link>
)}
{links?.website && (
<Link
className={clsx(styles.link, styles.websiteLink)}
to={links.website}
>
<svg fill="currentColor" height="14" viewBox="0 0 16 16" width="14">
<path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm7.5-6.923c-.67.204-1.335.82-1.887 1.855A7.97 7.97 0 0 0 5.145 4H7.5V1.077zM4.09 4a9.267 9.267 0 0 1 .64-1.539 6.7 6.7 0 0 1 .597-.933A7.025 7.025 0 0 0 2.255 4H4.09zm-.582 3.5c.03-.877.138-1.718.312-2.5H1.674a6.958 6.958 0 0 0-.656 2.5h2.49zM4.847 5a12.5 12.5 0 0 0-.338 2.5H7.5V5H4.847zM8.5 5v2.5h2.99a12.495 12.495 0 0 0-.337-2.5H8.5zM4.51 8.5a12.5 12.5 0 0 0 .337 2.5H7.5V8.5H4.51zm3.99 0V11h2.653c.187-.765.306-1.608.338-2.5H8.5zM5.145 12c.138.386.295.744.468 1.068.552 1.035 1.218 1.65 1.887 1.855V12H5.145zm.182 2.472a6.696 6.696 0 0 1-.597-.933A9.268 9.268 0 0 1 4.09 12H2.255a7.024 7.024 0 0 0 3.072 2.472zM3.82 11a13.652 13.652 0 0 1-.312-2.5h-2.49c.062.89.291 1.733.656 2.5H3.82zm6.853 3.472A7.024 7.024 0 0 0 13.745 12H11.91a9.27 9.27 0 0 1-.64 1.539 6.688 6.688 0 0 1-.597.933zM8.5 12v2.923c.67-.204 1.335-.82 1.887-1.855.173-.324.33-.682.468-1.068H8.5zm3.68-1h2.146c.365-.767.594-1.61.656-2.5h-2.49a13.65 13.65 0 0 1-.312 2.5zm2.802-3.5a6.959 6.959 0 0 0-.656-2.5H12.18c.174.782.282 1.623.312 2.5h2.49zM11.27 2.461c.247.464.462.98.64 1.539h1.835a7.024 7.024 0 0 0-3.072-2.472c.218.284.418.598.597.933zM10.855 4a7.966 7.966 0 0 0-.468-1.068C9.835 1.897 9.17 1.282 8.5 1.077V4h2.355z" />
</svg>
Website
</Link>
)}
</div>
)}
{/* Core Badge - Bottom */}
<div className={styles.coreBadge} data-core={core}>
{(coreIcon || coreConfig.iconSvg) && (
<img
alt={coreConfig.label}
className={styles.coreIconSvg}
src={coreIcon || coreConfig.iconSvg}
/>
)}
<span className={styles.coreLabel}>{coreConfig.label}</span>
</div>
</div>
</div>
)
}

View File

@@ -0,0 +1,557 @@
.clientCard {
background: var(--ifm-card-background-color);
border: 1px solid var(--ifm-color-emphasis-200);
border-radius: 12px;
overflow: visible;
transition: all 0.3s ease;
height: 100%;
display: flex;
flex-direction: column;
position: relative;
scroll-margin-top: 100px;
}
.clientCard:hover {
transform: translateY(-4px);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
}
[data-theme='dark'] .clientCard:hover {
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.4);
}
/* Core-specific border colors on hover */
.clientCard[data-core='mihomo']:hover {
border-color: #3a4f66;
}
.clientCard[data-core='xray']:hover {
border-color: #4a3d5a;
}
.clientCard[data-core='singbox']:hover {
border-color: #2d4a3d;
}
.clientCard[data-core='other']:hover {
border-color: #3d4349;
}
[data-theme='dark'] .clientCard[data-core='mihomo']:hover {
border-color: #2a3847;
}
[data-theme='dark'] .clientCard[data-core='xray']:hover {
border-color: #3a2d4a;
}
[data-theme='dark'] .clientCard[data-core='singbox']:hover {
border-color: #1d3a2d;
}
[data-theme='dark'] .clientCard[data-core='other']:hover {
border-color: #2d3339;
}
.featured {
border: 2px solid var(--ifm-color-primary);
background: linear-gradient(
135deg,
var(--ifm-card-background-color) 0%,
rgba(var(--ifm-color-primary-rgb), 0.03) 100%
);
}
/* Core Badge - Bottom of Card */
.coreBadge {
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.6rem 1rem;
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.6px;
margin-top: auto;
border-radius: 0 0 12px 12px;
}
.coreBadge[data-core='mihomo'] {
background: #3a4f66;
color: #d4e3f0;
}
.coreBadge[data-core='xray'] {
background: #4a3d5a;
color: #e5dff0;
}
.coreBadge[data-core='singbox'] {
background: #2d4a3d;
color: #d4f0e0;
}
.coreBadge[data-core='other'] {
background: #3d4349;
color: #e0e3e6;
}
[data-theme='dark'] .coreBadge[data-core='mihomo'] {
background: #2a3847;
color: #b8d0e5;
}
[data-theme='dark'] .coreBadge[data-core='xray'] {
background: #3a2d4a;
color: #d5c8e5;
}
[data-theme='dark'] .coreBadge[data-core='singbox'] {
background: #1d3a2d;
color: #b8e5d0;
}
[data-theme='dark'] .coreBadge[data-core='other'] {
background: #2d3339;
color: #c8ced3;
}
.coreIcon {
font-size: 1.1rem;
line-height: 1;
}
.coreIconSvg {
width: 18px;
height: 18px;
object-fit: contain;
flex-shrink: 0;
}
.coreLabel {
font-size: 0.75rem;
}
/* Badges Row */
.badgesRow {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 0.5rem;
flex-wrap: wrap;
min-height: 28px;
margin-bottom: 0.5rem;
}
.hwidBadge {
display: flex;
align-items: center;
gap: 0.3rem;
padding: 0.35rem 0.65rem;
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
border-radius: 6px;
font-size: 0.65rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
cursor: help;
transition: all 0.2s ease;
position: relative;
z-index: 1;
}
.hwidBadge::before {
content: attr(data-tooltip);
position: absolute;
bottom: calc(100% + 10px);
right: 0;
padding: 0.5rem 0.75rem;
background: var(--ifm-color-emphasis-900);
color: white;
border-radius: 6px;
font-size: 0.75rem;
font-weight: 500;
text-transform: none;
letter-spacing: normal;
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition:
opacity 0.2s ease,
transform 0.2s ease;
transform: translateY(5px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
z-index: 10000;
}
.hwidBadge::after {
content: '';
position: absolute;
bottom: calc(100% + 2px);
right: 15px;
border: 5px solid transparent;
border-top-color: var(--ifm-color-emphasis-900);
opacity: 0;
pointer-events: none;
transition: opacity 0.2s ease;
z-index: 10000;
}
.hwidBadge:hover::before,
.hwidBadge:hover::after {
opacity: 1;
transform: translateY(0);
}
.hwidBadge:hover {
background: #c3e6cb;
border-color: #b1dfbb;
transform: translateY(-1px);
z-index: 10001;
}
[data-theme='dark'] .hwidBadge {
background: #1e4620;
color: #a3d9a5;
border-color: #2d5a2f;
}
[data-theme='dark'] .hwidBadge:hover {
background: #2d5a2f;
border-color: #3d6a3f;
}
[data-theme='dark'] .hwidBadge::before {
background: var(--ifm-color-emphasis-100);
color: var(--ifm-color-emphasis-900);
}
[data-theme='dark'] .hwidBadge::after {
border-top-color: var(--ifm-color-emphasis-100);
}
.starsBadge {
display: flex;
align-items: center;
padding: 0.4rem 0.75rem;
background: #24292e;
color: white;
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 6px;
font-size: 0.75rem;
font-weight: 600;
transition: all 0.2s ease;
text-decoration: none;
cursor: pointer;
}
.starsBadge:hover {
background: #1a1e22;
border-color: rgba(255, 255, 255, 0.2);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
color: white;
text-decoration: none;
}
[data-theme='dark'] .starsBadge {
background: #2d333b;
border-color: rgba(255, 255, 255, 0.15);
}
[data-theme='dark'] .starsBadge:hover {
background: #373e47;
border-color: rgba(255, 255, 255, 0.25);
color: white;
}
/* Card Content */
.cardContent {
padding: 1.25rem;
flex: 1;
display: flex;
flex-direction: column;
gap: 0.85rem;
border-radius: 12px 12px 0 0;
}
.featured .cardContent {
background: linear-gradient(
135deg,
var(--ifm-card-background-color) 0%,
rgba(var(--ifm-color-primary-rgb), 0.03) 100%
);
}
.cardHeader {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 0.5rem;
}
.titleWrapper {
flex: 1;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.clientTitle {
margin: 0;
font-size: 1.15rem;
font-weight: 700;
color: var(--ifm-heading-color);
line-height: 1.3;
}
.clientAnchor {
color: inherit;
text-decoration: none;
}
.clientAnchor:hover {
color: var(--ifm-color-primary);
text-decoration: none;
}
.featuredBadge {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.3rem;
padding: 0.35rem 0.65rem;
background: var(--ifm-color-primary);
color: white;
border-radius: 6px;
font-size: 0.7rem;
font-weight: 600;
flex-shrink: 0;
box-shadow: 0 2px 8px rgba(var(--ifm-color-primary-rgb), 0.3);
}
.authorInfo {
display: flex;
align-items: center;
gap: 0.35rem;
font-size: 0.85rem;
}
.byText {
color: var(--ifm-color-emphasis-600);
font-weight: 400;
}
.authorLink {
color: var(--ifm-color-primary);
text-decoration: none;
font-weight: 600;
transition: all 0.2s ease;
}
.authorLink:hover {
text-decoration: underline;
color: var(--ifm-color-primary-dark);
}
.authorName {
color: var(--ifm-color-emphasis-800);
font-weight: 600;
}
[data-theme='dark'] .byText {
color: var(--ifm-color-emphasis-500);
}
[data-theme='dark'] .authorName {
color: var(--ifm-color-emphasis-700);
}
.platformBadge {
display: inline-block;
padding: 0.2rem 0.5rem;
background: var(--ifm-color-emphasis-100);
color: var(--ifm-color-emphasis-700);
border-radius: 4px;
font-size: 0.7rem;
font-weight: 600;
}
.description {
flex: 1;
margin: 0;
color: var(--ifm-color-emphasis-800);
line-height: 1.5;
font-size: 0.9rem;
}
.links {
display: flex;
flex-wrap: wrap;
gap: 0.4rem;
margin-top: auto;
padding-top: 0.75rem;
border-top: 1px solid var(--ifm-color-emphasis-200);
}
.link {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.35rem;
padding: 0.5rem 0.9rem;
min-height: 36px;
border-radius: 6px;
font-size: 0.8rem;
font-weight: 500;
text-decoration: none;
transition: all 0.2s ease;
white-space: nowrap;
}
.githubLink {
background: #24292e;
color: white;
}
.githubLink:hover {
background: #1a1e22;
color: white;
text-decoration: none;
box-shadow: 0 2px 8px rgba(36, 41, 46, 0.3);
}
[data-theme='dark'] .githubLink {
background: #2d333b;
color: white;
}
[data-theme='dark'] .githubLink:hover {
background: #404852;
color: white;
}
.docsLink {
background: var(--ifm-color-primary-lightest);
color: var(--ifm-color-primary-darker);
}
.docsLink:hover {
background: var(--ifm-color-primary);
color: white;
text-decoration: none;
}
.telegramLink {
background: #0088cc;
color: white;
}
.telegramLink:hover {
background: #006699;
color: white;
text-decoration: none;
}
[data-theme='dark'] .telegramLink:hover {
background: #33adff;
color: white;
}
.websiteLink {
background: #0097a7;
color: white;
}
.websiteLink:hover {
background: #00838f;
color: white;
text-decoration: none;
}
[data-theme='dark'] .websiteLink {
background: #00acc1;
color: white;
}
[data-theme='dark'] .websiteLink:hover {
background: #00bcd4;
color: white;
}
.downloadLink {
background: #475569;
color: white;
}
.downloadLink:hover {
background: #334155;
color: white;
text-decoration: none;
box-shadow: 0 2px 8px rgba(71, 85, 105, 0.3);
}
[data-theme='dark'] .downloadLink {
background: #64748b;
color: white;
}
[data-theme='dark'] .downloadLink:hover {
background: #475569;
color: white;
}
/* Mobile Responsive */
@media (max-width: 768px) {
.coreBadge {
padding: 0.5rem 0.75rem;
font-size: 0.7rem;
gap: 0.4rem;
}
.coreIcon {
font-size: 0.95rem;
}
.coreIconSvg {
width: 16px;
height: 16px;
}
.coreLabel {
font-size: 0.7rem;
}
.badgesRow {
gap: 0.4rem;
}
.hwidBadge,
.starsBadge,
.featuredBadge {
padding: 0.3rem 0.5rem;
font-size: 0.6rem;
}
.cardContent {
padding: 1rem;
gap: 0.75rem;
}
.clientTitle {
font-size: 1rem;
}
.description {
font-size: 0.85rem;
}
.link {
padding: 0.45rem 0.75rem;
min-height: 32px;
font-size: 0.75rem;
}
}

View File

@@ -0,0 +1,43 @@
import React from 'react'
import ClientCard from '@site/src/components/ClientCard'
import type { Client, Platform } from '@site/src/data/clients'
import { getClientsByPlatform } from '@site/src/data/clients'
interface ClientsListProps {
platform: Platform
}
export default function ClientsList({ platform }: ClientsListProps) {
const clients = getClientsByPlatform(platform)
return (
<>
{clients.map((client: Client) => {
// Merge platform-specific download link with general links
const platformDownloadLink = client.downloadLinks?.[platform]
const links = {
...client.links,
...(platformDownloadLink && { download: platformDownloadLink })
}
return (
<ClientCard
key={`${client.id}-${platform}`}
id={`${client.id}-${platform}`}
title={client.name}
description={client.description}
core={client.core}
coreIcon={client.coreIcon}
author={client.author}
authorLink={client.authorLink}
githubRepo={client.githubRepo}
featured={client.badges?.featured}
hwidSupported={client.badges?.hwid}
links={links}
/>
)
})}
</>
)
}

406
src/data/clients.ts Normal file
View File

@@ -0,0 +1,406 @@
/**
* Clients Data Source
*
* This file contains all proxy clients information.
* Each client can support multiple platforms with platform-specific download links.
*
* @example
* {
* id: 'my-client',
* name: 'My Client',
* core: 'mihomo',
* platforms: ['android', 'windows'],
* description: 'Amazing proxy client',
* badges: {
* featured: true, // Shows first on all platforms
* hwid: true // Shows HWID badge
* },
* githubRepo: 'user/repo', // Shows GitHub stars badge
* downloadLinks: {
* android: 'https://play.google.com/...', // Android-specific download
* windows: 'https://github.com/.../releases' // Windows-specific download
* },
* links: {
* github: 'https://github.com/...',
* telegram: 'https://t.me/...',
* website: 'https://...',
* docs: 'https://...'
* }
* }
*/
export type CoreType = 'mihomo' | 'other' | 'singbox' | 'xray'
export type Platform = 'android' | 'ios' | 'linux' | 'macos' | 'windows'
export interface Client {
author?: string
authorLink?: string
badges?: {
featured?: boolean
hwid?: boolean
}
core: CoreType
coreIcon?: string
description: string
downloadLinks?: {
android?: string
ios?: string
linux?: string
macos?: string
windows?: string
}
githubRepo?: string
id: string
links?: {
docs?: string
github?: string
telegram?: string
website?: string
}
name: string
platforms: Platform[]
}
export const CLIENTS: Client[] = [
{
id: 'happ',
name: 'Happ',
core: 'xray',
platforms: ['android', 'ios', 'macos', 'windows'],
description: 'Modern and feature-rich proxy client for Android, iOS, macOS, and Windows.',
badges: {
featured: true,
hwid: true
},
downloadLinks: {
android: 'https://play.google.com/store/apps/details?id=com.happproxy',
ios: 'https://apps.apple.com/us/app/happ-proxy-utility/id6504287215',
macos: 'https://apps.apple.com/us/app/happ-proxy-utility/id6504287215',
windows:
'https://github.com/Happ-proxy/happ-desktop/releases/latest/download/setup-Happ.x86.exe',
linux: 'https://github.com/Happ-proxy/happ-desktop/releases/'
},
links: {
website: 'https://happ.su/main',
telegram: 'https://t.me/happ_chat'
}
},
{
id: 'flclashx',
name: 'FlClashX',
core: 'mihomo',
platforms: ['android', 'windows', 'macos', 'linux'],
description: 'Fork of FlClash with improvements and additional features.',
badges: {
featured: true,
hwid: true
},
githubRepo: 'pluralplay/flclashx',
downloadLinks: {
android: 'https://github.com/pluralplay/FlClashX/releases',
windows: 'https://github.com/pluralplay/FlClashX/releases',
macos: 'https://github.com/pluralplay/FlClashX/releases',
linux: 'https://github.com/pluralplay/FlClashX/releases'
},
links: {
github: 'https://github.com/pluralplay/FlClashX',
telegram: 'https://t.me/flclashx'
}
},
{
id: 'clash-meta-android',
name: 'Clash Meta for Android',
core: 'mihomo',
platforms: ['android'],
description: 'A powerful Mihomo-based proxy client for Android',
githubRepo: 'MetaCubeX/ClashMetaForAndroid',
downloadLinks: {
android: 'https://github.com/MetaCubeX/ClashMetaForAndroid/releases'
},
links: {
github: 'https://github.com/MetaCubeX/ClashMetaForAndroid'
}
},
{
id: 'flclash',
name: 'FlClash',
core: 'mihomo',
platforms: ['android', 'windows', 'macos', 'linux'],
description: 'Multi-platform proxy client based on ClashMeta, simple and easy to use',
githubRepo: 'chen08209/FlClash',
downloadLinks: {
android: 'https://github.com/chen08209/FlClash/releases',
windows: 'https://github.com/chen08209/FlClash/releases',
macos: 'https://github.com/chen08209/FlClash/releases',
linux: 'https://github.com/chen08209/FlClash/releases'
},
links: {
github: 'https://github.com/chen08209/FlClash'
}
},
{
id: 'clash-mi',
name: 'Clash Mi',
core: 'mihomo',
platforms: ['android', 'ios'],
description: 'Mihomo client for Android and iOS (Alpha version)',
links: {
github: 'https://github.com/placeholder/clash-mi'
}
},
{
id: 'onexray',
name: 'OneXray',
core: 'xray',
platforms: ['android', 'ios', 'windows', 'macos', 'linux'],
description: 'Lightweight X-Ray proxy client',
githubRepo: 'OneXray/OneXray',
downloadLinks: {
android: 'https://play.google.com/store/apps/details?id=net.yuandev.onexray',
ios: 'https://apps.apple.com/app/onexray/id6503296188',
windows: 'https://github.com/OneXray/OneXray/releases',
macos: 'https://apps.apple.com/app/onexray/id6503296188',
linux: 'https://github.com/OneXray/OneXray/releases'
},
links: {
github: 'https://github.com/OneXray/OneXray'
}
},
{
id: 'v2rayng',
name: 'V2rayNG',
core: 'xray',
platforms: ['android'],
description: 'Popular and widely-used V2Ray client for Android',
githubRepo: '2dust/v2rayNG',
downloadLinks: {
android: 'https://github.com/2dust/v2rayNG/releases'
},
links: {
github: 'https://github.com/2dust/v2rayNG'
}
},
{
id: 'v2box',
name: 'V2Box',
core: 'xray',
platforms: ['android', 'ios', 'macos'],
description: 'Simple V2Ray client with clean interface',
downloadLinks: {
android: 'https://play.google.com/store/apps/details?id=dev.hexasoftware.v2box',
ios: 'https://apps.apple.com/app/v2box-v2ray-client/id6446814690',
macos: 'https://apps.apple.com/app/v2box-v2ray-client/id6446814690'
}
},
{
id: 'simple-gui-client',
name: 'Simple GUI Client',
core: 'xray',
platforms: ['android'],
description: 'Minimalistic V2Ray GUI client for Android',
author: 'SaeedDev94',
authorLink: 'https://github.com/SaeedDev94',
githubRepo: 'SaeedDev94/Xray',
downloadLinks: {
android: 'https://github.com/SaeedDev94/Xray/releases'
},
links: {
github: 'https://github.com/SaeedDev94/Xray'
}
},
{
id: 'simplexray',
name: 'SimpleXray',
core: 'xray',
platforms: ['android'],
description: 'Straightforward Xray client for Android',
githubRepo: 'lhear/SimpleXray',
downloadLinks: {
android: 'https://github.com/lhear/SimpleXray/releases'
},
links: {
github: 'https://github.com/lhear/SimpleXray'
}
},
{
id: 'singbox',
name: 'sing-box',
core: 'singbox',
platforms: ['android', 'ios', 'macos'],
description: 'Universal proxy platform with multiple protocol support',
links: {
github: 'https://github.com/placeholder/sing-box',
website: 'https://play.google.com/store/apps/placeholder'
}
},
{
id: 'husi',
name: 'Husi',
core: 'singbox',
platforms: ['android'],
description: 'Feature-rich Sing-box based proxy client',
links: {
github: 'https://github.com/placeholder/husi'
}
},
{
id: 'nekobox',
name: 'NekoBox',
core: 'singbox',
platforms: ['android'],
description: 'Sing-box based proxy client with modern UI',
links: {
github: 'https://github.com/placeholder/nekobox'
}
},
{
id: 'karing',
name: 'Karing',
core: 'singbox',
platforms: ['android', 'ios', 'macos', 'windows'],
description: 'Multi-platform proxy client based on Sing-box core',
links: {
github: 'https://github.com/placeholder/karing'
}
},
{
id: 'hiddify',
name: 'Hiddify',
core: 'singbox',
platforms: ['android', 'ios', 'macos', 'windows', 'linux'],
description: 'Sing-box client (⚠️ No updates since October 2024)',
links: {
github: 'https://github.com/placeholder/hiddify'
}
},
{
id: 'prizrakbox',
name: 'Prizrak-Box',
core: 'mihomo',
platforms: ['windows', 'macos', 'linux'],
description:
'Desktop client with custom routing templates (includes built-in templates for Russia)',
githubRepo: 'legiz-ru/Prizrak-Box',
badges: {
hwid: true
},
links: {
github: 'https://github.com/legiz-ru/Prizrak-Box'
}
},
{
id: 'clash-verge',
name: 'Clash Verge',
core: 'mihomo',
platforms: ['windows', 'macos', 'linux'],
description: 'Modern Clash Meta GUI based on Tauri framework',
links: {
github: 'https://github.com/placeholder/clash-verge'
}
},
{
id: 'koalaclash',
name: 'Koala Clash',
core: 'mihomo',
platforms: ['windows', 'macos', 'linux'],
description: 'Fork of Clash Verge Rev with improvements and optimizations.',
githubRepo: 'coolcoala/clash-verge-rev-lite',
badges: {
hwid: true
},
links: {
github: 'https://github.com/coolcoala/clash-verge-rev-lite',
telegram: 'https://t.me/+WCL__GOFzZJkYjZi'
}
},
{
id: 'v2rayn',
name: 'V2rayN',
core: 'xray',
platforms: ['windows', 'macos', 'linux'],
description: 'Popular V2Ray client.',
links: {
github: 'https://github.com/placeholder/v2rayn'
}
},
{
id: 'nekoray',
name: 'NekoRay',
core: 'singbox',
platforms: ['windows', 'macos', 'linux'],
description: 'Feature-rich Sing-box based client.',
links: {
github: 'https://github.com/placeholder/nekoray'
}
},
{
id: 'streisand',
name: 'Streisand',
core: 'xray',
platforms: ['ios', 'macos'],
description: 'X-Ray client (⚠️ sometimes has connection issues)',
links: {
website: 'https://apps.apple.com/placeholder'
}
},
{
id: 'v2raytun',
name: 'V2rayTun',
core: 'xray',
platforms: ['ios', 'macos'],
description: 'V2Ray client with tunnel support',
links: {
website: 'https://apps.apple.com/placeholder'
}
},
{
id: 'stash',
name: 'Stash',
core: 'other',
platforms: ['ios', 'macos'],
description: 'Advanced proxy client ($7)',
links: {
website: 'https://apps.apple.com/placeholder',
docs: 'https://placeholder.wiki'
}
},
{
id: 'shadowrocket',
name: 'ShadowRocket',
core: 'other',
platforms: ['ios', 'macos'],
description: 'Popular proxy client ($3)',
links: {
website: 'https://apps.apple.com/placeholder'
}
},
{
id: 'loon',
name: 'Loon',
core: 'other',
platforms: ['ios', 'macos'],
description: 'Advanced proxy client with scripting support ($8)',
links: {
website: 'https://apps.apple.com/placeholder'
}
}
]
export function getClientsByPlatform(platform: Platform): Client[] {
return CLIENTS.filter((client) => client.platforms.includes(platform)).sort((a, b) => {
const aFeatured = a.badges?.featured ? 1 : 0
const bFeatured = b.badges?.featured ? 1 : 0
return bFeatured - aFeatured
})
}
export function getPlatformClients() {
return {
android: getClientsByPlatform('android'),
ios: getClientsByPlatform('ios'),
windows: getClientsByPlatform('windows'),
macos: getClientsByPlatform('macos'),
linux: getClientsByPlatform('linux')
}
}

View File

@@ -5,7 +5,9 @@ import HeroSection from '@site/src/components/HeroSection'
import CategoryNav from '@site/src/components/CategoryNav'
import GitHubStars from '@site/src/components/GitHubStars'
import ProjectCard from '@site/src/components/ProjectCard'
import ClientsList from '@site/src/components/ClientsList'
import MDXComponents from '@theme-original/MDXComponents'
import ClientCard from '@site/src/components/ClientCard'
import StatsBar from '@site/src/components/StatsBar'
import Button from '@site/src/components/Button'
@@ -15,6 +17,8 @@ export default {
CategoryNav,
GitHubStars,
ProjectCard,
ClientCard,
ClientsList,
ProjectsGrid,
CategorySection,
HeroSection,

View File

@@ -0,0 +1,9 @@
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="30" height="30" rx="8" fill="#0A0A0A"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.81507 7.08697C6.42251 7.12893 6.07955 7.176 6.05289 7.19154C5.97699 7.23582 5.9854 18.3984 6.06135 18.458C6.0927 18.4825 6.58969 18.6008 7.16581 18.7209C8.02187 18.8993 8.29298 18.9392 8.64895 18.9392C9.0112 18.9392 9.09707 18.9262 9.15895 18.8616C9.22607 18.7916 9.23453 18.4889 9.24564 15.7657L9.25792 12.7474L9.3856 12.6438C9.545 12.5144 9.73043 12.5115 9.89802 12.636C9.969 12.6887 10.6305 13.2496 11.3681 13.8824C12.1056 14.5153 12.7555 15.0442 12.8125 15.0576C12.8694 15.0711 13.1065 15.042 13.3394 14.993C14.0241 14.8488 14.3187 14.817 14.9686 14.8168C15.5761 14.8167 16.1707 14.884 16.7271 15.0159C16.8848 15.0533 17.0669 15.0713 17.1317 15.056C17.1964 15.0406 17.499 14.8134 17.804 14.5511C18.4144 14.0261 18.537 13.9207 19.2692 13.2917C19.5443 13.0555 19.7795 12.8525 19.792 12.8407C20.1415 12.5097 20.3533 12.462 20.569 12.6657L20.702 12.7912V18.8055L20.8032 18.8724C20.9868 18.9937 21.6491 18.9609 22.4434 18.791C22.8246 18.7095 23.3003 18.6116 23.5005 18.5736C23.7106 18.5336 23.8886 18.4748 23.9214 18.4344C24.0071 18.3291 24.0045 7.35083 23.9188 7.2402C23.87 7.17724 23.7075 7.14825 23.0202 7.07984C22.5588 7.03393 22.0761 7.00202 21.9476 7.00889L21.714 7.02147L19.2913 9.1044C15.9468 11.9798 16.145 11.8167 16.0379 11.7813C15.9879 11.7648 15.4519 11.7498 14.8467 11.7481C13.8003 11.745 13.7413 11.7405 13.6409 11.6558C13.392 11.446 11.8464 10.1211 10.7342 9.16431C10.0724 8.59492 9.23408 7.87504 8.87123 7.56454L8.21148 7L7.87016 7.00533C7.68241 7.00829 7.20763 7.04501 6.81507 7.08697Z" fill="#FAFAFA"/>
<path d="M15.234 20.1822C15.1299 20.3529 14.8697 20.3529 14.7656 20.1822L14.3752 19.5423C14.2712 19.3717 14.4013 19.1584 14.6095 19.1584H15.3902C15.5983 19.1584 15.7285 19.3717 15.6244 19.5423L15.234 20.1822Z" fill="#FAFAFA"/>
<path d="M6 19.9263C6 19.7614 6.14126 19.6277 6.31551 19.6277H10.6426C10.8168 19.6277 10.9581 19.7614 10.9581 19.9263C10.9581 20.0912 10.8168 20.2249 10.6426 20.2249H6.31551C6.14126 20.2249 6 20.0912 6 19.9263Z" fill="#FAFAFA"/>
<path d="M6.24075 22.8012C6.18247 22.6457 6.26835 22.475 6.43256 22.4199L10.5104 21.05C10.6746 20.9949 10.855 21.0761 10.9133 21.2316C10.9716 21.387 10.8857 21.5577 10.7215 21.6129L6.64363 22.9827C6.47941 23.0379 6.29904 22.9566 6.24075 22.8012Z" fill="#FAFAFA"/>
<path d="M24 19.9263C24 19.7614 23.8587 19.6277 23.6845 19.6277H19.3574C19.1832 19.6277 19.0419 19.7614 19.0419 19.9263C19.0419 20.0912 19.1832 20.2249 19.3574 20.2249H23.6845C23.8587 20.2249 24 20.0912 24 19.9263Z" fill="#FAFAFA"/>
<path d="M23.7592 22.8012C23.8175 22.6457 23.7317 22.475 23.5674 22.4199L19.4896 21.05C19.3254 20.9949 19.145 21.0761 19.0867 21.2316C19.0284 21.387 19.1143 21.5577 19.2785 21.6129L23.3564 22.9827C23.5206 23.0379 23.701 22.9566 23.7592 22.8012Z" fill="#FAFAFA"/>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -0,0 +1,4 @@
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="30" height="30" rx="8" fill="#0A0A0A"/>
<path d="M15 25C14.5193 25 14.0477 24.8692 13.6356 24.6216L7.4192 20.8939C7.02351 20.6571 6.69485 20.3209 6.46782 19.9198C6.24619 19.5198 6.12726 19.07 6.12402 18.6127V10.9746C6.12226 10.5129 6.24076 10.0586 6.46786 9.65653C6.69496 9.25446 7.02282 8.91845 7.4192 8.68157L13.6356 5.36794C14.0499 5.12695 14.5207 5 15 5C15.4793 5 15.9501 5.12695 16.3644 5.36794L22.5808 8.68157C22.9773 8.91855 23.3053 9.25473 23.5324 9.657C23.7595 10.0593 23.8779 10.5138 23.876 10.9757V18.6116C23.8727 19.07 23.7538 19.5198 23.5322 19.9198C23.3051 20.3209 22.9765 20.6571 22.5808 20.8939L16.3644 24.6216C15.9523 24.8692 15.4807 25 15 25ZM15 25V14.7942M23.5203 9.67836L15 14.7942M15 14.7942L6.4797 9.67852M19.7353 16.0096V11.95L10.7469 6.91518" stroke="#FAFAFA" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 949 B

View File

@@ -0,0 +1,7 @@
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="30" height="30" rx="8" fill="#0A0A0A"/>
<path d="M14.5928 14.3694L14.5023 5L11.9683 11.9369L6.90045 14.3694H14.5928Z" fill="#FAFAFA"/>
<path d="M15.5882 14.3694V6.98198L18.2127 11.9369L25 14.3694H15.5882Z" fill="#FAFAFA"/>
<path d="M15.5882 25V15.4504H23.19L18.2127 17.973L15.5882 25Z" fill="#FAFAFA"/>
<path d="M14.5928 23.1982V15.4504H5L12.1493 17.973L14.5928 23.1982Z" fill="#FAFAFA"/>
</svg>

After

Width:  |  Height:  |  Size: 505 B