diff --git a/src/components/ClientDetails.css b/src/components/ClientDetails.css
new file mode 100644
index 00000000..5c5bf25e
--- /dev/null
+++ b/src/components/ClientDetails.css
@@ -0,0 +1,80 @@
+/* stylelint-disable docusaurus/copyright-header */
+
+.client__header {
+ display: flex;
+ align-items: center;
+}
+
+.client__header__start {
+ flex-grow: 1;
+ display: flex;
+}
+
+.client__header__start h3 {
+ margin-bottom: 0;
+}
+
+.client__header__start__badges {
+ margin-left: 1rem;
+}
+
+.client__footer {
+ display: flex;
+}
+
+.client__platform-icon {
+ margin-left: 1rem;
+}
+
+.client__footer .button {
+ margin-left: 1rem;
+}
+
+.client__footer .button:first-of-type {
+ margin-left: 0;
+}
+
+@media (max-width: 420px) {
+ .client__header {
+ flex-direction: column;
+ text-align: center;
+ }
+
+ .client__platform-icon {
+ margin-top: 0.5rem;
+ }
+
+ .client__platform-icon:first-of-type {
+ margin-left: 0;
+ }
+
+ .card__body {
+ padding-top: 0;
+ }
+}
+
+@media (max-width: 560px) {
+ .client__header__start {
+ flex-direction: column;
+ }
+
+ .client__header__start__badges {
+ margin-top: 0.5rem;
+ }
+
+ .client__header__start__badges:first-of-type {
+ margin-left: 0;
+ }
+
+ .client__footer {
+ flex-direction: column;
+ }
+
+ .client__footer .button {
+ margin: 1rem 0 0;
+ }
+
+ .client__footer .button:first-of-type {
+ margin-top: 0;
+ }
+}
diff --git a/src/components/ClientDetails.tsx b/src/components/ClientDetails.tsx
new file mode 100644
index 00000000..8aec4b41
--- /dev/null
+++ b/src/components/ClientDetails.tsx
@@ -0,0 +1,57 @@
+import React from 'react';
+
+import PlatformIcon from './PlatformIcon';
+import { Client, ClientType, LicenseType } from '../data/clients';
+
+import './ClientDetails.css';
+
+const ClientTypeBadge = ({ clientType }: { clientType: ClientType }) => {
+ if (clientType === ClientType.Official) {
+ return Official;
+ } else if (clientType === ClientType.ThirdParty) {
+ return Third Party;
+ }
+};
+
+const LicenseTypeBadge = ({ licenseType }: { licenseType: LicenseType }) => {
+ if (licenseType === LicenseType.OpenSource) {
+ return Open Source;
+ } else if (licenseType === LicenseType.Proprietary) {
+ return Proprietary;
+ }
+};
+
+const ClientDetails = ({ client }: { client: Client }) => (
+
+
+
+
{client.name}
+
+
+
+
+
+
+ {client.platforms.map((platform, index) => (
+
+ ))}
+
+
+
{client.description}
+
+ {client.secondaryLinks?.map(({ id, url, name }) => (
+
+ {name}
+
+ ))}
+
+ {client.primaryLinks.map(({ id, url, name }) => (
+
+ {name}
+
+ ))}
+
+
+);
+
+export default ClientDetails;
diff --git a/src/components/Pill.tsx b/src/components/Pill.tsx
new file mode 100644
index 00000000..91f968e0
--- /dev/null
+++ b/src/components/Pill.tsx
@@ -0,0 +1,27 @@
+import clsx from 'clsx';
+import React, { FunctionComponent, ReactNode } from 'react';
+
+type PillParams = {
+ children: ReactNode;
+ active: boolean;
+ onClick(): void;
+};
+
+const Pill: FunctionComponent = ({ children, active, onClick }: PillParams) => (
+ {
+ if (keyEvent.key === 'Enter') {
+ onClick();
+ }
+ }}
+ >
+ {children}
+
+);
+
+export default Pill;
diff --git a/src/components/PlatformIcon.tsx b/src/components/PlatformIcon.tsx
new file mode 100644
index 00000000..e04bcc8c
--- /dev/null
+++ b/src/components/PlatformIcon.tsx
@@ -0,0 +1,70 @@
+import {
+ Amazonfiretv,
+ Android,
+ Appletv,
+ Discord,
+ Ios,
+ Kodi,
+ Lg,
+ Roku,
+ Sailfishos
+} from '@icons-pack/react-simple-icons';
+import clsx from 'clsx';
+import React from 'react';
+
+import { Platform } from '../data/clients';
+import Desktop from '../../static/images/icons/monitor.svg';
+import Web from '../../static/images/icons/web.svg';
+
+const PlatformIcon = ({
+ platform,
+ size,
+ className = ''
+}: {
+ platform: Platform;
+ size: string | number;
+ className?: string;
+}) => {
+ className = clsx(className, 'fill--white');
+
+ switch (platform) {
+ case Platform.Android:
+ case Platform.AndroidTV:
+ return ;
+
+ case Platform.Browser:
+ return ;
+
+ case Platform.Desktop:
+ return ;
+
+ case Platform.Discord:
+ return ;
+
+ case Platform.FireOS:
+ return ;
+
+ case Platform.IOS:
+ return ;
+
+ case Platform.Kodi:
+ return ;
+
+ case Platform.Roku:
+ return ;
+
+ case Platform.SailfishOS:
+ return ;
+
+ case Platform.TVOS:
+ return ;
+
+ case Platform.WebOS:
+ return ;
+
+ default:
+ return null;
+ }
+};
+
+export default PlatformIcon;
diff --git a/src/css/custom.css b/src/css/custom.css
index 05db9398..06b7646a 100644
--- a/src/css/custom.css
+++ b/src/css/custom.css
@@ -29,7 +29,9 @@
--ifm-code-background: #292d3e; /* match code blocks */
--ifm-navbar-background-color: #000b25;
--ifm-background-color: #000b25 !important;
+ --ifm-card-background-color: #172138;
--ifm-footer-background-color: #333c44;
+ --ifm-pills-color-background-active: #172138;
--ifm-font-family-base: "Noto Sans", sans-serif;
--ifm-h1-font-size: 2.074em;
--ifm-h2-font-size: 1.728em;
diff --git a/src/data/clients.ts b/src/data/clients.ts
new file mode 100644
index 00000000..2771b21e
--- /dev/null
+++ b/src/data/clients.ts
@@ -0,0 +1,701 @@
+export enum ClientType {
+ Official,
+ ThirdParty
+}
+
+export enum DeviceType {
+ Desktop,
+ Mobile,
+ TV
+}
+
+export enum LicenseType {
+ OpenSource,
+ Proprietary
+}
+
+export enum Platform {
+ Android,
+ AndroidTV,
+ Browser,
+ Desktop,
+ Discord,
+ FireOS,
+ IOS,
+ Kodi,
+ Roku,
+ SailfishOS,
+ TVOS,
+ WebOS
+}
+
+type Link = {
+ id: string;
+ name: string;
+ url: string;
+};
+
+export type Client = {
+ id: string;
+ name: string;
+ description: string;
+ clientType: ClientType;
+ deviceTypes: Array;
+ licenseType: LicenseType;
+ platforms: Array;
+ primaryLinks: Array;
+ secondaryLinks?: Array;
+ recommended?: boolean;
+};
+
+export const Clients: Array = [
+ {
+ id: 'jellyfin-media-player',
+ name: 'Jellyfin Media Player',
+ description: 'The official Jellyfin desktop client.',
+ clientType: ClientType.Official,
+ deviceTypes: [DeviceType.Desktop],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.Desktop],
+ primaryLinks: [
+ {
+ id: 'flathub',
+ name: 'Flathub (Linux)',
+ url: 'https://flathub.org/apps/details/com.github.iwalton3.jellyfin-media-player'
+ },
+ {
+ id: 'gh-downloads',
+ name: 'GitHub Downloads',
+ url: 'https://github.com/jellyfin/jellyfin-media-player/releases'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/jellyfin/jellyfin-media-player'
+ }
+ ],
+ recommended: true
+ },
+ {
+ id: 'jellyfin-mpv-shim',
+ name: 'Jellyfin MPV Shim',
+ description: 'A cross-platform cast client for Jellyfin.',
+ clientType: ClientType.Official,
+ deviceTypes: [DeviceType.Desktop],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.Desktop],
+ primaryLinks: [
+ {
+ id: 'flathub',
+ name: 'Flathub (Linux)',
+ url: 'https://flathub.org/apps/details/com.github.iwalton3.jellyfin-mpv-shim'
+ },
+ {
+ id: 'gh-downloads',
+ name: 'GitHub Downloads',
+ url: 'https://github.com/jellyfin/jellyfin-mpv-shim/releases'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/jellyfin/jellyfin-mpv-shim'
+ }
+ ]
+ },
+ {
+ id: 'jellyamp',
+ name: 'Jellyamp',
+ description: 'A desktop client for listening to music from a Jellyfin server.',
+ clientType: ClientType.ThirdParty,
+ deviceTypes: [DeviceType.Desktop],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.Desktop],
+ primaryLinks: [
+ {
+ id: 'gh-downloads',
+ name: 'GitHub Downloads',
+ url: 'https://github.com/m0ngr31/jellyamp/releases'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/m0ngr31/jellyamp'
+ }
+ ]
+ },
+ {
+ id: 'preserve',
+ name: 'Preserve',
+ description: 'A music client inspired by players such as foobar2000 or Clementine.',
+ clientType: ClientType.ThirdParty,
+ deviceTypes: [DeviceType.Desktop],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.Browser, Platform.Desktop],
+ primaryLinks: [
+ {
+ id: 'browser',
+ name: 'Open in Browser',
+ url: 'https://preserveplayer.com/'
+ },
+ {
+ id: 'gl-downloads',
+ name: 'GitLab Downloads',
+ url: 'https://gitlab.com/tonyfinn/preserve/-/releases'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'gitlab',
+ name: 'GitLab',
+ url: 'https://gitlab.com/tonyfinn/preserve'
+ }
+ ]
+ },
+ {
+ id: 'sonixd',
+ name: 'Sonixd',
+ description: 'A full-featured Subsonic/Jellyfin compatible desktop music player.',
+ clientType: ClientType.ThirdParty,
+ deviceTypes: [DeviceType.Desktop],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.Desktop],
+ primaryLinks: [
+ {
+ id: 'install',
+ name: 'Installation Guide',
+ url: 'https://github.com/jeffvli/sonixd#install'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/jeffvli/sonixd'
+ }
+ ]
+ },
+ {
+ id: 'tauon-music-box',
+ name: 'Tauon Music Box',
+ description: "A modern streamlined music player for desktop with a minimal interface that's packed with features!",
+ clientType: ClientType.ThirdParty,
+ deviceTypes: [DeviceType.Desktop],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.Desktop],
+ primaryLinks: [
+ {
+ id: 'flathub',
+ name: 'Flathub (Linux)',
+ url: 'https://flathub.org/apps/details/com.github.taiko2k.tauonmb'
+ },
+ {
+ id: 'install',
+ name: 'Installation Guide',
+ url: 'https://github.com/Taiko2k/TauonMusicBox#download-and-install-dizzy'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/Taiko2k/TauonMusicBox'
+ },
+ {
+ id: 'tauon',
+ name: 'Website',
+ url: 'https://tauonmusicbox.rocks'
+ }
+ ]
+ },
+ {
+ id: 'jellycon',
+ name: 'JellyCon',
+ description:
+ 'A lightweight Kodi add-on that lets you browse and play media files directly from your Jellyfin server within the Kodi interface.',
+ clientType: ClientType.Official,
+ deviceTypes: [DeviceType.Desktop, DeviceType.Mobile, DeviceType.TV],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.Kodi],
+ primaryLinks: [
+ {
+ id: 'install',
+ name: 'Installation Guide',
+ url: 'https://github.com/jellyfin/jellycon#installation'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/jellyfin/jellycon'
+ }
+ ],
+ recommended: true
+ },
+ {
+ id: 'jellyfin-kodi',
+ name: 'Jellyfin for Kodi',
+ description: 'A Kodi add-on that syncs metadata from selected Jellyfin libraries into the local Kodi database.',
+ clientType: ClientType.Official,
+ deviceTypes: [DeviceType.Desktop, DeviceType.Mobile, DeviceType.TV],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.Kodi],
+ primaryLinks: [
+ {
+ id: 'install',
+ name: 'Installation Guide',
+ url: 'https://docs.jellyfin.org/general/clients/kodi.html'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/jellyfin/jellyfin-kodi'
+ }
+ ]
+ },
+ {
+ id: 'jellyfin-android',
+ name: 'Jellyfin for Android',
+ description: 'The official Jellyfin app for Android devices.',
+ clientType: ClientType.Official,
+ deviceTypes: [DeviceType.Mobile],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.Android],
+ primaryLinks: [
+ {
+ id: 'fdroid',
+ name: 'F-Droid',
+ url: 'https://f-droid.org/en/packages/org.jellyfin.mobile/'
+ },
+ {
+ id: 'amazon-store',
+ name: 'Amazon Appstore',
+ url: 'https://www.amazon.com/gp/aw/d/B081RFTTQ9'
+ },
+ {
+ id: 'play-store',
+ name: 'Play Store',
+ url: 'https://play.google.com/store/apps/details?id=org.jellyfin.mobile'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/jellyfin/jellyfin-android'
+ }
+ ],
+ recommended: true
+ },
+ {
+ id: 'jellyfin-expo',
+ name: 'Jellyfin Mobile for iOS',
+ description: 'The official Jellyfin app for iOS and iPadOS devices.',
+ clientType: ClientType.Official,
+ deviceTypes: [DeviceType.Mobile],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.IOS],
+ primaryLinks: [
+ {
+ id: 'apple-store',
+ name: 'App Store',
+ url: 'https://apps.apple.com/us/app/jellyfin-mobile/id1480192618?mt=8'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/jellyfin/jellyfin-expo'
+ }
+ ],
+ recommended: true
+ },
+ {
+ id: 'findroid',
+ name: 'Findroid',
+ description:
+ 'A third-party Android application for Jellyfin that provides a native user interface to browse and play movies and series.',
+ clientType: ClientType.ThirdParty,
+ deviceTypes: [DeviceType.Mobile],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.Android],
+ primaryLinks: [
+ {
+ id: 'izzy-fdroid',
+ name: 'IzzyOnDroid',
+ url: 'https://apt.izzysoft.de/fdroid/index/apk/dev.jdtech.jellyfin'
+ },
+ {
+ id: 'play-store',
+ name: 'Play Store',
+ url: 'https://play.google.com/store/apps/details?id=dev.jdtech.jellyfin'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/jarnedemeulemeester/findroid'
+ }
+ ]
+ },
+ {
+ id: 'gelli',
+ name: 'Gelli',
+ description:
+ 'A native music player for Android devices with transcoding support, gapless playback, favorites, playlists, and many other features.',
+ clientType: ClientType.ThirdParty,
+ deviceTypes: [DeviceType.Mobile],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.Android],
+ primaryLinks: [
+ {
+ id: 'gh-downloads',
+ name: 'GitHub Downloads',
+ url: 'https://github.com/dkanada/gelli/releases'
+ },
+ {
+ id: 'fdroid',
+ name: 'F-Droid',
+ url: 'https://f-droid.org/packages/com.dkanada.gramophone/'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/dkanada/gelli'
+ }
+ ]
+ },
+ {
+ id: 'finamp',
+ name: 'Finamp',
+ description: 'A third party app for music playback with support for offline mode/downloading songs.',
+ clientType: ClientType.ThirdParty,
+ deviceTypes: [DeviceType.Mobile],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.Android, Platform.IOS],
+ primaryLinks: [
+ {
+ id: 'fdroid',
+ name: 'F-Droid',
+ url: 'https://f-droid.org/packages/com.unicornsonlsd.finamp/'
+ },
+ {
+ id: 'play-store',
+ name: 'Play Store',
+ url: 'https://play.google.com/store/apps/details?id=com.unicornsonlsd.finamp'
+ },
+ {
+ id: 'app-store',
+ name: 'App Store',
+ url: 'https://apps.apple.com/us/app/finamp/id1574922594'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/UnicornsOnLSD/finamp'
+ }
+ ]
+ },
+ {
+ id: 'sailfin',
+ name: 'Sailfin',
+ description: 'A Sailfish OS client for Jellyfin.',
+ clientType: ClientType.ThirdParty,
+ deviceTypes: [DeviceType.Mobile],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.SailfishOS],
+ primaryLinks: [
+ {
+ id: 'open-repos',
+ name: 'OpenRepos',
+ url: 'https://openrepos.net/content/ahappyhuman/sailfin'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/heartfin/harbour-sailfin'
+ }
+ ]
+ },
+ {
+ id: 'yatse',
+ name: 'Yatse',
+ description: 'A third party remote control for Jellyfin with support for Chromecast playback.',
+ clientType: ClientType.ThirdParty,
+ deviceTypes: [DeviceType.Mobile],
+ licenseType: LicenseType.Proprietary,
+ platforms: [Platform.Android],
+ primaryLinks: [
+ {
+ id: 'play-store',
+ name: 'Play Store',
+ url: 'https://play.google.com/store/apps/details?id=org.leetzone.android.yatsewidgetfree'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'yatse',
+ name: 'Website',
+ url: 'https://yatse.tv/'
+ }
+ ]
+ },
+ {
+ id: 'jellyfin-androidtv',
+ name: 'Jellyfin for Android TV',
+ description: 'The official Jellyfin app for Android TV devices.',
+ clientType: ClientType.Official,
+ deviceTypes: [DeviceType.TV],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.AndroidTV, Platform.FireOS],
+ primaryLinks: [
+ {
+ id: 'amazon-store',
+ name: 'Amazon Appstore',
+ url: 'https://www.amazon.com/gp/aw/d/B07TX7Z725'
+ },
+ {
+ id: 'play-store',
+ name: 'Play Store',
+ url: 'https://play.google.com/store/apps/details?id=org.jellyfin.androidtv'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/jellyfin/jellyfin-androidtv'
+ }
+ ],
+ recommended: true
+ },
+ {
+ id: 'jellyfin-roku',
+ name: 'Jellyfin for Roku',
+ description: 'The official Jellyfin app for Roku devices.',
+ clientType: ClientType.Official,
+ deviceTypes: [DeviceType.TV],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.Roku],
+ primaryLinks: [
+ {
+ id: 'roku-store',
+ name: 'Channel Store',
+ url: 'https://channelstore.roku.com/details/592369/jellyfin'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/jellyfin/jellyfin-roku'
+ }
+ ],
+ recommended: true
+ },
+ {
+ id: 'jellyfin-webos',
+ name: 'Jellyfin for WebOS',
+ description: 'The official Jellyfin app for WebOS devices.',
+ clientType: ClientType.Official,
+ deviceTypes: [DeviceType.TV],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.WebOS],
+ primaryLinks: [
+ {
+ id: 'jf-blog',
+ name: 'Older webOS Versions',
+ url: '/posts/webos-july2022'
+ },
+ {
+ id: 'lg-store',
+ name: 'Content Store - webOS 6+',
+ url: 'https://us.lgappstv.com/main/tvapp/detail?appId=1030579'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/jellyfin/jellyfin-webos'
+ }
+ ],
+ recommended: true
+ },
+ {
+ id: 'infuse',
+ name: 'Infuse',
+ description: 'A third-party client for iOS, iPadOS, and tvOS devices.',
+ clientType: ClientType.ThirdParty,
+ deviceTypes: [DeviceType.Mobile, DeviceType.TV],
+ licenseType: LicenseType.Proprietary,
+ platforms: [Platform.IOS, Platform.TVOS],
+ primaryLinks: [
+ {
+ id: 'apple-store',
+ name: 'App Store',
+ url: 'https://apps.apple.com/app/id1136220934?mt=8'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'website',
+ name: 'Website',
+ url: 'https://firecore.com/infuse'
+ }
+ ],
+ recommended: true
+ },
+ {
+ id: 'mopidy',
+ name: 'Mopidy-Jellyfin',
+ description: 'An official plugin for Mopidy that uses Jellyfin as a backend.',
+ clientType: ClientType.Official,
+ deviceTypes: [],
+ licenseType: LicenseType.OpenSource,
+ platforms: [],
+ primaryLinks: [
+ {
+ id: 'install',
+ name: 'Installation Guide',
+ url: 'https://jellyfin.org/docs/general/clients/mopidy.html'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/jellyfin/mopidy-jellyfin'
+ }
+ ]
+ },
+ {
+ id: 'volumio',
+ name: 'Jellyfin Plugin for Volumio',
+ description: 'A Volumio plugin for playing audio from one or more Jellyfin servers.',
+ clientType: ClientType.ThirdParty,
+ deviceTypes: [],
+ licenseType: LicenseType.OpenSource,
+ platforms: [],
+ primaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/patrickkfkan/volumio-jellyfin'
+ }
+ ]
+ },
+ {
+ id: 'discord-music',
+ name: 'Discord Music Bot for Jellyfin',
+ description: 'A Discord bot that allows playing your Jellyfin music library in Discord voice channels.',
+ clientType: ClientType.ThirdParty,
+ deviceTypes: [],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.Discord],
+ primaryLinks: [
+ {
+ id: 'install',
+ name: 'Installation Guide',
+ url: 'https://github.com/kgt1/jellyfin-discord-music-bot#getting-started'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/kgt1/jellyfin-discord-music-bot'
+ }
+ ]
+ },
+ {
+ id: 'jellycli',
+ name: 'Jellycli',
+ description: 'A terminal player for Jellyfin, only for music at the moment.',
+ clientType: ClientType.ThirdParty,
+ deviceTypes: [],
+ licenseType: LicenseType.OpenSource,
+ platforms: [],
+ primaryLinks: [
+ {
+ id: 'gh-downloads',
+ name: 'GitHub Downloads',
+ url: 'https://github.com/tryffel/jellycli/releases'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/tryffel/jellycli'
+ }
+ ]
+ },
+ {
+ id: 'jftui',
+ name: 'jftui',
+ description: 'A terminal client for Jellyfin built as a REPL interface, that uses mpv for multimedia playback.',
+ clientType: ClientType.ThirdParty,
+ deviceTypes: [],
+ licenseType: LicenseType.OpenSource,
+ platforms: [],
+ primaryLinks: [
+ {
+ id: 'install',
+ name: 'Installation Guide',
+ url: 'https://github.com/Aanok/jftui#installation'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/Aanok/jftui'
+ }
+ ]
+ },
+ {
+ id: 'web-scrobbler',
+ name: 'Web Scrobbler',
+ description: 'Web Scrobbler helps online music listeners to scrobble their playback history.',
+ clientType: ClientType.ThirdParty,
+ deviceTypes: [],
+ licenseType: LicenseType.OpenSource,
+ platforms: [Platform.Browser],
+ primaryLinks: [
+ {
+ id: 'install',
+ name: 'Installation Guide',
+ url: 'https://github.com/web-scrobbler/web-scrobbler#installation'
+ }
+ ],
+ secondaryLinks: [
+ {
+ id: 'github',
+ name: 'GitHub',
+ url: 'https://github.com/web-scrobbler/web-scrobbler'
+ },
+ {
+ id: 'website',
+ name: 'Website',
+ url: 'https://web-scrobbler.com'
+ }
+ ]
+ }
+];
diff --git a/src/pages/clients.tsx b/src/pages/clients.tsx
index e49d9065..a9ba9a6b 100644
--- a/src/pages/clients.tsx
+++ b/src/pages/clients.tsx
@@ -1,11 +1,67 @@
-import React from 'react';
import Layout from '@theme/Layout';
+import React, { useState } from 'react';
+
+import ClientDetails from '../components/ClientDetails';
+import Pill from '../components/Pill';
+import { Clients, DeviceType, Platform } from '../data/clients';
+
+type ClientFilter = {
+ recommended: boolean;
+ deviceType?: DeviceType;
+ platform?: Platform;
+};
export default function Plugins() {
+ const [filter, setFilter] = useState({
+ recommended: true
+ });
+
return (
-
- Clients
- Placeholder page
+
+ Clients
+
+
+
+
+ {
+ setFilter({ ...filter, recommended: true });
+ }}
+ >
+ Recommended Clients
+
+ {
+ setFilter({ ...filter, recommended: false });
+ }}
+ >
+ All Clients
+
+
+
+ {Clients.filter((client) => {
+ let result = true;
+
+ if (filter.recommended) {
+ result = result && !!client.recommended;
+ }
+
+ if (typeof filter.deviceType !== 'undefined') {
+ result = result && client.deviceTypes.includes(filter.deviceType);
+ }
+
+ if (typeof filter.platform !== 'undefined') {
+ result = result && client.platforms.includes(filter.platform);
+ }
+
+ return result;
+ }).map((client) => (
+
+ ))}
+
+
);
}