<?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>Forem: Suraj Sharma</title>
    <description>The latest articles on Forem by Suraj Sharma (@creativesuraj).</description>
    <link>https://forem.com/creativesuraj</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%2F283325%2Fdb627392-bc87-4478-946d-5ddda2670cc7.jpg</url>
      <title>Forem: Suraj Sharma</title>
      <link>https://forem.com/creativesuraj</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/creativesuraj"/>
    <language>en</language>
    <item>
      <title>Why to choose PostgreSQL over MongoDB in 2026</title>
      <dc:creator>Suraj Sharma</dc:creator>
      <pubDate>Tue, 27 Jan 2026 23:05:31 +0000</pubDate>
      <link>https://forem.com/creativesuraj/why-to-choose-postgresql-over-mongodb-in-2026-onm</link>
      <guid>https://forem.com/creativesuraj/why-to-choose-postgresql-over-mongodb-in-2026-onm</guid>
      <description>&lt;p&gt;For a long time, MongoDB was the default choice when applications needed flexibility or scale. The argument was simple: SQL databases are rigid, NoSQL databases scale better.&lt;/p&gt;

&lt;p&gt;That argument no longer holds true in 2026.&lt;/p&gt;

&lt;p&gt;Modern PostgreSQL supports structured schemas, semi-structured data, vector search, advanced indexing, and complex queries, all in one system. In many real production systems, using PostgreSQL alone avoids the need for MongoDB entirely.&lt;/p&gt;

&lt;p&gt;This article explains &lt;strong&gt;why PostgreSQL is often a better choice than MongoDB today&lt;/strong&gt;, based on real backend systems running at scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structured schema (because it matters in production)
&lt;/h2&gt;

&lt;p&gt;In production systems, data consistency matters more than initial flexibility.&lt;/p&gt;

&lt;p&gt;PostgreSQL enforces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strong data types&lt;/li&gt;
&lt;li&gt;Primary and foreign keys&lt;/li&gt;
&lt;li&gt;Constraints and relationships&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This prevents invalid data from entering the system in the first place.&lt;/p&gt;

&lt;p&gt;In one of our systems (Merlin an AI-driven real estate search platform used by 60K+ active users), PostgreSQL was the source of truth for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Properties&lt;/li&gt;
&lt;li&gt;Canonical locations&lt;/li&gt;
&lt;li&gt;Images&lt;/li&gt;
&lt;li&gt;Metadata relationships&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With millions of records and daily ingestion of ~120K properties, schema enforcement helped catch errors early instead of letting bad data silently propagate.&lt;/p&gt;

&lt;p&gt;MongoDB’s schemaless model pushes validation to the application layer. This works initially, but as systems grow, different document shapes start appearing for the same logical entity. Debugging and migrating this later is painful.&lt;/p&gt;

&lt;h2&gt;
  
  
  JSONB for unstructured data (without losing relational guarantees)
&lt;/h2&gt;

&lt;p&gt;A common reason for choosing MongoDB is storing flexible or evolving data.&lt;/p&gt;

&lt;p&gt;PostgreSQL already solves this with &lt;code&gt;JSONB&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can store:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamic attributes&lt;/li&gt;
&lt;li&gt;Search filters&lt;/li&gt;
&lt;li&gt;Derived metadata&lt;/li&gt;
&lt;li&gt;Optional fields&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…directly inside relational tables.&lt;/p&gt;

&lt;p&gt;In our search backend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Core entities (property, location, image) were modeled relationally&lt;/li&gt;
&lt;li&gt;Flexible attributes and filters were stored using JSON/JSONB&lt;/li&gt;
&lt;li&gt;GIN indexes were used to query JSON fields efficiently&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allowed us to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid unnecessary JOINs on hot paths&lt;/li&gt;
&lt;li&gt;Keep strong consistency for critical data&lt;/li&gt;
&lt;li&gt;Avoid running a separate NoSQL database just for flexibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of choosing &lt;em&gt;either&lt;/em&gt; relational &lt;em&gt;or&lt;/em&gt; document storage, PostgreSQL lets you combine both.&lt;/p&gt;

&lt;h2&gt;
  
  
  Minimize JOINs where needed (without denormalizing everything)
&lt;/h2&gt;

&lt;p&gt;JOINs are often blamed for performance issues.&lt;/p&gt;

&lt;p&gt;In our system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex JOINs were used where correctness mattered&lt;/li&gt;
&lt;li&gt;JSONB and caching were used where read performance mattered&lt;/li&gt;
&lt;li&gt;Redis JSON was used for fast hybrid search paths&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach reduced query complexity &lt;em&gt;without duplicating core data everywhere&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;MongoDB often pushes developers to denormalize aggressively, which leads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data duplication&lt;/li&gt;
&lt;li&gt;Hard-to-maintain update logic&lt;/li&gt;
&lt;li&gt;Eventual consistency bugs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PostgreSQL gives you more control: normalize first, optimize selectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Complex SQL queries are an advantage
&lt;/h2&gt;

&lt;p&gt;PostgreSQL’s biggest strength is still SQL.&lt;/p&gt;

&lt;p&gt;SQL allows you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Express complex relationships clearly&lt;/li&gt;
&lt;li&gt;Debug queries easily&lt;/li&gt;
&lt;li&gt;Optimize step by step&lt;/li&gt;
&lt;li&gt;Reuse logic across services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Early versions of our search system relied on complex SQL queries across multiple tables. When latency increased, we didn’t rewrite the data model but we changed the architecture.&lt;/p&gt;

&lt;p&gt;We separated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Relational filtering (PostgreSQL)&lt;/li&gt;
&lt;li&gt;Vector similarity search (pgVector / Redis)&lt;/li&gt;
&lt;li&gt;Keyword and fuzzy matching (Elasticsearch)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Query latency dropped from ~5 minutes to ~10 seconds&lt;/li&gt;
&lt;li&gt;SQL remained readable and maintainable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MongoDB would require aggregation pipelines with multiple stages (&lt;code&gt;$lookup&lt;/code&gt;, &lt;code&gt;$unwind&lt;/code&gt;, &lt;code&gt;$group&lt;/code&gt;), which become harder to reason about as complexity grows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SQL scales better cognitively than aggregation pipelines.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  PostgreSQL is AI-ready (without MongoDB)
&lt;/h2&gt;

&lt;p&gt;There’s a common assumption that AI workloads require NoSQL databases.&lt;/p&gt;

&lt;p&gt;In reality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PostgreSQL + pgVector handled 1.2M+ image embeddings&lt;/li&gt;
&lt;li&gt;Vector similarity was separated from relational queries&lt;/li&gt;
&lt;li&gt;Multi-stage retrieval (keyword → vector → re-ranking) improved both performance and relevance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PostgreSQL acted as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The source of truth&lt;/li&gt;
&lt;li&gt;The filter engine&lt;/li&gt;
&lt;li&gt;The relational backbone&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Specialized systems handled specialized workloads without replacing PostgreSQL.&lt;/p&gt;

&lt;p&gt;This architecture scaled to ~10K searches per day while keeping infrastructure costs under control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Canonical data modeling works better in relational databases
&lt;/h2&gt;

&lt;p&gt;Location search is a good example.&lt;/p&gt;

&lt;p&gt;We stored canonical locations in PostgreSQL and used Elasticsearch only for fuzzy user input matching. User-entered locations were mapped to canonical IDs, which were then used for downstream queries.&lt;/p&gt;

&lt;p&gt;This eliminated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repeated database calls&lt;/li&gt;
&lt;li&gt;Duplicate location representations&lt;/li&gt;
&lt;li&gt;Inconsistent location data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Relational constraints ensured correctness. MongoDB would push this logic into application code instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fewer systems, lower operational complexity
&lt;/h2&gt;

&lt;p&gt;Every additional database increases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure cost&lt;/li&gt;
&lt;li&gt;Monitoring overhead&lt;/li&gt;
&lt;li&gt;Consistency challenges&lt;/li&gt;
&lt;li&gt;Developer cognitive load&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our backend, PostgreSQL remained the primary database. Redis and Elasticsearch were supporting systems and not sources of truth.&lt;/p&gt;

&lt;p&gt;MongoDB was never required.&lt;/p&gt;

&lt;p&gt;In 2026, reducing stack complexity is often more valuable than adding another database optimized for a narrow use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;PostgreSQL in 2026 is no longer “just a relational database”.&lt;/p&gt;

&lt;p&gt;It provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strong schemas for production safety&lt;/li&gt;
&lt;li&gt;JSONB for flexible data&lt;/li&gt;
&lt;li&gt;Advanced indexing&lt;/li&gt;
&lt;li&gt;Vector search support&lt;/li&gt;
&lt;li&gt;Powerful SQL for complex queries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For many real-world systems, PostgreSQL can replace MongoDB entirely while reducing risk, cost, and long-term maintenance.&lt;/p&gt;

&lt;p&gt;MongoDB still has valid use cases, but it should be a deliberate choice and not a default one.&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>Building Vaani - A Conversational AI Resume Reviewer and Writer</title>
      <dc:creator>Suraj Sharma</dc:creator>
      <pubDate>Tue, 13 Jan 2026 02:30:42 +0000</pubDate>
      <link>https://forem.com/creativesuraj/building-vaani-a-conversational-ai-resume-reviewer-and-writer-518p</link>
      <guid>https://forem.com/creativesuraj/building-vaani-a-conversational-ai-resume-reviewer-and-writer-518p</guid>
      <description>&lt;h2&gt;
  
  
  The Problem: Why Job Seekers Struggle to Show Their Impact
&lt;/h2&gt;



&lt;p&gt;Let me be honest. I've reviewed hundreds of resumes, and I see the same problem over and over again.&lt;/p&gt;

&lt;p&gt;Job seekers have real experience. They've built things, solved problems, led teams. But when they sit down to write their resume, something breaks. They write generic bullet points like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Responsible for developing features&lt;/li&gt;
&lt;li&gt;Worked with a team on projects&lt;/li&gt;
&lt;li&gt;Improved system performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These bullets don't tell the story. They don't show &lt;strong&gt;impact&lt;/strong&gt;. Recruiters want to know: What changed? Who benefited? Why did it matter?&lt;/p&gt;

&lt;p&gt;The real problem isn't that job seekers lack experience. It's that they don't know how to &lt;strong&gt;articulate their impact in a way that resonates with hiring managers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is where Vaani comes in.&lt;/p&gt;



&lt;h2&gt;
  
  
  What is Vaani? Your AI Resume Copilot
&lt;/h2&gt;



&lt;p&gt;Vaani is an AI resume copilot I built to solve this exact problem. It's not just another resume builder. It's a conversational AI system that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Parses your resume&lt;/strong&gt; – Extracts your experience, skills, education, and background into structured data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Classifies your seniority&lt;/strong&gt; – Calculates total years of experience to understand your career level&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analyzes your work experiences&lt;/strong&gt; – Identifies which experiences have strong impact signals and which are missing them&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asks the right questions&lt;/strong&gt; – Guides you through a conversation to uncover real business impact from your work&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refines your impact stories&lt;/strong&gt; – Transforms generic bullets into compelling achievement statements&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintains context&lt;/strong&gt; – Remembers everything across the entire conversation using persistent memory&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key insight? &lt;strong&gt;Impact isn't invented. It's uncovered.&lt;/strong&gt; Most job seekers have amazing stories buried in their experience. They just need someone (or something) to ask the right questions to bring them out.&lt;/p&gt;



&lt;h2&gt;
  
  
  How I Architected Vaani: The Three Pillars
&lt;/h2&gt;



&lt;p&gt;Vaani is built on three core pillars: &lt;strong&gt;Agentic Workflow&lt;/strong&gt;, &lt;strong&gt;Memory System&lt;/strong&gt;, and &lt;strong&gt;Interactive State Management&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pillar 1: Agentic Workflow
&lt;/h3&gt;

&lt;p&gt;An agentic workflow means Vaani doesn't just respond to user input. It &lt;strong&gt;orchestrates multiple AI agents&lt;/strong&gt; that work together to guide you through a structured review process.&lt;/p&gt;

&lt;p&gt;Here's how it works:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agent 1: Seniority Classifier&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Analyzes your work experience to calculate total years of experience&lt;/li&gt;
&lt;li&gt;Classifies you as Junior, Mid, or Senior level&lt;/li&gt;
&lt;li&gt;This context helps all other agents understand your career stage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Agent 2: Impact Analysis Agent&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reviews each of your work experiences&lt;/li&gt;
&lt;li&gt;Identifies which experiences have strong impact signals (outcomes, metrics, business value)&lt;/li&gt;
&lt;li&gt;Flags experiences that are missing impact details&lt;/li&gt;
&lt;li&gt;Provides reflection prompts to help you recall impact&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Agent 3: Experience Selector Agent&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Orchestrates which experience to focus on next&lt;/li&gt;
&lt;li&gt;Prioritizes most recent experiences with missing impact&lt;/li&gt;
&lt;li&gt;Ensures you work through experiences systematically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Agent 4: Impact Analysing Agent&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is where the magic happens&lt;/li&gt;
&lt;li&gt;Asks targeted, conversational questions about your work&lt;/li&gt;
&lt;li&gt;Focuses on outcomes: What changed? Who benefited? Why did it matter?&lt;/li&gt;
&lt;li&gt;Helps you articulate real business impact&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Agent 5: Impact Refinement Agent&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Takes your free-text impact description&lt;/li&gt;
&lt;li&gt;Translates it into clear, business-relevant language&lt;/li&gt;
&lt;li&gt;Produces resume-ready bullet points&lt;/li&gt;
&lt;li&gt;Ensures accuracy and authenticity&lt;/li&gt;
&lt;/ul&gt;



&lt;h3&gt;
  
  
  Pillar 2: Memory System (Redis-Backed)
&lt;/h3&gt;

&lt;p&gt;Here's the problem with most AI tools: they forget context. You tell them something in message 1, and by message 10, they've lost track.&lt;/p&gt;

&lt;p&gt;Vaani uses a &lt;strong&gt;persistent memory system&lt;/strong&gt; backed by Redis. Every conversation is stored with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Resume sections&lt;/strong&gt; – Your parsed resume data (name, skills, experience, education)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metadata&lt;/strong&gt; – Total years of experience, seniority level&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Impact analysis results&lt;/strong&gt; – Which experiences have strong impact, which need work&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conversation history&lt;/strong&gt; – Every message exchanged&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Current state&lt;/strong&gt; – Which experience you're working on, what stage you're in&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rewritten resume&lt;/strong&gt; – The improved version being built&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This memory persists for 24 hours, so you can close the browser and come back later. Vaani remembers everything.&lt;/p&gt;

&lt;p&gt;The memory structure looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"resume_sections"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John Doe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hard_skills"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Python"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"React"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AWS"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"work_experiences"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"metadata"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"total_years_experience"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"seniority_level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mid"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"current_state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"current_experience_index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"current_experience_processed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"current_step"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"impact_analysing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"processing"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rewritten_resume"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h3&gt;
  
  
  Pillar 3: Interactive State Management
&lt;/h3&gt;

&lt;p&gt;Vaani doesn't process everything at once. It moves through &lt;strong&gt;discrete stages&lt;/strong&gt;, each with a clear purpose:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Seniority Classification&lt;/strong&gt; → Calculate years of experience&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Impact Analysis&lt;/strong&gt; → Analyse all work experiences for impact signals&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Experience Selection&lt;/strong&gt; → Choose which experience to focus on next&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Impact Elicitation&lt;/strong&gt; → Ask targeted questions about that experience&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Impact Refinement&lt;/strong&gt; → Transform answers into resume-ready bullets&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Iteration&lt;/strong&gt; → Move to next experience and repeat&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each stage has a &lt;strong&gt;current state&lt;/strong&gt; that tracks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which experience you're working on&lt;/li&gt;
&lt;li&gt;Whether that experience has been processed&lt;/li&gt;
&lt;li&gt;What step you're currently in&lt;/li&gt;
&lt;li&gt;Overall processing status&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This prevents confusion and ensures the workflow guides you systematically through your resume.&lt;/p&gt;



&lt;h2&gt;
  
  
  The Agentic Workflow in Action: A Real Example
&lt;/h2&gt;



&lt;p&gt;Let me walk you through how Vaani works with a real job seeker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You:&lt;/strong&gt; Upload your resume (PDF)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vaani:&lt;/strong&gt; Parses it and says: "Got it! I see you're a Software Engineer with 5 years of experience at three companies. You have Python, React, and AWS skills. Let me analyze your experiences..."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vaani:&lt;/strong&gt; (Analyzing) "Calculating your seniority level... You have 5 years of experience, so you're at a Mid level. Now let me review each of your work experiences to see where you have strong impact stories and where we can dig deeper."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vaani:&lt;/strong&gt; "I've analysed your experiences. Your most recent role at TechCorp has some impact signals, but it's missing details. Let's start there. Tell me about your biggest achievement in that role. What did you build or improve? What changed because of your work?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You:&lt;/strong&gt; "Well, I built a microservices architecture that improved performance."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vaani:&lt;/strong&gt; "Great! Let's dig deeper. How much did performance improve? Who benefited from this? Why did it matter to the business?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You:&lt;/strong&gt; "Oh! We reduced API latency by 60%, which meant our mobile app users had a much faster experience. That led to a 15% increase in daily active users."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vaani:&lt;/strong&gt; "Perfect! That's real impact. Here's how I'd write that as a resume bullet:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Architected microservices migration reducing API latency by 60%, enabling 15% increase in daily active users and improving experience for users.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Does that feel accurate?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You:&lt;/strong&gt; "Yes! That's so much better than what I had."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vaani:&lt;/strong&gt; "Great. Let's move to your next role at PreviousCorp. Tell me about your biggest impact there..."&lt;/p&gt;

&lt;p&gt;And so on. By the end, you have a completely rewritten resume with impact-driven bullets for each experience.&lt;/p&gt;



&lt;h2&gt;
  
  
  The Architecture Diagram
&lt;/h2&gt;



&lt;p&gt;Here's how all the pieces fit together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────┐
│                    VAANI ARCHITECTURE                       │
└─────────────────────────────────────────────────────────────┘

┌──────────────────┐
│  User Interface  │
│  (Web/Mobile)    │
└────────┬─────────┘
         │
         ▼
┌──────────────────────────────────────────────────────────────┐
│              WebSocket Connection (Real-time)                │
└────────┬─────────────────────────────────────────────────────┘
         │
         ▼
┌──────────────────────────────────────────────────────────────┐
│           Vaani Backend (Go + Genkit)                        │
│                                                              │
│  ┌─────────────────────────────────────────────────────┐     │
│  │  Message Router                                     │     │
│  │  - Routes messages to appropriate agent             │     │
│  │  - Manages conversation flow                        │     │
│  │  - Tracks current state                             │     │
│  └────────────────┬────────────────────────────────────┘     │
│                   │                                          │
│     ┌─────────────┼──────────────┬──────────────┐            │
│     ▼             ▼              ▼              ▼            │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐      │
│  │Seniority │  │Impact    │  │Experience│  │Impact    │      │
│  │Classifier│  │Analysis  │  │Selector  │  │Analysis  │      │
│  └──────────┘  └──────────┘  └──────────┘  └──────────┘      │
│                                                              │
│  ┌──────────────────────────────────────────────────────┐    │
│  │  Impact Refinement Agent                             │    │
│  │  - Transforms user answers into resume bullets       │    │
│  │  - Maintains accuracy and authenticity               │    │
│  └──────────────────────────────────────────────────────┘    │
│                                                              │
└──────────────────────────────────────────────────────────────┘
                               │
                               ▼
┌──────────────────────────────────────────────────────────────┐
│              Memory Layer (Redis)                            │
│                                                              │
│  Key: memory:{chat_id}                                       │
│  Value: {                                                    │
│    resume_sections,                                          │
│    metadata (seniority, experience),                         │
│    impact_analysis_results,                                  │
│    conversation_history,                                     │
│    current_state,                                            │
│    rewritten_resume                                          │
│  }                                                           │
│  TTL: 24 hours                                               │
└──────────────────────────────────────────────────────────────┘
                             │
                             ▼
┌──────────────────────────────────────────────────────────────┐
│              LLM Layer                                       │
│                                                              │
│  - Structured outputs for parsing                            │
│  - Prompt engineering for each agent                         │
│  - JSON schema validation                                    │
└──────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h2&gt;
  
  
  The Memory Flow: How Context Persists
&lt;/h2&gt;



&lt;p&gt;Here's how memory works across a conversation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User uploads resume
        │
        ▼
Parse resume → Store in Redis memory
        │
        ▼
Classify seniority level
        │
        ▼
Retrieve memory → Add seniority data → Update Redis
        │
        ▼
Analyze all work experiences for impact
        │
        ▼
Retrieve memory → Add impact analysis → Update Redis
        │
        ▼
Select first experience to work on
        │
        ▼
Ask impact questions about that experience
        │
        ▼
Retrieve memory → Add conversation → Update Redis
        │
        ▼
Refine impact into resume bullet
        │
        ▼
Retrieve memory → Add refined bullet → Update Redis
        │
        ▼
Move to next experience (repeat)
        │
        ▼
User closes browser (memory persists for 24 hours)
        │
        ▼
User returns next day
        │
        ▼
Retrieve memory → Continue from where they left off
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is powerful because it means &lt;strong&gt;Vaani never loses context&lt;/strong&gt;. You can have a conversation over multiple days, and it remembers everything. You can close the browser mid-conversation and come back later to continue exactly where you left off.&lt;/p&gt;



&lt;h2&gt;
  
  
  Why This Architecture Matters
&lt;/h2&gt;



&lt;p&gt;Most AI resume tools are &lt;strong&gt;stateless&lt;/strong&gt;. They don't remember context. You tell them something, they respond, and that's it. If you want to refine something, you have to re-explain everything.&lt;/p&gt;

&lt;p&gt;Vaani is &lt;strong&gt;stateful and agentic&lt;/strong&gt;. It:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Remembers everything&lt;/strong&gt; – Via Redis memory that persists for 24 hours&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orchestrates multiple agents&lt;/strong&gt; – Each with a specific job (seniority classification, impact analysis, elicitation, refinement)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintains workflow state&lt;/strong&gt; – Knows exactly which experience you're working on and what stage you're in&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asks intelligent questions&lt;/strong&gt; – Based on your specific resume and career level&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never fabricates&lt;/strong&gt; – Only enhances what you confirm as true&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guides systematically&lt;/strong&gt; – Works through your experiences one by one, ensuring nothing is missed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why Vaani produces better results than generic AI tools. It's not just generating text. It's &lt;strong&gt;guiding you through a structured conversation&lt;/strong&gt; to uncover and articulate your real impact.&lt;/p&gt;



&lt;h2&gt;
  
  
  The Results: What Users Get
&lt;/h2&gt;



&lt;p&gt;After going through Vaani, users get:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Impact-driven resume bullets&lt;/strong&gt; – Focused on outcomes, not tasks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deeper self-awareness&lt;/strong&gt; – You understand your own impact better&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confidence in your story&lt;/strong&gt; – You can articulate your value clearly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A repeatable process&lt;/strong&gt; – You know how to uncover impact for any role&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better resume quality&lt;/strong&gt; – Each bullet is specific, measurable, and authentic&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Users report that their resume bullets are significantly stronger after Vaani. Instead of generic statements like "Improved system performance," they have specific, impact-driven bullets like "Architected microservices migration reducing API latency by 60%, enabling 15% increase in daily active users."&lt;/p&gt;



&lt;h2&gt;
  
  
  Building Vaani: Key Lessons
&lt;/h2&gt;



&lt;p&gt;If you're building AI systems, here are the key lessons I learned:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;State matters&lt;/strong&gt; – Stateless AI is limited. Persistent memory changes everything. Users can close the browser and come back later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agents are powerful&lt;/strong&gt; – Multiple specialized agents beat one general-purpose model. Each agent does one thing well.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accuracy over polish&lt;/strong&gt; – Never fabricate. Users trust systems that maintain fidelity. It's better to ask a clarifying question than to guess.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conversation &amp;gt; generation&lt;/strong&gt; – Asking the right questions is more powerful than generating answers. The user has the knowledge; you just need to help them articulate it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workflow design&lt;/strong&gt; – Clear stages and state management prevent confusion. Users should always know where they are in the process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Systematic over random&lt;/strong&gt; – Guide users through experiences systematically. Don't jump around randomly.&lt;/li&gt;
&lt;/ol&gt;



&lt;h2&gt;
  
  
  Try Vaani Today
&lt;/h2&gt;



&lt;p&gt;If you're struggling to tailor your resume, or if you want to uncover the real impact in your experience, try Vaani. It's free to start, and it works for any role in software, AI, ML, and data.&lt;/p&gt;

&lt;p&gt;Visit &lt;a href="https://speeduphire.com/try-vaani" rel="noopener noreferrer"&gt;try-vaani&lt;/a&gt; to get started.&lt;/p&gt;

&lt;p&gt;Your resume has more power than you think. Vaani helps you unlock it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Suraj Sharma</dc:creator>
      <pubDate>Fri, 26 Dec 2025 04:51:15 +0000</pubDate>
      <link>https://forem.com/creativesuraj/-48o2</link>
      <guid>https://forem.com/creativesuraj/-48o2</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/creativesuraj/reducing-latency-and-pagination-in-image-and-keyword-based-property-search-3ed7" class="crayons-story__hidden-navigation-link"&gt;Solving Latency and Pagination in Image and Keyword Based Property Search&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="/creativesuraj" 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%2F283325%2Fdb627392-bc87-4478-946d-5ddda2670cc7.jpg" alt="creativesuraj profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/creativesuraj" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Suraj Sharma
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Suraj Sharma
                
              
              &lt;div id="story-author-preview-content-3127508" 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="/creativesuraj" 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%2F283325%2Fdb627392-bc87-4478-946d-5ddda2670cc7.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Suraj Sharma&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/creativesuraj/reducing-latency-and-pagination-in-image-and-keyword-based-property-search-3ed7" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Dec 26 '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/creativesuraj/reducing-latency-and-pagination-in-image-and-keyword-based-property-search-3ed7" id="article-link-3127508"&gt;
          Solving Latency and Pagination in Image and Keyword Based Property Search
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/systemdesign"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;systemdesign&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/machinelearning"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;machinelearning&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/postgres"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;postgres&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/performance"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;performance&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/creativesuraj/reducing-latency-and-pagination-in-image-and-keyword-based-property-search-3ed7" 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/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;2&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/creativesuraj/reducing-latency-and-pagination-in-image-and-keyword-based-property-search-3ed7#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add 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;
            3 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>systemdesign</category>
      <category>machinelearning</category>
      <category>postgres</category>
      <category>performance</category>
    </item>
    <item>
      <title>Solving Latency and Pagination in Image and Keyword Based Property Search</title>
      <dc:creator>Suraj Sharma</dc:creator>
      <pubDate>Fri, 26 Dec 2025 03:14:39 +0000</pubDate>
      <link>https://forem.com/creativesuraj/reducing-latency-and-pagination-in-image-and-keyword-based-property-search-3ed7</link>
      <guid>https://forem.com/creativesuraj/reducing-latency-and-pagination-in-image-and-keyword-based-property-search-3ed7</guid>
      <description>&lt;p&gt;At my company, we realized that users do not search for homes the way traditional search systems expect. Some users type simple keywords. Others describe what they want to see in images, for example “homes with large glass windows in the living room” or “backyards with large trees”.&lt;/p&gt;

&lt;p&gt;Our existing search system was not designed for this behavior.&lt;/p&gt;

&lt;p&gt;Property descriptions usually do not contain visual details like trees, lighting, or window style. Because of this, keyword search and vector search on text were not enough. We needed image based search at scale.&lt;/p&gt;

&lt;p&gt;At the same time, the implementation was not scalable. We had around 1.3 million image embeddings created using Nomic vision models. Vector search was done inside PostgreSQL using pgvector, and most of the logic was written as complex SQL queries. As traffic and data increased, performance degraded badly. Search latency went up to 5 minutes, making the feature unusable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ownership and Approach
&lt;/h3&gt;

&lt;p&gt;As a senior software engineer, I took ownership of fixing both the performance and correctness of Deep Search.&lt;/p&gt;

&lt;p&gt;One key decision I made was to keep the system deterministic and not use LLMs for ranking or retrieval. LLMs are useful, but they are non deterministic and hard to control at scale.&lt;/p&gt;

&lt;p&gt;I used an LLM only to understand user intent. The LLM parses the user query and extracts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hard filters like number of bedrooms or location&lt;/li&gt;
&lt;li&gt;A flag that indicates whether image based search is required&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“2 bedroom apartment in Manhattan” only needs deterministic filters and keyword search&lt;/li&gt;
&lt;li&gt;“2 bedroom house with backyard having large trees” requires visual understanding and triggers Deep Search&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This keeps LLM usage limited and makes the rest of the system predictable and debuggable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenges Found During Implementation
&lt;/h3&gt;

&lt;p&gt;While redesigning the system, I discovered a major issue with how results from different retrieval systems were merged.&lt;/p&gt;

&lt;p&gt;BM25 search has its own ranking and pagination. Vector search also has its own ranking and pagination. When results were paginated first and then merged, pagination broke completely.&lt;/p&gt;

&lt;p&gt;Page 2 from BM25 and Page 2 from vector search did not represent the same set of results. Some pages contained mostly vector matches, some had none, and rankings changed between requests. This caused unstable and inconsistent results, which is not acceptable for a production search system.&lt;/p&gt;

&lt;p&gt;This problem required rethinking how ranking and pagination were handled.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;When Deep Search is triggered, I built a hybrid search pipeline with clear separation of concerns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hard deterministic filters&lt;/li&gt;
&lt;li&gt;BM25 full text search using RedisSearch&lt;/li&gt;
&lt;li&gt;Vector search on property images using pgvector&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key change was that none of these systems paginate independently anymore.&lt;/p&gt;

&lt;p&gt;To merge results correctly, I implemented Reciprocal Rank Fusion, which is designed to combine ranked lists from different search engines.&lt;/p&gt;

&lt;p&gt;For each property, we compute a single hybrid score:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;BM25 rank is converted into a reciprocal score&lt;/li&gt;
&lt;li&gt;Vector similarity scores are normalized&lt;/li&gt;
&lt;li&gt;We apply weights based on whether Deep Search is triggered
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hybridScore = alphaBM25 * bm25Score + betaVector * (vecScore / maxVec)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only after this unified hybrid score is computed do we apply pagination. This guarantees stable ordering across pages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Result
&lt;/h3&gt;

&lt;p&gt;This approach solved both performance and ranking issues.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Latency reduced from around 5 minutes to under 10 seconds&lt;/li&gt;
&lt;li&gt;Pagination is stable and deterministic&lt;/li&gt;
&lt;li&gt;Visual matches surface naturally when users ask for visual features&lt;/li&gt;
&lt;li&gt;Keyword intent still influences ranking&lt;/li&gt;
&lt;li&gt;Results are consistent across pages&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>systemdesign</category>
      <category>machinelearning</category>
      <category>postgres</category>
      <category>performance</category>
    </item>
    <item>
      <title>10 Classical ML Algorithms Every Fresher Should Learn in 2026</title>
      <dc:creator>Suraj Sharma</dc:creator>
      <pubDate>Wed, 24 Dec 2025 00:32:52 +0000</pubDate>
      <link>https://forem.com/creativesuraj/10-classical-ml-algorithms-every-fresher-should-learn-in-2026-e10</link>
      <guid>https://forem.com/creativesuraj/10-classical-ml-algorithms-every-fresher-should-learn-in-2026-e10</guid>
      <description>&lt;p&gt;This guide covers the 10 classical machine learning algorithms every fresher should learn. Each algorithm is explained with why it matters, how it works at a basic level, and when you should use it. By the end, you'll have a solid foundation to tackle real-world machine learning problems.&lt;/p&gt;



&lt;h2&gt;
  
  
  1. Linear Regression
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does&lt;/strong&gt;: Linear Regression models the relationship between input features and a continuous target value using a straight line (or hyperplane in multiple dimensions).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why learn it&lt;/strong&gt;: This is the starting point for understanding machine learning mathematically. It teaches you about loss functions, gradients, and how models learn from data. Linear Regression is simple but powerful for many real-world problems like predicting house prices, stock values, or sales forecasts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use it&lt;/strong&gt;: Use Linear Regression when you have a continuous target variable and suspect a linear relationship between features and the target. It's fast, interpretable, and works well as a baseline model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real example&lt;/strong&gt;: Predicting apartment rent based on square footage, location, and amenities.&lt;/p&gt;



&lt;h2&gt;
  
  
  2. Logistic Regression
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does&lt;/strong&gt;: Despite its name, Logistic Regression is a classification algorithm. It predicts the probability that an instance belongs to a particular class, typically used for binary classification (yes/no, spam/not spam).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why learn it&lt;/strong&gt;: Logistic Regression is everywhere in industry. It's used in fraud detection, email spam filtering, disease diagnosis, and customer churn prediction. Understanding it teaches you about probabilities, decision boundaries, and how to convert regression into classification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use it&lt;/strong&gt;: Use it for binary classification problems where you need interpretable results and probability estimates. It's also a great baseline for classification tasks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real example&lt;/strong&gt;: Predicting whether a customer will buy a product (yes/no) based on their browsing history and demographics.&lt;/p&gt;



&lt;h2&gt;
  
  
  3. k-Nearest Neighbors (KNN)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does&lt;/strong&gt;: KNN classifies data points based on the classes of their k nearest neighbors in the training dataset. If most neighbors belong to class A, the new point is classified as A.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why learn it&lt;/strong&gt;: KNN is intuitive and teaches you about distance metrics (how to measure similarity between data points). It's a lazy learning algorithm, meaning it doesn't build a model during training but instead stores all training data and makes predictions at test time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use it&lt;/strong&gt;: Use KNN for small to medium-sized datasets where you need a simple, interpretable classifier. It works well for image recognition, recommendation systems, and pattern matching.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real example&lt;/strong&gt;: Recommending movies to a user based on movies watched by similar users.&lt;/p&gt;



&lt;h2&gt;
  
  
  4. Naive Bayes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does&lt;/strong&gt;: Naive Bayes is a probabilistic classifier based on Bayes' theorem. It assumes that all features are independent of each other (the "naive" assumption) and calculates the probability of each class given the features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why learn it&lt;/strong&gt;: Naive Bayes is fast, scalable, and surprisingly effective despite its simplistic assumptions. It's widely used in text classification, spam detection, and sentiment analysis. Understanding it teaches you about probability and Bayesian thinking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use it&lt;/strong&gt;: Use Naive Bayes for text classification, spam detection, and when you need a fast, lightweight classifier. It works especially well with high-dimensional data like text.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real example&lt;/strong&gt;: Classifying emails as spam or not spam based on word frequencies.&lt;/p&gt;



&lt;h2&gt;
  
  
  5. Decision Trees
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does&lt;/strong&gt;: Decision Trees make predictions by recursively splitting data based on feature values. Each split creates a branch, and the tree continues until it reaches a leaf node that makes a prediction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why learn it&lt;/strong&gt;: Decision Trees are highly intuitive and interpretable. You can visualize exactly how the model makes decisions. They also teach you about feature importance and how to handle both classification and regression problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use it&lt;/strong&gt;: Use Decision Trees when you need interpretability and can afford some overfitting. They work well for both classification and regression and handle non-linear relationships naturally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real example&lt;/strong&gt;: Deciding whether to approve a loan based on credit score, income, and employment history.&lt;/p&gt;



&lt;h2&gt;
  
  
  6. Random Forest
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does&lt;/strong&gt;: Random Forest combines multiple Decision Trees to improve accuracy and reduce overfitting. Each tree is trained on a random subset of data and features, and predictions are made by averaging (regression) or voting (classification) across all trees.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why learn it&lt;/strong&gt;: Random Forest is powerful out-of-the-box and often works well without much tuning. It's one of the most popular algorithms in industry because it balances accuracy with interpretability. Understanding ensemble methods is crucial for modern machine learning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use it&lt;/strong&gt;: Use Random Forest as your first choice for most classification and regression problems. It handles missing values, non-linear relationships, and feature interactions well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real example&lt;/strong&gt;: Predicting customer churn by combining predictions from multiple decision trees trained on different data subsets.&lt;/p&gt;



&lt;h2&gt;
  
  
  7. Support Vector Machines (SVM)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does&lt;/strong&gt;: SVM finds the optimal boundary (hyperplane) that separates classes by maximizing the margin between them. It can also handle non-linear problems using kernel tricks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why learn it&lt;/strong&gt;: SVM has strong theoretical foundations and works exceptionally well for high-dimensional data. Understanding SVM teaches you about optimization, margins, and kernel methods—concepts that appear throughout machine learning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use it&lt;/strong&gt;: Use SVM for binary classification problems, especially with high-dimensional data. It's particularly effective for text classification and image recognition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real example&lt;/strong&gt;: Classifying handwritten digits (0-9) in image recognition tasks.&lt;/p&gt;



&lt;h2&gt;
  
  
  8. k-Means Clustering
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does&lt;/strong&gt;: k-Means is an unsupervised algorithm that groups data points into k clusters based on similarity. It iteratively assigns points to the nearest cluster center and updates centers until convergence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why learn it&lt;/strong&gt;: k-Means introduces you to unsupervised learning and clustering concepts. It's simple, fast, and widely used for customer segmentation, image compression, and data exploration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use it&lt;/strong&gt;: Use k-Means when you want to discover natural groupings in unlabeled data. It's great for exploratory data analysis and customer segmentation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real example&lt;/strong&gt;: Grouping customers into segments based on purchase behavior for targeted marketing.&lt;/p&gt;



&lt;h2&gt;
  
  
  9. Principal Component Analysis (PCA)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does&lt;/strong&gt;: PCA is a dimensionality reduction technique that transforms features into a smaller set of uncorrelated components that capture most of the variance in the data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why learn it&lt;/strong&gt;: PCA teaches you about feature reduction, which is crucial for handling high-dimensional data. It helps with visualization, noise removal, and improving model performance by reducing computational complexity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use it&lt;/strong&gt;: Use PCA when you have many features and want to reduce dimensionality while preserving information. It's useful for visualization, noise reduction, and speeding up model training.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real example&lt;/strong&gt;: Reducing 784 pixel features in handwritten digit images to 50 principal components for faster classification.&lt;/p&gt;



&lt;h2&gt;
  
  
  10. Gradient Boosting (GBM)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it does&lt;/strong&gt;: Gradient Boosting builds models sequentially, where each new model corrects errors made by previous models. It combines weak learners (usually decision trees) into a strong predictor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why learn it&lt;/strong&gt;: Gradient Boosting is the foundation for modern tools like XGBoost, LightGBM, and CatBoost that dominate machine learning competitions and industry applications. Understanding it prepares you for state-of-the-art techniques.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use it&lt;/strong&gt;: Use Gradient Boosting for both classification and regression when you want maximum accuracy. It requires careful tuning but often produces the best results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real example&lt;/strong&gt;: Predicting house prices by sequentially building trees that correct previous prediction errors.&lt;/p&gt;



&lt;h2&gt;
  
  
  Your Learning Path
&lt;/h2&gt;

&lt;p&gt;Practice each algorithm with real datasets from Kaggle or GitHub. Build projects, understand the math, and experiment with different parameters. This foundation will serve you well throughout your machine learning career.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to add google analytics to a Next.js website</title>
      <dc:creator>Suraj Sharma</dc:creator>
      <pubDate>Sun, 27 Dec 2020 10:49:54 +0000</pubDate>
      <link>https://forem.com/creativesuraj/how-to-add-google-analytics-to-a-next-js-website-3c9k</link>
      <guid>https://forem.com/creativesuraj/how-to-add-google-analytics-to-a-next-js-website-3c9k</guid>
      <description>&lt;p&gt;In this tutorial, you'are going to learn how you can add Google Analytics to your Next.js Website.&lt;/p&gt;

&lt;p&gt;A typical Google Analytics JavaScript code looks like this&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;async&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://www.googletagmanager.com/gtag/js?id=${YOUR_TRACKING_ID}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataLayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataLayer&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;gtag&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="nx"&gt;dataLayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;);}&lt;/span&gt;
  &lt;span class="nf"&gt;gtag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="nf"&gt;gtag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;YOUR_TRACKING_ID&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Adding this directly inside the &lt;code&gt;Head&lt;/code&gt; component on your Next project does not work because React converts it to a &lt;strong&gt;string before rendering&lt;/strong&gt;, &lt;br&gt;
which helps prevent &lt;a href="https://en.wikipedia.org/wiki/Cross-site_scripting" rel="noopener noreferrer"&gt;cross-site-scripting&lt;/a&gt; attack&lt;/p&gt;


&lt;h2&gt;
  
  
  The best way to add the google analytics script
&lt;/h2&gt;



&lt;p&gt;Open your &lt;code&gt;_document.js&lt;/code&gt; file, use the below code to insert the script into your &lt;code&gt;_document.js&lt;/code&gt; file.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NextScript&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;next/document&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;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyDocument&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Document&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;async&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://www.googletagmanager.com/gtag/js?id=${YOUR_TRACKING_ID}"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;
            &lt;span class="na"&gt;async&lt;/span&gt;
            &lt;span class="na"&gt;dangerouslySetInnerHTML&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;__html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`window.dataLayer = window.dataLayer || [];
              function gtag(){dataLayer.push(arguments);}
              gtag('js', new Date());

              gtag('config', &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;YOUR_TRACKING_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="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Main&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NextScript&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&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;Replace the &lt;code&gt;${YOUR_TRACKING_ID}&lt;/code&gt; variable with your &lt;strong&gt;google analytics tracking ID&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Now when you reload your website you can &lt;strong&gt;notice&lt;/strong&gt; one 'Active Users right now' on your google analytics dashboard.&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%2Ffenx6cf6vr2k84jg1qpx.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%2Ffenx6cf6vr2k84jg1qpx.png" alt="add google analytics to nextjs website" width="266" height="327"&gt;&lt;/a&gt;&lt;/p&gt;



</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>How to build a dark mode theme using React Material UI, React context API and React hooks</title>
      <dc:creator>Suraj Sharma</dc:creator>
      <pubDate>Sat, 15 Aug 2020 18:09:43 +0000</pubDate>
      <link>https://forem.com/creativesuraj/how-to-build-a-dark-mode-theme-in-react-material-ui-react-context-api-and-react-hooks-529d</link>
      <guid>https://forem.com/creativesuraj/how-to-build-a-dark-mode-theme-in-react-material-ui-react-context-api-and-react-hooks-529d</guid>
      <description>&lt;p&gt;This article is about creating your own 'ThemeProvider' component to toggle between the light mode and dark mode built using React Context API and React hooks useMemo() and useCallback() even created a new custom hook useChangeTheme()&lt;/p&gt;

&lt;p&gt;I recently added a button to toggle between light mode and dark mode on &lt;a href="https://surajsharma.net" rel="noopener noreferrer"&gt;my personal blog&lt;/a&gt;, for that I created a separate library called &lt;strong&gt;'react-material-ui-dark-mode'&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're interested in reading more about how to build own your toggle button or want to use my library in your projects.&lt;/p&gt;

&lt;p&gt;Follow my &lt;a href="https://www.surajsharma.net/blog/react-material-ui-dark-mode" rel="noopener noreferrer"&gt;blog post on my personal website&lt;/a&gt; or you can fork the GitHub repository &lt;a href="https://github.com/creativesuraj/react-material-ui-dark-mode" rel="noopener noreferrer"&gt;react-material-ui-dark-mode&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please leave your feedback on the comment box below.&lt;/p&gt;

&lt;p&gt;Thank You!&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Which URL Shortener Tool Do You Use and Why?</title>
      <dc:creator>Suraj Sharma</dc:creator>
      <pubDate>Sat, 02 May 2020 17:02:43 +0000</pubDate>
      <link>https://forem.com/creativesuraj/which-url-shortener-tool-do-you-use-and-why-2on1</link>
      <guid>https://forem.com/creativesuraj/which-url-shortener-tool-do-you-use-and-why-2on1</guid>
      <description>&lt;p&gt;&lt;strong&gt;There are many URL shortener tools available in the market some are free and many require paid subscriptions to use their service.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here are few URL shortener tools I already know about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;bitly,&lt;/li&gt;
&lt;li&gt;tinyURL,&lt;/li&gt;
&lt;li&gt;rebrandly,&lt;/li&gt;
&lt;li&gt;shorturl.at&lt;/li&gt;
&lt;li&gt;t.co - twitter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All the above tools are fast and secure, they also come with url hit tracker that let you know how many clicks your short links get.&lt;/p&gt;

&lt;p&gt;But the URL shortener tool I use is &lt;a href="https://longurl.in" rel="noopener noreferrer"&gt;longurl.in&lt;/a&gt;, created by me and is free to use.&lt;/p&gt;

&lt;p&gt;I created my own URL shortener tool using and named it longURL.in. It is built using Next.js, Typescript, serverless and MongoDB cloud. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is fast and secure, communication is happening through HTTPS,&lt;/li&gt;
&lt;li&gt;It always generates the same short URL for the same long URL, I did because I wanted a one to one mapping for a long URL, so that the database space consumption is less.&lt;/li&gt;
&lt;li&gt;Shortened URLs read the metadata of the long urls when shared in social networking sites so that the short links don't look like spam links.
&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%2Fkgvvjhjs6nmzw3x79ryk.png" alt="longurl.in-thumbnail" width="497" height="242"&gt;
&lt;/li&gt;
&lt;li&gt;It is hosted in AWS cloud.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Not Implemented&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It does not monitor how many hits a short URL gets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Please comment which URL shortener tools do you use and why?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you have any suggestion or feedback, please comment&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Personal Blog Built using Nextjs and TypeScript</title>
      <dc:creator>Suraj Sharma</dc:creator>
      <pubDate>Fri, 17 Apr 2020 01:56:18 +0000</pubDate>
      <link>https://forem.com/creativesuraj/personal-blog-built-using-nextjs-and-typescript-50gk</link>
      <guid>https://forem.com/creativesuraj/personal-blog-built-using-nextjs-and-typescript-50gk</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is taken from my original &lt;a href="https://surajsharma.net/blog/personal-blog-built-using-nextjs-and-typescript" rel="noopener noreferrer"&gt;post&lt;/a&gt; on my website &lt;a href="https://surajsharma.net/" rel="noopener noreferrer"&gt;surajsharma.net&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I had a personal website before that was a single page static website built using HTML5, &lt;br&gt;
&lt;a href="https://materializecss.com" rel="noopener noreferrer"&gt;materialize&lt;/a&gt;, and jquery. It is still there on Heroku &lt;a href="http://suraj-sharma.herokuapp.com/" rel="noopener noreferrer"&gt;click here →&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have been working on React for more than a year now. One day I thought of redesigning &lt;br&gt;
my blog using React and Typescript but React has a major problem in terms of SEO, because of &lt;br&gt;
client-side rendering, search engines' bot are unable to scrape content from websites resulting &lt;br&gt;
in zero organic views.&lt;/p&gt;

&lt;h4&gt;
  
  
  These were the requirements I had for my new personal website :
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;support for blog posts&lt;/li&gt;
&lt;li&gt;Typescript support😘&lt;/li&gt;
&lt;li&gt;SEO friendly (must have)&lt;/li&gt;
&lt;li&gt;Progressive Web App (everyone is doing it why not me)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Research
&lt;/h4&gt;

&lt;p&gt;I have read about React frameworks Nextjs and Gatsby before, they are static site generators on &lt;br&gt;
the build time, which means the website has static HTML and CSS files with fully loaded content &lt;br&gt;
from the server itself, unlike React where contents are generated on the client-side that is not &lt;br&gt;
the best option for blog websites.&lt;/p&gt;

&lt;h4&gt;
  
  
  I chose Nextjs over Gatsby because of the two reasons:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Option for server-side rendering on every request,&lt;/li&gt;
&lt;li&gt;Serverless support.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Is TypeScript supported?
&lt;/h4&gt;

&lt;p&gt;Yes, Nextjs has the support for TypeScript&lt;/p&gt;

&lt;h4&gt;
  
  
  Development
&lt;/h4&gt;

&lt;p&gt;I kick started my project with Material UI's &lt;a href="https://github.com/mui-org/material-ui/tree/master/examples/nextjs-with-typescript" rel="noopener noreferrer"&gt;nextjs-with-typescript example&lt;/a&gt;. &lt;/p&gt;

&lt;h4&gt;
  
  
  Whether to use Headless CMS or Markdown files for writing blogs?
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="nx"&gt;The&lt;/span&gt; &lt;span class="nx"&gt;choice&lt;/span&gt; &lt;span class="nx"&gt;was&lt;/span&gt; &lt;span class="nx"&gt;easy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Markdown&lt;/span&gt;&lt;span class="err"&gt;🏆&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Opensource projects like Babel, Nextjs and many other projects use Markdown files to create &lt;br&gt;
their blog posts so the choice was clear, then came how to render markdown files to JSX? &lt;/p&gt;

&lt;p&gt;For the time being, I'm using the &lt;a href="https://www.npmjs.com/package/markdown-to-jsx" rel="noopener noreferrer"&gt;markdown-to-JSX&lt;/a&gt; &lt;br&gt;
library (I might migrate to MDX in future because of its capabilities to import react components on markdown &lt;br&gt;
files and later embed them on jsx files to demonstrate live examples).&lt;/p&gt;

&lt;h4&gt;
  
  
  To Summarize, following framework and libraries are being used to complete the development of the website:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Nextjs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://material-ui.com/" rel="noopener noreferrer"&gt;React Material UI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/markdown-to-jsx" rel="noopener noreferrer"&gt;Markdown to JSX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://highlightjs.org/" rel="noopener noreferrer"&gt;HighLightjs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.mongodb.com/cloud/atlas" rel="noopener noreferrer"&gt;MongoDB Atlas&lt;/a&gt; to store email and name of subscribers who joined my newsletter. &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://zeit.co/" rel="noopener noreferrer"&gt;Zeit Now&lt;/a&gt;- by default websites get the HTTPS support&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Lighthouse Audit Report
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://lighthouse-dot-webdotdevsite.appspot.com//lh/html?url=https%3A%2F%2Fsurajsharma.net%2Fblog%2Fpersonal-blog-built-using-nextjs-and-typescript" rel="noopener noreferrer"&gt;View Report&lt;/a&gt;&lt;br&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%2Flmxruc1t94kp4bdsf5ll.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%2Flmxruc1t94kp4bdsf5ll.png" alt="Lighthouse Audit Report" width="792" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Plans for future enhancements:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Improve the UX&lt;/li&gt;
&lt;li&gt;Migrate to MDX&lt;/li&gt;
&lt;li&gt;Improve the lighthouse report for accessibility, and performance&lt;/li&gt;
&lt;li&gt;Progressive Web App&lt;/li&gt;
&lt;li&gt;Send weekly newsletter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PS: I have a &lt;a href="https://github.com/creativesuraj/surajsharma.net" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; where I push all the posts of this blog. &lt;br&gt;
If you find any mistake on my posts, please feel free to raise an issue or a pull request.&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>blog</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>A Login Form built using React Hooks</title>
      <dc:creator>Suraj Sharma</dc:creator>
      <pubDate>Sun, 01 Dec 2019 17:43:13 +0000</pubDate>
      <link>https://forem.com/creativesuraj/a-login-form-built-using-react-hooks-2ko2</link>
      <guid>https://forem.com/creativesuraj/a-login-form-built-using-react-hooks-2ko2</guid>
      <description>&lt;p&gt;Created a simple login form using &lt;strong&gt;React, Typescript and React Material UI&lt;/strong&gt; featuring &lt;code&gt;useReducer&lt;/code&gt; and &lt;code&gt;useEffect&lt;/code&gt; hooks.&lt;br&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%2Fsr01mm928gy47r88i1az.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%2Fsr01mm928gy47r88i1az.png" alt="Login Form" width="795" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A detailed article on &lt;a href="https://surajsharma.net/blog/react-login-form-typescript" rel="noopener noreferrer"&gt;How to build a React Login Form with Typescript and React hooks&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
