diff --git a/README.md b/README.md index 77427e9..d0131f9 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,132 @@ The workflow checks: - ESLint linting - Next.js build process +## Personalizing Your Portfolio + +After forking this repository, you'll need to update various files with your personal information. Here's a comprehensive guide based on the actual project structure: + +### 1. Core Components +- **Navbar** (`/components/navbar.tsx`) + - Update navigation links + - Modify logo and branding + - Customize menu items + +- **Hero Section** (`/components/hero.tsx`) + - Update main headline + - Modify tagline and description + - Change call-to-action buttons + +- **Layout** (`/app/layout.tsx`) + - Update metadata and SEO settings + - Modify default page structure + - Customize loading screen + +### 2. Main Pages +- **Home Page** (`/app/page.tsx`) + - Update hero content + - Modify featured projects + - Customize welcome message + +- **About Page** (`/app/about/page.tsx`) + - Update biography + - Modify personal story + - Add professional background + +- **Projects** (`/app/projects/page.tsx`) + - Update project cards (`/components/project-card.tsx`) + - Add your own projects + - Customize project descriptions + +- **Experience** (`/app/experience/page.tsx`) + - Update work history (`/components/experience-card.tsx`) + - Add education details (`/components/education-card.tsx`) + - Modify role descriptions + +### 3. Skills and Expertise +- **Skills Page** (`/app/skills/page.tsx`) + - Update skill sections (`/components/skills-section.tsx`) + - Modify skill cards (`/components/skill-card.tsx`) + - Customize tag cloud (`/components/skills-tag-cloud.tsx`) + +### 4. Interactive Features +- **Gallery** (`/app/gallery/page.tsx`) + - Update gallery items (`/components/gallery-item.tsx`) + - Modify filters (`/components/gallery-filter.tsx`) + - Add your own images + +- **Chat** (`/app/chat/page.tsx`) + - Customize chat interface + - Update AI settings + - Modify authentication requirements + +- **Audio** (`/app/audio/page.tsx`) + - Add your audio content + - Update audio player settings + - Customize audio descriptions + +### 5. Professional Content +- **Resume** (`/app/resume/page.tsx`) + - Update resume content + - Add professional experience + - Upload new resume PDF + +- **Case Studies** (`/app/case-studies/page.tsx`) + - Add detailed project analyses + - Include project outcomes + - Update metrics and results + +### 6. Blog +- **Blog Posts** (`/app/blog/`) + - Add your own posts + - Update blog layout + - Customize categories + +### 7. Environment Variables +Create a `.env.local` file with these variables: +```bash +# Authentication +NEXTAUTH_URL=http://localhost:3000 +NEXTAUTH_SECRET=your-secret-key + +# OpenAI (for Chat Feature) +OPENAI_API_KEY=your-openai-key + +# Supabase +NEXT_PUBLIC_SUPABASE_URL=your-supabase-url +NEXT_PUBLIC_SUPABASE_ANON_KEY=your-supabase-key + +# Email (for Contact Form) +RESEND_API_KEY=your-resend-key +``` + +### 8. Assets and Media +- **Public Directory** (`/public/`) + - Replace profile images + - Update project screenshots + - Add custom icons and media + - Update resume PDF + - Modify audio files + +### 9. UI Components +- **Custom Components** (`/components/ui/`) + - Customize button styles + - Update card designs + - Modify form elements + - Adjust animations + +### 10. Additional Features +- **Dashboard** (`/app/dashboard/page.tsx`) + - Configure visitor counter + - Set up analytics + - Customize admin features + +Remember to: +1. Test all changes locally using `npm run dev` +2. Verify responsive design on multiple devices +3. Check all links and media work correctly +4. Update SEO metadata for all pages +5. Remove placeholder content + ## Todos should be completed starting from the most easiest to implement. The Todo list should be updated periodically and in order from easiest to most difficult for the AI to implement. - [-] Initial setup @@ -175,42 +301,6 @@ Built using: - [shadcn/ui](https://ui.shadcn.com/) - [shadcn/ui-docs](https://ui.shadcn.com/docs) -## Personalizing Your Fork - -After forking this repository, you'll need to update the following: - -### Required Updates -1. **Personal Information** - - `/app/config/site.ts`: Update site metadata, name, and social links - - `/app/components/about.tsx`: Modify the about section content - - `/app/components/hero.tsx`: Update hero section with your name and title - - `/public/images/`: Replace profile and project images - -2. **Project Details** - - `/app/projects/page.tsx`: Update project cards with your own projects - - `/app/projects/[slug]/page.tsx`: Create case studies for your projects - -3. **Resume and Experience** - - `/app/resume/page.tsx`: Update with your experience and education - - `/public/resume.pdf`: Replace with your resume file - -4. **Environment Variables** - - Copy `.env.example` to `.env.local` - - Update the following variables: - ``` - DATABASE_URL=your_database_url - NEXT_PUBLIC_SUPABASE_URL=your_supabase_url - NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_key - RESEND_API_KEY=your_resend_api_key - ``` - -### Optional Updates -- `/app/blog/`: Add your own blog posts -- `/app/components/footer.tsx`: Update footer links and information -- `/app/components/nav.tsx`: Modify navigation items -- `/public/favicon.ico`: Replace with your own favicon -- `/app/layout.tsx`: Update metadata and default SEO settings - ## Development Notes ### Git Commands diff --git a/app/chat/page.tsx b/app/chat/page.tsx index 9d6c8e8..4afb2ae 100644 --- a/app/chat/page.tsx +++ b/app/chat/page.tsx @@ -2,11 +2,10 @@ import { useState, useEffect } from "react" import { Button } from "@/components/ui/button" -import { ArrowLeft, Bot } from "lucide-react" +import { ArrowLeft } from "lucide-react" import Link from "next/link" import { MessageList, type Message } from "@/components/chat/message-list" import { ChatInput } from "@/components/chat/chat-input" -import { motion, AnimatePresence } from "framer-motion" import { useAuth } from "@/lib/auth-context" import { AuthDialog } from "@/components/chat/auth-dialog" import { Breadcrumb } from "@/components/breadcrumb" diff --git a/components/chat/chat-input.tsx b/components/chat/chat-input.tsx index 3f4df3a..1a209b9 100644 --- a/components/chat/chat-input.tsx +++ b/components/chat/chat-input.tsx @@ -7,15 +7,15 @@ import { SendHorizontal } from "lucide-react" interface ChatInputProps { onSend: (message: string) => void - disabled?: boolean + isLoading?: boolean } -export function ChatInput({ onSend, disabled }: ChatInputProps) { +export function ChatInput({ onSend, isLoading }: ChatInputProps) { const [input, setInput] = useState("") const handleSubmit = (e: React.FormEvent) => { e.preventDefault() - if (input.trim()) { + if (input.trim() && !isLoading) { onSend(input) setInput("") } @@ -34,17 +34,17 @@ export function ChatInput({ onSend, disabled }: ChatInputProps) { value={input} onChange={(e) => setInput(e.target.value)} onKeyDown={handleKeyDown} - placeholder="Type a message..." - className="min-h-[60px] w-full resize-none rounded-lg border bg-background pr-16 shadow-sm focus:ring-2 focus:ring-primary/20" - disabled={disabled} + placeholder="Type your message..." + className="min-h-[80px] resize-none pr-14" + disabled={isLoading} /> ) diff --git a/components/chat/message-list.tsx b/components/chat/message-list.tsx index 9ec178e..b1de746 100644 --- a/components/chat/message-list.tsx +++ b/components/chat/message-list.tsx @@ -8,9 +8,10 @@ export type Message = { interface MessageListProps { messages: Message[] + isLoading?: boolean } -export function MessageList({ messages }: MessageListProps) { +export function MessageList({ messages, isLoading }: MessageListProps) { return (
{messages.map((message, index) => ( @@ -20,35 +21,43 @@ export function MessageList({ messages }: MessageListProps) { animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.3 }} className={`flex gap-3 ${ - message.role === "user" ? "flex-row-reverse" : "" + message.role === "assistant" ? "flex-row" : "flex-row-reverse" }`} > -
- {message.role === "user" ? ( - +
+ {message.role === "assistant" ? ( + ) : ( - + )}
-
-
-

- {message.content} -

+
+
+ {message.content}
))} + {isLoading && ( + +
+ +
+
+
+
+
+ )}
) } diff --git a/lib/openai.ts b/lib/openai.ts index 69f1177..5035585 100644 --- a/lib/openai.ts +++ b/lib/openai.ts @@ -5,6 +5,10 @@ const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, }); +interface OpenAIError extends Error { + code?: string; +} + // Implement exponential backoff for rate limiting async function withRetry( fn: () => Promise, @@ -15,8 +19,9 @@ async function withRetry( while (true) { try { return await fn(); - } catch (error: any) { - if (error?.code === 'rate_limit_exceeded' && retries < maxRetries) { + } catch (error) { + const openAIError = error as OpenAIError; + if (openAIError.code === 'rate_limit_exceeded' && retries < maxRetries) { retries++; const delay = initialDelay * Math.pow(2, retries - 1); console.log(`Rate limit exceeded. Retrying in ${delay}ms...`); @@ -45,7 +50,7 @@ export async function generateChatResponse( try { const completion = await withRetry(() => openai.chat.completions.create({ - model: "gpt-4", // Using GPT-4 + model: "gpt-4o", // Using GPT-4 messages: messages, temperature: finalSettings.temperature, max_tokens: finalSettings.maxTokens, @@ -58,7 +63,8 @@ export async function generateChatResponse( return completion.choices[0].message; } catch (error) { console.error('Error calling OpenAI:', error); - if (error?.code === 'rate_limit_exceeded') { + const openAIError = error as OpenAIError; + if (openAIError.code === 'rate_limit_exceeded') { throw new Error('Rate limit exceeded. Please try again in a few minutes.'); } throw error; diff --git a/public/sitemap.xml b/public/sitemap.xml index 3e7f0d0..502e44b 100644 --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -1,20 +1,20 @@ -https://chriscelaya.com/audio-recorder2024-12-01T11:58:28.933Zweekly0.7 -https://chriscelaya.com/blog/hello-world2024-12-01T11:58:28.934Zweekly0.7 -https://chriscelaya.com/blog2024-12-01T11:58:28.934Zweekly0.7 -https://chriscelaya.com/auth/sign-in2024-12-01T11:58:28.934Zweekly0.7 -https://chriscelaya.com/case-studies2024-12-01T11:58:28.934Zweekly0.9 -https://chriscelaya.com/dashboard2024-12-01T11:58:28.934Zweekly0.7 -https://chriscelaya.com/chat2024-12-01T11:58:28.934Zweekly0.7 -https://chriscelaya.com/auth/sign-up2024-12-01T11:58:28.934Zweekly0.7 -https://chriscelaya.com/profile2024-12-01T11:58:28.934Zweekly0.7 -https://chriscelaya.com2024-12-01T11:58:28.934Zweekly1 -https://chriscelaya.com/gallery2024-12-01T11:58:28.934Zweekly0.7 -https://chriscelaya.com/skills2024-12-01T11:58:28.934Zweekly0.7 -https://chriscelaya.com/resume2024-12-01T11:58:28.934Zweekly0.7 -https://chriscelaya.com/projects2024-12-01T11:58:28.934Zweekly0.9 -https://chriscelaya.com/about2024-12-01T11:58:28.934Zweekly0.8 -https://chriscelaya.com/experience2024-12-01T11:58:28.934Zweekly0.8 -https://chriscelaya.com/audio2024-12-01T11:58:28.934Zweekly0.7 +https://chriscelaya.com/about2024-12-01T12:32:13.749Zweekly0.8 +https://chriscelaya.com/blog2024-12-01T12:32:13.750Zweekly0.7 +https://chriscelaya.com/case-studies2024-12-01T12:32:13.750Zweekly0.9 +https://chriscelaya.com/audio-recorder2024-12-01T12:32:13.750Zweekly0.7 +https://chriscelaya.com/chat2024-12-01T12:32:13.750Zweekly0.7 +https://chriscelaya.com/gallery2024-12-01T12:32:13.750Zweekly0.7 +https://chriscelaya.com2024-12-01T12:32:13.750Zweekly1 +https://chriscelaya.com/auth/sign-in2024-12-01T12:32:13.750Zweekly0.7 +https://chriscelaya.com/profile2024-12-01T12:32:13.750Zweekly0.7 +https://chriscelaya.com/dashboard2024-12-01T12:32:13.750Zweekly0.7 +https://chriscelaya.com/audio2024-12-01T12:32:13.750Zweekly0.7 +https://chriscelaya.com/experience2024-12-01T12:32:13.750Zweekly0.8 +https://chriscelaya.com/projects2024-12-01T12:32:13.750Zweekly0.9 +https://chriscelaya.com/blog/hello-world2024-12-01T12:32:13.750Zweekly0.7 +https://chriscelaya.com/resume2024-12-01T12:32:13.750Zweekly0.7 +https://chriscelaya.com/auth/sign-up2024-12-01T12:32:13.750Zweekly0.7 +https://chriscelaya.com/skills2024-12-01T12:32:13.750Zweekly0.7 \ No newline at end of file