"use client"; import { useState, useEffect } from "react"; import Link from "next/link"; import { useSession, signIn } from "next-auth/react"; import { Search, Flame, Sparkles, TrendingUp, Loader2, Eye, MessageCircle, Filter, } from "lucide-react"; import toast, { Toaster } from "react-hot-toast"; export default function ExplorePage() { const { data: session, status } = useSession(); const [characters, setCharacters] = useState([]); const [loading, setLoading] = useState(true); const [search, setSearch] = useState(""); useEffect(() => { fetchCharacters(); }, []); const fetchCharacters = async () => { setLoading(true); try { const res = await fetch("/api/characters"); const data = await res.json(); if (data.characters) { const publicCustom = data.characters.filter((c) => c.isPublic && c.isCustom); setCharacters(publicCustom); } } catch (err) { console.error("Failed to load characters", err); toast.error("Failed to load characters"); } finally { setLoading(false); } }; const filtered = characters.filter((c) => { const matchesSearch = !search || c.name.toLowerCase().includes(search.toLowerCase()) || c.description.toLowerCase().includes(search.toLowerCase()) || c.personality.toLowerCase().includes(search.toLowerCase()); return matchesSearch; }); if (status === "loading") { return (
); } return (
HuggingFace Community Marketplace

Explore Community Characters

Discover personas crafted by other HuggingFace users. From historical figures to anime companions, find your next conversation partner — or publish your own creations to the community.

setSearch(e.target.value)} placeholder="Search characters, personalities, or topics..." className="w-full bg-bg-card border border-divider rounded-lg pl-10 pr-4 py-3 text-sm text-primary-text placeholder-secondary-text/50 focus:outline-none focus:border-primary/50" />
Create Your Own

{filtered.length} Public Character{filtered.length === 1 ? "" : "s"}

Sorted by most recent
{loading ? (
) : filtered.length === 0 ? (
🎭

No characters found

{search ? `No matches for "${search}". Try a different keyword.` : "Be the first to publish a public character to the marketplace!"}

+ Create Character
) : (
{filtered.map((c) => )}
)}
); } function CharacterCard({ character, session }) { const slug = character.name.toLowerCase().replace(/[^a-z0-9]+/g, "-"); const [starting, setStarting] = useState(false); const handleStart = async (e) => { e.preventDefault(); if (!session?.user) return; setStarting(true); try { const res = await fetch("/api/chats", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ character_id: character.id }), }); if (res.ok) { const data = await res.json(); if (data.chat) window.location.href = `/${slug}/${data.chat.id}`; } } catch (err) { console.error(err); } finally { setStarting(false); } }; return (
{character.profileUrl || (character.avatar?.length > 2 && character.avatar?.startsWith("http")) ? ( {character.name} ) : ( {character.avatar || "🤖"} )}
Public

{character.name}

{character.description}

{character.personality}

{session?.user ? ( ) : ( Sign in to chat )}
); }