{ "name": "gemini-chatbot", "version": "1.0.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "@google/generative-ai": "^0.2.1", "next": "14.1.0", "react": "^18.2.0", "react-dom": "^18.2.0" }, "devDependencies": { "autoprefixer": "^10.4.17", "postcss": "^8.4.35", "tailwindcss": "^3.4.1" } } === next.config.js = /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, images: { domains: ['www.google.com', 'fonts.googleapis.com'], }, } module.exports = nextConfig === postcss.config.js = module.exports = { plugins: { tailwindcss: {}, autoprefixer: {}, }, } === tailwind.config.js = /** @type {import('tailwindcss').Config} */ module.exports = { content: [ './pages/**/*.{js,ts,jsx,tsx,mdx}', './components/**/*.{js,ts,jsx,tsx,mdx}', ], theme: { extend: { colors: { gemini: { light: '#e8f0fe', DEFAULT: '#8ab4f8', dark: '#1a73e8', }, }, }, }, plugins: [], } === styles/globals.css = @tailwind base; @tailwind components; @tailwind utilities; * { box-sizing: border-box; padding: 0; margin: 0; } html, body { max-width: 100vw; overflow-x: hidden; } body { background: #0f0f0f; color: #ffffff; } /* Custom scrollbar */ ::-webkit-scrollbar { width: 8px; -track { background: #1a} ::-webkit-scrollbar1a1a; } ::-webkit-scrollbar-thumb { background: #333; border-radius: 4px; } ::-webkit-scrollbar-thumb:hover { background: #444; } /* Animation for typing indicator */ @keyframes bounce { 0%, 60%, 100% { transform: translateY(0); } 30% { transform: translateY(-4px); } } .typing-dot { animation: bounce 1.4s infinite ease-in-out; } .typing-dot:nth-child(1) { animation-delay: 0s; } .typing-dot:nth-child(2) { animation-delay: 0.2s; } .typing-dot:nth-child(3) { animation-delay: 0.4s; } === components/ChatMessage.jsx = import React from 'react'; export default function ChatMessage({ message, isUser }) { return (
{!isUser && (
)}
{message}
{isUser && (
)}
); } === components/ApiKeyInput.jsx = import React, { useState } from 'react'; export default function ApiKeyInput({ onSave, initialKey }) { const [apiKey, setApiKey] = useState(initialKey || ''); const [showKey, setShowKey] = useState(false); const handleSubmit = (e) => { e.preventDefault(); if (apiKey.trim()) { onSave(apiKey.trim()); } }; return (

Enter Gemini API Key

Get your free API key from{' '} Google AI Studio

setApiKey(e.target.value)} placeholder="Paste your Gemini API key here..." className="w-full px-4 py-3 pr-12 bg-gray-800 border border-gray-600 rounded-xl text-white placeholder-gray-500 focus:outline-none focus:border-gemini-dark focus:ring-1 focus:ring-gemini-dark transition-colors" />

⚠️ Your API key is stored locally in your browser and never sent to any server except Google's Gemini API.

); } === components/ChatInput.jsx = import React, { useState } from 'react'; export default function ChatInput({ onSend, disabled }) { const [message, setMessage] = useState(''); const handleSubmit = (e) => { e.preventDefault(); if (message.trim() && !disabled) { onSend(message.trim()); setMessage(''); } }; const handleKeyDown = (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSubmit(e); } }; return (