import React, { useState, useEffect } from "react"; import Layout from "@theme/Layout"; import styles from "./marketplace.module.css"; interface Plugin { name: string; title: string; description: string; file: string; url?: string; } const REGISTRY_URL = "https://raw.githubusercontent.com/floatpane/matcha/master/plugins/registry.json"; const RAW_BASE = "https://raw.githubusercontent.com/floatpane/matcha/master/plugins/"; function pluginUrl(plugin: Plugin): string { return plugin.url || `${RAW_BASE}${plugin.file}`; } function installCmd(plugin: Plugin): string { return `matcha install ${pluginUrl(plugin)}`; } function CopyButton({ text }: { text: string }) { const [copied, setCopied] = useState(false); const handleCopy = () => { navigator.clipboard.writeText(text); setCopied(true); setTimeout(() => setCopied(false), 2000); }; return ( ); } function PluginCard({ plugin }: { plugin: Plugin }) { const cmd = installCmd(plugin); return (

{plugin.title}

{plugin.description}

Install:
{cmd}
); } export default function Marketplace(): React.JSX.Element { const [plugins, setPlugins] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { fetch(REGISTRY_URL) .then((res) => { if (!res.ok) throw new Error(`Failed to fetch registry (${res.status})`); return res.json(); }) .then((data: Plugin[]) => { setPlugins(data); setLoading(false); }) .catch((err) => { setError(err.message); setLoading(false); }); }, []); return (

Plugin Marketplace

Browse community plugins for Matcha. Click install commands to copy.

{loading &&

Loading plugins...

} {error &&

Error: {error}

} {!loading && !error && ( <>

{plugins.length} plugins available

{plugins.map((plugin) => ( ))}
)}
); }