<?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: Atul Tripathi</title>
    <description>The latest articles on DEV Community by Atul Tripathi (@atultrp).</description>
    <link>https://dev.to/atultrp</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F548182%2Fb1c13c31-65a6-4134-9275-166991bbdfa0.jpeg</url>
      <title>DEV Community: Atul Tripathi</title>
      <link>https://dev.to/atultrp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/atultrp"/>
    <language>en</language>
    <item>
      <title>How to Build a RAG App in Next.js (2026 Guide) — Claude, Pinecone, Voyage AI</title>
      <dc:creator>Atul Tripathi</dc:creator>
      <pubDate>Sun, 12 Jul 2026 10:59:37 +0000</pubDate>
      <link>https://dev.to/atultrp/how-to-build-a-rag-app-in-nextjs-2026-guide-claude-pinecone-voyage-ai-336p</link>
      <guid>https://dev.to/atultrp/how-to-build-a-rag-app-in-nextjs-2026-guide-claude-pinecone-voyage-ai-336p</guid>
      <description>&lt;p&gt;If you've tried to build an AI app that answers questions about &lt;em&gt;your own&lt;/em&gt; content — docs, PDFs, a knowledge base — you've probably run into RAG (retrieval-augmented generation). It's the pattern behind almost every "chat with your documents" product, and it's simpler than it looks once you break it into pieces.&lt;/p&gt;

&lt;p&gt;This guide walks through building one in Next.js: scraping content, embedding it, storing it in a vector database, and streaming answers back with citations. By the end you'll have a working doc-chat pipeline you can extend into your own product.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four pieces of any RAG app
&lt;/h2&gt;

&lt;p&gt;Every RAG system, no matter how fancy, is four steps wearing a trench coat:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ingestion&lt;/strong&gt; — get your content (a webpage, a PDF, a doc) into plain text&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedding&lt;/strong&gt; — turn chunks of that text into vectors (numbers that capture meaning)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage &amp;amp; retrieval&lt;/strong&gt; — put those vectors in a database you can search by similarity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generation&lt;/strong&gt; — hand the most relevant chunks to an LLM along with the user's question, and stream back an answer&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. Everything else — chunking strategy, reranking, multi-tenancy — is refinement on top of these four steps. Let's build each one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Ingestion without a headless browser
&lt;/h2&gt;

&lt;p&gt;If you've scraped web pages in a Next.js serverless function before, you've probably hit the Puppeteer/Playwright wall: huge bundle sizes, slow cold starts, and occasional ESM import conflicts on Vercel. For most content — docs sites, blog posts, articles — you don't need a full browser at all. A DOM parser like Cheerio is enough, because you're not interacting with the page, just reading it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;cheerio&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cheerio&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;scrapeUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AbortSignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// don't hang forever&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cheerio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Strip the noise before extracting text&lt;/span&gt;
  &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script, style, nav, footer, header, aside&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Prefer semantic content zones, fall back to body&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;article&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;body&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This runs cleanly inside a standard serverless function — no special runtime config needed. It won't work on JS-rendered SPAs (you'd need a real browser for those), but for the majority of docs and content sites, it's faster and lighter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Chunking and embedding
&lt;/h2&gt;

&lt;p&gt;Raw text is too long to embed as one block — you need to split it into chunks small enough to be semantically coherent but large enough to carry context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RecursiveCharacterTextSplitter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;langchain/text_splitter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;chunkSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;chunkOverlap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;splitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scrapedText&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The overlap matters more than people expect — without it, a sentence that spans a chunk boundary gets cut in half and loses meaning in both halves.&lt;/p&gt;

&lt;p&gt;Once you have chunks, you embed them — turn each one into a vector using an embedding model. Here's an underexplained detail worth knowing: &lt;strong&gt;most production RAG systems use two different embedding calls, one for documents and one for queries.&lt;/strong&gt; This is called asymmetric retrieval. A short question ("how do I reset my password?") and a long passage that answers it aren't symmetric in structure, so some embedding models (Voyage AI's among them) let you specify an &lt;code&gt;input_type&lt;/code&gt; to optimize the vector space for each side of that mismatch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;VoyageEmbeddings&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@langchain/community/embeddings/voyage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;documentEmbedder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;VoyageEmbeddings&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VOYAGEAI_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;modelName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;voyage-3.5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;inputType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;document&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;queryEmbedder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;VoyageEmbeddings&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VOYAGEAI_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;modelName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;voyage-3.5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;inputType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;vectors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;documentEmbedder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;embedDocuments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Storing and retrieving with a vector database
&lt;/h2&gt;

&lt;p&gt;Once you have vectors, you need somewhere to store and search them. Pinecone's serverless tier is a common choice for this because it needs no infrastructure management.&lt;/p&gt;

&lt;p&gt;A detail that matters once you have more than one user: &lt;strong&gt;namespace-based multi-tenancy.&lt;/strong&gt; Instead of provisioning a separate index per user or organization, you scope every upsert and query to a namespace string within a single index.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;upsertVectors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;vectors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pinecone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PINECONE_INDEX&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;records&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vectors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}));&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;upsert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;records&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;querySimilar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queryVector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;topK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pinecone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PINECONE_INDEX&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;queryVector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;topK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;includeMetadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Filter out weak matches — don't force irrelevant context into the prompt&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One index, unlimited namespaces, and zero cross-contamination between tenants — swap &lt;code&gt;namespace&lt;/code&gt; for a &lt;code&gt;userId&lt;/code&gt; or &lt;code&gt;orgId&lt;/code&gt; and you have multi-tenant isolation without any schema migration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Streaming the answer
&lt;/h2&gt;

&lt;p&gt;This is where retrieval meets generation. You embed the user's question, retrieve the most relevant chunks, inject them into the system prompt, and stream the response back token by token.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;queryVector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;queryEmbedder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;embedQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;querySimilar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queryVector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/event-stream&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cache-Control&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no-cache&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keep-alive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;claude-haiku-4-5-20251001&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;system&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Answer using only the following context. If the context doesn't contain the answer, say so — don't make one up.\n\n&amp;lt;context&amp;gt;\n&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\n&amp;lt;/context&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Send sources before any text, so the UI can render citations immediately&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`data: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})}&lt;/span&gt;&lt;span class="s2"&gt;\n\n`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`data: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;})}&lt;/span&gt;&lt;span class="s2"&gt;\n\n`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;end&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`data: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})}&lt;/span&gt;&lt;span class="s2"&gt;\n\n`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things worth calling out here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The system prompt explicitly permits "I don't know."&lt;/strong&gt; Without that instruction, LLMs tend to answer confidently even when the retrieved context doesn't actually support an answer — graceful degradation beats confident fabrication.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sending sources before text starts&lt;/strong&gt; means your frontend can render citation cards immediately, instead of waiting for the full response to know what was cited.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Putting it together
&lt;/h2&gt;

&lt;p&gt;That's a complete, working RAG pipeline: scrape or upload → chunk → embed → store → retrieve → stream. From here, the places to go deeper are chunking strategy (fixed-size vs. semantic chunking), reranking (a second, more expensive relevance pass on your top results), and hybrid search (combining vector similarity with keyword search for queries that need exact matches).&lt;/p&gt;

&lt;p&gt;If you'd rather skip the wiring than build it from scratch, I packaged this exact pattern — plus PDF ingestion, demo rate limiting, and multi-tenant namespace isolation — into a Next.js starter kit called &lt;a href="https://fastrag.live" rel="noopener noreferrer"&gt;FastRAG&lt;/a&gt;. There's a live, unauthenticated demo at &lt;a href="https://fastrag.live/demo" rel="noopener noreferrer"&gt;fastrag.live/demo&lt;/a&gt; if you want to see the retrieval quality before deciding either way.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>ai</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How Forcing 1024-Dim Embeddings Cut Our Pinecone Bill by ~33%</title>
      <dc:creator>Atul Tripathi</dc:creator>
      <pubDate>Sun, 05 Jul 2026 04:34:15 +0000</pubDate>
      <link>https://dev.to/atultrp/how-forcing-1024-dim-embeddings-cut-our-pinecone-bill-by-33-fml</link>
      <guid>https://dev.to/atultrp/how-forcing-1024-dim-embeddings-cut-our-pinecone-bill-by-33-fml</guid>
      <description>&lt;p&gt;If you've built a RAG pipeline before, you know the pattern: hook up an embedding model, dump vectors into Pinecone, and forget about it until the invoice shows up. That invoice is where most people first realize embedding dimensionality isn't just a technical detail — it's a direct line item on your bill.&lt;/p&gt;

&lt;p&gt;Here's what we found while building &lt;a href="https://www.fastrag.live" rel="noopener noreferrer"&gt;FastRAG&lt;/a&gt;, and why we ended up forcing 1024 dimensions instead of letting the default ride.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem: dimension count is a hidden cost multiplier
&lt;/h2&gt;

&lt;p&gt;Pinecone (like most vector databases) charges based on storage, and storage scales linearly with vector dimensionality. A lot of popular embedding models default to 1536 or higher dimensions. That's not wrong, but it's often more resolution than the retrieval task actually needs — especially for the kind of document-chunk semantic search most RAG apps are doing.&lt;/p&gt;

&lt;p&gt;The math is simple: every vector at 1536 dimensions costs roughly 50% more to store than the same vector at 1024 dimensions. Multiply that across every chunk of every document a user uploads, and it adds up fast once you have real usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why 1024 and not lower
&lt;/h2&gt;

&lt;p&gt;We didn't pick 1024 arbitrarily. A few considerations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Retrieval quality holds up.&lt;/strong&gt; For chunk-level semantic search (as opposed to fine-grained tasks like clustering or classification), 1024 dimensions preserves enough of the embedding space's structure that nearest-neighbor retrieval quality doesn't meaningfully degrade for most document types.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's a clean truncation point.&lt;/strong&gt; Many embedding models support Matryoshka-style representation learning or clean dimensionality reduction to 1024 without retraining, which means you're not fighting the model to get there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diminishing returns above it.&lt;/strong&gt; Going from 512 → 1024 tends to show a noticeable jump in retrieval quality. Going from 1024 → 1536 shows a much smaller one, for most general-purpose RAG use cases. You're paying for resolution you can't fully use.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What this actually saved
&lt;/h2&gt;

&lt;p&gt;Forcing this dimensionality across our ingestion pipeline reduced Pinecone storage costs by about a third compared to running with the un-truncated default. That's not a marginal optimization — for anyone running a document-chat product with meaningful upload volume, it's the difference between a Pinecone bill that scales sublinearly with growth and one that doesn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it fits into the pipeline
&lt;/h2&gt;

&lt;p&gt;In FastRAG's ingestion flow, this is enforced at the point of embedding generation, before anything touches the vector store — so it's not a post-hoc cleanup step, it's baked into &lt;code&gt;lib/vector-store.ts&lt;/code&gt; from the start. Every chunk, whether it came from a scraped URL or an uploaded PDF, gets embedded and truncated consistently, which also avoids a subtler bug: mixing dimensions across your index, which some vector DBs won't even let you do without a full re-index.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;If you're building a RAG app and haven't looked at your embedding dimensionality, it's worth five minutes to check. It's one of the few places where a config-level decision has a direct, compounding effect on unit economics — the kind of thing that's easy to ignore early and expensive to fix later once you have real data volume in the index.&lt;/p&gt;

&lt;p&gt;If you want this pre-configured rather than tuning it yourself, that's exactly what &lt;a href="https://www.fastrag.live" rel="noopener noreferrer"&gt;FastRAG&lt;/a&gt; does out of the box — Pinecone and LangChain wired up with sane defaults, including this one.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Questions about the tradeoffs, or how this interacts with specific embedding models? Drop them in the comments — happy to go deeper on the retrieval-quality side too.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>claude</category>
      <category>software</category>
    </item>
    <item>
      <title>Why building RAG apps feels harder than it should and what I built to fix it</title>
      <dc:creator>Atul Tripathi</dc:creator>
      <pubDate>Mon, 26 Jan 2026 12:15:29 +0000</pubDate>
      <link>https://dev.to/atultrp/why-building-rag-apps-feels-harder-than-it-should-and-what-i-built-to-fix-it-2l4m</link>
      <guid>https://dev.to/atultrp/why-building-rag-apps-feels-harder-than-it-should-and-what-i-built-to-fix-it-2l4m</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/atultrp" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F548182%2Fb1c13c31-65a6-4134-9275-166991bbdfa0.jpeg" alt="atultrp"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/atultrp/why-building-rag-apps-feels-harder-than-it-should-and-what-i-built-to-fix-it-5788" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Why building RAG apps feels harder than it should (and what I built to fix it)&lt;/h2&gt;
      &lt;h3&gt;Atul Tripathi ・ Jan 26&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#rag&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#ai&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#buildinpublic&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>rag</category>
      <category>ai</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>Why building RAG apps feels harder than it should (and what I built to fix it)</title>
      <dc:creator>Atul Tripathi</dc:creator>
      <pubDate>Mon, 26 Jan 2026 12:13:50 +0000</pubDate>
      <link>https://dev.to/atultrp/why-building-rag-apps-feels-harder-than-it-should-and-what-i-built-to-fix-it-5788</link>
      <guid>https://dev.to/atultrp/why-building-rag-apps-feels-harder-than-it-should-and-what-i-built-to-fix-it-5788</guid>
      <description>&lt;p&gt;I kept seeing the same pattern whenever someone attempted to create an AI app 🤖&lt;/p&gt;

&lt;p&gt;The idea was always exciting 🚀&lt;br&gt;
The demo was always ambitious 💡&lt;/p&gt;

&lt;p&gt;Then everything came to a halt ⛔&lt;/p&gt;

&lt;p&gt;This happened not because the idea was flawed, but due to messy foundations 🧱&lt;br&gt;
PDF ingestion broke down 📄❌&lt;br&gt;
Scrapers failed on random websites 🕷️⚠️&lt;br&gt;
Embeddings were slow 🐌&lt;br&gt;
The UI wasn’t set up correctly 🧩❌&lt;br&gt;
Every small change brought about three new bugs 🐛🐛🐛&lt;/p&gt;

&lt;p&gt;People didn’t quit because they were lazy 😴&lt;br&gt;
They quit because the tools weren’t made for builders who need speed ⚡&lt;/p&gt;

&lt;p&gt;So, I created &lt;a href="//fastrag.live"&gt;Fastrag&lt;/a&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%2F98b4z8gipvy2z0zopmcm.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%2F98b4z8gipvy2z0zopmcm.png" alt=" " width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="//fastrag.live"&gt;Fastrag&lt;/a&gt; is a ready-made backbone for RAG-based AI products 🧠&lt;br&gt;
You can plug in PDFs or URLs, and it turns them into a searchable knowledge base with a working chat interface instantly 🔍💬&lt;/p&gt;

&lt;p&gt;There’s no need to struggle with infrastructure 🏗️&lt;br&gt;
No more stitching together half-working scripts 🧵❌&lt;br&gt;
You won’t spend your first week on plumbing 🚿&lt;/p&gt;

&lt;p&gt;You can start building features on day one 📅&lt;br&gt;
Fastrag takes care of the rest 🤝&lt;/p&gt;

&lt;p&gt;Because the real bottleneck in AI isn’t ideas 💭&lt;br&gt;
It’s execution speed 🏎️&lt;/p&gt;

&lt;p&gt;Build your AI product this weekend without burning out. 🔥&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>rag</category>
      <category>ai</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>Uploaded a 120-page PDF instant AI chat.
If you want the same setup, FastRAG is live - https://www.fastrag.live/</title>
      <dc:creator>Atul Tripathi</dc:creator>
      <pubDate>Sat, 03 Jan 2026 05:37:48 +0000</pubDate>
      <link>https://dev.to/atultrp/uploaded-a-120-page-pdf-instant-ai-chat-if-you-want-the-same-setup-fastrag-is-live--4lp</link>
      <guid>https://dev.to/atultrp/uploaded-a-120-page-pdf-instant-ai-chat-if-you-want-the-same-setup-fastrag-is-live--4lp</guid>
      <description>&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://www.fastrag.live/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.fastrag.live%2Fog-image.png" height="435" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://www.fastrag.live/" rel="noopener noreferrer" class="c-link"&gt;
            FastRAG | Ship your AI App in days 🚀
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Stop building RAG from scratch. Grab the starter kit with Pinecone &amp;amp; LangChain pre-configured.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.fastrag.live%2Ffavicon_io%2Ffavicon.ico" width="48" height="48"&gt;
          fastrag.live
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Uploaded a 120-page PDF instant AI chat.
If you want the same setup, FastRAG is live - fastrag.live</title>
      <dc:creator>Atul Tripathi</dc:creator>
      <pubDate>Sat, 03 Jan 2026 05:37:04 +0000</pubDate>
      <link>https://dev.to/atultrp/uploaded-a-120-page-pdf-instant-ai-chatif-you-want-the-same-setup-fastrag-is-live-fastraglive-484n</link>
      <guid>https://dev.to/atultrp/uploaded-a-120-page-pdf-instant-ai-chatif-you-want-the-same-setup-fastrag-is-live-fastraglive-484n</guid>
      <description></description>
    </item>
    <item>
      <title>Uploaded a 120-page PDF instant AI chat. 
If you want the same setup, FastRAG is live - https://www.fastrag.live/</title>
      <dc:creator>Atul Tripathi</dc:creator>
      <pubDate>Sat, 03 Jan 2026 04:59:51 +0000</pubDate>
      <link>https://dev.to/atultrp/uploaded-a-120-page-pdf-instant-ai-chat-if-you-want-the-same-setup-fastrag-is-live--27lk</link>
      <guid>https://dev.to/atultrp/uploaded-a-120-page-pdf-instant-ai-chat-if-you-want-the-same-setup-fastrag-is-live--27lk</guid>
      <description>&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://www.fastrag.live/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.fastrag.live%2Fog-image.png" height="435" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://www.fastrag.live/" rel="noopener noreferrer" class="c-link"&gt;
            FastRAG | Ship your AI App in days 🚀
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Stop building RAG from scratch. Grab the starter kit with Pinecone &amp;amp; LangChain pre-configured.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.fastrag.live%2Ffavicon_io%2Ffavicon.ico" width="48" height="48"&gt;
          fastrag.live
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>How to Build a "Chat with Website" App using Next.js, LangChain, and Cheerio</title>
      <dc:creator>Atul Tripathi</dc:creator>
      <pubDate>Mon, 15 Dec 2025 09:42:10 +0000</pubDate>
      <link>https://dev.to/atultrp/how-to-build-a-chat-with-website-app-using-nextjs-langchain-and-cheerio-3o97</link>
      <guid>https://dev.to/atultrp/how-to-build-a-chat-with-website-app-using-nextjs-langchain-and-cheerio-3o97</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/atultrp/how-to-build-a-chat-with-website-app-using-nextjs-langchain-and-cheerio-576k" class="crayons-story__hidden-navigation-link"&gt;How to Build a "Chat with Website" App using Next.js, LangChain, and Cheerio 🦜🔗&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/atultrp" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F548182%2Fb1c13c31-65a6-4134-9275-166991bbdfa0.jpeg" alt="atultrp profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/atultrp" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Atul Tripathi
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Atul Tripathi
                
              
              &lt;div id="story-author-preview-content-3106189" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/atultrp" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F548182%2Fb1c13c31-65a6-4134-9275-166991bbdfa0.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Atul Tripathi&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/atultrp/how-to-build-a-chat-with-website-app-using-nextjs-langchain-and-cheerio-576k" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Dec 15 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/atultrp/how-to-build-a-chat-with-website-app-using-nextjs-langchain-and-cheerio-576k" id="article-link-3106189"&gt;
          How to Build a "Chat with Website" App using Next.js, LangChain, and Cheerio 🦜🔗
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/nextjs"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;nextjs&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tutorial"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tutorial&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/atultrp/how-to-build-a-chat-with-website-app-using-nextjs-langchain-and-cheerio-576k" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;5&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/atultrp/how-to-build-a-chat-with-website-app-using-nextjs-langchain-and-cheerio-576k#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>nextjs</category>
      <category>tutorial</category>
      <category>ai</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to Build a "Chat with Website" App using Next.js, LangChain, and Cheerio 🦜🔗</title>
      <dc:creator>Atul Tripathi</dc:creator>
      <pubDate>Mon, 15 Dec 2025 09:41:34 +0000</pubDate>
      <link>https://dev.to/atultrp/how-to-build-a-chat-with-website-app-using-nextjs-langchain-and-cheerio-576k</link>
      <guid>https://dev.to/atultrp/how-to-build-a-chat-with-website-app-using-nextjs-langchain-and-cheerio-576k</guid>
      <description>&lt;p&gt;Building RAG (Retrieval Augmented Generation) apps usually starts with PDFs. 📄&lt;br&gt;
But let's be honest: users really want to chat with &lt;strong&gt;live URLs&lt;/strong&gt;—documentation, wikis, and blogs. 🌐&lt;/p&gt;

&lt;p&gt;I spent this weekend adding a &lt;strong&gt;Web Scraper&lt;/strong&gt; to my RAG Starter Kit. Here is the technical breakdown of how I built it, so you can do it too. 👇&lt;/p&gt;
&lt;h3&gt;
  
  
  🛑 The Problem with Scraping for LLMs
&lt;/h3&gt;

&lt;p&gt;You can't just &lt;code&gt;fetch(url)&lt;/code&gt; and pass the HTML to GPT-4.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Too much noise:&lt;/strong&gt; Navbars, footers, and ads waste tokens. 💸&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Context Window:&lt;/strong&gt; Raw HTML is huge and confuses the model.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Headless Browsers:&lt;/strong&gt; Tools like Puppeteer are heavy and often timeout on serverless functions (like Vercel). ⏳&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  🛠 The Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Framework:&lt;/strong&gt; Next.js 14&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scraper:&lt;/strong&gt; &lt;code&gt;Cheerio&lt;/code&gt; (via LangChain). It parses HTML like jQuery, making it lightweight and fast. ⚡️&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vector DB:&lt;/strong&gt; Pinecone (Serverless).&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Step 1: The Scraper Logic 🕷️
&lt;/h3&gt;

&lt;p&gt;We use &lt;code&gt;CheerioWebBaseLoader&lt;/code&gt; from LangChain. It grabs the raw HTML and lets us select only the &lt;code&gt;body&lt;/code&gt; or specific content tags (like &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt;), ignoring the junk.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CheerioWebBaseLoader&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;langchain/document_loaders/web/cheerio&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;scrapeUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 1. Load the URL&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CheerioWebBaseLoader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;p, h1, h2, h3, article&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 🎯 Only grab text content&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;docs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 2: The Cleaning (Smart Chunking) 🧹
&lt;/h3&gt;

&lt;p&gt;LLMs need manageable chunks of text. If you cut a sentence in half, you lose context. We use &lt;code&gt;RecursiveCharacterTextSplitter&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RecursiveCharacterTextSplitter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;langchain/text_splitter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;chunkSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 📏 Tokens per chunk&lt;/span&gt;
  &lt;span class="na"&gt;chunkOverlap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 🔗 Overlap to preserve context across chunks&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;splitDocs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;splitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitDocuments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Step 3: The Cost Hack (1024 Dimensions) 💡
&lt;/h3&gt;

&lt;p&gt;This is the most important part! 💰&lt;/p&gt;

&lt;p&gt;By default, OpenAI's embedding models output 1536 dimensions. But Pinecone charges based on storage size.&lt;/p&gt;

&lt;p&gt;OpenAI's new &lt;code&gt;text-embedding-3-small&lt;/code&gt; allows you to "shorten" the dimensions with minimal accuracy loss.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I configured my implementation to force 1024 dimensions:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;embeddings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OpenAIEmbeddings&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;modelName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text-embedding-3-small&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 📉 Saves ~33% on storage costs&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  ✅ The Result
&lt;/h3&gt;

&lt;p&gt;We now have a clean pipeline: URL ➡️ Clean Text ➡️ Chunks ➡️ Vectors ➡️ Chat.&lt;/p&gt;

&lt;p&gt;This allows users to point the app at their documentation and ask questions immediately.&lt;/p&gt;




&lt;h3&gt;
  
  
  🎁 Want the Full Source Code?
&lt;/h3&gt;

&lt;p&gt;I cleaned up this entire logic (plus Multi-File PDF support, Mobile UI, and Streaming response) and packaged it into a production-ready Starter Kit called FastRAG.&lt;/p&gt;

&lt;p&gt;It saves you the ~40 hours of setting up the boilerplate so you can focus on building your AI SaaS over the holiday break. 🎅&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🏁 I'm running a "Holiday Build" race:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;🥇 First 69 devs: Get 69% OFF (~$9). Code: &lt;code&gt;FAST69&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;🥈 Everyone else: Get 40% OFF. Code: &lt;code&gt;HOLIDAY40&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Check out the Live Demo &amp;amp; Repo here: 👉 &lt;a href="https://rag-starter-kit.vercel.app/" rel="noopener noreferrer"&gt;FastRAG&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy coding and happy holidays! 🎄🚀&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>tutorial</category>
      <category>ai</category>
      <category>javascript</category>
    </item>
    <item>
      <title>🛑 Stop Re-Writing RAG Pipelines: My Next.js + Pinecone Architecture ⚡️</title>
      <dc:creator>Atul Tripathi</dc:creator>
      <pubDate>Fri, 21 Nov 2025 17:23:16 +0000</pubDate>
      <link>https://dev.to/atultrp/stop-re-writing-rag-pipelines-my-nextjs-pinecone-architecture-5cfm</link>
      <guid>https://dev.to/atultrp/stop-re-writing-rag-pipelines-my-nextjs-pinecone-architecture-5cfm</guid>
      <description>&lt;p&gt;Let's be real for a second. ☕️&lt;/p&gt;

&lt;p&gt;I have built the "Chat with your PDF" feature for clients about &lt;strong&gt;five times&lt;/strong&gt; in the last two months.&lt;/p&gt;

&lt;p&gt;The frontend? Fun. streaming UI, Tailwind, those fancy typing effects... I love it. 🎨&lt;br&gt;
The backend? &lt;strong&gt;Absolute headache.&lt;/strong&gt; 🤯&lt;/p&gt;

&lt;p&gt;Every single time, I found myself staring at VS Code, copying and pasting the same boring boilerplate to handle:&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;The PDF Loader:&lt;/strong&gt; Chunking text without breaking sentences mid-thought.&lt;br&gt;
❌ &lt;strong&gt;The Embeddings:&lt;/strong&gt; Batching data to OpenAI so I don't hit rate limits.&lt;br&gt;
❌ &lt;strong&gt;The Vector Store:&lt;/strong&gt; Upserting into Pinecone/Supabase without errors.&lt;br&gt;
❌ &lt;strong&gt;The Context Window:&lt;/strong&gt; Calculating tokens so the AI doesn't crash.&lt;/p&gt;

&lt;p&gt;After the 5th time, I realized I was wasting &lt;strong&gt;40+ hours per project&lt;/strong&gt; just setting up the "plumbing" before I could actually build the cool stuff.&lt;/p&gt;

&lt;p&gt;So, I decided to fix it. Forever. 🛠️&lt;/p&gt;
&lt;h2&gt;
  
  
  🏗️ The Architecture
&lt;/h2&gt;

&lt;p&gt;Here is the stack I finally settled on for a production-ready RAG (&lt;em&gt;Retrieval Augmented Generation&lt;/em&gt;) app. It's typed, it scales, and it just works.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;▲ &lt;strong&gt;Framework:&lt;/strong&gt; Next.js (App Router)&lt;/li&gt;
&lt;li&gt;🦜 &lt;strong&gt;Orchestration:&lt;/strong&gt; LangChain.js&lt;/li&gt;
&lt;li&gt;🌲 &lt;strong&gt;Vector DB:&lt;/strong&gt; Pinecone (My go-to for speed)&lt;/li&gt;
&lt;li&gt;⚡️ &lt;strong&gt;Database/Auth:&lt;/strong&gt; Supabase&lt;/li&gt;
&lt;li&gt;💅 &lt;strong&gt;Styling:&lt;/strong&gt; Tailwind CSS&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  🧠 The Hard Part: Handling Vectors
&lt;/h2&gt;

&lt;p&gt;The biggest pain point isn't the chat; it's the &lt;strong&gt;Ingestion Pipeline&lt;/strong&gt;. You can't just dump a PDF into ChatGPT. You have to slice and dice it first. 🔪&lt;/p&gt;

&lt;p&gt;Here is the logic I standardized:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; User uploads file 📂&lt;/li&gt;
&lt;li&gt; Server reads buffer 👓&lt;/li&gt;
&lt;li&gt; &lt;code&gt;RecursiveCharacterTextSplitter&lt;/code&gt; breaks it into chunks 🧩&lt;/li&gt;
&lt;li&gt; Upsert to Pinecone with metadata 💾&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It looks something like this (simplified for sanity):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;OpenAIEmbeddings&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;langchain/embeddings/openai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PineconeStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;langchain/vectorstores/pinecone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;RecursiveCharacterTextSplitter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;langchain/text_splitter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 🪄 The logic that usually takes 3 hours to debug&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addDocumentsToVectorStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fileId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// 1. Split the text intelligently&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;chunkSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;chunkOverlap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;docs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;splitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createDocuments&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="c1"&gt;// 2. Embed and Upsert to the Cloud ☁️&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;embeddings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OpenAIEmbeddings&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;PineconeStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromDocuments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;pineconeIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`file_&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fileId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 🔒 Isolate vectors per file&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Vectors Upserted. We are ready to chat. ⚡️&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📦 So, I Productized It.
&lt;/h2&gt;

&lt;p&gt;I got tired of setting this up from scratch.&lt;/p&gt;

&lt;p&gt;I took my personal repo, cleaned it up, added a polished UI, and turned it into a reusable Starter Kit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's inside the box?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✅ Pre-configured LangChain Setup&lt;/p&gt;

&lt;p&gt;✅ Built-in Vector Ingestion (PDF/TXT/MD)&lt;/p&gt;

&lt;p&gt;✅ Streaming Chat Components (ChatGPT style)&lt;/p&gt;

&lt;p&gt;✅ Rate Limiting (Save your API credits!)&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 The Experiment (Smoke Test)
&lt;/h2&gt;

&lt;p&gt;I'm running a little experiment this weekend.&lt;/p&gt;

&lt;p&gt;Instead of charging the full launch price ($149), I set up a $9 Early Bird Deposit.&lt;/p&gt;

&lt;p&gt;Why $9? It acts as a "Skin in the Game" filter. If the pain of building RAG pipelines isn't worth the price of a coffee ☕️, then I know this isn't worth building further.&lt;/p&gt;

&lt;p&gt;But if you want to save 40 hours of work?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rag-starter-kit.vercel.app/" rel="noopener noreferrer"&gt;👉 Grab the RAG Starter Kit (Early Access)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(Even if you don't buy it, feel free to roast my landing page in the comments! I'm building this in public and feedback is gold. 🥇)&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>
    <item>
      <title>Yo!</title>
      <dc:creator>Atul Tripathi</dc:creator>
      <pubDate>Mon, 03 Nov 2025 06:32:40 +0000</pubDate>
      <link>https://dev.to/atultrp/yo-5050</link>
      <guid>https://dev.to/atultrp/yo-5050</guid>
      <description></description>
    </item>
    <item>
      <title>Data Structure and Algorithms roadmap (with resources)</title>
      <dc:creator>Atul Tripathi</dc:creator>
      <pubDate>Mon, 03 Nov 2025 06:19:30 +0000</pubDate>
      <link>https://dev.to/atultrp/data-structure-and-algorithms-roadmap-with-resources-54kb</link>
      <guid>https://dev.to/atultrp/data-structure-and-algorithms-roadmap-with-resources-54kb</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/atultrp/leetcode-in-2025-1io3" class="crayons-story__hidden-navigation-link"&gt;🚀 LeetCode in 2025&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/atultrp" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F548182%2Fb1c13c31-65a6-4134-9275-166991bbdfa0.jpeg" alt="atultrp profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/atultrp" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Atul Tripathi
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Atul Tripathi
                
              
              &lt;div id="story-author-preview-content-2982198" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/atultrp" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F548182%2Fb1c13c31-65a6-4134-9275-166991bbdfa0.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Atul Tripathi&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/atultrp/leetcode-in-2025-1io3" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Nov 1 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/atultrp/leetcode-in-2025-1io3" id="article-link-2982198"&gt;
          🚀 LeetCode in 2025
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/leetcode"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;leetcode&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/dsa"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;dsa&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/algorithms"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;algorithms&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/coding"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;coding&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/atultrp/leetcode-in-2025-1io3#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            2 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>leetcode</category>
      <category>dsa</category>
      <category>algorithms</category>
      <category>coding</category>
    </item>
  </channel>
</rss>
