diff --git a/frontend/app/shows/[slug]/loading.tsx b/frontend/app/shows/[slug]/loading.tsx
new file mode 100644
index 0000000..8570fca
--- /dev/null
+++ b/frontend/app/shows/[slug]/loading.tsx
@@ -0,0 +1,57 @@
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
+import { Skeleton, SetlistSkeleton } from "@/components/ui/skeleton"
+
+export default function ShowLoading() {
+ return (
+
+ {/* Header */}
+
+
+
+
+ {/* Setlist Card */}
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Sidebar */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/frontend/app/shows/loading.tsx b/frontend/app/shows/loading.tsx
new file mode 100644
index 0000000..0a09d0b
--- /dev/null
+++ b/frontend/app/shows/loading.tsx
@@ -0,0 +1,23 @@
+import { Skeleton, ShowCardSkeleton, PageHeaderSkeleton } from "@/components/ui/skeleton"
+
+export default function ShowsLoading() {
+ return (
+
+
+
+ {/* Filters skeleton */}
+
+
+
+
+
+
+ {/* Shows grid */}
+
+ {Array.from({ length: 12 }).map((_, i) => (
+
+ ))}
+
+
+ )
+}
diff --git a/frontend/app/songs/loading.tsx b/frontend/app/songs/loading.tsx
new file mode 100644
index 0000000..9e0bfeb
--- /dev/null
+++ b/frontend/app/songs/loading.tsx
@@ -0,0 +1,19 @@
+import { Skeleton, SongCardSkeleton, PageHeaderSkeleton } from "@/components/ui/skeleton"
+
+export default function SongsLoading() {
+ return (
+
+
+
+ {/* Search skeleton */}
+
+
+ {/* Songs grid */}
+
+ {Array.from({ length: 16 }).map((_, i) => (
+
+ ))}
+
+
+ )
+}
diff --git a/frontend/components/ui/skeleton.tsx b/frontend/components/ui/skeleton.tsx
index cbb1704..8811e0f 100644
--- a/frontend/components/ui/skeleton.tsx
+++ b/frontend/components/ui/skeleton.tsx
@@ -1,15 +1,97 @@
+"use client"
+
import { cn } from "@/lib/utils"
-function Skeleton({
- className,
- ...props
-}: React.HTMLAttributes) {
+interface SkeletonProps extends React.HTMLAttributes { }
+
+export function Skeleton({ className, ...props }: SkeletonProps) {
return (
)
}
-export { Skeleton }
+// Preset skeleton layouts for common patterns
+export function ShowCardSkeleton() {
+ return (
+
+ )
+}
+
+export function SongCardSkeleton() {
+ return (
+
+
+
+
+ )
+}
+
+export function SetlistSkeleton() {
+ return (
+
+ {/* Set 1 */}
+
+
+ {Array.from({ length: 8 }).map((_, i) => (
+
+
+
+
+ ))}
+
+ {/* Set 2 */}
+
+
+ {Array.from({ length: 6 }).map((_, i) => (
+
+
+
+
+ ))}
+
+
+ )
+}
+
+export function TableSkeleton({ rows = 5, cols = 4 }: { rows?: number; cols?: number }) {
+ return (
+
+ {/* Header */}
+
+ {Array.from({ length: cols }).map((_, i) => (
+
+ ))}
+
+ {/* Rows */}
+ {Array.from({ length: rows }).map((_, i) => (
+
+ {Array.from({ length: cols }).map((_, j) => (
+
+ ))}
+
+ ))}
+
+ )
+}
+
+export function PageHeaderSkeleton() {
+ return (
+
+
+
+
+ )
+}