Tool

import React, { useState, useEffect, useMemo, useRef } from ‘react’; import { Search, Plus, Star, ExternalLink, Trash2, Edit3, ChevronLeft, Youtube, Globe, X, Command, LayoutGrid, Zap, Cpu, Activity } from ‘lucide-react’; import { motion, AnimatePresence, useScroll, useSpring } from ‘framer-motion’; // ───────────────────────────────────────────── // CONSTANTS // ───────────────────────────────────────────── const CATEGORIES = [‘AI’, ‘DevTools’, ‘Design’, ‘Productivity’, ‘Marketing’, ‘Utilities’, ‘Learning’]; const EMPTY_FORM = { name: ”, url: ”, category: CATEGORIES[0], description: ”, notes: ”, tags: ”, youtube_links: [”], is_favorite: false }; // ← Paste your Make.com webhook URL here const MAKE_WEBHOOK_URL = ‘https://hook.eu2.make.com/YOUR_WEBHOOK_ID’; // ───────────────────────────────────────────── // UTILITIES // ───────────────────────────────────────────── const generateId = () => Math.random().toString(36).substr(2, 9); const getYouTubeId = (url) => { const m = url?.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/); return (m && m[2].length === 11) ? m[2] : null; }; // ───────────────────────────────────────────── // MAKE.COM AUTOFILL (no API keys in frontend) // ───────────────────────────────────────────── const autofillViaMake = async (url) => { const res = await fetch(MAKE_WEBHOOK_URL, { method: ‘POST’, headers: { ‘Content-Type’: ‘application/json’ }, body: JSON.stringify({ url }), }); if (!res.ok) throw new Error(`Webhook error ${res.status}`); const data = await res.json(); // data must be { name, category, description, tags[] } return data; }; // ───────────────────────────────────────────── // DATA STORE (in-memory) // ───────────────────────────────────────────── const useTools = () => { const [tools, setTools] = useState([ { id: ‘demo1’, name: ‘Claude AI’, url: ‘https://claude.ai’, category: ‘AI’, description: “Anthropic’s AI assistant for coding, writing, analysis, and complex reasoning tasks.”, notes: ‘Best for long-form reasoning. Use for code review and documentation.’, tags: [‘llm’, ‘anthropic’, ‘chatbot’], youtube_links: [], is_favorite: true, created_at: new Date().toISOString() }, { id: ‘demo2’, name: ‘Figma’, url: ‘https://figma.com’, category: ‘Design’, description: ‘Collaborative interface design tool for teams. Create, prototype, and hand off designs.’, notes: ‘Use auto-layout for responsive components. Plugins: Iconify, Unsplash.’, tags: [‘design’, ‘ui’, ‘prototyping’], youtube_links: [], is_favorite: false, created_at: new Date(Date.now() – 86400000).toISOString() }, { id: ‘demo3’, name: ‘Make’, url: ‘https://make.com’, category: ‘Productivity’, description: ‘Visual automation platform to connect apps and automate workflows without code.’, notes: ‘Incredible for webhook automation. Way more flexible than Zapier.’, tags: [‘automation’, ‘no-code’, ‘workflows’], youtube_links: [], is_favorite: true, created_at: new Date(Date.now() – 172800000).toISOString() }, ]); const addTool = (tool) => setTools(prev => [{ …tool, id: generateId(), created_at: new Date().toISOString(), is_favorite: tool.is_favorite || false, tags: tool.tags || [], youtube_links: tool.youtube_links || [] }, …prev]); const updateTool = (t) => setTools(prev => prev.map(p => p.id === t.id ? t : p)); const deleteTool = (id) => setTools(prev => prev.filter(t => t.id !== id)); const toggleFavorite = (id) => setTools(prev => prev.map(t => t.id === id ? { …t, is_favorite: !t.is_favorite } : t)); return { tools, addTool, updateTool, deleteTool, toggleFavorite }; }; // ───────────────────────────────────────────── // SHARED VISUAL PRIMITIVES // ───────────────────────────────────────────── const AntiGravityOrb = ({ color, size, top, left, delay }) => ( ); const GlassCard = ({ children, onClick, className = ” }) => ( {children} ); const CategoryPill = ({ label, active, onClick }) => ( {label} ); const PulsingDot = () => ( ); // ───────────────────────────────────────────── // TOOL CARD // ───────────────────────────────────────────── const ToolCard = ({ tool, onClick, onToggleFavorite }) => ( onClick(tool)} className=”flex flex-col h-full”>
{tool.category}
{ e.stopPropagation(); onToggleFavorite(tool.id); }} className={`p-2 rounded-full transition-all ${tool.is_favorite ? ‘text-[#FF4500] bg-[#FF4500]/10’ : ‘text-white/30 hover:text-[#FF4500] hover:bg-white/5’}`} >
{/* Name — bright white, clearly readable */}

{tool.name}

{/* Description — lighter grey with enough contrast */}

{tool.description}

{tool.tags?.length > 0 && (
{tool.tags.slice(0, 3).map(t => ( #{t} ))}
)}
{tool.youtube_links?.length > 0 && (
)}
{/* Date — readable warm grey */}
{new Date(tool.created_at).toLocaleDateString()}
); // ───────────────────────────────────────────── // TOOL DETAIL PAGE // ───────────────────────────────────────────── const ToolDetail = ({ tool, onBack, onEdit, onDelete }) => { if (!tool) return null; return ( Back to Tools
{tool.category}

{tool.name}

{tool.description}

{tool.notes && (

My Notes

{tool.notes}
)} {tool.youtube_links?.filter(l => getYouTubeId(l)).length > 0 && (

Videos to Watch

{tool.youtube_links.map((link, idx) => { const yid = getYouTubeId(link); return yid ? (