mirror of
https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools.git
synced 2025-12-16 05:25:11 +00:00
This commit adds a complete, production-ready web application for browsing and exploring AI tool system prompts. The interface provides an intuitive, responsive, and feature-rich experience for discovering AI tools. ## Web Application Features **Core Functionality:** - 🔍 Advanced search with real-time filtering - 📊 Interactive statistics dashboard with visualizations - 🔄 Side-by-side comparison of up to 4 tools - ⭐ Favorites system with local persistence - 📱 Fully responsive mobile-first design - 🎨 Dark/light mode with system preference detection - ⚡ Optimized performance with Next.js Server Components **Pages:** - Home: Hero section, features showcase, featured tools - Browse: Advanced filtering, grid/list views, category filters - Stats: Comprehensive analytics and visualizations - Compare: Side-by-side tool comparison - Tool Detail: In-depth tool information - About: Project information and tech stack **Components:** - Responsive navbar with mobile menu - Tool cards with interactive actions - Reusable UI components (Button, Card, Badge, Input) - Footer with quick links and stats - Theme provider for dark mode - Loading and error states ## Technical Stack **Framework & Libraries:** - Next.js 15 with App Router - React 19.0 with Server Components - TypeScript 5.6 for type safety - Tailwind CSS for styling - Zustand for state management - next-themes for theme switching - Lucide React for icons **Features:** - Server-side rendering (SSR) - Static site generation (SSG) for tool pages - Optimized bundle with automatic code splitting - SEO-friendly with metadata API - Accessibility best practices ## Project Structure web/ ├── app/ # Next.js pages ├── components/ # React components ├── lib/ # Utilities and data ├── data/ # Static data (index.json) ├── setup.sh # Setup script └── README.md # Documentation ## Developer Experience - TypeScript for type safety - ESLint for code quality - Hot module replacement - Fast refresh - Comprehensive documentation - Setup script for quick start ## Updated Documentation - Enhanced main README with web interface section - Created comprehensive web/README.md - Updated roadmap to mark completed features - Added Quick Start guide for web app ## Stats - 33 new files created - ~3,500 lines of TypeScript/TSX - Full responsive design (mobile, tablet, desktop) - Production-ready with build optimizations Users can now explore 32+ AI tools through an intuitive web interface instead of just command-line tools. Version: 2.0.0
226 lines
8.2 KiB
TypeScript
226 lines
8.2 KiB
TypeScript
import { notFound } from 'next/navigation'
|
|
import Link from 'next/link'
|
|
import { ArrowLeft, ExternalLink, FileText, Code, Calendar, GitCompare, Heart } from 'lucide-react'
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
|
import { Badge } from '@/components/ui/badge'
|
|
import { Button } from '@/components/ui/button'
|
|
import { getAllTools, getCategoryIcon, getCategoryColor } from '@/lib/data'
|
|
import { formatNumber, formatBytes, slugify } from '@/lib/utils'
|
|
|
|
export async function generateStaticParams() {
|
|
const tools = getAllTools()
|
|
return tools.map((tool) => ({
|
|
slug: slugify(tool.directory),
|
|
}))
|
|
}
|
|
|
|
export default function ToolDetailPage({ params }: { params: { slug: string } }) {
|
|
const tools = getAllTools()
|
|
const tool = tools.find((t) => slugify(t.directory) === params.slug)
|
|
|
|
if (!tool) {
|
|
notFound()
|
|
}
|
|
|
|
return (
|
|
<div className="container mx-auto px-4 py-8">
|
|
{/* Back Button */}
|
|
<Button asChild variant="ghost" className="mb-6">
|
|
<Link href="/browse">
|
|
<ArrowLeft className="w-4 h-4 mr-2" />
|
|
Back to Browse
|
|
</Link>
|
|
</Button>
|
|
|
|
{/* Header */}
|
|
<div className="mb-8">
|
|
<div className="flex items-start gap-4 mb-4">
|
|
<div className="text-5xl">{getCategoryIcon(tool.category)}</div>
|
|
<div className="flex-1">
|
|
<div className="flex flex-wrap items-center gap-2 mb-2">
|
|
<h1 className="text-4xl font-bold">{tool.name}</h1>
|
|
<Badge variant="secondary">{tool.category}</Badge>
|
|
<Badge variant="outline">{tool.type}</Badge>
|
|
</div>
|
|
<p className="text-xl text-muted-foreground mb-4">{tool.company}</p>
|
|
<p className="text-lg">{tool.description}</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Quick Stats */}
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
<Card>
|
|
<CardHeader className="pb-2">
|
|
<CardDescription className="text-xs">Files</CardDescription>
|
|
<CardTitle className="text-2xl">{tool.file_count}</CardTitle>
|
|
</CardHeader>
|
|
</Card>
|
|
<Card>
|
|
<CardHeader className="pb-2">
|
|
<CardDescription className="text-xs">Total Lines</CardDescription>
|
|
<CardTitle className="text-2xl">{formatNumber(tool.total_lines)}</CardTitle>
|
|
</CardHeader>
|
|
</Card>
|
|
<Card>
|
|
<CardHeader className="pb-2">
|
|
<CardDescription className="text-xs">Models</CardDescription>
|
|
<CardTitle className="text-2xl">{tool.models.length || '-'}</CardTitle>
|
|
</CardHeader>
|
|
</Card>
|
|
<Card>
|
|
<CardHeader className="pb-2">
|
|
<CardDescription className="text-xs">Category</CardDescription>
|
|
<CardTitle className="text-xl truncate">{tool.category}</CardTitle>
|
|
</CardHeader>
|
|
</Card>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid gap-6 lg:grid-cols-3">
|
|
<div className="lg:col-span-2 space-y-6">
|
|
{/* Files */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<FileText className="w-5 h-5" />
|
|
Configuration Files
|
|
</CardTitle>
|
|
<CardDescription>
|
|
{tool.file_count} files containing system prompts and configurations
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="space-y-2">
|
|
{tool.files.map((file) => (
|
|
<div
|
|
key={file.path}
|
|
className="flex items-center justify-between p-3 border rounded-lg hover:bg-muted/50 transition-colors"
|
|
>
|
|
<div className="flex-1 min-w-0">
|
|
<div className="font-medium truncate">{file.name}</div>
|
|
<div className="text-xs text-muted-foreground">
|
|
{formatBytes(file.size)}
|
|
{file.lines && ` • ${formatNumber(file.lines)} lines`}
|
|
</div>
|
|
</div>
|
|
<Badge variant="outline" className="ml-2">
|
|
{file.type}
|
|
</Badge>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Models */}
|
|
{tool.models.length > 0 && (
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<Code className="w-5 h-5" />
|
|
AI Models
|
|
</CardTitle>
|
|
<CardDescription>Models used or supported by this tool</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="flex flex-wrap gap-2">
|
|
{tool.models.map((model) => (
|
|
<Badge key={model} variant="secondary" className="text-sm">
|
|
{model}
|
|
</Badge>
|
|
))}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
)}
|
|
|
|
{/* Subcategories */}
|
|
{tool.subcategories && tool.subcategories.length > 0 && (
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Related Tools</CardTitle>
|
|
<CardDescription>Other tools in this collection</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="flex flex-wrap gap-2">
|
|
{tool.subcategories.map((sub) => (
|
|
<Badge key={sub} variant="outline">
|
|
{sub}
|
|
</Badge>
|
|
))}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
)}
|
|
</div>
|
|
|
|
{/* Sidebar */}
|
|
<div className="space-y-6">
|
|
{/* Actions */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="text-lg">Actions</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="space-y-2">
|
|
{tool.website && (
|
|
<Button asChild className="w-full">
|
|
<a href={tool.website} target="_blank" rel="noopener noreferrer">
|
|
<ExternalLink className="w-4 h-4 mr-2" />
|
|
Visit Website
|
|
</a>
|
|
</Button>
|
|
)}
|
|
<Button variant="outline" className="w-full">
|
|
<a
|
|
href={`https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools/tree/main/${encodeURIComponent(
|
|
tool.directory
|
|
)}`}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="flex items-center w-full"
|
|
>
|
|
<FileText className="w-4 h-4 mr-2" />
|
|
View on GitHub
|
|
</a>
|
|
</Button>
|
|
<Button variant="outline" className="w-full">
|
|
<GitCompare className="w-4 h-4 mr-2" />
|
|
Add to Compare
|
|
</Button>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Info */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="text-lg">Information</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="space-y-3 text-sm">
|
|
<div>
|
|
<div className="text-muted-foreground mb-1">Company</div>
|
|
<div className="font-medium">{tool.company}</div>
|
|
</div>
|
|
<div>
|
|
<div className="text-muted-foreground mb-1">Category</div>
|
|
<div className="font-medium">{tool.category}</div>
|
|
</div>
|
|
<div>
|
|
<div className="text-muted-foreground mb-1">Type</div>
|
|
<Badge variant="outline" className="capitalize">
|
|
{tool.type}
|
|
</Badge>
|
|
</div>
|
|
<div>
|
|
<div className="text-muted-foreground mb-1">Total Size</div>
|
|
<div className="font-medium">
|
|
{formatBytes(tool.files.reduce((acc, f) => acc + f.size, 0))}
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|