<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Oka Sutarto Putra</title>
    <description>The latest articles on DEV Community by Oka Sutarto Putra (@okasputra).</description>
    <link>https://dev.to/okasputra</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3683441%2Ff1af1d83-1098-4ed7-bc9f-4cba532c9f13.jpg</url>
      <title>DEV Community: Oka Sutarto Putra</title>
      <link>https://dev.to/okasputra</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/okasputra"/>
    <language>en</language>
    <item>
      <title>Stop Sending Static Resumes: How I Built a "Chat With My Resume" Bot (Next.js + RAG)</title>
      <dc:creator>Oka Sutarto Putra</dc:creator>
      <pubDate>Mon, 29 Dec 2025 05:05:27 +0000</pubDate>
      <link>https://dev.to/okasputra/stop-sending-static-resumes-how-i-built-a-chat-with-my-resume-bot-nextjs-rag-4kdm</link>
      <guid>https://dev.to/okasputra/stop-sending-static-resumes-how-i-built-a-chat-with-my-resume-bot-nextjs-rag-4kdm</guid>
      <description>&lt;p&gt;Let’s be honest: &lt;strong&gt;recruiters spend about 6 seconds looking at your portfolio.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You spend weeks building a beautiful site, polishing your CSS, and optimizing your Lightouse score, only for most visitors to glance at the hero section and leave.&lt;/p&gt;

&lt;p&gt;I wanted to change that. I wanted a portfolio that was active, not passive. I wanted a site that could answer questions like:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"What is his experience with TypeScript?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Has he ever worked with AWS?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Why should we hire him?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So, I built a &lt;strong&gt;RAG-Powered AI Chatbot&lt;/strong&gt; that "reads" my resume and answers questions in real-time. Here is how I built it (and how you can too).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi5o5e8sjsbw8jwee05wm.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi5o5e8sjsbw8jwee05wm.gif" alt="test" width="560" height="801"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Architecture: Keeping it "Pure"&lt;/strong&gt;&lt;br&gt;
When I started, I looked at libraries like LangChain. While powerful, they felt like overkill for a simple portfolio bot. I didn't want 500MB of dependencies just to make an API call.&lt;/p&gt;

&lt;p&gt;I decided to go with a &lt;strong&gt;"Pure Code"&lt;/strong&gt; stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: Next.js 15 (App Router) for the UI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: Node.js (Express) to handle the API keys securely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI&lt;/strong&gt;: OpenAI API (gpt-4o-mini) for the intelligence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logic&lt;/strong&gt;: Custom RAG (Retrieval-Augmented Generation) pipeline.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Challenge: Context &amp;amp; Streaming&lt;/strong&gt;&lt;br&gt;
Building a chatbot is easy. Building a chatbot that knows who you are is harder.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The "Brain" (RAG)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can't just paste your whole resume into the prompt every time—it wastes tokens and money. Instead, I implemented a simple &lt;strong&gt;Vector Search&lt;/strong&gt; logic.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The app loads my portfolio data (experience, skills, bio) on startup.&lt;/li&gt;
&lt;li&gt;When a user asks a question, the system finds the most relevant "chunk" of text.&lt;/li&gt;
&lt;li&gt;It feeds only that chunk to OpenAI with a system prompt like:&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"You are an AI assistant for [Name]. Answer the recruiter's question using only the context provided below."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;2. The "Typewriter" Effect (Streaming)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nothing kills the vibe like waiting 5 seconds for a response. I wanted that "ChatGPT feel" where the text types out word-by-word.&lt;/p&gt;

&lt;p&gt;To do this, I avoided standard REST responses and used Server-Sent Events (SSE). In Node.js, it looks a bit like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;JavaScript&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpv1h9unkr4nhgl9el3s3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpv1h9unkr4nhgl9el3s3.png" alt=" " width="800" height="574"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This ensures the user sees activity immediately, keeping them engaged.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Result&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, when a recruiter visits my site, they don't just scroll—they engage. They ask about my rates, my availability, and my tech stack. It turns a static monologue into a dynamic interview.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Want to add this to your portfolio?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want to build this yourself, I highly recommend looking into the OpenAI Node SDK and Server-Sent Events. It’s a great learning experience.&lt;/p&gt;

&lt;p&gt;It’s a fully typed, production-ready starter kit:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Pure RAG setup&lt;/strong&gt; (No complex libraries).&lt;br&gt;
✅ &lt;strong&gt;Pre-built Streaming UI&lt;/strong&gt; (Next.js 15).&lt;br&gt;
✅ &lt;strong&gt;Easy "Resume" Configuration.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpd6hwdgxllpzccnty5tb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpd6hwdgxllpzccnty5tb.png" alt=" " width="800" height="597"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can grab the template and start customizing it this weekend:&lt;/p&gt;

&lt;p&gt;Download the Template:&lt;/p&gt;

&lt;p&gt;🚀 Get it on &lt;a href="https://okaspai.lemonsqueezy.com/checkout/buy/a4a2cf68-88ad-4e63-ada3-89a49a336dfd" rel="noopener noreferrer"&gt;Lemon Squeezy&lt;/a&gt; 💡 Use code &lt;strong&gt;HOLIDAY2026&lt;/strong&gt; at checkout for a discount!&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>ai</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
