From 9511682906c126a105577ce061aab0363038b289 Mon Sep 17 00:00:00 2001 From: AyrisAI Date: Fri, 24 Jul 2026 00:04:12 +0300 Subject: [PATCH] feat: restore prompts page to public site --- app/[locale]/prompts/page.tsx | 178 +++++++++++++++++++++++++++++++++- components/Navbar.tsx | 3 +- 2 files changed, 177 insertions(+), 4 deletions(-) diff --git a/app/[locale]/prompts/page.tsx b/app/[locale]/prompts/page.tsx index bbe25a3..2f45874 100644 --- a/app/[locale]/prompts/page.tsx +++ b/app/[locale]/prompts/page.tsx @@ -1,6 +1,178 @@ -import { redirect } from 'next/navigation'; +'use client'; + +import { useState, useEffect, use } from 'react'; +import Link from 'next/link'; +import { getPrompts } from '@/lib/actions/promptActions'; +import { Search, Sparkles, Copy, Check, Terminal, ArrowRight, Tag } from 'lucide-react'; export default function PromptsPage({ params }: { params: Promise<{ locale: string }> }) { - // Prompts are admin-only – redirect public visitors to lessons - redirect('/lessons'); + const { locale } = use(params); + const [search, setSearch] = useState(''); + const [selectedCategory, setSelectedCategory] = useState(null); + const [prompts, setPrompts] = useState([]); + const [loading, setLoading] = useState(true); + const [copiedId, setCopiedId] = useState(null); + + useEffect(() => { + async function loadData() { + setLoading(true); + const res = await getPrompts({ query: search, category: selectedCategory || undefined }); + setPrompts(res); + setLoading(false); + } + loadData(); + }, [search, selectedCategory]); + + const handleCopy = async (id: string, content: string) => { + try { + await navigator.clipboard.writeText(content); + setCopiedId(id); + setTimeout(() => setCopiedId(null), 2000); + } catch (err) { + console.error('Failed to copy prompt:', err); + } + }; + + const categories = Array.from(new Set(prompts.map((p) => p.category))); + + return ( +
+ + {/* Page Header */} +
+
+ + Curated AI System Prompts & Templates +
+

+ AI Prompts & Agent Templates Library +

+

+ Battle-tested system prompts, coding instructions, and LLM templates for ChatGPT, Claude, and Gemini agents. +

+
+ + {/* Search & Filter Bar */} +
+ + {/* Search Input */} +
+ + setSearch(e.target.value)} + className="w-full bg-slate-950 border border-slate-800 rounded-xl pl-10 pr-4 py-2 text-xs text-white placeholder-slate-500 focus:outline-none focus:border-red-500/50" + /> +
+ + {/* Category Filter Pills */} +
+ + {categories.map((cat) => ( + + ))} +
+ +
+ + {/* Prompts Grid */} + {loading ? ( +
+ + Loading data... +
+ ) : prompts.length > 0 ? ( +
+ {prompts.map((item) => ( +
+
+
+ + {item.category} + +
+ + {item.tags?.join(', ')} +
+
+ +

+ + {item.title} + +

+ +

+ {item.description} +

+ + {/* Prompt Code Preview Box */} +
+
+                    {item.content}
+                  
+ + +
+
+ +
+ + View Full Prompt & Usage + + +
+
+ ))} +
+ ) : ( +
+ No prompts found matching your search. +
+ )} + +
+ ); } diff --git a/components/Navbar.tsx b/components/Navbar.tsx index 319330f..bead771 100644 --- a/components/Navbar.tsx +++ b/components/Navbar.tsx @@ -3,7 +3,7 @@ import Link from 'next/link'; import { usePathname } from 'next/navigation'; import { useTranslations } from 'next-intl'; -import { Code2, BookOpen, Mail, Sparkles } from 'lucide-react'; +import { Code2, BookOpen, Mail, Sparkles, Terminal } from 'lucide-react'; export function Navbar({ locale }: { locale: string }) { const t = useTranslations('nav'); @@ -13,6 +13,7 @@ export function Navbar({ locale }: { locale: string }) { { href: `/${locale}`, label: t('home'), icon: Sparkles }, { href: `/${locale}/lessons`, label: t('lessons'), icon: Code2 }, { href: `/${locale}/cheatsheets`, label: t('cheatsheets'), icon: BookOpen }, + { href: `/${locale}/prompts`, label: 'Prompts', icon: Terminal }, { href: `/${locale}/contact`, label: t('contact'), icon: Mail }, ];