mirror of
https://github.com/karpathy/nanochat.git
synced 2026-05-09 17:30:14 +00:00
Build services/frontend/ replacing the legacy nanochat/ui.html single-file UI. Landing, login, and chat pages ported with full design system: Devanagari + Great Vibes hero, samosa/chai/toran SVG animations, gold/cream palette. - App Router pages: / (hero + floating illustrations), /login (split-screen OAuth with mandala motif), /chat (260px collapsible sidebar, suggestion chips, markdown + code-copy, auto-expanding input, slash commands) - SSE streaming via useSSE hook and /api/chat/stream BFF route (proxies to CHAT_API_URL when set, falls back to mock echo for local dev) - NextAuth.js v5 with Google + GitHub providers; middleware gates /chat/* - Zustand store with localStorage persistence for conversations/settings - Tailwind theme carries all ui.html tokens + keyframes (pendulum, float, wobble, steamFloat, steamType); SVG assets componentized under components/svg - Multi-stage node:20-alpine Dockerfile with Next standalone output Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
40 lines
1.7 KiB
TypeScript
40 lines
1.7 KiB
TypeScript
'use client';
|
|
|
|
import { Sparkles, BookOpen, Code2, Smile } from 'lucide-react';
|
|
|
|
const CHIPS = [
|
|
{ icon: BookOpen, label: 'Summarize a topic', prompt: 'Summarize the history of samosas in 3 paragraphs.' },
|
|
{ icon: Sparkles, label: 'Explain a concept', prompt: 'Explain transformers to a curious beginner.' },
|
|
{ icon: Code2, label: 'Write some code', prompt: 'Write a Python function that reverses a linked list.' },
|
|
{ icon: Smile, label: 'Tell me a joke', prompt: 'Tell me a joke about chai.' },
|
|
];
|
|
|
|
export default function EmptyState({ onPick }: { onPick: (prompt: string) => void }) {
|
|
return (
|
|
<div className="flex-1 flex flex-col items-center justify-center px-4 text-center">
|
|
<h2 className="font-baloo font-bold text-3xl md:text-4xl text-gray-900 mb-2">
|
|
How can I help you today?
|
|
</h2>
|
|
<p className="font-caveat text-lg text-brown-light mb-8">
|
|
Ask anything — a doubt, a recipe, a code snippet, or a fresh idea.
|
|
</p>
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 w-full max-w-xl">
|
|
{CHIPS.map(({ icon: Icon, label, prompt }) => (
|
|
<button
|
|
key={label}
|
|
type="button"
|
|
onClick={() => onPick(prompt)}
|
|
className="flex items-center gap-3 px-4 py-3 rounded-xl border border-cream-border bg-cream-light hover:bg-cream text-left transition-colors"
|
|
>
|
|
<Icon size={18} className="text-gold flex-shrink-0" />
|
|
<div>
|
|
<div className="text-sm font-medium text-gray-800">{label}</div>
|
|
<div className="text-xs text-gray-500 truncate">{prompt}</div>
|
|
</div>
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|