Repository: tensorzero/tensorzero (language: rust)

Issue:
Add a simple home page to the dashboard
We can start with a very simple home page. Later we'll add more information, metrics, etc.

![CleanShot 2024-12-24 at 16 41 59@2x](https://github.com/user-attachments/assets/c1e74887-5946-4239-8e9e-4d26f372646d)

https://v0.dev/chat/MjOv5O0HwV9?b=b_vwIdC2Dh2Dd


The sidebar (#594) should also show up.


Discussion / hints:
Would it be alright if I take this up?
Sounds good @ChetanXpro thanks!

This one should be straightforward, you can ~copy the code generated by v0.


Fix patch:
diff --git a/dashboard/app/components/ui/card.tsx b/dashboard/app/components/ui/card.tsx
new file mode 100644
index 000000000..66416021c
--- /dev/null
+++ b/dashboard/app/components/ui/card.tsx
@@ -0,0 +1,77 @@
+import * as React from "react"
+import { cn } from "~/utils/common"
+
+
+
+const Card = React.forwardRef<
+  HTMLDivElement,
+  React.HTMLAttributes<HTMLDivElement>
+>(({ className, ...props }, ref) => (
+  <div
+    ref={ref}
+    className={cn(
+      "rounded-xl border bg-card text-card-foreground shadow",
+      className
+    )}
+    {...props}
+  />
+))
+Card.displayName = "Card"
+
+const CardHeader = React.forwardRef<
+  HTMLDivElement,
+  React.HTMLAttributes<HTMLDivElement>
+>(({ className, ...props }, ref) => (
+  <div
+    ref={ref}
+    className={cn("flex flex-col space-y-1.5 p-6", className)}
+    {...props}
+  />
+))
+CardHeader.displayName = "CardHeader"
+
+const CardTitle = React.forwardRef<
+  HTMLDivElement,
+  React.HTMLAttributes<HTMLDivElement>
+>(({ className, ...props }, ref) => (
+  <div
+    ref={ref}
+    className={cn("font-semibold leading-none tracking-tight", className)}
+    {...props}
+  />
+))
+CardTitle.displayName = "CardTitle"
+
+const CardDescription = React.forwardRef<
+  HTMLDivElement,
+  React.HTMLAttributes<HTMLDivElement>
+>(({ className, ...props }, ref) => (
+  <div
+    ref={ref}
+    className={cn("text-sm text-muted-foreground", className)}
+    {...props}
+  />
+))
+CardDescription.displayName = "CardDescription"
+
+const CardContent = React.forwardRef<
+  HTMLDivElement,
+  React.HTMLAttributes<HTMLDivElement>
+>(({ className, ...props }, ref) => (
+  <div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
+))
+CardContent.displayName = "CardContent"
+
+const CardFooter = React.forwardRef<
+  HTMLDivElement,
+  React.HTMLAttributes<HTMLDivElement>
+>(({ className, ...props }, ref) => (
+  <div
+    ref={ref}
+    className={cn("flex items-center p-6 pt-0", className)}
+    {...props}
+  />
+))
+CardFooter.displayName = "CardFooter"
+
+export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
diff --git a/dashboard/app/routes.ts b/dashboard/app/routes.ts
index 7555c6a66..a63d47a57 100644
--- a/dashboard/app/routes.ts
+++ b/dashboard/app/routes.ts
@@ -1,6 +1,7 @@
 import { type RouteConfig, route } from "@react-router/dev/routes";
 
 export default [
+  route("/", "routes/index.tsx"),
   route(
     "optimization/supervised-fine-tuning/:job_id?",
     "routes/optimization/supervised-fine-tuning/route.tsx",
diff --git a/dashboard/app/routes/index.tsx b/dashboard/app/routes/index.tsx
new file mode 100644
index 000000000..30c92d395
--- /dev/null
+++ b/dashboard/app/routes/index.tsx
@@ -0,0 +1,69 @@
+import { Link } from "react-router";
+import { Button } from "~/components/ui/button";
+import { Card, CardHeader, CardTitle } from "~/components/ui/card";
+import { BarChart2, GitBranch, Zap, BookOpen } from "lucide-react";
+
+export default function Home() {
+  return (
+    <div className="min-h-screen flex flex-col">
+      <main className="flex-grow py-12">
+        <div className="container px-4 md:px-6 mx-auto max-w-5xl">
+          <div id="observability" className="mb-12">
+            <h2 className="text-3xl font-bold mb-6">Observability</h2>
+            <div className="grid md:grid-cols-2 gap-6">
+              <Link to="#" className="block">
+                <Card className="h-full transition-shadow hover:shadow-md">
+                  <CardHeader>
+                    <div className="flex items-center space-x-2">
+                      <BarChart2 className="h-6 w-6 text-primary" />
+                      <CardTitle>Inferences</CardTitle>
+                    </div>
+                  </CardHeader>
+                </Card>
+              </Link>
+              <Link to="#" className="block">
+                <Card className="h-full transition-shadow hover:shadow-md">
+                  <CardHeader>
+                    <div className="flex items-center space-x-2">
+                      <GitBranch className="h-6 w-6 text-primary" />
+                      <CardTitle>Episodes</CardTitle>
+                    </div>
+                  </CardHeader>
+                </Card>
+              </Link>
+            </div>
+          </div>
+
+          <div id="optimization" className="mb-12">
+            <h2 className="text-3xl font-bold mb-6">Optimization</h2>
+            <div className="grid md:grid-cols-2 gap-6">
+              <Link to="/optimization/fine-tuning" className="block">
+                <Card className="h-full transition-shadow hover:shadow-md">
+                  <CardHeader>
+                    <div className="flex items-center space-x-2">
+                      <Zap className="h-6 w-6 text-primary" />
+                      <CardTitle>Fine-tuning</CardTitle>
+                    </div>
+                  </CardHeader>
+                </Card>
+              </Link>
+            </div>
+          </div>
+        </div>
+      </main>
+
+      <footer className="py-10 bg-muted">
+        <div className="container mx-auto px-4 md:px-6 text-center">
+          <p className="text-lg text-muted-foreground mb-6">
+            Explore our documentation to get the most out of TensorZero.
+          </p>
+          <Button size="default" variant="default" asChild>
+            <Link to="https://www.tensorzero.com/docs" target="_blank">
+              View Documentation <BookOpen className="ml-2 h-4 w-4" />
+            </Link>
+          </Button>
+        </div>
+      </footer>
+    </div>
+  );
+}


Test patch: