diff --git a/client/components/Skeleton.tsx b/client/components/Skeleton.tsx
new file mode 100644
index 00000000..c9dbb39a
--- /dev/null
+++ b/client/components/Skeleton.tsx
@@ -0,0 +1,183 @@
+import { cn } from "@/lib/utils";
+
+interface SkeletonProps {
+ className?: string;
+ variant?: 'text' | 'avatar' | 'card' | 'button' | 'image';
+ lines?: number;
+ animate?: boolean;
+}
+
+export function Skeleton({ className, variant = 'text', lines = 1, animate = true }: SkeletonProps) {
+ const baseClasses = cn(
+ "bg-muted rounded",
+ animate && "skeleton",
+ className
+ );
+
+ switch (variant) {
+ case 'avatar':
+ return
;
+
+ case 'button':
+ return ;
+
+ case 'image':
+ return ;
+
+ case 'card':
+ return (
+
+ );
+
+ case 'text':
+ default:
+ return (
+
+ {Array.from({ length: lines }).map((_, i) => (
+
+ ))}
+
+ );
+ }
+}
+
+export function SkeletonCard() {
+ return (
+
+ );
+}
+
+export function SkeletonStats() {
+ return (
+
+ {Array.from({ length: 4 }).map((_, i) => (
+
+ ))}
+
+ );
+}
+
+export function SkeletonUserPath() {
+ return (
+
+ {Array.from({ length: 4 }).map((_, i) => (
+
+
+
+ {Array.from({ length: 4 }).map((_, j) => (
+
+ ))}
+
+
+
+ ))}
+
+ );
+}
+
+export function SkeletonOnboardingStep() {
+ return (
+
+
+
+
+
+
+
+
+ {Array.from({ length: 4 }).map((_, i) => (
+
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+ );
+}
+
+export function SkeletonLayout() {
+ return (
+
+ {/* Header Skeleton */}
+
+
+
+
+
+
+
+ {Array.from({ length: 4 }).map((_, i) => (
+
+ ))}
+
+
+
+
+
+
+
+
+ {/* Content Skeleton */}
+
+
+ );
+}