diff --git a/components/Catalog/CatalogLandingHeader.tsx b/components/Catalog/CatalogLandingHeader.tsx
new file mode 100644
index 000000000..9f8dc2093
--- /dev/null
+++ b/components/Catalog/CatalogLandingHeader.tsx
@@ -0,0 +1,57 @@
+"use client";
+
+import Link from "next/link";
+import { Sparkles } from "lucide-react";
+import { Button } from "@/components/ui/button";
+import { Skeleton } from "@/components/ui/skeleton";
+import useCatalogs from "@/hooks/useCatalogs";
+import useArtistCatalogSongs from "@/hooks/useArtistCatalogSongs";
+
+interface CatalogLandingHeaderProps {
+ catalogId: string;
+}
+
+/**
+ * Landing header for a catalog deep-link (e.g. a warm lead arriving from a
+ * marketing valuation). Shows the catalog name, how many tracks it holds, and
+ * a single clear next action — open the agent pre-asked about this catalog —
+ * so the work the lead just did has an obvious continuation.
+ */
+const CatalogLandingHeader = ({ catalogId }: CatalogLandingHeaderProps) => {
+ const { data: catalogsData } = useCatalogs();
+ const catalog = catalogsData?.catalogs?.find((c) => c.id === catalogId);
+
+ const { data, isLoading } = useArtistCatalogSongs({
+ catalogId,
+ pageSize: 1,
+ });
+ const trackCount = data?.pages?.[0]?.pagination?.total_count ?? 0;
+
+ const name = catalog?.name ?? "Your catalog";
+ const prompt = `Tell me about my catalog "${name}" — what stands out across these tracks, and what should I do next?`;
+
+ return (
+
+ );
+};
+
+export default CatalogLandingHeader;
diff --git a/components/Catalog/CatalogSongsPage.tsx b/components/Catalog/CatalogSongsPage.tsx
index 228d29e65..eec78ab23 100644
--- a/components/Catalog/CatalogSongsPage.tsx
+++ b/components/Catalog/CatalogSongsPage.tsx
@@ -1,6 +1,7 @@
"use client";
import CatalogSongsPageContent from "./CatalogSongsPageContent";
+import CatalogLandingHeader from "./CatalogLandingHeader";
import { useRouter } from "next/navigation";
import { ArrowLeft } from "lucide-react";
@@ -27,7 +28,7 @@ const CatalogSongsPage = ({ catalogId }: CatalogSongsPageProps) => {
Back to Catalogs
-
Catalog Songs
+
);
diff --git a/components/Catalog/CatalogsPageContent.tsx b/components/Catalog/CatalogsPageContent.tsx
index dff747ae6..b84466806 100644
--- a/components/Catalog/CatalogsPageContent.tsx
+++ b/components/Catalog/CatalogsPageContent.tsx
@@ -2,6 +2,7 @@
import useCatalogs from "@/hooks/useCatalogs";
import CatalogCard from "./CatalogCard";
+import EmptyCatalogsState from "./EmptyCatalogsState";
import { Skeleton } from "@/components/ui/skeleton";
import { useUserProvider } from "@/providers/UserProvder";
@@ -35,7 +36,7 @@ const CatalogsPageContent = () => {
const catalogs = data?.catalogs || [];
if (!catalogs.length) {
- return
No catalogs found.
;
+ return ;
}
return (
diff --git a/components/Catalog/EmptyCatalogsState.tsx b/components/Catalog/EmptyCatalogsState.tsx
new file mode 100644
index 000000000..2744fa7bb
--- /dev/null
+++ b/components/Catalog/EmptyCatalogsState.tsx
@@ -0,0 +1,43 @@
+"use client";
+
+import Link from "next/link";
+import { Sparkles, BarChart3 } from "lucide-react";
+import { Button } from "@/components/ui/button";
+
+const VALUATION_URL = "https://recoupable.com/valuation";
+const AGENT_PROMPT =
+ "Help me set up my first catalog and understand what my music is worth.";
+
+/**
+ * Onboarding empty state for an account with no catalogs yet. Replaces the bare
+ * "No catalogs found." text with a guided next step: run a free valuation (the
+ * same flow that materializes a catalog) or ask the agent to help build one.
+ */
+const EmptyCatalogsState = () => {
+ return (
+
+
No catalogs yet
+
+ A catalog is your collection of tracks with their play counts and
+ estimated value. Run a free valuation to measure your catalog, or ask the
+ agent to help you build one.
+