diff --git a/.gitignore b/.gitignore
index e62a663..1d8ad5f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,5 +18,6 @@ venv/
.env
applyai-475622-6ebc0281eea9.json
-# Learning files
-learning/
\ No newline at end of file
+# Mics
+learning/
+cli.txt
\ No newline at end of file
diff --git a/client/app/chat/page.tsx b/client/app/chat/page.tsx
new file mode 100644
index 0000000..57ac8f2
--- /dev/null
+++ b/client/app/chat/page.tsx
@@ -0,0 +1,21 @@
+import Chat from "@/components/Chat";
+import Link from "next/link";
+
+export default function ChatPage() {
+ return (
+
+ {/* Navigation Header */}
+
+
+ ← Back
+
+
AI Career Chat
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/client/app/globals.css b/client/app/globals.css
index ab19ef9..4701b22 100644
--- a/client/app/globals.css
+++ b/client/app/globals.css
@@ -1,2 +1,31 @@
@import "tailwindcss";
-@plugin "@tailwindcss/typography";
\ No newline at end of file
+@plugin "@tailwindcss/typography";
+
+@theme {
+/* MAIN BRAND COLORS */
+ --color-primary: #E55934; /* High-Vis Orange (The Hero Color) */
+ --color-secondary: #8C8787; /* Brand Gray (Supporting Elements) */
+
+ /* UI COLORS */
+ --color-background: #0a0a0a; /* Very Dark Gray (Not pure black, softer) */
+ --color-surface: #1a1a1a; /* Lighter Dark Gray (Cards/Inputs) */
+ --color-text-main: #FFFFFF; /* Main Text */
+ --color-text-muted: #a3a3a3; /* Secondary Text */
+}
+
+/* Apply the background color globally */
+body {
+ background-color: var(--color-background);
+ color: var(--color-text-main);
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+/* Custom Utilities */
+@utility animate-in {
+ animation: fade-in 0.5s ease-out forwards;
+}
+
+@keyframes fade-in {
+ from { opacity: 0; transform: translateY(10px); }
+ to { opacity: 1; transform: translateY(0); }
+}
\ No newline at end of file
diff --git a/client/app/layout.tsx b/client/app/layout.tsx
index 9c85130..8353817 100644
--- a/client/app/layout.tsx
+++ b/client/app/layout.tsx
@@ -1,22 +1,15 @@
import type { Metadata } from "next";
-import { Geist, Geist_Mono } from "next/font/google";
+// import { Geist, Geist_Mono } from "next/font/google";
+import { Inter } from "next/font/google";
import "./globals.css";
import { AuthProvider } from "@/context/AuthContext";
import Navbar from "@/components/Navbar";
-const geistSans = Geist({
- variable: "--font-geist-sans",
- subsets: ["latin"],
-});
-
-const geistMono = Geist_Mono({
- variable: "--font-geist-mono",
- subsets: ["latin"],
-});
+const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
- title: "Create Next App",
- description: "Generated by create next app",
+ title: "ApplyAI - Job Assistant",
+ description: "AI-powered resume tailoring and career coaching",
};
export default function RootLayout({
@@ -26,13 +19,10 @@ export default function RootLayout({
}>) {
return (
-
+
-
+
{children}
diff --git a/client/app/page.tsx b/client/app/page.tsx
index 4e64464..1d3d99d 100644
--- a/client/app/page.tsx
+++ b/client/app/page.tsx
@@ -1,10 +1,50 @@
-import Chat from "@/components/Chat";
+import Link from "next/link";
export default function Home() {
return (
-
-
ApplyAI
-
+
+
+
+ {/* The Title - Now using Text-Main or Primary explicitly */}
+
+ ApplyAI
+
+
+ Your intelligent career companion. Tailor resumes and practice interviews in seconds.
+
+
+
+ {/* NAVIGATION CARDS */}
+
+
+ {/* Link 1: Chat */}
+
+
💬
+
+ AI Career Chat
+
+
+ Chat with an expert agent about your career goals and interview prep.
+
+
+
+ {/* Link 2: Resume */}
+
+
📄
+
+ Tailor Resume
+
+
+ Instant resume rewriting based on job descriptions.
+
+
+
);
-}
+}
\ No newline at end of file
diff --git a/client/app/resume/page.tsx b/client/app/resume/page.tsx
new file mode 100644
index 0000000..04a15bb
--- /dev/null
+++ b/client/app/resume/page.tsx
@@ -0,0 +1,21 @@
+import ResumeBuilder from "@/components/ResumeBuilder";
+import Link from "next/link";
+
+export default function ResumePage() {
+ return (
+
+ {/* Navigation Header */}
+
+
+ ← Back
+
+
Resume Tailor
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/client/components/Chat.tsx b/client/components/Chat.tsx
index de367f2..66a90d8 100644
--- a/client/components/Chat.tsx
+++ b/client/components/Chat.tsx
@@ -1,123 +1,105 @@
"use client";
import { useState } from "react";
-import type { MouseEvent } from "react";
-import ResumeDisplay from "./ResumeDisplay"
+import ReactMarkdown from "react-markdown";
-// The URL for the deployed backend.
-const API_URL = process.env.NEXT_PUBLIC_API_URL;
-
-export default function Chat() {
- // State for the user's input
- const [resume, setResume] = useState("");
- const [jobDescription, setJobDescription] = useState("");
+interface Message {
+ role: "user" | "ai";
+ content: string;
+}
- // State for the API response
- const [tailoredResume, setTailoredResume] = useState("");
+export default function Chat(){
+ const [input, setInput] = useState("");
+ const [messages, setMessages] = useState([])
const [isLoading, setIsLoading] = useState(false);
- const [error, setError] = useState(null);
+ const handleSend = async () => {
+ if (!input.trim()) return;
-
- const handleSubmit = async (e : MouseEvent) => {
- e.preventDefault();
+ const userMessage: Message = { role: "user", content: input };
+ setMessages((prev) => [...prev, userMessage]);
+ setInput("");
setIsLoading(true);
- setError(null);
- setTailoredResume(""); // Clear previous results
-
- // Use FormData because FastAPI endpoint expects Form()
- const formData = new FormData();
- formData.append("base_resume", resume);
- formData.append("job_description", jobDescription);
- try{
- // Make the API call to /resumes endpoint
- const response = await fetch(`${API_URL}/resumes`, {
+ try {
+ const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/chat`, {
method: "POST",
- body: formData,
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ message: userMessage.content }),
});
- if (!response.ok) {
- // Handle HTTP errors (e.g., 500 from the server)
- throw new Error(`API Error: ${response.status} ${response.statusText}`);
- }
-
- const data = await response.json();
-
- // Update state with the AI's response
- setTailoredResume(data.tailored_resume);
- } catch (err){
- console.error("Fetch error:", err);
- if (err instanceof Error) {
- setError(err.message);
- } else {
- setError("An unknown error occurred.");
- }
+ if (!res.ok) throw new Error("Failed to fetch response");
+
+ const data = await res.json();
+ const aiMessage: Message = { role: "ai", content: data.reply || data.response };
+ setMessages((prev) => [...prev, aiMessage]);
+ } catch (error) {
+ console.error(error);
+ setMessages((prev) => [
+ ...prev,
+ { role: "ai", content: "Sorry, I encountered an error. Please try again." },
+ ]);
} finally {
- // Whether it worked or failed, we're done loading
setIsLoading(false);
- };
-
+ }
};
- return (
-