diff --git a/services/frontend/src/features/analytics/index.tsx b/services/frontend/src/features/analytics/index.tsx
index 4dff37a..6338edd 100644
--- a/services/frontend/src/features/analytics/index.tsx
+++ b/services/frontend/src/features/analytics/index.tsx
@@ -1,7 +1,7 @@
import { motion } from "framer-motion";
import { useState } from "react";
import { cardItem, cardStagger } from "../../shared/hooks/useFramerStagger";
-import { EmptyStateMascot } from "../../widgets/mascot/ChibiMascot";
+import { EmptyStateMascot } from "../../shared/ui";
import { ActivityChart } from "./components/ActivityChart";
import { ControlBar } from "./components/ControlBar";
import { Heatmap } from "./components/Heatmap";
@@ -53,12 +53,7 @@ export function AnalyticsPanel({ guildId, guildName }: AnalyticsPanelProps) {
}
if (!guildId) {
- return (
-
- );
+ return ;
}
return (
diff --git a/services/frontend/src/features/auth/index.tsx b/services/frontend/src/features/auth/index.tsx
index 9ec786f..cfadf5c 100644
--- a/services/frontend/src/features/auth/index.tsx
+++ b/services/frontend/src/features/auth/index.tsx
@@ -10,8 +10,8 @@ import {
CardHeader,
CardTitle,
Input,
+ MascotImage,
} from "../../shared/ui";
-import { ChibiMascot } from "../../widgets/mascot/ChibiMascot";
interface AuthOverlayProps {
onAuthenticated: () => void;
@@ -50,7 +50,7 @@ export function AuthOverlay({ onAuthenticated }: AuthOverlayProps) {
-
+
Admin Access Required
diff --git a/services/frontend/src/features/live/components/ActiveSpeakers.tsx b/services/frontend/src/features/live/components/ActiveSpeakers.tsx
index fa2b03e..3e5117c 100644
--- a/services/frontend/src/features/live/components/ActiveSpeakers.tsx
+++ b/services/frontend/src/features/live/components/ActiveSpeakers.tsx
@@ -7,9 +7,7 @@ interface ActiveSpeakersProps {
export function ActiveSpeakers({ speakers }: ActiveSpeakersProps) {
if (speakers.length === 0) {
- return (
-
- );
+ return ;
}
return (
diff --git a/services/frontend/src/features/live/components/RecordingsSubPanel.tsx b/services/frontend/src/features/live/components/RecordingsSubPanel.tsx
index cab8851..f07a910 100644
--- a/services/frontend/src/features/live/components/RecordingsSubPanel.tsx
+++ b/services/frontend/src/features/live/components/RecordingsSubPanel.tsx
@@ -92,7 +92,7 @@ export function RecordingsSubPanel() {
}
if (recordings.length === 0) {
- return ;
+ return ;
}
return (
diff --git a/services/frontend/src/features/messages/components/ImageGrid.tsx b/services/frontend/src/features/messages/components/ImageGrid.tsx
index 017e24e..fe8161b 100644
--- a/services/frontend/src/features/messages/components/ImageGrid.tsx
+++ b/services/frontend/src/features/messages/components/ImageGrid.tsx
@@ -1,6 +1,6 @@
import { parseMetadata } from "../../../entities/message/types";
import type { MessageRecord } from "../../../shared/api/client";
-import { EmptyStateMascot } from "../../../widgets/mascot/ChibiMascot";
+import { EmptyStateMascot } from "../../../shared/ui";
interface ImageItem {
url: string;
@@ -68,7 +68,7 @@ export function ImageGrid({ messages }: { messages: MessageRecord[] }) {
}
if (images.length === 0) {
- return ;
+ return ;
}
return (
diff --git a/services/frontend/src/features/messages/components/MessageFeed.tsx b/services/frontend/src/features/messages/components/MessageFeed.tsx
index 733bfe6..d24cf39 100644
--- a/services/frontend/src/features/messages/components/MessageFeed.tsx
+++ b/services/frontend/src/features/messages/components/MessageFeed.tsx
@@ -2,8 +2,7 @@ import { motion } from "framer-motion";
import { useEffect, useMemo, useRef } from "react";
import type { MessageRecord } from "../../../shared/api/client";
import { cardItem, cardStagger } from "../../../shared/hooks/useFramerStagger";
-import { ScrollArea } from "../../../shared/ui";
-import { EmptyStateMascot } from "../../../widgets/mascot/ChibiMascot";
+import { ScrollArea, EmptyStateMascot } from "../../../shared/ui";
import { MessageCard, MessageCardSkeleton } from "./MessageCard";
export interface MessageFeedProps {
@@ -84,7 +83,7 @@ export function MessageFeed({
}
if (messages.length === 0) {
- return ;
+ return ;
}
return (
diff --git a/services/frontend/src/shared/ui/index.ts b/services/frontend/src/shared/ui/index.ts
index c0e2504..8f72bf6 100644
--- a/services/frontend/src/shared/ui/index.ts
+++ b/services/frontend/src/shared/ui/index.ts
@@ -1,6 +1,6 @@
// ─── Shared UI barrel export ────────────────────────────────────────────────
-export { EmptyStateMascot } from "../../widgets/mascot/ChibiMascot";
+export { EmptyStateMascot, MascotImage } from "../../widgets/mascot/MascotImage";
export { Badge } from "./badge";
export { Button } from "./button";
export {
diff --git a/services/frontend/src/widgets/Sidebar.tsx b/services/frontend/src/widgets/Sidebar.tsx
index 05ea0ef..4790df8 100644
--- a/services/frontend/src/widgets/Sidebar.tsx
+++ b/services/frontend/src/widgets/Sidebar.tsx
@@ -2,7 +2,7 @@ import { motion } from "framer-motion";
import { BarChart3, MessageSquare, Radio } from "lucide-react";
import type { DashboardTab } from "../entities/ui/types";
import { cn } from "../shared/lib/utils";
-import { ChibiMascot } from "./mascot/ChibiMascot";
+import { MascotImage } from "./mascot/MascotImage";
const navItems: Array<{ id: DashboardTab; label: string; icon: typeof Radio }> =
[
@@ -84,9 +84,9 @@ export function Sidebar({
{/* Spacer pushes mascot to bottom */}
- {/* Chibi mascot */}
+ {/* Mascot PNG */}
-
+
);
diff --git a/services/frontend/src/widgets/mascot/MascotImage.tsx b/services/frontend/src/widgets/mascot/MascotImage.tsx
new file mode 100644
index 0000000..1615896
--- /dev/null
+++ b/services/frontend/src/widgets/mascot/MascotImage.tsx
@@ -0,0 +1,40 @@
+/**
+ * MascotImage — Anime mascot PNG from GitHub CDN
+ * Replaces ChibiMascot SVG component with external PNG asset
+ */
+
+interface MascotImageProps {
+ size?: "sm" | "md" | "lg";
+ className?: string;
+}
+
+const sizeMap = {
+ sm: "w-16 h-auto",
+ md: "w-32 h-auto",
+ lg: "w-48 h-auto",
+};
+
+export function MascotImage({ size = "md", className = "" }: MascotImageProps) {
+ const sizeClass = sizeMap[size];
+
+ return (
+
+ );
+}
+
+/**
+ * EmptyStateMascot — Mascot for empty states
+ * Replaces ChibiMascot when showing empty data states
+ */
+export function EmptyStateMascot() {
+ return (
+
+ );
+}