@ragrabbit/mcp
by madarco
Verified
import { Metadata } from "next";
import { authOrLogin } from "@repo/auth";
import { Button } from "@repo/design/shadcn/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@repo/design/shadcn/card";
import { ScrollArea } from "@repo/design/shadcn/scroll-area";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@repo/design/shadcn/tabs";
import { FileTextIcon, Link, Calendar, Hash, Type, Database } from "@repo/design/base/icons";
import { headers } from "next/headers";
import { ResetCacheButton } from "./components/reset-cache-button";
import { getLlmStats } from "./actions";
export const metadata: Metadata = {
title: "LLMs.txt",
description: "Generate the LLMs.txt file for your website",
};
function formatBytes(bytes: number) {
if (bytes === 0) return "0 Bytes";
const k = 1024;
const sizes = ["Bytes", "KB", "MB", "GB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
}
function formatNumber(num: number) {
return new Intl.NumberFormat().format(num);
}
async function getBaseUrl() {
const headersList = await headers();
const host = headersList.get("host") || "";
const protocol = host.includes("localhost") || host.includes("127.0.0.1") ? "http" : "https";
return `${protocol}://${host}`;
}
export default async function LlmPage() {
const session = await authOrLogin();
const baseUrl = await getBaseUrl();
const { data: stats } = await getLlmStats({});
const response = await fetch(`${baseUrl}/llms.txt?organizationId=${session.user.organizationId}`, {
cache: "no-store",
});
const content = await response.text();
const fullResponse = await fetch(`${baseUrl}/llms-full.txt?organizationId=${session.user.organizationId}`, {
cache: "no-store",
});
const fullContent = await fullResponse.text();
return (
<>
<div className="flex items-center justify-between space-y-2 mb-8">
<div>
<h2 className="text-2xl font-bold tracking-tight">LLMs.txt</h2>
<p className="text-muted-foreground">
A markdown file containing all your indexed content, perfect for helping language models use your website.
</p>
</div>
<div className="flex items-center space-x-2">
<ResetCacheButton organizationId={session.user.organizationId} />
</div>
</div>
<Card className="mb-8">
<CardContent className="pt-6">
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
<div className="flex flex-col gap-1">
<div className="text-sm text-muted-foreground flex items-center gap-2">
<Database className="h-4 w-4" />
Pages
</div>
<div className="font-medium">{formatNumber(stats.totalIndexed)}</div>
</div>
<div className="flex flex-col gap-1">
<div className="text-sm text-muted-foreground flex items-center gap-2">
<Type className="h-4 w-4" />
Total Tokens
</div>
<div className="font-medium">{formatNumber(stats.totalTokens)}</div>
</div>
<div className="flex flex-col gap-1">
<div className="text-sm text-muted-foreground flex items-center gap-2">
<Hash className="h-4 w-4" />
Total Size
</div>
<div className="font-medium">{formatBytes(stats.totalSizeBytes)}</div>
</div>
<div className="flex flex-col gap-1">
<div className="text-sm text-muted-foreground flex items-center gap-2">
<Calendar className="h-4 w-4" />
Last Updated
</div>
<div className="font-medium">
{stats.lastUpdated ? new Date(stats.lastUpdated).toLocaleString() : "Never"}
</div>
</div>
</div>
</CardContent>
</Card>
<Tabs defaultValue="toc" className="space-y-4">
<TabsList>
<TabsTrigger value="toc">Table of Contents</TabsTrigger>
<TabsTrigger value="full">Full Content</TabsTrigger>
</TabsList>
<TabsContent value="toc">
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<div>
<CardTitle>Table of Contents</CardTitle>
<CardDescription>
This is how your{" "}
<a href="/llms.txt" target="_blank" className="text-blue-500 underline">
{baseUrl}/llms.txt
</a>{" "}
file looks like. The content is cached for 1 hour.
</CardDescription>
</div>
<Button variant="outline" size="sm" asChild>
<a href={`/llms.txt?organizationId=${session.user.organizationId}`} target="_blank">
<FileTextIcon className="h-4 w-4 mr-2" />
Open LLMs.txt
</a>
</Button>
</CardHeader>
<CardContent>
<ScrollArea className="h-[500px] w-full rounded-md border p-4">
<pre className="text-sm whitespace-pre-wrap font-mono">{content}</pre>
</ScrollArea>
</CardContent>
</Card>
</TabsContent>
<TabsContent value="full">
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<div>
<CardTitle>Full Content</CardTitle>
<CardDescription>
This is how your{" "}
<a href="/llms-full.txt" target="_blank" className="text-blue-500 underline">
{baseUrl}/llms-full.txt
</a>{" "}
file looks like. The content is cached for 1 hour.
</CardDescription>
</div>
<Button variant="outline" size="sm" asChild>
<a href={`/llms-full.txt?organizationId=${session.user.organizationId}`} target="_blank">
<FileTextIcon className="h-4 w-4 mr-2" />
Open LLMs-full.txt
</a>
</Button>
</CardHeader>
<CardContent>
<ScrollArea className="h-[500px] w-full rounded-md border p-4">
<pre className="text-sm whitespace-pre-wrap font-mono">{fullContent}</pre>
</ScrollArea>
</CardContent>
</Card>
</TabsContent>
</Tabs>
</>
);
}