diff --git a/package.json b/package.json
index 80185f8d..69f08e01 100644
--- a/package.json
+++ b/package.json
@@ -28,7 +28,8 @@
"og:clean-orphans": "tsx --tsconfig scripts/tsconfig.json scripts/clean-og-images.ts",
"og:optimize": "node scripts/optimize-og-images.js",
"og:optimize-replace": "node scripts/optimize-og-images.js --replace",
- "prisma:seed": "tsx --tsconfig prisma/tsconfig.json prisma/seed.ts"
+ "prisma:seed": "tsx --tsconfig prisma/tsconfig.json prisma/seed.ts",
+ "seed:tools": "node scripts/seed-tools.js"
},
"browserslist": "defaults, not ie <= 11",
"dependencies": {
diff --git a/scripts/seed-tools.js b/scripts/seed-tools.js
new file mode 100755
index 00000000..63fee929
--- /dev/null
+++ b/scripts/seed-tools.js
@@ -0,0 +1,186 @@
+#!/usr/bin/env node
+
+const { PrismaClient } = require('@prisma/client');
+const prisma = new PrismaClient();
+
+async function main() {
+ console.log('Starting to seed AI developer tools...');
+
+ // Delete all existing tools
+ await prisma.tool.deleteMany({});
+ console.log('Cleared existing tools');
+
+ // Sample tools data
+ const tools = [
+ {
+ name: 'GitHub Copilot',
+ description: 'AI pair programmer that helps you write code faster with less work',
+ category: 'Code Autocompletion',
+ websiteUrl: 'https://github.com/features/copilot',
+ githubUrl: 'https://github.com/features/copilot',
+ pricing: 'Free for students, $10/month individual, $19/user/month for businesses',
+ openSource: false,
+ features: ['Code completion', 'Function generation', 'Test generation', 'Code explanations', 'Natural language to code'],
+ languages: ['JavaScript', 'TypeScript', 'Python', 'Go', 'Ruby', 'Java', 'C#', 'PHP'],
+ pros: ['Seamless GitHub integration', 'Multi-IDE support', 'Fast suggestions', 'Context-aware completion'],
+ cons: ['Subscription cost', 'Sometimes generates incorrect code', 'May suggest code with security vulnerabilities'],
+ reviewCount: 1254,
+ logoUrl: 'https://github.githubassets.com/images/modules/site/features/copilot/copilot.png'
+ },
+ {
+ name: 'Codeium',
+ description: 'Free AI-powered code completion and chat tool',
+ category: 'Code Autocompletion',
+ websiteUrl: 'https://codeium.com',
+ githubUrl: null,
+ pricing: 'Free tier, $12/month Pro',
+ openSource: false,
+ features: ['Code completion', 'Code chat', 'Context awareness', 'Multi-file understanding', 'API suggestions'],
+ languages: ['JavaScript', 'TypeScript', 'Python', 'Go', 'Ruby', 'Rust', 'C++', 'PHP'],
+ pros: ['Free tier available', 'Accurate suggestions', 'Good privacy practices', 'Supports many IDEs'],
+ cons: ['Newer tool with fewer users', 'Sometimes slower than alternatives'],
+ reviewCount: 863,
+ logoUrl: 'https://codeium.com/images/landing/codeium-logo.png'
+ },
+ {
+ name: 'Cursor',
+ description: 'AI-first code editor built on VSCode with chat, edit, and generation capabilities',
+ category: 'AI-Enhanced IDE',
+ websiteUrl: 'https://cursor.sh',
+ githubUrl: null,
+ pricing: 'Free tier, $20/month Pro',
+ openSource: false,
+ features: ['AI chat', 'Code editing', 'Code generation', 'Codebase understanding', 'Full IDE functionality'],
+ languages: ['JavaScript', 'TypeScript', 'Python', 'Go', 'Ruby', 'Rust', 'C++', 'PHP', 'Java'],
+ pros: ['Built on VSCode', 'Powerful chat interface', 'Understands your entire codebase', 'Active development'],
+ cons: ['Occasionally high resource usage', 'Newer tool still maturing'],
+ reviewCount: 742,
+ logoUrl: 'https://cursor.sh/cursor.svg'
+ },
+ {
+ name: 'Tabnine',
+ description: 'AI-powered code completion assistant that helps developers write code faster',
+ category: 'Code Autocompletion',
+ websiteUrl: 'https://www.tabnine.com',
+ githubUrl: 'https://github.com/codota/tabnine',
+ pricing: 'Free tier, $12/month Pro, Team plans available',
+ openSource: false,
+ features: ['Code completion', 'Whole line completion', 'Local processing option', 'Code snippets'],
+ languages: ['JavaScript', 'TypeScript', 'Python', 'Java', 'C#', 'PHP', 'Go', 'Ruby'],
+ pros: ['Privacy-focused local AI option', 'Good free tier', 'Lightweight', 'Works with many IDEs'],
+ cons: ['Sometimes less context-aware than competitors', 'Local model has less advanced capabilities'],
+ reviewCount: 917,
+ logoUrl: 'https://www.tabnine.com/favicon.ico'
+ },
+ {
+ name: 'Amazon CodeWhisperer',
+ description: 'AI coding companion from AWS that provides code suggestions',
+ category: 'Code Autocompletion',
+ websiteUrl: 'https://aws.amazon.com/codewhisperer/',
+ githubUrl: null,
+ pricing: 'Free for individual developers, Professional tier for businesses',
+ openSource: false,
+ features: ['Code completion', 'Security scans', 'Reference tracking', 'AWS service integration'],
+ languages: ['Java', 'Python', 'JavaScript', 'TypeScript', 'C#', 'Go', 'Ruby', 'PHP'],
+ pros: ['AWS integration', 'Security scanning', 'Free for individual use', 'Provides references for generated code'],
+ cons: ['Less effective outside of AWS context', 'Fewer IDE integrations'],
+ reviewCount: 485,
+ logoUrl: 'https://a0.awsstatic.com/libra-css/images/logos/aws_logo_smile_1200x630.png'
+ },
+ {
+ name: 'Aider',
+ description: 'Voice and chat-based AI coding assistant that helps edit your code',
+ category: 'CLI Tool',
+ websiteUrl: 'https://aider.chat',
+ githubUrl: 'https://github.com/paul-gauthier/aider',
+ pricing: 'Free and open source (requires OpenAI API key)',
+ openSource: true,
+ features: ['Terminal-based coding', 'Voice control', 'Edit code through chat', 'Git integration'],
+ languages: ['Python', 'JavaScript', 'TypeScript', 'Go', 'Rust', 'Ruby', 'Java', 'C++'],
+ pros: ['Open source', 'Works in terminal', 'Voice control option', 'Edits code directly'],
+ cons: ['Requires OpenAI API key and costs', 'Less polished UI than IDE alternatives'],
+ reviewCount: 312,
+ logoUrl: null
+ },
+ {
+ name: 'Warp',
+ description: 'Terminal reimagined with AI assistance for commands and workflows',
+ category: 'CLI Tool',
+ websiteUrl: 'https://www.warp.dev',
+ githubUrl: null,
+ pricing: 'Free tier, $8.25/month Team plan',
+ openSource: false,
+ features: ['AI command search', 'Workflow sharing', 'Block-based terminal', 'Command history'],
+ languages: ['Bash', 'Zsh', 'Fish', 'PowerShell'],
+ pros: ['Modern terminal design', 'Block-based output', 'Command suggestions', 'Workflow sharing'],
+ cons: ['macOS only (Linux in beta)', 'Learning curve for terminal power users'],
+ reviewCount: 623,
+ logoUrl: 'https://warp.dev/static/logo-4a1ade13a372fa822a9fd1b271a61386.svg'
+ },
+ {
+ name: 'Cody',
+ description: 'AI coding assistant from Sourcegraph that understands your entire codebase',
+ category: 'Code Chat',
+ websiteUrl: 'https://sourcegraph.com/cody',
+ githubUrl: 'https://github.com/sourcegraph/cody',
+ pricing: 'Free tier, $19/month Pro, Enterprise plans',
+ openSource: true,
+ features: ['Codebase understanding', 'Context-aware answers', 'Multi-repo support', 'Code explanations'],
+ languages: ['JavaScript', 'TypeScript', 'Python', 'Go', 'Java', 'C#', 'Ruby', 'Rust'],
+ pros: ['Understands large codebases', 'Good free tier', 'Context-aware responses', 'Partially open source'],
+ cons: ['Pro features require subscription', 'VSCode-focused'],
+ reviewCount: 520,
+ logoUrl: 'https://sourcegraph.com/.assets/img/sourcegraph-mark.svg'
+ },
+ {
+ name: 'Zed',
+ description: 'High-performance code editor with built-in AI pair programming',
+ category: 'AI-Enhanced IDE',
+ websiteUrl: 'https://zed.dev',
+ githubUrl: 'https://github.com/zed-industries/zed',
+ pricing: 'Free (currently in alpha)',
+ openSource: true,
+ features: ['Collaboration', 'AI pair programming', 'High performance', 'Multi-user editing'],
+ languages: ['JavaScript', 'TypeScript', 'Python', 'Rust', 'Go', 'Ruby', 'C++', 'PHP'],
+ pros: ['Rust-based for speed', 'Real-time collaboration', 'Open source', 'Low resource usage'],
+ cons: ['Still in alpha stage', 'Missing some features of mature IDEs', 'macOS only currently'],
+ reviewCount: 387,
+ logoUrl: 'https://zed.dev/img/logo-black.svg'
+ },
+ {
+ name: 'Descript',
+ description: 'AI-powered audio and video editor that lets you edit media like a text document',
+ category: 'Visual Editor',
+ websiteUrl: 'https://www.descript.com',
+ githubUrl: null,
+ pricing: 'Free tier, $12/month Creator, $24/month Pro',
+ openSource: false,
+ features: ['Transcription', 'Text-based editing', 'Voice cloning', 'Screen recording', 'AI generation'],
+ languages: ['English', 'Spanish', 'French', 'German', 'Portuguese', 'Italian'],
+ pros: ['Intuitive interface', 'Powerful AI features', 'Text-based editing workflow', 'Good free tier'],
+ cons: ['Resource intensive', 'Advanced features require subscription'],
+ reviewCount: 934,
+ logoUrl: 'https://assets-global.website-files.com/61d7d85891c3310080c170cf/6228a9bf741a11434a14252d_descript-favicon-256.png'
+ }
+ ];
+
+ // Add tools to database
+ for (const tool of tools) {
+ await prisma.tool.create({
+ data: tool
+ });
+ console.log(`Added ${tool.name}`);
+ }
+
+ const toolCount = await prisma.tool.count();
+ console.log(`Database now has ${toolCount} tools`);
+}
+
+main()
+ .catch((e) => {
+ console.error('Error seeding tools:', e);
+ process.exit(1);
+ })
+ .finally(async () => {
+ await prisma.$disconnect();
+ });
\ No newline at end of file
diff --git a/src/actions/tool-actions.js b/src/actions/tool-actions.js
new file mode 100644
index 00000000..910fd13a
--- /dev/null
+++ b/src/actions/tool-actions.js
@@ -0,0 +1,176 @@
+'use server'
+
+import { prisma } from '@/lib/prisma'
+import { revalidatePath } from 'next/cache'
+
+export async function getToolByName(name) {
+ if (!name) return null
+
+ return prisma.tool.findFirst({
+ where: {
+ name: {
+ equals: name,
+ mode: 'insensitive'
+ }
+ }
+ })
+}
+
+export async function getToolBySlug(slug) {
+ if (!slug) return null
+
+ return prisma.tool.findFirst({
+ where: {
+ name: {
+ equals: slug.replace(/-/g, ' '),
+ mode: 'insensitive'
+ }
+ }
+ })
+}
+
+export async function getToolById(id) {
+ if (!id) return null
+
+ return prisma.tool.findUnique({
+ where: { id }
+ })
+}
+
+export async function getAllTools() {
+ return prisma.tool.findMany({
+ orderBy: { name: 'asc' }
+ })
+}
+
+export async function getPopularTools(limit = 10) {
+ return prisma.tool.findMany({
+ orderBy: { reviewCount: 'desc' },
+ take: limit
+ })
+}
+
+export async function getToolsByCategory(category) {
+ return prisma.tool.findMany({
+ where: { category },
+ orderBy: { name: 'asc' }
+ })
+}
+
+export async function getToolPairs() {
+ const tools = await getAllTools()
+ const pairs = []
+
+ for (let i = 0; i < tools.length; i++) {
+ for (let j = i + 1; j < tools.length; j++) {
+ pairs.push([tools[i], tools[j]])
+ }
+ }
+
+ return pairs
+}
+
+export async function getPopularComparisons(limit = 20) {
+ // This is a placeholder - ideally you would track popular comparisons
+ // For now, we'll just return the first n pairs of tools
+ const pairs = await getToolPairs()
+ return pairs.slice(0, limit)
+}
+
+// Admin CRUD operations
+export async function addTool(formData) {
+ try {
+ // Convert array fields from string to actual arrays
+ const features = formData.features ? formData.features.split(',').map(f => f.trim()) : []
+ const languages = formData.languages ? formData.languages.split(',').map(l => l.trim()) : []
+ const pros = formData.pros ? formData.pros.split(',').map(p => p.trim()) : []
+ const cons = formData.cons ? formData.cons.split(',').map(c => c.trim()) : []
+
+ const tool = await prisma.tool.create({
+ data: {
+ name: formData.name,
+ description: formData.description,
+ category: formData.category,
+ website: formData.website,
+ githubUrl: formData.githubUrl || null,
+ pricing: formData.pricing || null,
+ features,
+ languages,
+ pros,
+ cons,
+ openSource: formData.openSource === 'true',
+ rating: parseFloat(formData.rating) || 0,
+ reviewCount: parseInt(formData.reviewCount) || 0,
+ logoUrl: formData.logoUrl || null,
+ demosUrl: formData.demosUrl || null
+ }
+ })
+
+ revalidatePath('/comparisons')
+ revalidatePath('/devtools')
+ revalidatePath('/admin/tools')
+
+ return { success: true, tool }
+ } catch (error) {
+ console.error('Error adding tool:', error)
+ return { success: false, error: error.message }
+ }
+}
+
+export async function updateTool(id, formData) {
+ try {
+ // Convert array fields from string to actual arrays
+ const features = formData.features ? formData.features.split(',').map(f => f.trim()) : []
+ const languages = formData.languages ? formData.languages.split(',').map(l => l.trim()) : []
+ const pros = formData.pros ? formData.pros.split(',').map(p => p.trim()) : []
+ const cons = formData.cons ? formData.cons.split(',').map(c => c.trim()) : []
+
+ const tool = await prisma.tool.update({
+ where: { id },
+ data: {
+ name: formData.name,
+ description: formData.description,
+ category: formData.category,
+ website: formData.website,
+ githubUrl: formData.githubUrl || null,
+ pricing: formData.pricing || null,
+ features,
+ languages,
+ pros,
+ cons,
+ openSource: formData.openSource === 'true',
+ rating: parseFloat(formData.rating) || 0,
+ reviewCount: parseInt(formData.reviewCount) || 0,
+ logoUrl: formData.logoUrl || null,
+ demosUrl: formData.demosUrl || null
+ }
+ })
+
+ revalidatePath('/comparisons')
+ revalidatePath('/devtools')
+ revalidatePath('/admin/tools')
+ revalidatePath(`/comparisons/${tool.name.toLowerCase().replace(/ /g, '-')}`)
+
+ return { success: true, tool }
+ } catch (error) {
+ console.error('Error updating tool:', error)
+ return { success: false, error: error.message }
+ }
+}
+
+export async function deleteTool(id) {
+ try {
+ const tool = await prisma.tool.delete({
+ where: { id }
+ })
+
+ revalidatePath('/comparisons')
+ revalidatePath('/devtools')
+ revalidatePath('/admin/tools')
+
+ return { success: true, tool }
+ } catch (error) {
+ console.error('Error deleting tool:', error)
+ return { success: false, error: error.message }
+ }
+}
\ No newline at end of file
diff --git a/src/app/comparisons/page.jsx b/src/app/comparisons/page.jsx
index a9cb929a..11eea1fc 100644
--- a/src/app/comparisons/page.jsx
+++ b/src/app/comparisons/page.jsx
@@ -1,22 +1,228 @@
-import { SimpleLayout } from '@/components/SimpleLayout'
-import { getAllComparisons } from '@/lib/comparisons'
-import { createMetadata } from '@/utils/createMetadata'
-import ComparisonSearch from '@/components/ComparisonSearch'
+'use client'
-export const metadata = createMetadata({
- title: "Vector Database Comparisons",
- description: "Compare different vector databases side by side"
-});
-
-export default async function ComparisonsIndex() {
- let comparisons = await getAllComparisons()
+import { useState, useEffect } from 'react'
+import { useRouter } from 'next/navigation'
+import Link from 'next/link'
+import { getAllTools, getPopularComparisons } from '@/actions/tool-actions'
+import { slugifyToolName } from '@/utils/comparison-helpers'
+import { Button } from '@/components/ui/button'
+import { Input } from '@/components/ui/input'
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
+import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'
+import { ArrowRight, Search, TrendingUp } from 'lucide-react'
+export default function ComparisonsPage() {
+ const router = useRouter()
+ const [tools, setTools] = useState([])
+ const [popularComparisons, setPopularComparisons] = useState([])
+ const [selectedTool1, setSelectedTool1] = useState('')
+ const [selectedTool2, setSelectedTool2] = useState('')
+ const [isLoading, setIsLoading] = useState(true)
+ const [searchQuery, setSearchQuery] = useState('')
+
+ useEffect(() => {
+ async function fetchData() {
+ setIsLoading(true)
+
+ try {
+ const fetchedTools = await getAllTools()
+ setTools(fetchedTools)
+
+ // Only run this if there are 2+ tools
+ if (fetchedTools.length >= 2) {
+ const fetchedComparisons = await getPopularComparisons(10)
+ setPopularComparisons(fetchedComparisons)
+ }
+ } catch (error) {
+ console.error("Error fetching data:", error)
+ } finally {
+ setIsLoading(false)
+ }
+ }
+
+ fetchData()
+ }, [])
+
+ const handleCompare = () => {
+ if (selectedTool1 && selectedTool2 && selectedTool1 !== selectedTool2) {
+ const tool1Slug = slugifyToolName(selectedTool1)
+ const tool2Slug = slugifyToolName(selectedTool2)
+ router.push(`/comparisons/${tool1Slug}/vs/${tool2Slug}`)
+ }
+ }
+
+ const filteredTools = searchQuery
+ ? tools.filter(tool =>
+ tool.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ tool.category.toLowerCase().includes(searchQuery.toLowerCase())
+ )
+ : tools
+
+ // Group tools by category
+ const toolsByCategory = filteredTools.reduce((acc, tool) => {
+ if (!acc[tool.category]) {
+ acc[tool.category] = []
+ }
+ acc[tool.category].push(tool)
+ return acc
+ }, {})
+
return (
-
+ Compare features, pricing, and capabilities of popular AI-assisted development tools + to find the best fit for your workflow. +
+ ++ {tool.description} +
+{paragraph}
: