<?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: Vedant chidrawar</title>
    <description>The latest articles on DEV Community by Vedant chidrawar (@vedant01111).</description>
    <link>https://dev.to/vedant01111</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%2F4215506%2F7fc9aaa4-a6c6-405c-a214-38c943dff993.jpg</url>
      <title>DEV Community: Vedant chidrawar</title>
      <link>https://dev.to/vedant01111</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vedant01111"/>
    <language>en</language>
    <item>
      <title>Building an Agentic AI Assistant with LangGraph and MCP</title>
      <dc:creator>Vedant chidrawar</dc:creator>
      <pubDate>Thu, 29 Oct 2026 14:43:31 +0000</pubDate>
      <link>https://dev.to/vedant01111/building-an-agentic-ai-assistant-with-langgraph-and-mcp-j0</link>
      <guid>https://dev.to/vedant01111/building-an-agentic-ai-assistant-with-langgraph-and-mcp-j0</guid>
      <description>&lt;p&gt;A basic chatbot receives a question and generates a response. An AI agent can go further: it can select tools, execute actions, observe the results, and decide what to do next.&lt;/p&gt;

&lt;p&gt;I explored this approach in my &lt;strong&gt;Agentic AI Assistant with MCP Tools&lt;/strong&gt; project, built with Python, LangGraph, the Model Context Protocol (MCP), Groq, and Streamlit.&lt;/p&gt;

&lt;p&gt;The assistant supports multi-turn conversations and can use a sandboxed filesystem tool and a web-search tool. This article explains how the components fit together and what I learned about building tool-using AI systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. From chatbots to agents
&lt;/h2&gt;

&lt;p&gt;Consider a user asking:&lt;/p&gt;

&lt;p&gt;"Search for the latest LangGraph release notes and save a short summary in a text file."&lt;/p&gt;

&lt;p&gt;A simple chatbot might explain how to perform these steps. An agent can instead work through the task:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Interpret the user's request.&lt;/li&gt;
&lt;li&gt;Decide to use a web-search tool.&lt;/li&gt;
&lt;li&gt;Examine the search results.&lt;/li&gt;
&lt;li&gt;Summarize the relevant information.&lt;/li&gt;
&lt;li&gt;Use a filesystem tool to write the summary.&lt;/li&gt;
&lt;li&gt;Report the result to the user.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The important difference is that the application can coordinate multiple tool calls rather than generating only a text response.&lt;/p&gt;

&lt;p&gt;Tool use does not mean an agent is always correct. The model can choose an unsuitable tool, misunderstand results, or produce an inaccurate summary. The surrounding application must therefore control which actions are available and how they are executed.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. What does LangGraph do?
&lt;/h2&gt;

&lt;p&gt;LangGraph provides orchestration for agent workflows.&lt;/p&gt;

&lt;p&gt;In my project, the assistant uses a ReAct-style agent pattern. The model can alternate between reasoning about the request, selecting a tool, receiving its output, and deciding whether another action is needed.&lt;/p&gt;

&lt;p&gt;The simplified flow is:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;User request → Agent → Tool call → Tool result → Agent → Final response&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Some requests require only a final response. Others require multiple tool calls.&lt;/p&gt;

&lt;p&gt;The agent orchestration is handled through LangGraph's prebuilt agent functionality, while the Streamlit application provides the conversational interface.&lt;/p&gt;

&lt;p&gt;This separation is useful because the interface does not need to implement the agent's decision-making logic itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Why use the Model Context Protocol?
&lt;/h2&gt;

&lt;p&gt;Integrating every external tool directly into an agent can make the application tightly coupled to individual implementations.&lt;/p&gt;

&lt;p&gt;The Model Context Protocol (MCP) defines a standard way for applications to communicate with tool-providing servers and discover available capabilities.&lt;/p&gt;

&lt;p&gt;In this project, I use MCP to connect the agent to two separate servers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Filesystem server:&lt;/strong&gt; Lists, reads, and writes files inside a designated sandbox directory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search server:&lt;/strong&gt; Uses Tavily to perform web searches.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent uses &lt;code&gt;MultiServerMCPClient&lt;/code&gt; from &lt;code&gt;langchain-mcp-adapters&lt;/code&gt; to connect to the servers and retrieve their available tools.&lt;/p&gt;

&lt;p&gt;In the current implementation, the servers are launched as subprocesses and communicate over standard input/output (stdio).&lt;/p&gt;

&lt;p&gt;This architecture separates the agent's orchestration from the individual tool implementations. Adding another compatible server can extend the assistant's capabilities without placing every tool implementation directly inside the agent.&lt;/p&gt;

&lt;p&gt;MCP standardizes communication; it does not automatically make a tool safe. The application still needs to validate inputs, limit permissions, and control access to sensitive resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Understanding tool discovery
&lt;/h2&gt;

&lt;p&gt;Tool discovery allows the agent application to learn which operations a connected MCP server exposes.&lt;/p&gt;

&lt;p&gt;For example, the filesystem server provides operations for listing, reading, and writing files within its allowed directory. The search server exposes a web-search capability.&lt;/p&gt;

&lt;p&gt;The application retrieves these tools and makes them available to the agent.&lt;/p&gt;

&lt;p&gt;When a request arrives, the model can select an appropriate tool based on the request and the tool descriptions. The orchestration layer then routes the call to the correct server and returns its result to the agent.&lt;/p&gt;

&lt;p&gt;This approach is more flexible than writing a separate hard-coded branch for every possible user request.&lt;/p&gt;

&lt;p&gt;However, the model's choice should never be treated as authorization by itself. Tool execution must remain constrained by the application's actual permissions.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Adding memory to multi-turn conversations
&lt;/h2&gt;

&lt;p&gt;Without conversation history, a chatbot may struggle with follow-up questions such as "Now save that result to a file."&lt;/p&gt;

&lt;p&gt;My project uses LangGraph's &lt;code&gt;MemorySaver&lt;/code&gt; with a conversation-specific &lt;code&gt;thread_id&lt;/code&gt; to maintain state across turns.&lt;/p&gt;

&lt;p&gt;The application assigns a thread identifier to the session, allowing follow-up requests to access the relevant conversation history.&lt;/p&gt;

&lt;p&gt;This helps the agent understand references to earlier questions and results.&lt;/p&gt;

&lt;p&gt;There is an important distinction between in-memory conversation state and durable storage. An in-memory checkpointer is useful for a prototype, but its state should not be assumed to survive every process restart or to provide a permanent database-backed conversation archive.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Why sandboxing matters
&lt;/h2&gt;

&lt;p&gt;An AI agent that can read and write files needs stronger safeguards than a chatbot that only generates text.&lt;/p&gt;

&lt;p&gt;My filesystem tool restricts access to a designated sandbox directory and resolves requested paths against that directory. Paths that attempt to escape the sandbox, such as those containing traversal sequences, are rejected.&lt;/p&gt;

&lt;p&gt;This is an important defense because an agent may construct a path incorrectly or respond to an unsafe instruction.&lt;/p&gt;

&lt;p&gt;Other safeguards worth considering include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validating tool arguments before execution.&lt;/li&gt;
&lt;li&gt;Keeping API keys in environment variables rather than source code.&lt;/li&gt;
&lt;li&gt;Limiting network and filesystem permissions.&lt;/li&gt;
&lt;li&gt;Recording tool calls and errors for debugging.&lt;/li&gt;
&lt;li&gt;Requiring user confirmation for consequential actions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A sandbox is one layer of defense, not a guarantee of complete security.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Lessons from building the assistant
&lt;/h2&gt;

&lt;p&gt;This project helped me understand several practical aspects of agent development:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tool calling requires orchestration, not just a capable language model.&lt;/li&gt;
&lt;li&gt;MCP can separate tool providers from the agent that consumes them.&lt;/li&gt;
&lt;li&gt;Multi-turn memory helps the assistant interpret follow-up requests.&lt;/li&gt;
&lt;li&gt;Tool descriptions and return values influence how effectively the agent works.&lt;/li&gt;
&lt;li&gt;Filesystem access should be restricted and validated.&lt;/li&gt;
&lt;li&gt;Observability becomes increasingly important as workflows involve multiple tool calls.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Building an agentic assistant helped me explore how language models, workflow orchestration, and external tools can work together to complete multi-step tasks.&lt;/p&gt;

&lt;p&gt;LangGraph manages the agent workflow, MCP provides a consistent tool-integration layer, and Streamlit makes the system accessible through a chat interface.&lt;/p&gt;

&lt;p&gt;The most important lesson is that useful agents need more than tool access. They also need clear boundaries, reliable error handling, and careful control over what actions they are permitted to perform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project:&lt;/strong&gt; &lt;a href="https://github.com/Vedant01111/Agentic-AI-Assistant-with-MCP-tools" rel="noopener noreferrer"&gt;Explore Agentic AI Assistant with MCP Tools on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live demo:&lt;/strong&gt; &lt;a href="https://vedant-agentic-assistant.streamlit.app/" rel="noopener noreferrer"&gt;MCP-Assistant&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Technologies:&lt;/strong&gt; Python, LangGraph, MCP, Groq, Tavily, Streamlit, and Docker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Further reading:&lt;/strong&gt; &lt;a href="https://docs.langchain.com/oss/python/learn" rel="noopener noreferrer"&gt;LangChain and LangGraph learning resources&lt;/a&gt; · &lt;a href="https://modelcontextprotocol.io/" rel="noopener noreferrer"&gt;MCP documentation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>python</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Building a PDF Question-Answering Chatbot Using RAG and FastAPI</title>
      <dc:creator>Vedant chidrawar</dc:creator>
      <pubDate>Thu, 29 Oct 2026 14:39:38 +0000</pubDate>
      <link>https://dev.to/vedant01111/building-a-pdf-question-answering-chatbot-using-rag-and-fastapi-4o1p</link>
      <guid>https://dev.to/vedant01111/building-a-pdf-question-answering-chatbot-using-rag-and-fastapi-4o1p</guid>
      <description>&lt;p&gt;Large language models can explain concepts and generate useful responses, but they do not automatically know the contents of a private PDF uploaded by a user.&lt;/p&gt;

&lt;p&gt;A document question-answering application needs a way to retrieve relevant information from that document and provide it to the language model before generating an answer.&lt;/p&gt;

&lt;p&gt;That is the idea behind &lt;strong&gt;Retrieval-Augmented Generation (RAG)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In my PDF Chatbot project, I worked with a stack involving FastAPI, LangChain, FAISS, PostgreSQL, SQLAlchemy, Streamlit, and Docker. The application combines document retrieval with conversational question answering and persistent chat history.&lt;/p&gt;

&lt;p&gt;This article explains the architecture and some of the engineering decisions involved.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. What is RAG?
&lt;/h2&gt;

&lt;p&gt;RAG combines two main operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Retrieval:&lt;/strong&gt; Find information relevant to a user's question.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generation:&lt;/strong&gt; Give that information to a language model so it can formulate an answer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of relying entirely on information learned during model training, the application retrieves relevant passages from the uploaded documents.&lt;/p&gt;

&lt;p&gt;A typical workflow is:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PDF upload → Text extraction → Chunking → Embeddings → Vector search → Answer generation&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The quality of the final answer depends on more than the language model. If retrieval misses the relevant passage, the model may not have enough information to answer correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Preparing documents for retrieval
&lt;/h2&gt;

&lt;p&gt;A PDF is not automatically suitable for semantic search. Its text needs to be extracted and organized into manageable sections.&lt;/p&gt;

&lt;h3&gt;
  
  
  Text extraction and chunking
&lt;/h3&gt;

&lt;p&gt;The application processes uploaded PDFs and divides their content into smaller text chunks.&lt;/p&gt;

&lt;p&gt;Chunking is useful because embedding and retrieval systems generally work better with manageable pieces of text than with an entire long document treated as one unit.&lt;/p&gt;

&lt;p&gt;However, chunk size involves a trade-off:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Very small chunks may lose important context.&lt;/li&gt;
&lt;li&gt;Very large chunks may contain irrelevant information and make retrieval less precise.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The right strategy depends on the document structure and the questions users are likely to ask.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generating embeddings
&lt;/h3&gt;

&lt;p&gt;An embedding model converts text into numerical vectors that represent semantic information.&lt;/p&gt;

&lt;p&gt;In my project, local ONNX-based embeddings are used as part of the retrieval pipeline. Using a local embedding model can reduce dependence on an external embedding API, although model quality and deployment resource requirements still matter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Searching with FAISS
&lt;/h3&gt;

&lt;p&gt;FAISS provides vector similarity search. The application can use it to retrieve document chunks that are semantically related to a question.&lt;/p&gt;

&lt;p&gt;This is different from ordinary keyword matching: a semantic search system can find related passages even when the wording of the question differs from the original text.&lt;/p&gt;

&lt;p&gt;FAISS handles vector search; it is not itself the language model that generates the final answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Generating answers from retrieved context
&lt;/h2&gt;

&lt;p&gt;After retrieving relevant chunks, the application passes the available context and the user's question to the language model.&lt;/p&gt;

&lt;p&gt;A useful instruction is to answer using the supplied context and acknowledge when the retrieved material does not contain enough information.&lt;/p&gt;

&lt;p&gt;This reduces the risk of unsupported answers, but it cannot guarantee that hallucinations will never occur. Retrieval quality, prompt design, and answer validation all affect reliability.&lt;/p&gt;

&lt;p&gt;My project also uses history-aware retrieval so that follow-up questions can be rewritten using previous conversation turns.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;First question: "What does the document say about authentication?"&lt;/li&gt;
&lt;li&gt;Follow-up: "What are its main limitations?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The second question is ambiguous by itself. Conversation history can help the retrieval system understand that "its" refers to the authentication approach discussed previously.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Designing persistent conversation storage
&lt;/h2&gt;

&lt;p&gt;A chatbot becomes more useful when users can return to earlier conversations instead of losing their history whenever the interface reloads.&lt;/p&gt;

&lt;p&gt;I used SQLAlchemy ORM models to organize the application's relational data into three main entities.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Document&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stores document metadata, including the filename, page count, chunk count, and creation time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Conversation&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Associates a conversation with a document and stores its title and creation time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Message&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stores each message's role, content, source information, and creation time&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The relationships follow a straightforward structure:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Document → Conversations → Messages&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A document can have multiple conversations, and each conversation can contain multiple messages. Foreign keys maintain the associations between these records, while SQLAlchemy's ORM relationships make it easier to work with related objects in Python.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Message&lt;/code&gt; model also includes a JSON field for source information, allowing retrieved source details to be stored alongside the response.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Why separate vector search from relational storage?
&lt;/h2&gt;

&lt;p&gt;The application has two different data responsibilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FAISS&lt;/strong&gt; supports similarity search over embedded document chunks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt; stores structured application information such as document metadata, conversation records, and messages.&lt;/p&gt;

&lt;p&gt;Keeping these responsibilities separate makes the design easier to understand. Relational data can be queried and managed through SQLAlchemy, while vector search is handled by the retrieval component.&lt;/p&gt;

&lt;p&gt;The two systems still need consistent lifecycle management. For example, if a document is deleted or reprocessed, the application must handle its associated retrieval data and metadata appropriately.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Managing the application layers
&lt;/h2&gt;

&lt;p&gt;The project uses FastAPI for backend API functionality and Streamlit for the interactive interface.&lt;/p&gt;

&lt;p&gt;FastAPI provides a boundary for operations such as uploading documents and asking questions. Streamlit gives users a convenient way to interact with the application without building a separate JavaScript frontend.&lt;/p&gt;

&lt;p&gt;SQLAlchemy sessions also require careful handling. A session should have a clear lifecycle, and database changes that need to persist must be committed. Closing a session alone does not guarantee that pending changes are committed.&lt;/p&gt;

&lt;p&gt;Docker provides a consistent packaging approach for running the application and its dependencies, while deployment configuration must still account for environment variables, database connectivity, and persistent storage.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Lessons from building a RAG application
&lt;/h2&gt;

&lt;p&gt;This project reinforced several important ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieval quality is just as important as answer generation.&lt;/li&gt;
&lt;li&gt;Chunking affects both relevance and context.&lt;/li&gt;
&lt;li&gt;Conversation history can help interpret follow-up questions.&lt;/li&gt;
&lt;li&gt;Source references improve traceability, but do not independently prove an answer is correct.&lt;/li&gt;
&lt;li&gt;Persistent chat history needs a clear relational data model.&lt;/li&gt;
&lt;li&gt;Database sessions and application resources need explicit lifecycle management.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Building a PDF chatbot involves more than connecting a language model to a file. It requires document processing, semantic retrieval, context-aware generation, persistent storage, and a user interface that brings the components together.&lt;/p&gt;

&lt;p&gt;RAG provides a practical foundation for document-grounded question answering, but reliable results still require careful testing of retrieval relevance, answer correctness, and failure cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Technologies:&lt;/strong&gt; FastAPI, LangChain, FAISS, PostgreSQL, SQLAlchemy, Streamlit, ONNX embeddings, and Docker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live Demo:&lt;/strong&gt;&lt;a href="https://pdfqa-frontend.onrender.com/" rel="noopener noreferrer"&gt;PDF Chatbot with RAG&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project:&lt;/strong&gt; &lt;a href="https://github.com/Vedant01111/PDF-Q-A-Chatbot-using-RAG" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Further reading:&lt;/strong&gt; &lt;a href="https://docs.langchain.com/oss/python/learn" rel="noopener noreferrer"&gt;LangChain learning resources&lt;/a&gt; · &lt;a href="https://docs.sqlalchemy.org/en/20/orm/" rel="noopener noreferrer"&gt;SQLAlchemy ORM documentation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>python</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>ShopSphere</title>
      <dc:creator>Vedant chidrawar</dc:creator>
      <pubDate>Thu, 29 Oct 2026 14:35:24 +0000</pubDate>
      <link>https://dev.to/vedant01111/shopsphere-23pm</link>
      <guid>https://dev.to/vedant01111/shopsphere-23pm</guid>
      <description>&lt;h1&gt;
  
  
  Building a Full-Stack E-commerce Platform with Next.js, Express, PostgreSQL, and Redis
&lt;/h1&gt;

&lt;p&gt;A full-stack e-commerce application is more than a product listing page and a shopping cart. It needs to manage users, protect private operations, process orders, handle payments, and keep inventory consistent.&lt;/p&gt;

&lt;p&gt;While building &lt;strong&gt;ShopSphere&lt;/strong&gt;, I worked on bringing these pieces together in a single application. The project uses Next.js and TypeScript for the frontend, Node.js and Express for backend APIs, PostgreSQL with Prisma for data persistence, Redis for caching, and Razorpay for payment processing.&lt;/p&gt;

&lt;p&gt;In this article, I'll explain the architecture, important engineering decisions, and lessons from building the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Understanding the architecture
&lt;/h2&gt;

&lt;p&gt;ShopSphere separates the user interface from the backend services.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js and TypeScript:&lt;/strong&gt; Provide the application interface, product pages, cart, checkout, order history, and admin dashboard.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node.js and Express:&lt;/strong&gt; Handle API requests, authentication, validation, and business logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL and Prisma:&lt;/strong&gt; Store structured application data and provide an ORM for database operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redis:&lt;/strong&gt; Cache frequently requested product information and selected dashboard results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Razorpay:&lt;/strong&gt; Handles the payment checkout flow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Separating these responsibilities makes the application easier to maintain. For example, the frontend can display products without needing to know how the backend queries PostgreSQL.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Authentication and authorization are different
&lt;/h2&gt;

&lt;p&gt;One important lesson from ShopSphere was that authentication and authorization solve different problems.&lt;/p&gt;

&lt;p&gt;Authentication answers: &lt;strong&gt;Who is the user?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Authorization answers: &lt;strong&gt;What is this user allowed to do?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The application uses JWT-based authentication with short-lived access tokens and refresh tokens stored in HTTP-only cookies. The access token is sent through the &lt;code&gt;Authorization&lt;/code&gt; header when calling protected APIs.&lt;/p&gt;

&lt;p&gt;Role-based authorization adds another layer. A customer should be able to manage their cart and view their orders, while administrative operations—such as managing the product catalog—must be restricted to authorized administrators.&lt;/p&gt;

&lt;p&gt;The backend must enforce these permissions. Hiding an admin button in the frontend is not sufficient because a user can still attempt to call the API directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Improving response times with Redis
&lt;/h2&gt;

&lt;p&gt;Product listings and product details are requested frequently, so repeatedly querying the database for unchanged information can introduce unnecessary work.&lt;/p&gt;

&lt;p&gt;ShopSphere uses Redis to cache selected product data.&lt;/p&gt;

&lt;p&gt;A simplified cache-aside flow looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check whether the requested data exists in Redis.&lt;/li&gt;
&lt;li&gt;If it exists, return the cached result.&lt;/li&gt;
&lt;li&gt;If it does not, query PostgreSQL.&lt;/li&gt;
&lt;li&gt;Store the result in Redis and return it.&lt;/li&gt;
&lt;li&gt;When the underlying product data changes, invalidate the affected cache entries.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The last step is important. Caching without invalidation can cause users to see outdated prices, product information, or stock details.&lt;/p&gt;

&lt;p&gt;Caching is useful for frequently read data, but it should not replace database validation for operations such as checkout.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Handling payments safely
&lt;/h2&gt;

&lt;p&gt;Payment processing requires particular care because an incorrect implementation can leave an order and its payment status inconsistent.&lt;/p&gt;

&lt;p&gt;The ShopSphere checkout flow creates an order in a pending state and initiates a Razorpay order. After the checkout process, the backend verifies the payment signature before marking the order as paid.&lt;/p&gt;

&lt;p&gt;The backend also uses a Prisma database transaction to update the payment-related order state and decrement inventory atomically.&lt;/p&gt;

&lt;p&gt;Why does this matter?&lt;/p&gt;

&lt;p&gt;Imagine an order contains the last available unit of a product. Payment verification and inventory updates must be handled carefully so that concurrent checkouts do not accidentally oversell stock.&lt;/p&gt;

&lt;p&gt;A database transaction helps ensure that related database changes succeed together or roll back together. It does not, by itself, make an external payment operation atomic with the database; payment verification and failure handling still need to be designed correctly.&lt;/p&gt;

&lt;p&gt;For a production system, I would also pay close attention to duplicate callbacks, idempotency, transaction failures, and reconciliation between the payment provider and the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Making the application useful for administrators
&lt;/h2&gt;

&lt;p&gt;ShopSphere also includes an administrative dashboard that displays information such as revenue, order status, top products, low-stock alerts, and customer counts.&lt;/p&gt;

&lt;p&gt;This transforms the application from a basic shopping interface into a tool for managing the business.&lt;/p&gt;

&lt;p&gt;The dashboard combines backend aggregation with frontend visualizations. Frequently requested summary data can be cached briefly, provided that the application handles invalidation and freshness appropriately.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. What I learned
&lt;/h2&gt;

&lt;p&gt;Building ShopSphere reinforced several practical lessons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication must be complemented by server-side authorization.&lt;/li&gt;
&lt;li&gt;Cache invalidation is part of the feature, not an afterthought.&lt;/li&gt;
&lt;li&gt;Payment status should be verified by the backend rather than trusted from the browser.&lt;/li&gt;
&lt;li&gt;Related inventory and order updates require careful transaction handling.&lt;/li&gt;
&lt;li&gt;A clear separation between frontend, API, and persistence responsibilities makes debugging easier.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;ShopSphere helped me understand how frontend development, backend APIs, databases, caching, authentication, and payment integrations work together in a full-stack product.&lt;/p&gt;

&lt;p&gt;The biggest takeaway is that a working interface is only one part of a reliable application. Correct data handling, security, and failure management are equally important.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project:&lt;/strong&gt; &lt;a href="https://shop-sphere-gilt-gamma.vercel.app/" rel="noopener noreferrer"&gt;ShopShpere&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live Demo:&lt;/strong&gt;&lt;a href="https://github.com/Vedant01111/ShopSphere" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Technologies:&lt;/strong&gt; Next.js, TypeScript, Express, PostgreSQL, Prisma, Redis, and Razorpay.&lt;/p&gt;

</description>
      <category>python</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
