# Gaurav Sharma — Full Stack, Flutter & AI Engineer Gaurav Sharma is a Full Stack (MERN) Developer, Flutter Developer and AI Engineer who builds production web applications with React, Next.js, Node.js, Express and MongoDB, cross-platform mobile apps with Flutter, and AI-powered features using LLM APIs such as Google Gemini and Groq. ## Skills - **Languages:** C++, JavaScript (ES6+), TypeScript, Dart, SQL - **Frontend:** React 19, Next.js, TypeScript, Vite, React Router, Tailwind CSS, Zustand, HTML5 & CSS3 - **Mobile:** Flutter, Dart, Provider, Bloc, MVVM, Firebase, REST APIs - **Backend:** Node.js, Express.js, REST APIs, JWT Auth, bcryptjs, Socket.IO, Supabase - **Databases:** MongoDB, Mongoose, MySQL, Supabase (Postgres), SQL - **AI & Automation:** AI Agents, Content-generation Agents, Google Gemini API, Groq SDK, n8n Workflows, Workflow Automation, Scheduled Jobs (node-cron), Structured Output (Zod), Prompt Engineering - **Tools & Cloud:** Git & GitHub, Vercel, Postman, VS Code, Google Cloud, Clerk, ImageKit ## Services ### MERN stack & Next.js developer for hire URL: https://www.gaurav-sharma.in/services/mern-stack-developer Gaurav Sharma is a freelance MERN stack and Next.js developer in Noida, India, who builds production web apps with React, Next.js, TypeScript, Node.js, Express and MongoDB: REST APIs with JWT or Clerk auth, admin dashboards, and real-time features with Socket.IO, deployed on Vercel. Deliverables: REST APIs & auth (JWT, Clerk); Dashboards & admin panels; Real-time features with Socket.IO. Stack: React, Next.js, TypeScript, Node.js, Express.js, MongoDB, Mongoose, Supabase, Socket.IO, Tailwind CSS, Vercel. **Can I hire Gaurav Sharma as a freelance MERN stack developer?** Yes. Gaurav takes freelance and contract MERN stack and Next.js work, remotely or in Noida and Delhi NCR. Send a short brief to gauravsharma.dev@outlook.com. **Does Gaurav Sharma build with Next.js or plain React?** Both. Gaurav uses Next.js when a project needs SEO, server rendering or API routes in one codebase, and React with Vite plus an Express API for dashboards and internal tools. **Can Gaurav Sharma add real-time features to a web app?** Yes. Gaurav built PingChat, a real-time chat app using Socket.IO, Express and MongoDB, and can add live chat, notifications or presence to an existing app. ### Flutter app developer for iOS & Android URL: https://www.gaurav-sharma.in/services/flutter-app-developer Gaurav Sharma is a Flutter developer in Noida, India, who builds cross-platform iOS and Android apps from one Dart codebase, using MVVM architecture with Provider or Bloc state management and Firebase or REST API backends. Deliverables: Provider / Bloc state management; Firebase & REST integration; Video, quizzes & content flows. Stack: Flutter, Dart, Provider, Bloc, MVVM, Firebase, REST APIs, Git. **Does Gaurav Sharma build Flutter apps for both iOS and Android?** Yes. Gaurav builds cross-platform Flutter apps from a single Dart codebase for iOS and Android. **Which state management does Gaurav Sharma use in Flutter?** Provider for small and medium apps and Bloc when business logic grows, both inside an MVVM architecture so screens, state and data stay separate. **Can Gaurav Sharma connect a Flutter app to Firebase or an existing API?** Yes. Gaurav connects Flutter apps to Firebase services (auth, Firestore, storage) or to an existing REST API, with proper loading and error states. ### AI engineer for LLM features & AI agents URL: https://www.gaurav-sharma.in/services/ai-engineer Gaurav Sharma is an AI engineer in Noida, India, who adds LLM features and AI agents to web apps using the Google Gemini and Groq APIs, with Zod-validated structured output so the app always receives well-formed data. Gaurav is an AI Trainee at Garage Collective and built HireMate and Atlass CRM. Deliverables: AI agents that automate real work; Structured output with Zod; Resume, CRM & content AI tools. Stack: Google Gemini API, Groq SDK, Zod, Prompt Engineering, Node.js, Next.js, TypeScript, n8n. **What AI work has Gaurav Sharma shipped?** An AI content-generation agent at Garage Collective that cut manual content effort by roughly 40%, HireMate (a Gemini-powered resume and job-description skill-gap analyzer), and Groq-powered insights in Atlass CRM. **Which LLM APIs does Gaurav Sharma use?** Mainly Google Gemini (via @google/genai) and Groq, with Zod schemas to validate structured JSON output, integrated into Node.js, Express and Next.js backends. **Can Gaurav Sharma add an AI feature to my existing app?** Yes. Gaurav integrates LLM features such as summaries, classification, content generation and analysis into existing React, Next.js or Node.js apps. Email a short brief to gauravsharma.dev@outlook.com. ### AI automation & n8n workflow developer URL: https://www.gaurav-sharma.in/services/ai-automation-developer Gaurav Sharma is an AI automation developer in Noida, India, who builds n8n workflows, scheduled Node.js jobs and LLM-powered agents that take over repetitive work. At Garage Collective, Gaurav built an AI content agent that produces daily Instagram, LinkedIn and blog content and cut manual effort by roughly 40%. Deliverables: n8n workflows; Scheduled jobs (node-cron); Social & content pipelines. Stack: n8n, node-cron, Node.js, Google Gemini API, Groq SDK, Supabase, REST APIs, Webhooks. **Does Gaurav Sharma build n8n automations?** Yes. Gaurav builds n8n workflows and scheduled Node.js jobs that connect tools through APIs and webhooks, with LLM steps where content or judgement is needed. **What automation has Gaurav Sharma built?** An AI content-generation agent at Garage Collective that produces daily Instagram, LinkedIn and blog content and reduced manual content-creation effort by roughly 40%. **Can Gaurav Sharma automate social media content?** Yes. Gaurav has built a production pipeline that generates daily social and blog content with LLMs. Email gauravsharma.dev@outlook.com to discuss your workflow. ## Strengths - **Problem Solving:** Tracked down and fixed post-integration bugs across frontend and backend at Garage Collective, backed by solid DSA fundamentals in C++. - **Clean, Efficient Code:** A reusable CVA-based component system in Atlass CRM, Zod-validated AI output in HireMate, and MVVM with Provider and Bloc in Flutter. - **Clear Communication:** Every project here ships with a plain-English case study, and the FAQ answers questions before you ask them. - **Team Collaboration:** Shipped features into shared codebases for internal tools and multi-tenant SaaS products at Garage Collective. - **Analytical Thinking:** Built Recharts analytics dashboards and redesigned Excel export reporting for a campaign-management platform. - **Fast Learner:** Went from Flutter and Dart to Next.js, Supabase and LLM agents across two roles in under a year. - **Design-System Thinking:** Reusable UI kits with Tailwind, CVA, clsx and HeroUI, plus a genuine interest in UI/UX design. - **Ownership:** Took an AI content agent from idea to deployment, cutting manual content work by roughly 40%. - **User-First Thinking:** Built PingChat's interface on React Aria Components for keyboard and screen-reader support. ## Experience ### AI Trainee, Garage Collective (2026-08 to Present) Building AI agents and full-stack features across internal tools and multi-tenant SaaS products with Next.js, React, TypeScript and Supabase. - Developed and deployed an AI content-generation agent that produces daily Instagram, LinkedIn and blog content, reducing manual content-creation effort by roughly 40%. - Shipped UTM auto-tagging and partner-portal link generation for a multi-tenant affiliate-marketing SaaS platform using Next.js and Supabase. - Extended an internal zero-knowledge credential management tool with credential revocation and multi-currency vendor billing. - Integrated a new analytics dashboard module into a campaign-management platform, redesigned Excel export reporting, and resolved post-integration bugs across frontend and backend. ## Education - Bachelor of Technology (B.Tech), Computer Science Engineering, JECRC University, Jaipur, Rajasthan (2022 to 2026) - Senior Secondary (12th), CBSE Board, Rainbow School, Jaipur, Rajasthan (2021 to 2022) ## Certifications - Google Cloud Computing Foundations Certificate - Soft Skills Certificate ## Frequently asked questions ### Who is Gaurav Sharma? Gaurav Sharma is a Full Stack (MERN) Developer, Flutter Developer and AI Engineer based in Noida, India. Gaurav builds web apps with React, Next.js, Node.js, Express and MongoDB, mobile apps with Flutter, and AI features with the Google Gemini and Groq APIs. Gaurav is currently an AI Trainee at Garage Collective. ### What technologies does Gaurav Sharma work with? React, Next.js, TypeScript, Node.js, Express.js, MongoDB, MySQL, Supabase, Socket.IO, Flutter and Dart, plus AI integration with Google Gemini, Groq and n8n automation. Tooling includes Git, GitHub, Vercel, Postman and Firebase. ### Does Gaurav Sharma build mobile apps? Yes. Gaurav builds cross-platform mobile apps with Flutter and Dart, using MVVM architecture with Provider or Bloc state management and Firebase or REST API backends. ### What AI projects has Gaurav Sharma built? Gaurav built an AI content-generation agent at Garage Collective that cut manual content effort by roughly 40%, Atlass CRM with Groq-powered insights, and HireMate, a resume and job-description skill-gap analyzer using Google Gemini with Zod-validated structured output. ### Does Gaurav Sharma build AI automations? Yes. Gaurav builds AI agents and workflow automations, including an AI content-generation agent at Garage Collective that produces daily Instagram, LinkedIn and blog content and cut manual effort by roughly 40%. The toolkit includes Google Gemini, Groq, n8n workflows, scheduled jobs with node-cron, and Zod-validated structured LLM output. ### Can I hire Gaurav Sharma as a freelance developer in Noida? Yes. Gaurav takes freelance and contract work for MERN and Next.js web apps, Flutter mobile apps, AI agents and n8n workflow automation, remotely or in Noida and Delhi NCR. Email gauravsharma.dev@outlook.com with a short brief. ### Is Gaurav Sharma available for hire? Open to full-time full-stack, Flutter and AI engineering roles, internships, and freelance projects. The fastest way to reach Gaurav is by email at gauravsharma.dev@outlook.com. ### Where did Gaurav Sharma study? Gaurav completed a Bachelor of Technology (B.Tech) in Computer Science Engineering at JECRC University, Jaipur, from 2022 to 2026, and holds the Google Cloud Computing Foundations Certificate. --- # Project: Atlass CRM — AI-Powered CRM Platform URL: https://www.gaurav-sharma.in/projects/atlass-crm Live demo: https://thecrm-frontend.onrender.com Source code: https://github.com/iblamethebackend/TheCRM Tech: React 19, Vite, Express.js, MongoDB, Groq, Tailwind CSS Atlass CRM is a full-stack customer relationship management platform that helps teams track leads and deals on a drag-and-drop Kanban board, see pipeline analytics, and get AI-generated insights from their CRM data. ## What it does - **Visual deal pipeline.** Leads and deals move between stages on a drag-and-drop Kanban board built with `@dnd-kit`. - **Analytics dashboards.** Pipeline and performance charts built with Recharts. - **AI insights.** The Groq SDK turns raw CRM data into readable, actionable insights. - **Secure accounts.** JWT authentication with passwords hashed using bcryptjs. ## How it is built | Layer | Technology | | --- | --- | | Frontend | React 19, Vite, Tailwind CSS | | UI system | CVA, clsx, React Hook Form, Sonner toasts | | Backend | Express.js REST API | | Database | MongoDB with Mongoose | | Auth | JWT, bcryptjs | | AI | Groq SDK | ## Engineering notes The UI is a reusable component system built on Tailwind CSS with class-variance-authority (CVA) and clsx, so buttons, inputs, and cards share variants instead of duplicating styles. Forms use React Hook Form for fast, controlled validation, and Sonner provides non-blocking toast feedback. --- # Project: PingChat — Real-Time Chat Application URL: https://www.gaurav-sharma.in/projects/pingchat Live demo: https://chat-app-6oi7.onrender.com Source code: https://github.com/iblamethebackend/chat-app Tech: React, Socket.IO, Express.js, MongoDB, Clerk, Zustand PingChat is a real-time chat application where messages are delivered instantly over WebSockets with Socket.IO, persisted in MongoDB, and secured with Clerk authentication. ## What it does - **Instant messaging.** Socket.IO pushes new messages to every participant the moment they are sent. - **Persistent history.** Conversations are stored in MongoDB through Mongoose. - **Media sharing.** Images upload through Multer to ImageKit for optimised delivery. - **Scheduled jobs.** `node-cron` runs recurring background tasks on the server. - **Secure sign-in.** Authentication and sessions are handled by Clerk. ## How it is built | Layer | Technology | | --- | --- | | Frontend | React, Vite, Tailwind CSS | | UI & accessibility | HeroUI, React Aria Components | | State | Zustand | | Real-time | Socket.IO | | Backend | Express.js, node-cron, Multer | | Database | MongoDB with Mongoose | | Auth & media | Clerk, ImageKit | ## Engineering notes Accessibility was a first-class goal. React Aria Components provide keyboard navigation, focus management, and screen-reader semantics, while Zustand keeps chat state small and predictable across the app. --- # Project: HireMate — AI Resume Checker & JD Skill-Gap Analyzer URL: https://www.gaurav-sharma.in/projects/hiremate Live demo: https://hire-mate-rouge.vercel.app Source code: https://github.com/iblamethebackend/HireMate Tech: React, Express.js, Google Gemini, Zod, MongoDB, JWT HireMate is an AI career tool that evaluates a resume or self-description against a job description, surfaces the exact skill gaps, and generates a preparation plan with technical and behavioural interview questions. ## What it does 1. The user pastes a job description and uploads a resume or writes a short self-description. 2. Google's Gemini API (`@google/genai`) analyses both texts. 3. The response is validated against a **Zod schema**, so the app always receives well-formed, structured data. 4. HireMate shows a skill-gap breakdown, a step-by-step preparation plan, and likely technical and behavioural interview questions with answers. ## Why structured output matters LLMs sometimes return malformed or incomplete JSON. Validating every response with Zod means the UI never renders broken data, and invalid responses can be retried automatically instead of crashing the page. ## How it is built | Layer | Technology | | --- | --- | | Frontend | React, Vite | | Backend | Express.js | | AI | Google Gemini API (`@google/genai`) | | Validation | Zod | | Database | MongoDB with Mongoose | | Auth | JWT | --- # Placement Series: JavaScript Handwritten Notes for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/javascript-handwritten-notes Author: Gaurav Sharma Published: 2026-10-20 Updated: 2026-10-20 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style JavaScript notes for placements and interviews: hoisting, closures, this, prototypes, promises, the event loop, polyfills and output-based questions, explained in English with Hinglish. Topics: - How JavaScript runs: engine, runtime, JIT - var, let, const and scope - Hoisting and the Temporal Dead Zone - Primitive vs reference data types - Type coercion, == vs ===, truthy and falsy - Optional chaining, nullish coalescing, spread, rest, destructuring - Functions, arrow functions, higher-order functions, callbacks - Execution context and the call stack - Closures, with interview questions - The this keyword - call, apply, bind and their polyfill - Objects: copying, freezing, methods - Array methods: map, filter, reduce and more - Prototypes, inheritance and classes - Callbacks to Promises - async/await and Promise.all, allSettled, race, any - The event loop: microtasks vs macrotasks - DOM events: bubbling, capturing, delegation - Debounce, throttle, currying, memoization - Polyfills: map, filter, reduce, Promise.all - ES6+ goodies: Map, Set, modules, storage - Output-based questions - Last-minute revision cheat sheet These are the JavaScript notes I wish I had before my first frontend interview. Each topic fits on one page: the definition you should say out loud, a small code example you can run, the trap that catches most people, and the question interviewers usually ask about it. ## What makes these JavaScript notes different? - **One concept per page.** No 200-page textbook. Each page is a quick revision you can finish in a few minutes. - **Colour-coded highlights.** Yellow for definitions, pink for "asked in almost every interview", green for best practices, orange for traps. - **Hinglish where it helps.** Closures, `this` and the event loop get a simple explanation in Hinglish next to the English definition. - **Predict-the-output practice.** The output-based questions are the ones that show up in online assessments and first-round interviews. ## How should you use these JavaScript notes? Read a page, run its snippet in the browser console, and guess the output before you look at the answer. In the last week before an interview, the final page is a one-page cheat sheet with the ten questions to be able to explain. Next in the series: the [React handwritten notes](/placement/react-handwritten-notes) (Part 3) build on these JavaScript basics, and the [C++ handwritten notes](/placement/cpp-handwritten-notes) cover DSA-round C++ in the same format. Ready to test yourself? Try the [Top 50 JavaScript interview questions with answers](/placement/javascript-interview-questions), a free PDF with a short answer to say and a detailed explanation for every question. ### Are these JavaScript notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for placements. ### Who are these JavaScript notes for? Students preparing for campus placements and freshers preparing for frontend, MERN or full-stack interviews. They assume you have written some JavaScript before and want to revise the concepts interviewers actually ask about. ### Why are the notes in Hinglish? Definitions and code are in English, the way you will say them in an interview. The harder ideas, like closures and the event loop, also get a short Hinglish explanation in a purple box, because that is how many of us actually understand things. ### Can I print these notes? Yes. Every page is A4, so the PDF prints cleanly at home or at a print shop. --- # Placement Series: C++ Handwritten Notes for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/cpp-handwritten-notes Author: Gaurav Sharma Published: 2026-10-21 Updated: 2026-10-21 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style C++ notes for placements and interviews: pointers, references, memory, OOP, virtual functions and vtables, templates, STL and smart pointers, explained in English with Hinglish. Topics: - What C++ is and how code compiles: preprocessor, compiler, assembler, linker - Data types, sizes, integer overflow and type casting - Operators, bit tricks and control-flow traps - Functions: pass by value, reference and pointer - Pointers and pointer arithmetic - Pointer vs reference, const with pointers - Memory: stack vs heap, new/delete, leaks, dangling pointers - Arrays and strings - OOP: class, object, access specifiers, struct vs class - Constructors, destructors and their call order - Copy constructor, shallow vs deep copy, Rule of 3/5 - this, static, friend and const members - Inheritance and the diamond problem - Function and operator overloading - Virtual functions, vtable and vptr - Abstract classes and virtual destructors - Templates - STL and vector - map, set, unordered_map, stack, queue, priority_queue - STL algorithms, lambdas and custom comparators - Smart pointers and move semantics - Exceptions and keyword meanings - Output-based questions - Last-minute revision cheat sheet C++ is still the language most campus placement tests and DSA rounds expect, and the theory round almost always asks about pointers, OOP and virtual functions. These notes cover exactly that, one concept per page, in the order you should learn it. ## What makes these C++ notes different? - **Pointers explained with pictures.** Hand-drawn diagrams for pointers, stack vs heap, shallow vs deep copy and the vtable. - **The OOP questions interviewers ask.** Why a copy constructor takes a reference, why you need a virtual destructor, how the diamond problem is solved. - **STL you will actually use.** A table of every common container with its time complexity, plus the traps, like `map[key]` silently inserting a key. - **Hinglish where it helps.** Every hard concept gets a short Hinglish explanation next to the English definition. ## How should you use these C++ notes? Compile and run every snippet, and guess the output before you read the answer. The output-based questions near the end are the kind that appear in online assessments. The last page is a one-page cheat sheet for the night before the interview. Applying for web roles as well? The [JavaScript handwritten notes](/placement/javascript-handwritten-notes) are Part 1 of the same series. Ready to test yourself? Try the [Top 50 C++ interview questions with answers](/placement/cpp-interview-questions), a free PDF with a short answer to say and a detailed explanation for every question. ### Are these C++ notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for placements. ### Do these notes cover OOP in C++ for interviews? Yes. Ten of the 26 pages are OOP: classes, constructors, copy constructors and deep copy, static and friend, inheritance and the diamond problem, operator overloading, virtual functions with the vtable and vptr, abstract classes and virtual destructors. ### Are these notes enough for DSA in C++? They cover the C++ and STL you need to write DSA solutions: vector, map, set, unordered_map, stack, queue, priority_queue, sort with custom comparators, lower_bound and lambdas. They do not teach DSA algorithms themselves. ### Can I print these notes? Yes. Every page is A4, so the PDF prints cleanly at home or at a print shop. --- # Placement Series: React Handwritten Notes for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/react-handwritten-notes Author: Gaurav Sharma Published: 2026-10-21 Updated: 2026-10-21 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style React notes for placements and frontend interviews: JSX, state, useEffect, useRef, memoization, Context, useReducer, custom hooks, virtual DOM, React Router, Redux Toolkit, React 18 and 19, and SSR, explained in English with Hinglish. Topics: - What React is and why companies use it - JSX rules and what JSX compiles to - Components, props and children - State, useState and batching - Lists, keys and conditional rendering - Events and forms: controlled vs uncontrolled inputs - useEffect, dependency arrays and cleanup - Class lifecycle methods mapped to hooks - useRef and refs - Virtual DOM, reconciliation and Fiber - Re-renders, React.memo, useMemo, useCallback - Context API and prop drilling - useReducer - Rules of hooks and custom hooks - Lifting state up and component patterns - React Router - Data fetching, race conditions and TanStack Query - State management: Context vs Redux Toolkit vs Zustand - Performance and code splitting - React 18 and React 19 features - Error boundaries, portals and StrictMode - CSR vs SSR vs SSG, and hydration - Output-based questions - Last-minute revision cheat sheet Most React interviews for freshers circle the same ten ideas: state vs props, the `useEffect` dependency array, keys, the virtual DOM, re-renders and memoization, Context vs Redux, and how you would speed up a slow page. These notes give each of them one page, with a small example and the trap that catches people. ## What makes these React notes different? - **Built around interview questions.** Pink boxes hold the questions that come up again and again, with answers you can say out loud. - **The traps that cost marks.** Why `setCount(count + 1)` three times only adds one, why `{items.length && }` prints a 0, and why your effect runs twice in development. - **Modern React.** Function components and hooks throughout, React 18 and 19 features, and how Next.js fits in with SSR and Server Components. - **Hinglish where it helps.** Reconciliation, context and lifting state get a short Hinglish explanation next to the English definition. ## How should you use these React notes? Create a small Vite app and run each snippet as you read. Try the output-based questions before looking at the answers, then use the last page as a one-page revision sheet before the interview. This is Part 3 of the series. Start with the [JavaScript handwritten notes](/placement/javascript-handwritten-notes) if you want to revise closures, promises and the event loop first. Ready to test yourself? Try the [Top 50 React interview questions with answers](/placement/react-interview-questions), a free PDF with a short answer to say and a detailed explanation for every question. ### Are these React notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for frontend and MERN interviews. ### Do these notes cover React hooks? Yes. useState, useEffect, useRef, useMemo, useCallback, useContext, useReducer, useTransition and the React 19 hooks are all covered, along with the rules of hooks and how to write your own custom hooks. ### Do I need to know JavaScript before reading these? Yes. React questions often turn into JavaScript questions about closures, this, promises and the event loop. Read the JavaScript handwritten notes (Part 1) first if those are shaky. ### Are the notes up to date with React 19? Yes. They cover React 19 features such as Actions, useActionState, useOptimistic, use(), ref as a prop and Server Components, and mention where React 18 code looks different. --- # Placement Series: Node.js Handwritten Notes for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/nodejs-handwritten-notes Author: Gaurav Sharma Published: 2026-10-21 Updated: 2026-10-21 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style Node.js notes for placements and backend interviews: the event loop, libuv thread pool, modules, streams, Express middleware, REST APIs, JWT auth, security, MongoDB, scaling and Socket.io, explained in English with Hinglish. Topics: - What Node.js is and when to use it - Architecture: V8, libuv and the thread pool - Event loop phases, process.nextTick vs setImmediate - CommonJS vs ES Modules, exports vs module.exports - npm, package.json and semantic versioning - fs and path - Events and EventEmitter - Streams, pipeline and backpressure - Buffers and encodings - The http module - Express basics: routes, params, query, body - Middleware and the request pipeline - REST API design, idempotency and status codes - Error handling in Express 4 and 5 - Auth: sessions vs JWT, bcrypt, httpOnly cookies - Security: helmet, CORS, rate limiting, injection - MongoDB and Mongoose: schemas, queries, populate, indexes - Async patterns: callbacks, promisify, Promise.all - Scaling: cluster, worker threads, PM2, queues - Performance and Redis caching - process, environment variables, child_process, graceful shutdown - Real-time: WebSockets and Socket.io - Output-based questions - Last-minute revision cheat sheet Backend interviews for MERN and Node.js roles test two things: whether you understand how Node actually runs your code, and whether you can build an API that is correct, secure and fast. These notes cover both, one topic per page. ## What makes these Node.js notes different? - **The event loop, properly.** Why Node is single-threaded yet fast, what the libuv thread pool does, and the exact order of `nextTick`, promises, timers and `setImmediate`. - **Express the way it's used at work.** Middleware chains, a central error handler, REST conventions, JWT auth with bcrypt and httpOnly cookies, and a security checklist. - **Scaling questions answered.** Cluster vs worker threads, stateless servers with Redis, queues, caching and the N+1 query trap. - **Hinglish where it helps.** Streams, middleware and the thread pool each get a short Hinglish explanation next to the English definition. ## How should you use these Node.js notes? Run each snippet with `node file.js` and guess the output before you look at the answer. Build a small Express API alongside the Express pages. The last page is a one-page cheat sheet for the night before the interview. This is Part 4 of the series. Pair it with the [React handwritten notes](/placement/react-handwritten-notes) for the full MERN stack, and the [JavaScript handwritten notes](/placement/javascript-handwritten-notes) for the language basics. ### Are these Node.js notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for backend and MERN interviews. ### Do these notes cover Express.js? Yes. Routing, params, query and body, middleware and the order it runs in, error-handling middleware, the async error difference between Express 4 and 5, and security middleware like helmet, cors and rate limiting. ### Is the Node.js event loop explained in detail? Yes. Two pages cover the architecture and the five event loop phases with a diagram, plus process.nextTick vs promises vs setTimeout vs setImmediate, with output questions to practise the order. ### Do I need to know JavaScript first? Yes. Node.js interviews test JavaScript too: closures, promises and async/await. Read the JavaScript handwritten notes (Part 1) first if those are shaky. --- # Placement Series: Python Handwritten Notes for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/python-handwritten-notes Author: Gaurav Sharma Published: 2026-10-21 Updated: 2026-10-21 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style Python notes for placements and interviews: mutability, lists and dicts, comprehensions, *args and **kwargs, decorators, generators, OOP, dunder methods, the GIL and Python for DSA, explained in English with Hinglish. Topics: - What Python is and how it runs - Data types, mutable vs immutable - Strings, slicing and f-strings - Lists, the 2D list trap, shallow vs deep copy - Tuples, sets and dictionaries - Comprehensions, for-else and the walrus operator - Functions, *args, **kwargs and the mutable default trap - Scope (LEGB), closures, late binding and lambda - Decorators - Iterators and generators - OOP: classes, self, class vs instance attributes - Inheritance, super() and MRO - Dunder methods, __str__ vs __repr__ - classmethod, staticmethod and property - Exceptions, EAFP vs LBYL - Files and context managers - Modules, packages, __name__, pip and venv - Memory: references, is vs ==, garbage collection - The GIL: threading vs multiprocessing vs asyncio - collections, itertools and functools - Python for DSA: complexity, heapq and contest tricks - Modern Python: type hints, dataclasses, match - Output-based questions - Last-minute revision cheat sheet Python interviews look easy until they ask why a default list keeps growing, why `[[0] * 3] * 3` changes every row, or what the GIL actually stops. These notes cover the questions that separate "I've used Python" from "I understand Python", one topic per page. ## What makes these Python notes different? - **The traps interviewers love.** Mutable default arguments, late binding in lambdas, shallow copies, `is` vs `==`, and `sort()` returning `None`. - **Decorators and generators explained simply.** How `@decorator` turns into `f = decorator(f)`, and why `yield` lets you read a 20 GB file line by line. - **Python for DSA.** Time complexity of every common operation, `heapq`, `deque`, `Counter`, `lru_cache` and the floor-division difference from C++. - **Hinglish where it helps.** Mutability, closures, the GIL and context managers each get a short Hinglish explanation next to the English definition. ## How should you use these Python notes? Open a Python shell and run each snippet. Guess the output-based questions before you read the answers, then use the last page as a one-page revision sheet before the interview. This is Part 5 of the series. Doing DSA in C++ instead? See the [C++ handwritten notes](/placement/cpp-handwritten-notes). ### Are these Python notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for placements. ### Do these notes cover OOP in Python? Yes. Classes and self, class vs instance attributes, inheritance with super() and the MRO, dunder methods, classmethod, staticmethod, property and name mangling are all covered. ### Can I use these notes for DSA in Python? Yes. There's a page on the time complexity of list, dict, set and heapq operations, plus collections (Counter, defaultdict, deque), itertools, lru_cache and contest tricks like fast input and the recursion limit. They don't teach DSA algorithms themselves. ### Do the notes explain the GIL? Yes. One page explains what the Global Interpreter Lock is and when to use threading, multiprocessing or asyncio, with examples of each. --- # Placement Series: SQL Handwritten Notes for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/sql-handwritten-notes Author: Gaurav Sharma Published: 2026-10-21 Updated: 2026-10-21 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style SQL and DBMS notes for placements and interviews: joins, NULL traps, order of execution, GROUP BY, subqueries, CTEs, window functions, Nth highest salary, normalization, indexes, ACID and isolation levels, explained in English with Hinglish. Topics: - DBMS, RDBMS, SQL vs NoSQL and the sample tables - DDL, DML, DCL, TCL and DELETE vs TRUNCATE vs DROP - Keys and constraints: primary, foreign, candidate, composite - SELECT, WHERE, LIKE, BETWEEN, ORDER BY, LIMIT - NULL, three-valued logic and the NOT IN trap - Order of execution - GROUP BY, HAVING and WHERE vs HAVING - Joins: inner, left, right, full, cross, with diagrams - Self joins, anti joins and row explosion - Subqueries, correlated subqueries, EXISTS vs IN - CTEs and recursive CTEs - Window functions: ROW_NUMBER, RANK, DENSE_RANK - LAG, LEAD, running totals and moving averages - Nth highest salary and deleting duplicates - Classic interview queries, gaps and islands - UNION vs UNION ALL, CASE and common functions - Indexes: B+ tree, clustered vs non-clustered - Normalization: 1NF, 2NF, 3NF, BCNF - Transactions and ACID - Isolation levels, locks and deadlocks - Views, stored procedures, triggers and SQL injection - Query optimization, EXPLAIN and keyset pagination - Output-based questions - Last-minute revision cheat sheet SQL rounds in placements test two things: whether you can write the query, and whether you understand what the database does with it. These notes use one small pair of tables throughout, so every example has a concrete answer you can check, and they cover the DBMS theory that interviewers mix into the same round. ## What makes these SQL notes different? - **One dataset, every concept.** Five employees and three departments, including an employee with no department and a department with no employees, so every join and NULL trap shows up clearly. - **The queries interviewers ask.** Nth highest salary, deleting duplicates, top earner per department, employees earning more than their manager, and consecutive-day streaks. - **Theory that goes with it.** Order of execution, normalization with a worked example, indexes, ACID and isolation levels with the MySQL and PostgreSQL defaults. - **Hinglish where it helps.** NULL, joins, window functions and transactions each get a short Hinglish explanation next to the English definition. ## How should you use these SQL notes? Create the two sample tables in DB Fiddle or a local database, then run each query as you read. Try the output-based questions before checking the answers, and use the last page as a one-page revision sheet. This is Part 6 of the series. For the backend side of the same interviews, see the [Node.js handwritten notes](/placement/nodejs-handwritten-notes). ### Are these SQL notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for placements. ### Do these notes cover DBMS theory too? Yes. Keys, normalization from 1NF to BCNF, indexes, transactions, ACID, isolation levels, locks and deadlocks are covered alongside the SQL queries, because placement interviews mix both. ### Is the Nth highest salary question covered? Yes. The notes show it with LIMIT/OFFSET and with DENSE_RANK, explain what to return when there is no Nth salary, and also cover finding and deleting duplicate rows. ### Which database do the queries use? Standard SQL that runs on MySQL and PostgreSQL. Where the two differ, such as integer division, TRUNCATE rollback or default isolation level, the notes say so. --- # Placement Series: Operating System Handwritten Notes for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/os-handwritten-notes Author: Gaurav Sharma Published: 2026-10-21 Updated: 2026-10-21 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style OS notes for placements and interviews: processes, threads, CPU scheduling with Gantt charts, mutex vs semaphore, deadlock and Banker's algorithm, paging, virtual memory, page replacement and disk scheduling, with solved numericals, in English with Hinglish. Topics: - What an OS does, user vs kernel mode, system calls - Types of OS, monolithic vs microkernel, booting - Process, PCB and process memory layout - Process states, context switch, schedulers - Process vs thread, concurrency vs parallelism - fork(), zombie and orphan processes, IPC - CPU scheduling terms and formulas - FCFS and SJF with Gantt charts - Round Robin, priority, SRTF and aging - Race condition, critical section, Peterson's solution - Mutex vs semaphore - Producer-consumer, readers-writers, dining philosophers - Deadlock and the four Coffman conditions - Deadlock prevention, avoidance and Banker's algorithm - Memory allocation and fragmentation - Paging, TLB and address translation - Segmentation and multi-level page tables - Virtual memory, demand paging and page faults - Page replacement: FIFO, LRU, Optimal, Belady's anomaly - Thrashing and the working set - File allocation, inodes, hard vs soft links - Disk scheduling: FCFS, SSTF, SCAN, LOOK, C-SCAN - Numericals and output questions - Last-minute revision cheat sheet Operating Systems is the theory subject that shows up in almost every placement interview, and the questions are surprisingly predictable: process vs thread, mutex vs semaphore, the four deadlock conditions, paging, and one scheduling or page-replacement numerical. These notes cover all of it, one topic per page, with every numerical solved. ## What makes these Operating System notes different? - **Numericals solved properly.** FCFS, SJF and Round Robin on the same four processes, with Gantt charts and full tables, so you can see how the averages change. - **Diagrams for the hard parts.** Process states, threads in a process, address translation, the deadlock cycle and the thrashing curve, all drawn by hand. - **The comparisons interviewers ask.** Process vs thread, mutex vs semaphore, paging vs segmentation, zombie vs orphan, deadlock vs starvation. - **Hinglish where it helps.** Every hard concept gets a short Hinglish explanation next to the English definition. ## How should you use these Operating System notes? Solve each numerical on paper before you read the answer, then check yourself with the questions near the end. The last page is a one-page revision sheet for the night before the interview. This is Part 7 of the series. Pair it with the [SQL and DBMS handwritten notes](/placement/sql-handwritten-notes) for the other core CS subject in placement interviews. ### Are these OS notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for placements. ### Do these notes include solved numericals? Yes. FCFS, SJF and Round Robin scheduling are solved with Gantt charts and full TAT/WT tables, plus Banker's algorithm, paging address translation, effective access time, page replacement and disk scheduling, all worked step by step. ### Is this enough for OS questions in placement interviews? It covers the topics that come up most: process vs thread, scheduling, mutex vs semaphore, deadlock, paging, virtual memory and page replacement. For deeper study, pair it with a standard textbook like Silberschatz. ### Do the notes cover mutex vs semaphore? Yes, with definitions, the wait() and signal() code, a comparison table, the ownership difference and the classic producer-consumer solution. --- # Placement Series: Computer Networks Handwritten Notes for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/computer-networks-handwritten-notes Author: Gaurav Sharma Published: 2026-10-21 Updated: 2026-10-21 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style Computer Networks notes for placements and interviews: OSI and TCP/IP models, subnetting, ARP, DHCP, NAT, routing, TCP vs UDP, the 3-way handshake, DNS, HTTP, HTTPS and TLS, and what happens when you type a URL, with solved numericals, in English with Hinglish. Topics: - Network types and topologies - Devices: hub vs switch vs router, collision and broadcast domains - The OSI model: 7 layers, protocols and PDUs - TCP/IP model and encapsulation - Data link: MAC address, Ethernet frame, error detection - Flow control (stop-and-wait, Go-Back-N, Selective Repeat), CSMA/CD vs CSMA/CA - IPv4 addressing, classes and private ranges - Subnetting and CIDR with a worked example - VLSM and IPv4 vs IPv6 - ARP, DHCP (DORA) and NAT - Routing: RIP, OSPF, BGP, count-to-infinity - TCP vs UDP and port numbers - TCP 3-way handshake and 4-way termination - TCP flow control and congestion control - DNS resolution and record types - HTTP methods, status codes and HTTP/1.1 vs 2 vs 3 - HTTPS, TLS handshake, symmetric vs asymmetric encryption - What happens when you type a URL - Application protocols and their ports - Network security: DDoS, MITM, firewalls, VPN - Proxy vs reverse proxy, load balancer, CDN - Transmission and propagation delay, throughput - Numericals and quick questions - Last-minute revision cheat sheet Computer Networks questions in placement interviews are mostly about a handful of ideas: the OSI layers, TCP vs UDP, the 3-way handshake, DNS, HTTPS, subnetting, and the famous "what happens when you type a URL". These notes cover each of them on one page, with diagrams and solved numericals. ## What makes these Computer Networks notes different? - **The URL question, step by step.** One page that walks through DNS, ARP, NAT, TCP, TLS, HTTP and rendering in the right order. - **Subnetting without fear.** A cheat table and a block-size shortcut that solves most subnetting questions in under a minute. - **Diagrams for every flow.** OSI vs TCP/IP, encapsulation, DHCP's DORA, the 3-way handshake, DNS resolution and TCP's congestion window. - **Hinglish where it helps.** Every hard concept gets a short Hinglish explanation next to the English definition. ## How should you use these Computer Networks notes? Do the subnetting and delay numericals on paper, then check yourself with the questions near the end. Try `ping`, `traceroute` and `nslookup` on your own machine as you read. The last page is a one-page revision sheet. This is Part 8 of the series. Together with the [Operating System notes](/placement/os-handwritten-notes) and the [SQL and DBMS notes](/placement/sql-handwritten-notes), it covers the core CS theory asked in placements. ### Are these Computer Networks notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for placements. ### Is subnetting explained with examples? Yes. There is a prefix cheat table, a worked split of a /24 into four /26 subnets, finding the subnet of a given host, and a VLSM example, plus subnetting questions to practise. ### Do the notes answer 'what happens when you type a URL'? Yes. A full page walks through the browser cache, DNS lookup, ARP and NAT, the TCP and TLS handshakes, the HTTP request, the server side and rendering, in the order interviewers expect. ### Are numericals included? Yes: subnetting, transmission and propagation delay, stop-and-wait efficiency, window sizes, bandwidth-delay product and TCP congestion window growth, all solved step by step. --- # Placement Series: OOPs Handwritten Notes for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/oops-handwritten-notes Author: Gaurav Sharma Published: 2026-10-21 Updated: 2026-10-21 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style OOPs notes for placements and interviews: the 4 pillars, abstract class vs interface, overloading vs overriding, dynamic dispatch, composition vs aggregation, SOLID, design patterns, equals and hashCode, with Java examples and Hinglish explanations. Topics: - What OOP is, procedural vs object-oriented, the 4 pillars - Class and object, references and the heap - Constructors and constructor chaining - this and static - Encapsulation and access modifiers - Abstraction with abstract classes and interfaces - Abstract class vs interface - Inheritance, super and types of inheritance - The diamond problem in Java, C++ and Python - Compile-time vs runtime polymorphism - Overloading vs overriding rules - Upcasting, downcasting and dynamic method dispatch - Association, aggregation and composition - Composition over inheritance, coupling and cohesion - SOLID: single responsibility and open/closed - SOLID: Liskov, interface segregation, dependency inversion - Design patterns: Singleton and Factory - Builder, Strategy and Observer - equals, hashCode and == - Immutability and final vs finally vs finalize - Checked vs unchecked exceptions, custom exceptions - OOP in Java vs C++ vs Python - Output-based questions - Last-minute revision cheat sheet OOPs is asked in almost every placement interview, whatever the role. The questions are predictable: the four pillars with real examples, abstract class vs interface, overloading vs overriding, why Java has no multiple inheritance, SOLID, and a design pattern or two. These notes cover all of it, one topic per page, with Java examples. ## What makes these OOPs notes different? - **The comparisons interviewers ask.** Abstract class vs interface, overloading vs overriding, aggregation vs composition, encapsulation vs abstraction, `==` vs `equals`, final vs finally vs finalize. - **SOLID with bad and good code.** Each principle shown as a violation and a fix, including the classic Square–Rectangle Liskov example. - **Design patterns you can explain.** A thread-safe Singleton, a Factory, a Builder, Strategy and Observer, with where each appears in real Java. - **Tricky output questions.** Field hiding, static method hiding, and the overridden-method-in-a-constructor trap that prints 0. ## How should you use these OOPs notes? Run the Java snippets as you read and try to explain each pillar with your own real-life example. Guess the output questions before reading the answers, then use the last page as a one-page revision sheet. This is Part 9 of the series. For OOP details specific to C++, such as the vtable and virtual destructors, see the [C++ handwritten notes](/placement/cpp-handwritten-notes). ### Are these OOPs notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for placements. ### Which language do the examples use? Java, because it's the most common language for OOPs interview questions. One page compares how the same concepts work in Java, C++ and Python. For C++-specific OOP (vtable, virtual destructor, copy constructor), see the C++ handwritten notes. ### Do the notes cover SOLID principles and design patterns? Yes. Two pages cover all five SOLID principles with bad and good examples, and two pages cover Singleton (thread-safe), Factory, Builder, Strategy and Observer, plus where each is used in real code. ### Are there tricky output questions? Yes: field hiding vs method overriding, static method hiding, calling an overridden method from a constructor, overload resolution with null and with widening vs boxing, and String comparison. --- # Placement Series: Java Handwritten Notes for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/java-handwritten-notes Author: Gaurav Sharma Published: 2026-10-21 Updated: 2026-10-21 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style core Java notes for placements and interviews: JVM memory, the Integer cache, Strings, pass by value, Collections, HashMap internals, generics, multithreading, Java 8 streams and garbage collection, explained in English with Hinglish. Topics: - What Java is, JDK vs JRE vs JVM - How Java runs, JIT, and JVM memory areas - Data types, wrapper classes and the Integer cache - Casting and operator traps - Strings and the string pool - String vs StringBuilder vs StringBuffer - Arrays and the Arrays class - Why Java is always pass-by-value - The Collections framework - ArrayList vs LinkedList, ConcurrentModificationException - HashSet, TreeSet, HashMap, TreeMap, ConcurrentHashMap - How HashMap works internally - Comparable vs Comparator - Generics, wildcards, PECS and type erasure - Exceptions, try-with-resources and finally traps - Creating threads, start vs run, thread states - synchronized, volatile, wait vs sleep, deadlock - ExecutorService, Future, CompletableFuture, concurrent collections - Lambdas and functional interfaces - Streams API: map, filter, collect, groupingBy, flatMap - Optional, records, sealed classes and virtual threads - Garbage collection, StackOverflowError vs OutOfMemoryError - Output-based questions - Last-minute revision cheat sheet Java interviews for freshers go beyond syntax. They ask how HashMap works inside, why `127 == 127` is true but `128 == 128` is false, whether Java is pass-by-value, what `volatile` really guarantees, and how to answer a stream question on the spot. These notes cover those questions, one topic per page. ## What makes these Java notes different? - **Internals explained with diagrams.** JVM memory areas, the string pool, HashMap buckets and collisions, thread states and GC generations. - **The traps that cost marks.** The Integer cache, `b = b + 1` on a byte, `return` inside `finally`, removing from a list while iterating, and `remove(int)` vs `remove(Object)`. - **Modern Java.** Streams with the classic interview questions, Optional, records, sealed classes and virtual threads. - **Hinglish where it helps.** Hard ideas get a short Hinglish explanation next to the English definition. ## How should you use these Java notes? Open `jshell` and try each snippet as you read. Attempt the output-based questions before checking the answers, then use the last page as a one-page revision sheet. This is Part 10 of the series. Read it with the [OOPs handwritten notes](/placement/oops-handwritten-notes), which cover classes, SOLID and design patterns with Java examples. ### Are these Java notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for placements. ### Do these notes cover OOP in Java? They focus on the Java language itself: JVM, types, Strings, Collections, concurrency and Java 8+. OOP concepts (the four pillars, abstract class vs interface, SOLID, design patterns) are in the separate OOPs handwritten notes, which also use Java examples. ### Is HashMap internal working explained? Yes, with a diagram: hashing, the bucket index, collisions, equals, the 16 / 0.75 resize rule and treeification into red-black trees since Java 8, plus HashMap vs Hashtable vs ConcurrentHashMap. ### Do the notes cover Java 8 and newer features? Yes: lambdas, functional interfaces, method references, the Streams API, Optional, var, switch expressions, records, sealed classes, pattern matching and Java 21 virtual threads. --- # Placement Series: DSA Handwritten Notes for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/dsa-handwritten-notes Author: Gaurav Sharma Published: 2026-10-21 Updated: 2026-10-21 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style DSA notes for placements and coding interviews: Big-O, sliding window, two pointers, binary search, linked lists, trees, heaps, graphs, Dijkstra, union-find, greedy and dynamic programming, with clean C++ templates and Hinglish explanations. Topics: - Big-O, complexity classes and reading constraints - Recursion and backtracking - Prefix sums, two pointers and Kadane's algorithm - Sliding window: fixed and variable - Hashing patterns: two sum, subarray sum equals k - Binary search, lower bound and search on the answer - Sorting algorithms and their complexities - Linked list: reverse, middle, Floyd's cycle detection - Stack, queue and the monotonic stack - Trees and the four traversals - Binary search trees: search, insert, validate, LCA - Tree problems: height, diameter, level order - Heaps and top-K problems - Graphs: representation, BFS and DFS - Topological sort and cycle detection - Shortest paths: Dijkstra, Bellman-Ford, Floyd-Warshall - Union-find and minimum spanning trees - Greedy algorithms and when they fail - Dynamic programming: memoization vs tabulation - DP: 0/1 knapsack and longest increasing subsequence - DP: longest common subsequence and coin change - Bit manipulation tricks and tries - Which pattern to use, plus a complexity quiz - Last-minute revision cheat sheet DSA rounds reward recognising patterns, not memorising thousands of problems. These notes give each important pattern one page: when to use it, a short C++ template you can write from memory, its complexity, and the classic problems it solves. ## What makes these DSA notes different? - **Templates, not just theory.** Sliding window, binary search on the answer, monotonic stack, BFS, Dijkstra, Kahn's topological sort, union-find and DP, each in a few clean lines of C++. - **"Which pattern?" table.** A one-page map from what the problem says to what to try first. - **The traps that cause wrong answers.** Mid-point overflow, validating a BST the wrong way, greedy failing on coin change, and the knapsack loop direction. - **Hinglish where it helps.** Recursion, sliding window, heaps and DP each get a short Hinglish explanation. ## How should you use these DSA notes? Write each template once from memory, then solve three to five problems of that pattern. Use the complexity table to check your approach against the constraints before you code, and the last page as a revision sheet before the interview. This is Part 11 of the series. For the C++ STL used in the code, see the [C++ handwritten notes](/placement/cpp-handwritten-notes). ### Are these DSA notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for placements. ### Which language is the code in? C++, the most common choice for DSA rounds. The templates are short and use the STL; the C++ handwritten notes (Part 2) cover the STL itself. The logic carries over directly to Java or Python. ### Do the notes teach how to recognise which pattern to use? Yes. One page maps problem signals to patterns, for example 'longest substring with a rule' to sliding window or 'minimum value that works' to binary search on the answer, and every pattern page lists the classic problems it solves. ### Is dynamic programming explained for beginners? Yes. A 4-step recipe (state, transition, base cases, order), memoization vs tabulation, then worked 0/1 knapsack, LIS, LCS and coin change with the common loop-order traps. --- # Placement Series: Aptitude Handwritten Notes with Tricks for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/aptitude-handwritten-notes Author: Gaurav Sharma Published: 2026-10-21 Updated: 2026-10-21 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style aptitude notes for placement tests: speed maths, number system, percentages, profit and loss, interest, time and work, time speed distance, permutations, probability, series, coding-decoding, blood relations, directions, seating, syllogisms and clocks, with shortcuts, solved examples and Hinglish explanations. Topics: - Speed maths: squares, cubes and multiplication tricks - Divisibility rules, HCF and LCM - Remainders, unit digits, factors and trailing zeros - Percentages and successive change - Profit, loss and discount - Simple and compound interest shortcuts - Ratio, proportion and partnership - Averages, mixtures and alligation - Problems on ages - Time and work, pipes and cisterns (LCM method) - Time, speed and distance, trains - Boats, streams and races - Permutations and combinations - Probability: dice, coins, cards and 'at least one' - Mensuration formulas for 2D and 3D shapes - Number and letter series - Coding-decoding - Blood relations with family trees - Direction sense - Seating arrangement and puzzles - Syllogisms with Venn diagrams - Clocks and calendars - Mixed practice questions and exam strategy - Formula cheat sheet Placement aptitude tests are a race against the clock. These notes give each topic one page: the formulas, the shortcut that turns a two-minute question into a twenty-second one, and solved examples you can check yourself. ## What makes these Aptitude notes different? - **Shortcuts, not just formulas.** The LCM method for time and work, successive percentage change, the alligation cross, CI minus SI, the unit-digit cycle and the clock-angle formula. - **Reasoning as methods.** Family trees for blood relations, net-movement tracking for directions, the four-step method for seating puzzles and Venn diagrams for syllogisms. - **The traps.** +50% then −50% is not zero, profit is on CP but discount is on MP, average speed is not the simple mean, and left and right flip when people face the centre. - **Hinglish where it helps.** Each topic gets a short Hinglish explanation of the idea behind the trick. ## How should you use these Aptitude notes? Learn the squares and cubes on page 3 first, since they speed up every other topic. Then work through a topic a day: read the page, redo the solved examples with a pen, and solve 20 questions against a timer. Use the last page as a formula sheet before the test. This is Part 12 of the series. For coding rounds after the aptitude test, see the [DSA handwritten notes](/placement/dsa-handwritten-notes). ### Are these aptitude notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for placements. ### Do the notes cover both quant and reasoning? Yes. Pages 3 to 17 cover quantitative aptitude (number system to mensuration) and pages 18 to 24 cover logical reasoning (series, coding-decoding, blood relations, directions, seating, syllogisms, clocks and calendars). ### Are there shortcuts and tricks, or just formulas? Both. Each topic has its formulas plus the shortcut that saves time in the test, such as the LCM method for time and work, a + b + ab/100 for successive percentages, the alligation cross and the clock-angle formula, each with a solved example. ### Is there practice with answers? Yes. Every page has solved examples, and page 25 has 12 mixed timed questions with answers and short workings, plus an exam-day strategy. --- # Placement Series: System Design Handwritten Notes for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/system-design-handwritten-notes Author: Gaurav Sharma Published: 2026-10-21 Updated: 2026-10-21 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style system design notes for placements and interviews: a step-by-step answer framework, estimation, load balancers, caching, CDN, SQL vs NoSQL, replication, sharding, consistent hashing, CAP, Kafka, API design, rate limiting, microservices and reliability, plus case studies and a low-level design, with Hinglish explanations. Topics: - How to answer a system design question, step by step - Back-of-envelope estimation: QPS, storage, latency numbers - Vertical vs horizontal scaling and stateless servers - Load balancers: algorithms, L4 vs L7 - Caching strategies, eviction, stampede and penetration - CDN and DNS - SQL vs NoSQL and the four NoSQL types - Replication, replication lag and quorums - Sharding and consistent hashing - CAP theorem and PACELC - Message queues, Kafka and delivery guarantees - API design: REST, GraphQL, gRPC, pagination, idempotency - Rate limiting: token bucket and sliding windows - Monolith vs microservices, API gateway, sagas - Reliability: availability nines, retries, circuit breakers - Security and observability basics - Object storage, search indexes and real-time updates - Case study: URL shortener - Case study: chat app (WhatsApp) - Case study: news feed - Case study: video streaming (YouTube) - Low-level design: parking lot in Java - Interview questions with short answers - Revision cheat sheet System design interviews don't have one right answer. They test whether you can turn vague requirements into a sensible architecture and explain the trade-offs. These notes give each building block one page, then put them together in four classic case studies. ## What makes these System Design notes different? - **A framework, not just facts.** A 7-step way to answer any design question, with time boxes for a 45-minute round. - **Trade-offs spelled out.** Every concept lists when to use it and what it costs: write-back caches lose data, sharding breaks joins, AP systems return stale reads. - **Case studies you can redraw.** URL shortener, chat, news feed and video streaming, each with a diagram and the decisions interviewers probe. - **LLD included.** A parking lot in Java showing abstraction, the strategy pattern and thread safety. ## How should you use these System Design notes? Learn the building blocks (pages 4 to 19) first, then practise each case study out loud with a timer, drawing the diagram from memory. Use the interview Q&A and the last page for a final revision. This is Part 13 of the series. For the database fundamentals underneath, see the [SQL and DBMS handwritten notes](/placement/sql-handwritten-notes). ### Are these system design notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for placements. ### Is system design asked in fresher placements? Often in a lighter form: product companies ask basics like caching, SQL vs NoSQL, scaling and CAP, or a simple design such as a URL shortener, and many have a low-level design round. These notes cover both. ### Which case studies are included? URL shortener, a WhatsApp-style chat app, an Instagram-style news feed and YouTube-style video streaming, each with requirements, a diagram and the key decisions, plus a parking lot low-level design in Java. ### Do I need to know a specific cloud like AWS? No. The notes teach the concepts and name real tools (Redis, Kafka, Cassandra, S3, Nginx) as examples, so the ideas carry over to any cloud. --- # Placement Series: TypeScript Handwritten Notes for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/typescript-handwritten-notes Author: Gaurav Sharma Published: 2026-10-21 Updated: 2026-10-21 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style TypeScript notes for placements and interviews: basic types, any vs unknown vs never, type vs interface, narrowing, discriminated unions, generics, keyof, utility types, mapped and conditional types, classes, enums, tsconfig, React and Node with Zod, common errors and a type quiz, with Hinglish explanations. Topics: - What TypeScript is, type erasure and structural typing - Basic types, tuples, any vs unknown vs never - Type inference, literal types and as const - Function types, optional params and overloads - type vs interface, readonly, index signatures - Unions, intersections and the 5 ways to narrow - Discriminated unions and exhaustive checks - Type guards, assertion functions and satisfies - Generics, constraints and defaults - keyof, typeof and indexed access types - Utility types: Partial, Pick, Omit, Record, ReturnType and more - Mapped types and key remapping - Conditional types, infer and distribution - Template literal types - Classes: modifiers, parameter properties, abstract, #private - Enums vs union types and as const objects - import type, declaration files and @types - tsconfig and what strict mode turns on - TypeScript with React: props, hooks and events - Runtime validation with Zod in Node APIs - Common TypeScript errors and how to fix them - Interview questions with short answers - "What's the type?" quiz - Revision cheat sheet TypeScript questions now come up in most frontend and full-stack interviews. These notes explain the type system one idea per page, with short examples you can paste into the TypeScript Playground and check by hovering. ## What makes these TypeScript notes different? - **Answers to the classic questions.** any vs unknown, type vs interface, private vs #private, enums vs unions and annotation vs `as` vs `satisfies`, each with a clear rule. - **The type system, step by step.** From narrowing and discriminated unions to generics, utility types, mapped types and conditional types with `infer`. - **Real project use.** tsconfig strict mode, React props and events, and runtime validation with Zod, because types disappear at runtime. - **A quiz and an error guide.** Predict the type of 14 snippets, and fix the 8 compiler errors you'll see most. ## How should you use these TypeScript notes? Paste each example into the TypeScript Playground and hover the variables to see the inferred types. Try writing `Partial`, `Pick` and `ReturnType` yourself after reading the mapped and conditional type pages. Use the quiz and the last page as revision before the interview. This is Part 14 of the series. For the JavaScript underneath, see the [JavaScript handwritten notes](/placement/javascript-handwritten-notes). ### Are these TypeScript notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for placements. ### Do I need to know JavaScript first? Yes, the basics. TypeScript is JavaScript plus types, so the notes focus on the type system. The JavaScript handwritten notes (Part 1) cover the language itself. ### Do the notes cover advanced types like generics and conditional types? Yes. Generics, keyof and indexed access, every common utility type, mapped types with key remapping, conditional types with infer, distribution and template literal types, each with short examples. ### Is TypeScript with React covered? Yes. Typing props and children, useState and useRef with generics, reducers with discriminated unions, form and change events, and extending native element props. --- # Placement Series: Next.js Handwritten Notes for Placements (Free PDF, Next.js 16) URL: https://www.gaurav-sharma.in/placement/nextjs-handwritten-notes Author: Gaurav Sharma Published: 2026-10-21 Updated: 2026-10-21 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style Next.js 16 notes for placements and interviews: App Router, special files, dynamic and parallel routes, Server vs Client Components, data fetching and streaming, use cache, cacheLife and revalidation, Partial Prerendering, Server Actions, forms, route handlers, proxy, metadata and SEO, with Hinglish explanations. Topics: - What Next.js is: CSR vs SSR vs SSG vs ISR - App Router: pages, layouts and templates - Special files: loading, error, not-found, route - Dynamic routes, route groups and async params - Parallel and intercepting routes (modal pattern) - Server vs Client Components - Composition: 'use client' boundaries and serializable props - Data fetching, parallel requests and streaming with Suspense - Caching in Next.js 16 with 'use cache' - cacheLife profiles, cacheTag, updateTag and revalidateTag - Static vs dynamic rendering and Partial Prerendering - Server Actions and their security - Forms with useActionState and useFormStatus - Route handlers vs Server Actions - proxy.ts (formerly middleware) - Navigation: Link, useRouter, redirect, notFound - Metadata, generateMetadata, sitemap and robots - next/image, next/font and next/script - Error handling with error.tsx and retry() - Environment variables and deployment options - What changed in Next.js 16, App vs Pages Router - Hydration errors and common mistakes - Interview questions with short answers - Revision cheat sheet Next.js is the most asked-about React framework in frontend and full-stack interviews, and version 16 changed a lot: caching is now explicit with `'use cache'`, middleware became proxy, and request APIs are async. These notes cover the current App Router one idea per page, with short TypeScript examples. ## What makes these Next.js notes different? - **Up to date with Next.js 16.** Cache Components, `cacheLife` and `cacheTag`, `updateTag` vs `revalidateTag`, `proxy.ts`, async `params` and the new `error.tsx` `retry()`. - **The mental model first.** Server vs Client Components, where `'use client'` boundaries go, and why passing a Server Component as children keeps it on the server. - **Security called out.** Server Actions are public endpoints and proxy is only an optimistic check, so every page shows where the real auth check belongs. - **Interview ready.** An old-vs-new API table, the common hydration errors and their fixes, and short answers to the questions asked most. ## How should you use these Next.js notes? Create a fresh app with `npx create-next-app@latest` and build each page's example as you read. Pay extra attention to the caching and Server Actions pages, since they come up most in interviews. Use the last page as a revision sheet. This is Part 15 of the series. For the basics underneath, see the [React handwritten notes](/placement/react-handwritten-notes). ### Are these Next.js notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for placements. ### Which version of Next.js do the notes cover? Next.js 16 with the App Router, including Cache Components and 'use cache', proxy.ts (the renamed middleware), async params, updateTag and the other 16 changes. A table maps the old Pages Router APIs to their App Router equivalents. ### Do I need to know React first? Yes. Next.js is built on React, so learn components, props, state and hooks first. The React handwritten notes (Part 3) cover those, and the TypeScript notes (Part 14) help with the typed examples. ### Are Next.js interview questions included? Yes. One page has short answers to the most common questions, such as Server vs Client Components, SSR vs SSG vs ISR, Partial Prerendering, Server Action security and hydration errors, and the last page is a revision sheet. --- # Placement Series: C Language Handwritten Notes for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/c-handwritten-notes Author: Gaurav Sharma Published: 2026-10-22 Updated: 2026-10-22 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style C language notes for placements and interviews: compilation stages, data types and format specifiers, operators and precedence traps, functions and call by value, storage classes, arrays, strings, pointers, pointer arithmetic, const and function pointers, malloc and free, structure padding, bit manipulation, macros, file handling, undefined behaviour and an output quiz, with Hinglish explanations. Topics: - What C is and the 4 compilation stages - Data types, sizes and format specifiers - Operators, precedence and undefined-behaviour traps - Control flow: if, switch fall-through and loops - Functions and call by value (swap with pointers) - Storage classes: auto, static, extern, register - Arrays, 2D arrays and array decay - Strings, char[] vs char* and string.h - Pointer basics: NULL, wild, dangling and void pointers - Pointer arithmetic and pointers vs arrays - Double pointers and const pointer variants - Function pointers, callbacks and qsort - Dynamic memory: malloc, calloc, realloc, free - Memory layout, leaks, dangling pointers and double free - struct, union, enum and typedef - Structure padding and alignment - Bit manipulation tricks - Preprocessor, macros and macro pitfalls - File handling with FILE * - Recursion and the call stack - Undefined behaviour and segmentation faults - Interview questions with short answers - Output prediction quiz - Revision cheat sheet C is still the first coding language in many campus placement tests, and its output questions catch even good programmers. These notes explain one idea per page, with short programs you can compile with gcc and check yourself. ## What makes these C notes different? - **The classic traps, explained.** `i++ + ++i`, integer division, `switch` fall-through, macro expansion and `sizeof` inside a function, each with the reason behind the answer. - **Pointers and memory, step by step.** From `&` and `*` to pointer arithmetic, const pointers, function pointers, `malloc`/`realloc` and the memory layout. - **What interviewers love to ask.** struct vs union, structure padding, storage classes, bit tricks, and undefined behaviour vs segmentation faults. - **A quiz and a cheat sheet.** Predict the output of 11 snippets, then revise everything from the last page. ## How should you use these C notes? Type each example, compile it with `gcc -Wall`, and guess the output before you run it. Redo the padding and bit manipulation examples on paper, since they come up as written questions. Use the interview Q&A and the cheat sheet the night before the test. This is Part 16 of the series. For object-oriented C++ on top of these basics, see the [C++ handwritten notes](/placement/cpp-handwritten-notes). ### Are these C language notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for placements. ### Are these notes good for beginners? Yes. They start from compilation, data types and operators, then build up to pointers, dynamic memory and structure padding. You only need a C compiler such as gcc to try the examples. ### Do the notes cover pointers and memory in depth? Yes. Pointer basics, pointer arithmetic, double and const pointers, function pointers, malloc, calloc, realloc and free, the memory layout, and common bugs like leaks, dangling pointers, double free and segmentation faults. ### Do the notes include C output questions? Yes. There is an output prediction quiz with answers and explanations, plus output-style traps on operators, macros, structure padding and undefined behaviour throughout the notes. --- # Placement Series: Git and GitHub Handwritten Notes for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/git-handwritten-notes Author: Gaurav Sharma Published: 2026-10-22 Updated: 2026-10-22 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style Git and GitHub notes for placements and interviews: the three areas, commits and Git internals, branches, merge vs rebase, merge conflicts, fetch vs pull, forks and pull requests, branching strategies, reset vs revert, stash, cherry-pick, reflog, bisect, commit messages and GitHub Actions, with Hinglish explanations. Topics: - What Git is, centralized vs distributed version control, Git vs GitHub - Install and git config levels - The three areas: working directory, staging area and repository - init, clone, status, add and commit - Inside .git: blob, tree, commit, HEAD and SHA hashes - log, diff and show - .gitignore and untracking committed files - Branches and HEAD - switch vs checkout and detached HEAD - Merge: fast-forward vs three-way - Resolving merge conflicts - Rebase vs merge and the golden rule - Interactive rebase and squash - Remotes: fetch vs pull vs push - GitHub: fork, pull request and code review - Branching strategies: GitHub Flow, Git Flow, trunk-based - Undo: restore vs reset (soft, mixed, hard) vs revert - stash and cherry-pick - Tags, reflog and bisect - Good commit messages and Conventional Commits - GitHub extras: SSH keys, Actions CI and Issues - Interview questions with short answers - "Which command?" quiz - Revision cheat sheet Git comes up in almost every developer interview, and you use it from day one at any job. These notes explain Git one idea per page, with commit-graph sketches and commands you can run in a practice repo. ## What makes these Git notes different? - **Answers to the classic questions.** fetch vs pull, merge vs rebase, reset vs revert, switch vs checkout and Git vs GitHub, each with a clear rule. - **Pictures of what really happens.** The three areas, commit objects, branches as pointers, fast-forward and three-way merges, and rebasing are all drawn as graphs. - **Real team workflow.** Forks and pull requests, branching strategies, good commit messages, SSH keys and a GitHub Actions CI file. - **Rescue tools.** stash, cherry-pick, reflog and bisect, so you can recover from mistakes instead of deleting the folder. ## How should you use these Git notes? Create a practice repo and run every command as you read. Make two branches, cause a merge conflict on purpose and resolve it, then try a rebase and a reset and recover with reflog. Use the quiz and the last page as revision before the interview. This is Part 17 of the series. For the coding side of interviews, see the [DSA handwritten notes](/placement/dsa-handwritten-notes). ### Are these Git notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for placements. ### Do I need any coding background to follow these Git notes? No. You only need to open a terminal. The notes start from what version control is and build up to branches, merging, rebasing and pull requests, with a command for every step. ### Do the notes explain merge vs rebase and reset vs revert? Yes. Both have their own pages with commit-graph sketches and comparison tables: fast-forward vs three-way merge, the golden rule of rebasing, the three modes of git reset, and when to use revert instead. ### Is GitHub covered, or only Git? Both. The notes cover forks and pull requests, code review, branching strategies, SSH keys, a basic GitHub Actions CI workflow, Issues and branch protection. --- # Placement Series: HTML and CSS Handwritten Notes for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/html-css-handwritten-notes Author: Gaurav Sharma Published: 2026-10-22 Updated: 2026-10-22 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style HTML and CSS notes for placements and frontend interviews: how the browser renders, semantic HTML5, images, forms, accessibility, meta tags, specificity and the cascade, box model, units, position and z-index, Flexbox, Grid, centering, responsive design, pseudo-elements, animations, CSS variables and modern CSS, with Hinglish explanations. Topics: - How the browser renders: DOM, CSSOM, layout, paint, async vs defer - Document structure, doctype and meta tags for SEO - Semantic HTML5 elements and headings - Text, links and responsive images with srcset and lazy loading - Lists and accessible tables - Forms, input types and built-in validation - Accessibility basics: labels, alt text, keyboard and ARIA rules - Block vs inline vs inline-block, and three ways to hide elements - Ways to add CSS, selectors and combinators - Specificity, the cascade, !important and inheritance - Box model, box-sizing and margin collapse - Units (px, em, rem, vw, dvh, fr), clamp() and colours - Position, z-index and stacking contexts - Flexbox: container and item properties - CSS Grid: template areas and auto-fit with minmax - Every way to centre a div - Responsive design, mobile-first and media queries - Pseudo-classes vs pseudo-elements - Transitions, keyframe animations and transform - CSS variables, :has(), container queries and nesting - BEM naming and common CSS mistakes - Interview questions with short answers - "What will you see?" quiz - Revision cheat sheet HTML and CSS are tested in almost every frontend and full-stack interview, and many freshers lose easy marks on specificity, the box model and positioning. These notes explain each idea on one page, with diagrams and short snippets you can try in the browser. ## What makes these HTML and CSS notes different? - **The questions interviewers really ask.** Semantic tags, async vs defer, em vs rem, relative vs absolute, display none vs visibility hidden, each with a clear answer. - **Specificity you can calculate.** An (ID, class, type) scoring table and worked examples, so you can predict which rule wins instead of guessing. - **Layout from the ground up.** Box model, margin collapse, position and stacking contexts, then Flexbox, Grid and six ways to centre a div. - **Modern CSS.** CSS variables, `:has()`, container queries, native nesting and accessible, responsive habits. ## How should you use these HTML and CSS notes? Open CodePen or your browser's DevTools next to the PDF and try each snippet: change a value and watch what moves. Do the "What will you see?" quiz without looking at the answers, then use the last page as a revision sheet before the interview. This is Part 18 of the series. For the language that makes pages interactive, see the [JavaScript handwritten notes](/placement/javascript-handwritten-notes). ### Are these HTML and CSS notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for placements. ### Do I need any coding background for these notes? No. They start from how a browser turns HTML and CSS into pixels, so beginners can follow along. Paste the snippets into CodePen and inspect them in DevTools as you read. ### Do the notes cover Flexbox, Grid and specificity? Yes. Flexbox and Grid each get a full page with diagrams, specificity is explained with an (ID, class, type) scoring table and worked examples, and there is a page on every way to centre a div. ### Are the notes useful for frontend interviews? Yes. They include the questions asked most often, such as semantic HTML, box model, em vs rem, position values, display none vs visibility hidden and Flexbox vs Grid, plus a six-question output quiz and a one-page revision sheet. --- # Placement Series: AI, ML and Generative AI Handwritten Notes for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/ai-ml-handwritten-notes Author: Gaurav Sharma Published: 2026-10-22 Updated: 2026-10-22 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style AI, machine learning and generative AI notes for placements and interviews: ML types and workflow, regression, trees and ensembles, k-means and PCA, bias-variance, confusion matrix and F1, gradient descent, neural networks, CNN, RNN, transformers and attention, LLMs, prompt engineering, embeddings, RAG, agents and MCP, with Hinglish explanations. Topics: - AI vs ML vs deep learning vs generative AI - Supervised, unsupervised, reinforcement and self-supervised learning - ML workflow, train / validation / test split and data leakage - Linear and logistic regression - Decision trees, random forest, boosting, KNN, SVM and Naive Bayes - Unsupervised learning: k-means and PCA - Bias-variance, overfitting and regularization (L1, L2, dropout) - Confusion matrix, precision, recall and F1 with a worked example - ROC-AUC and regression metrics (MAE, MSE, RMSE, R²) - Gradient descent, learning rate and optimisers - Neural networks, activation functions and backpropagation - CNN and RNN / LSTM - Transformers, self-attention and Q, K, V - LLM basics: tokens, context window, temperature and top-p - Pretraining, fine-tuning, LoRA and RLHF - Prompt engineering techniques and prompt injection - Embeddings, cosine similarity and vector databases - RAG pipeline: chunk, embed, retrieve, generate - Prompting vs RAG vs fine-tuning, and calling an LLM API - AI agents, tool calling and MCP - Evaluation, hallucinations and guardrails - Interview questions with short answers - "Which one?" scenario quiz - Revision cheat sheet AI and machine learning questions now come up in placement interviews for software, data and AI roles alike. These notes cover classic machine learning first, then deep learning, then the generative AI topics companies hire for today: LLMs, RAG and agents. ## What makes these AI and ML notes different? - **Classic ML and GenAI in one place.** Regression, trees, metrics and overfitting, followed by transformers, LLMs, RAG and agents, so you can answer both kinds of interview question. - **Worked examples, not just definitions.** A confusion matrix with real numbers, regression error calculations, and short scikit-learn and Python snippets you can run. - **Practical GenAI.** When to prompt, when to use RAG and when to fine-tune, how tool calling and MCP work, and how to reduce hallucinations and evaluate an LLM app. - **A scenario quiz.** Fifteen "which one would you use?" questions on models, metrics and GenAI design, the way interviewers actually ask them. ## How should you use these AI and ML notes? Read the pages in order once, then run each code example in Colab or Jupyter. Work the confusion matrix example by hand, and try explaining RAG and attention out loud in two minutes each. Use the quiz and the last page as revision before the interview. This is Part 19 of the series. For the Python the examples use, see the [Python handwritten notes](/placement/python-handwritten-notes). ### Are these AI and ML notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for placements. ### Do I need strong maths to follow these notes? No. School-level maths and basic Python are enough. Formulas such as sigmoid, gradient descent, precision and recall, cosine similarity and attention are shown with plain-language explanations and worked examples. ### Do the notes cover generative AI and LLMs? Yes. About half the notes cover generative AI: transformers and attention, tokens and temperature, pretraining, fine-tuning and RLHF, prompt engineering, embeddings and vector databases, RAG, AI agents with tool calling, MCP, and evaluation and guardrails. ### Are these notes useful for AI engineer and data science interviews? Yes. They include a page of common interview questions with short answers, a scenario quiz (which model or metric to pick), and a one-page revision sheet, alongside small scikit-learn and Python examples. --- # Placement Series: Flutter and Dart Handwritten Notes for Placements (Free PDF) URL: https://www.gaurav-sharma.in/placement/flutter-handwritten-notes Author: Gaurav Sharma Published: 2026-10-22 Updated: 2026-10-22 Full PDF: 26 pages, English + Hinglish; free by email request 26 pages of handwritten-style Flutter and Dart notes for placements and interviews: Dart basics, null safety, OOP, mixins, records and sealed classes, Futures, Streams and isolates, Stateless vs Stateful widgets, the State lifecycle, widget, element and render trees, keys, layout, navigation, forms, state management, networking, performance, testing and release, with Hinglish explanations. Topics: - What Flutter is and how it draws the UI (engine, Impeller, JIT vs AOT) - Dart basics: var vs final vs const, and late - Sound null safety: ?, !, ?? and ?. - Functions, named and optional params, closures - Classes and constructors: named, factory and const - Mixins, extensions and Dart 3 class modifiers - Dart 3 records, patterns and sealed classes - Future, async/await, the event loop and isolates - Streams, async* and StreamController - StatelessWidget vs StatefulWidget and setState - The State lifecycle from initState to dispose - Widget, Element and RenderObject trees, and BuildContext - Keys: when you need them and which one to use - Layout and constraints: Row, Column, Expanded, Flexible, Stack - Lists, grids and everyday widgets - Navigation with Navigator and go_router - Forms, validation and TextEditingController - State management compared: setState, InheritedWidget, Provider, Riverpod, Bloc - Networking, JSON, FutureBuilder and local storage - Performance, build modes, hot reload vs hot restart - Platform channels, testing and release builds - Interview questions with short answers - "What prints? What rebuilds?" quiz - Revision cheat sheet Flutter interviews test two things: how well you know Dart, and whether you understand what Flutter does when your widgets rebuild. These notes cover both, one idea per page, with short snippets you can run in DartPad or hot reload in an emulator. ## What makes these Flutter notes different? - **Answers to the classic questions.** final vs const, Stateless vs Stateful, hot reload vs hot restart, Expanded vs Flexible and Provider vs Riverpod vs Bloc, each with a clear rule. - **What happens under the hood.** The State lifecycle diagram, the widget, element and render trees, BuildContext and why keys matter when a list changes. - **Real app patterns.** go_router, form validation, fromJson models, FutureBuilder without repeated API calls, secure token storage, testing and release builds. - **A quiz.** Fifteen "what prints, what rebuilds" questions that catch the usual mistakes. ## How should you use these Flutter notes? Run the Dart pages in DartPad first, then build a small app and change it while reading the widget, lifecycle and layout pages. Before the interview, go through the Q&A page, the quiz and the cheat sheet on the last page. This is Part 20 of the series. For the object-oriented ideas Dart builds on, see the [OOPs handwritten notes](/placement/oops-handwritten-notes). ### Are these Flutter notes really free? Yes. The full 26-page PDF is free; email me to request the complete PDF. Share it with friends preparing for placements. ### Do the notes cover Dart as well as Flutter? Yes. The first third covers Dart: variables, null safety, functions, classes and constructors, mixins and extensions, Dart 3 records, patterns and sealed classes, Futures, Streams and isolates. The rest covers Flutter itself. ### Is state management covered? Yes. The notes explain ephemeral vs app state and compare setState, InheritedWidget, Provider, Riverpod and Bloc/Cubit in one table, with short Provider and Cubit examples and when to pick each. ### Are the notes up to date with Flutter 3 and Dart 3? Yes. They use sound null safety, Dart 3 records, patterns, sealed classes and class modifiers, the Impeller renderer, Isolate.run and go_router. --- # Placement Series: Top 50 JavaScript Interview Questions with Answers (Free PDF) URL: https://www.gaurav-sharma.in/placement/javascript-interview-questions Author: Gaurav Sharma Published: 2026-10-22 Updated: 2026-10-22 Full PDF: 49 pages, English + Hinglish; free by email request 49 pages covering the 50 most-asked JavaScript interview questions, each with a short answer to say first and a detailed explanation: var/let/const, hoisting, closures, this, the event loop and output puzzles, promises and async/await, plus coding answers for debounce, throttle, deep clone, Promise.all, bind, curry, memoize and an LRU cache, with Hinglish explanations. Topics: - Difference between var, let and const - Data types in JavaScript - == vs === - null vs undefined - Hoisting (output question) - Temporal Dead Zone - Closures and their real use cases - Arrow functions vs regular functions - How the this keyword works - Spread vs rest - Destructuring - Truthy and falsy values - slice vs splice vs split - map vs forEach vs filter vs reduce - Pass by value vs pass by reference - Shallow copy vs deep copy - call vs apply vs bind - The event loop - Microtasks vs macrotasks (output question) - Promises and their states - async/await and error handling - Promise.all vs allSettled vs race vs any - Callback hell - setTimeout in a loop with var vs let - Event bubbling, capturing and delegation - Prototypes and the prototype chain - Classes vs constructor functions - Higher-order functions and currying - IIFE and the module pattern - Implement debounce - Implement throttle - Object.freeze vs Object.seal vs const - Optional chaining and nullish coalescing - ES Modules vs CommonJS - localStorage vs sessionStorage vs cookies - The tricky this puzzle (output question) - Implement deep clone - Flatten a nested array and object - Promise.all polyfill - bind, call and apply polyfills - Implement curry and sum(1)(2)(3)() - Implement memoize - Iterators and generators - Garbage collection and memory leaks - Map vs Object, WeakMap vs Map - async/await execution order (output question) - map, filter and reduce polyfills - Implement an EventEmitter - sleep and retry with exponential backoff - Implement an LRU cache These are the 50 JavaScript questions that come up again and again in fresher and junior interviews, in the order of difficulty you're likely to face them. Every answer starts with a short version you can say in two lines, then explains the why with code, output and the traps interviewers look for. ## What does each answer include? - **A short answer first.** The one or two lines to say before going into detail, so you never ramble. - **A detailed explanation.** Code you can paste into the console, the exact output, and tables or sketches for things like the event loop and the prototype chain. - **Traps and follow-ups.** The mistakes people make and the next question the interviewer usually asks. - **Coding answers.** Working implementations of debounce, throttle, deep clone, flatten, Promise.all, bind/call/apply, curry, memoize, an EventEmitter, retry with backoff and an LRU cache. ## How should you prepare with these questions? Start with the starred "most asked" questions in the index. Read each short answer out loud, run the snippets yourself, and write the 8 coding questions from memory at least once. The night before, revise from the two pages of one-line answers at the end. This is Part 1 of the Interview Q&A series. To learn the concepts behind these answers, start with the free [JavaScript handwritten notes](/placement/javascript-handwritten-notes). ### Is this JavaScript interview questions PDF free? Yes. The full 49-page PDF with all 50 questions and answers is free; email me to request the complete PDF. ### Are these JavaScript questions good for freshers? Yes. Questions 1 to 15 cover fresher basics like var/let/const, hoisting, closures and this. Questions 16 to 35 cover async JavaScript and the DOM, and 36 to 50 are the coding and polyfill questions asked for 0 to 2 years of experience. ### Does the PDF include output-based questions? Yes. It includes the common predict-the-output questions on hoisting, == coercion, closures in loops, this, microtasks vs macrotasks and async/await ordering, each with a step-by-step explanation. ### How is this different from the JavaScript handwritten notes? The handwritten notes (Placement Series, Part 1) teach the concepts one page at a time. This PDF is the interview layer on top: the exact questions, a short answer to say first, the detailed answer, traps and follow-up questions. --- # Placement Series: Top 50 C++ Interview Questions with Answers (Free PDF) URL: https://www.gaurav-sharma.in/placement/cpp-interview-questions Author: Gaurav Sharma Published: 2026-10-22 Updated: 2026-10-22 Full PDF: 56 pages, English + Hinglish; free by email request 56 pages covering the 50 most-asked C++ interview questions, each with a short answer to say first and a detailed answer with code, output and follow-ups: OOP, pointers vs references, virtual functions and vtable, virtual destructors, Rule of 3/5/0, smart pointers, RAII, STL, move semantics, output questions and coding questions, with Hinglish explanations. Topics: - C vs C++ - Four pillars of OOP - struct vs class - Pointer vs reference - The this pointer - Overloading vs overriding - Inline functions vs macros - Static members and functions - Namespaces and using namespace std - Constructor types and destructor - new/delete vs malloc/free - Access specifiers and inheritance modes - Friend function and friend class - const pointers and const methods - Call by value, reference and pointer - Virtual functions and runtime polymorphism - vtable and vptr - Pure virtual functions and abstract classes - Virtual destructor - Shallow vs deep copy - Copy constructor and why it takes a reference - Rule of 3, 5 and 0 - Operator overloading - Templates and specialisation - STL containers and complexities - vector internals: size vs capacity - map vs unordered_map - Iterator invalidation - Lambdas and captures - Exception handling - unique_ptr vs shared_ptr vs weak_ptr - RAII - Memory leaks, dangling and wild pointers - The four C++ casts - Object slicing - lvalues, rvalues and rvalue references - Move semantics and the move constructor - std::move vs std::forward - Diamond problem and virtual inheritance - Virtual call inside a constructor (output) - Constructor and destructor order (output) - Undefined behaviour - sizeof, padding and alignment - Virtual constructor and clone() - Coding: String class - Coding: unique_ptr - Coding: thread-safe Singleton - Coding: LRU cache - C++11, 14, 17 and 20 features - Output round: 5 snippets These are the 50 C++ questions that come up again and again in campus placements and fresher interviews, from "C vs C++" to move semantics and an LRU cache. Each answer starts with a short version you can say in 20 seconds, then explains why, with code and output. ## What do the 50 C++ questions cover? - **OOP and classes.** The four pillars, struct vs class, constructors, the copy constructor, Rule of 3/5/0, friend, static and const. - **Polymorphism.** Virtual functions, how the vtable and vptr work, abstract classes, virtual destructors, object slicing and the diamond problem. - **Memory.** Pointers vs references, new vs malloc, leaks and dangling pointers, smart pointers, RAII and undefined behaviour. - **STL and modern C++.** Container complexities, vector internals, map vs unordered_map, iterator invalidation, lambdas, move semantics, perfect forwarding and C++11–20 features. - **Output and coding rounds.** Predict-the-output questions, plus a String class, unique_ptr, a thread-safe Singleton and an LRU cache written in full. ## How should you prepare with this PDF? Read the short answer, say it out loud, then read the detailed answer and compile the example yourself. Questions marked most asked come up first in most interviews, so start there. The night before, go through the last pages: all 50 answers in one line each. This is Part 2 of the Interview Q&A series. To learn each topic in depth first, see the [C++ handwritten notes](/placement/cpp-handwritten-notes). ### Is this C++ interview questions PDF free? Yes. The full 56-page PDF with all 50 questions and answers is free; email me to request the complete PDF. ### Is it suitable for freshers? Yes. Questions go from easy (1–15) to medium (16–35) to hard (36–50), so freshers can start with the basics and work up to move semantics, the diamond problem and coding questions asked in product-company interviews. ### Do the answers include code? Almost every answer has a short, compilable C++17/20 example with its output, plus a short answer to say first, the common trap, and the follow-up question interviewers usually ask next. ### How is this different from the C++ handwritten notes? The C++ handwritten notes (Part 2) teach the language topic by topic. This PDF is organised by interview question, with answers written the way you would say them, and ends with all 50 answers in one line each for last-minute revision. --- # Placement Series: Top 50 React Interview Questions with Answers (Free PDF) URL: https://www.gaurav-sharma.in/placement/react-interview-questions Author: Gaurav Sharma Published: 2026-10-22 Updated: 2026-10-22 Full PDF: 51 pages, English + Hinglish; free by email request The 50 most-asked React interview questions with detailed answers, for freshers and developers with up to 2 years of experience: virtual DOM, keys, props vs state, every common hook, re-renders, reconciliation, Fiber, concurrent rendering, React 19 Actions, Server Components, hydration, performance, testing and four coding questions, with code, diagrams and Hinglish explanations. Topics: - What is React and why use it? - What is JSX? - What is the virtual DOM and how does it work? - Function components vs class components? - Props vs state? - How does useState work? - Why do lists need keys? Why not use the index? - Controlled vs uncontrolled components? - What are the ways to render conditionally? - How are events handled in React? - What is lifting state up? - What is prop drilling and how do you avoid it? - What are Fragments? - What are hooks? What are the rules of hooks? - How does a child send data to its parent? - How does useEffect work? Dependencies and cleanup? - How do class lifecycle methods map to hooks? - setCount(count + 1) three times: what is count? - Is setState synchronous? Why is the old value logged? - What is useRef? useRef vs useState? - useMemo vs useCallback? - What does React.memo do and when does it fail? - What makes a component re-render? - How does the Context API work? Downsides? - useReducer vs useState? - What are custom hooks? Write useDebounce. - What is reconciliation? How does diffing work? - What does StrictMode do? Why do effects run twice? - What are error boundaries? - What are lazy and Suspense? Code splitting? - What are portals? - How do you pass a ref to a child? forwardRef in React 19? - HOC vs render props vs custom hooks? - Write useFetch. How do you avoid race conditions? - Output: how many renders? - What is React Fiber? - Concurrent rendering: useTransition vs useDeferredValue? - How do you test React components? - React 19 Actions: useActionState and useFormStatus? - What is useOptimistic? - What does the use() API do? - Server Components vs Client Components? - CSR vs SSR vs SSG vs ISR? - What is hydration? What causes hydration errors? - Context vs Redux Toolkit vs Zustand vs TanStack Query? - How do you optimise React performance? - What is a stale closure in hooks? - useLayoutEffect vs useEffect? - Build a todo app with useReducer. - Build infinite scroll. These are the 50 React questions that come up most in frontend and full-stack interviews, ordered from easy to hard. Each one starts with the short answer you should say first, then explains it properly with code, diagrams and the follow-up questions interviewers tend to ask next. ## What does each answer include? - **A two-line short answer** you can say word for word at the start. - **The detailed answer**: how it works, with code and its output where it helps. - **Traps and follow-ups**: the mistakes interviewers look for, and the next question they usually ask. - **Hinglish explanations** for the tricky ideas: snapshots, reconciliation, stale closures and hydration. ## How should you practise with these questions? Cover the answer, say yours out loud, then compare. Write the four coding questions yourself (useDebounce, useFetch, the todo app and infinite scroll) before reading the solutions. The night before the interview, go through the one-line answers at the end of the PDF. This is Part 3 of the interview questions series. To learn the concepts first, see the [React handwritten notes](/placement/react-handwritten-notes). ### Is this React interview questions PDF free? Yes. All 51 pages are free; email me to request the complete PDF. Share it with friends preparing for frontend interviews. ### Are the answers updated for React 19? Yes. The answers cover React 19 features such as Actions with useActionState and useFormStatus, useOptimistic, the use() API, ref as a prop and context as a provider, plus Server Components, concurrent rendering and the React Compiler. ### Is it for freshers or experienced developers? Both. Questions 1 to 15 are easy fundamentals for freshers, 16 to 35 are medium hook and rendering questions, and 36 to 50 are hard questions asked to developers with one or two years of experience, including four coding questions. ### How is this different from the React handwritten notes? The React handwritten notes (Part 3 of the Placement Series) teach React one concept per page. This PDF is interview practice: each question starts with a two-line answer to say first, followed by a detailed explanation, code, traps and follow-up questions. --- # Placement Series: Top 50 Node.js Interview Questions with Answers (Free PDF) URL: https://www.gaurav-sharma.in/placement/nodejs-interview-questions Author: Gaurav Sharma Published: 2026-10-25 Updated: 2026-10-25 Full PDF: 61 pages, English + Hinglish; free by email request The 50 most-asked Node.js interview questions with detailed answers, for freshers and backend developers with up to 2 years of experience: the event loop, libuv, process.nextTick vs setImmediate, streams and backpressure, EventEmitter, cluster vs worker_threads vs child_process, Express middleware, JWT auth, Mongoose, graceful shutdown, testing, and coding and output-prediction questions, with code and Hinglish explanations. Topics: - What is Node.js and how does it differ from running JS in a browser? - What is the event loop? - CommonJS vs ES Modules in Node? - What is semver and what do ^ and ~ mean in package.json? - How does Node's module caching work? - What is a Buffer and why does Node need it? - What are streams in Node? Name the four types. - What is EventEmitter and how is it used? - process.nextTick vs setImmediate vs setTimeout(0)? - Blocking vs non-blocking I/O in Node? - What is Express.js and how does the middleware chain work? - How does error-handling middleware work in Express? - What makes an API RESTful? Key design principles? - How do you manage environment config in a Node app? - How do you handle errors in async/await code? - What is libuv and how does the thread pool fit in? - Microtasks vs macrotasks: what order do they run in? - How does Node resolve and cache CommonJS modules? - What is backpressure in streams and how do you handle it? - Duplex vs Transform streams, with an example? - What does the cluster module do and when would you use it? - worker_threads vs cluster vs child_process? - exec vs spawn vs fork in child_process? - Explain the JWT-based authentication flow. - How should passwords be hashed with bcrypt? - What is CORS and how do you fix a CORS error in Express? - How do you implement rate limiting? - What security headers does helmet add and why? - How do you structure Mongoose schemas and manage DB connection pooling? - How do you implement graceful shutdown on SIGTERM? - How is Redis commonly used for caching in a Node app? - What should good logging in a Node app look like? - How do you test an Express API with Jest and Supertest? - Promise.all vs Promise.allSettled? - What commonly causes memory leaks in a long-running Node process? - Predict the output: setTimeout, Promise.then and nextTick mixed. - Implement a simple EventEmitter from scratch. - Implement a debounce function. - Walk through the event loop's phases in order. - How does the libuv thread pool size affect fs and crypto performance? - How does stream.pipe() handle backpressure internally? - How do you debug and find a memory leak in production Node? - How do you run Node behind a load balancer and handle sticky sessions? - Design a REST CRUD API with validation and centralised error handling. - Implement JWT authentication middleware for Express. - Write full graceful-shutdown code for an Express + MongoDB app. - How do you size and tune a database connection pool for a Node service? - Predict the output of an async function awaiting inside a for loop vs a forEach. - How does Node handle circular require()s between two CommonJS modules? - How would you scale a Node.js API to handle 10x traffic? These are the 50 Node.js questions that come up most in backend and full-stack interviews, ordered from easy to hard. Each one starts with the short answer you should say first, then explains it properly with code, diagrams and the follow-up questions interviewers tend to ask next. ## What does each answer include? - **A two-line short answer** you can say word for word at the start. - **The detailed answer**: how it works, with code and its output where it helps. - **Traps and follow-ups**: the mistakes interviewers look for, and the next question they usually ask. - **Hinglish explanations** for the tricky ideas: the event loop's phases, backpressure and graceful shutdown. ## How should you practise with these questions? Cover the answer, say yours out loud, then compare. Write the coding questions yourself (a custom EventEmitter, debounce, a REST CRUD route with Express, JWT middleware) before reading the solutions. The night before the interview, go through the one-line answers at the end of the PDF. This is Part 4 of the interview questions series. To learn the concepts first, see the [Node.js handwritten notes](/placement/nodejs-handwritten-notes). --- # Article: RAG vs Fine-Tuning: How to Choose for Your AI Application URL: https://www.gaurav-sharma.in/blog/rag-vs-fine-tuning Author: Gaurav Sharma Published: 2026-11-02 Updated: 2026-11-02 Use retrieval-augmented generation (RAG) when an AI answer needs current or private information from documents. Consider fine-tuning when the model repeatedly fails a well-defined task despite a strong prompt and good examples. Test a prompt-based baseline first, then choose the approach that addresses the measured failure. Suppose a support assistant gives the wrong cancellation policy. Training may sound like the solution, but the failure could be simpler: it never received the current policy. Conversely, retrieving the same policy repeatedly will not necessarily fix an assistant that consistently classifies a request into the wrong category. Diagnose missing information separately from inconsistent task behavior. ## What is RAG? RAG finds relevant material outside the model and supplies it alongside a question. A typical document pipeline imports files, splits them into useful sections, indexes them, retrieves relevant sections and asks the model to answer from that evidence. [Google Cloud's RAG overview](https://docs.cloud.google.com/gemini-enterprise-agent-platform/build/rag-engine/rag-overview) describes this context-augmentation process. If embeddings are unfamiliar, start with [vector embeddings explained](/blog/vector-embeddings-explained) and the introductory [guide to RAG](/blog/what-is-rag-explained). Think of a support assistant looking up the right handbook before answering. The handbook can change without changing the underlying model. That separation is especially useful for policies, product documentation and organization-specific knowledge. ## What is fine-tuning? Fine-tuning continues training a model using examples for a more specific task. For supervised tuning, those examples demonstrate the desired relationship between an input and an output. The goal might be more consistent classification, a specialized response style or better performance on a narrow workflow. [Google Cloud's supervised tuning documentation](https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/tuning/supervised-tuning) explains adapting supported models with task-specific data. Availability and training requirements depend on the provider and model, so check them before committing to an implementation. Fine-tuning is not a convenient replacement for looking up a frequently edited policy. It also does not create a reliable reference trail back to the training examples. If the user needs to inspect the source, design that source handling explicitly. ## RAG vs fine-tuning: compare the trade-offs | Question | RAG | Fine-tuning | | --- | --- | --- | | What changes? | Context supplied during a request | Model behavior through additional training | | What data is prepared? | Searchable source material and metadata | Curated task examples and evaluation cases | | How are new facts introduced? | Update documents and refresh their index | Training is not a practical live lookup mechanism | | Can an answer reference a source? | Retrieved document IDs can support citations | Source retrieval must be designed separately | | What can go wrong? | Missing passages, stale data, permission leaks | Poor examples, overfitting, behavior regressions | | What adds cost? | Ingestion, retrieval and context tokens | Dataset work, training and model operation | Neither option is automatically cheaper or faster. Compare the full workload, including data preparation, retrieval latency, context size and the cost of correcting a bad answer. ## How would you build a support assistant? Consider a hypothetical SaaS product with separate customer workspaces. Its assistant must answer questions about plan limits and support policies without revealing another workspace's tickets. First, classify the information source. General product documentation can be searchable across users; private tickets require workspace-level restrictions. Record a document's owner, version, source URL and access scope during ingestion. Second, filter retrieval using trusted identity and authorization data from the server. Do not ask the model to decide which customer is allowed to see a document. Information already placed in its context has already crossed that boundary. Third, attach stable source IDs to retrieved passages. Ask the model to reference those IDs and verify that the returned references belong to the supplied evidence. A generated URL that looks plausible is not proof that an answer has support. Finally, define the insufficient-evidence response. “I could not find the current policy” is more useful than an invented answer. Where needed, route the question to a person with the retrieved evidence attached. ## When should you try fine-tuning instead? Consider tuning after collecting examples of a persistent, measurable behavior problem. A useful candidate might be a classifier that confuses two domain-specific request types even when the definitions and examples are present. Before training, review the labels. If two reviewers disagree on the correct category, the dataset may encode ambiguity rather than a learnable rule. Separate training examples from a held-out test set, and include edge cases that matter to the actual workflow. For an output-format problem, try a response schema and server-side validation first. The [Gemini structured-output guide](/blog/gemini-structured-output-zod) shows that pattern. Valid JSON alone does not establish that the content is true; check business rules and evidence separately. ## How do you evaluate the result? Create a small, versioned evaluation set before changing the architecture. Include ordinary questions, outdated facts, ambiguous requests and questions that should be refused for lack of access or evidence. Record these outcomes for each version: - Whether retrieval found the necessary source passage. - Whether each important claim is supported by that passage. - Whether references point to the supplied evidence. - Whether an unauthorized user can obtain restricted information. - Whether the app handles missing evidence without inventing an answer. - End-to-end latency and cost per completed task. These checks help isolate the next improvement. Fix retrieval when the evidence is missing; fix prompting or task behavior when the evidence is present but used incorrectly. If both problems remain, RAG and fine-tuning can be combined and evaluated as separate components. For implementation support, my [AI engineering service](/services/ai-engineer) covers LLM integrations and validated application output. ### What is the main difference between RAG and fine-tuning? RAG retrieves external information and supplies it as context during a request. Fine-tuning trains a model on examples to adapt its behavior. RAG changes the information available to an answer; fine-tuning changes how a model performs a task. ### Should I use RAG for frequently changing business documents? RAG is usually a useful starting point because documents can be updated and reindexed without retraining the model. You still need freshness checks, access controls and evaluation of the retrieved evidence. ### Can RAG and fine-tuning be used together? Yes. A tuned model can use retrieved documents as context. Evaluate retrieval and model behavior separately so that training does not hide missing evidence or incorrect document access. ### Does RAG prevent hallucinations? No. A model can misread retrieved text or answer without enough evidence. Evaluate factual support, verify citations and provide an explicit response for questions the documents cannot answer. --- # Article: Next.js vs React: Which Should You Choose for an SEO-Friendly Website? URL: https://www.gaurav-sharma.in/blog/nextjs-vs-react-seo Author: Gaurav Sharma Published: 2026-11-02 Updated: 2026-11-02 Choose Next.js when public pages, search discovery and server-rendered content are central to the product. React with Vite can suit an authenticated dashboard with an existing backend. Next.js uses React, so the decision is about the application framework and rendering model, rather than replacing React. An agency website and a sales dashboard might share buttons, forms and charts. Their discovery requirements are different: a prospective client must find the agency's services before logging in, while the dashboard's customer records must stay private. Start with that distinction before choosing a stack. ## What is the difference between Next.js and React? React provides the component model used to build interfaces. Next.js adds application conventions for routing, server execution, rendering and metadata. Vite supplies a development and build toolchain; a typical React and Vite single-page app still needs decisions about routing and backend integration. The [React documentation recommends starting new applications with a framework](https://react.dev/learn/creating-a-react-app). That guidance is compatible with choosing a smaller setup when an existing backend or a constrained interface makes it appropriate. The right question is which responsibilities the framework should own. ## Next.js vs React with Vite: a decision table | Requirement | Next.js | Typical React with Vite SPA | | --- | --- | --- | | Public articles and service pages | Built-in options for serving rendered HTML | Requires a deliberate rendering strategy if initial HTML is needed | | Page titles and canonical URLs | Metadata conventions integrated with routes | Set up metadata management and verify crawler output | | Existing independent REST API | Can consume it from server or client | A natural fit for a client interface | | Static hosting | Possible for supported export use cases | Straightforward for a client-only build | | Server-only credentials | Can live in server code | Belong in a separate backend, never the browser bundle | | Authenticated business tools | Supported | Supported | These are implementation trade-offs, not a ranking of framework quality. A small static site can be excellent for search, and a poorly implemented server-rendered site can still expose duplicate or empty pages. ## Why does rendering matter for SEO? Imagine a service page whose initial response contains only a root element and a script. The crawler must execute that script, fetch content and finish rendering before the service description becomes available. If an API fails or the script cannot load, the page's main answer may be absent. Google describes crawling, rendering and indexing as separate parts of [processing JavaScript websites](https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics). It can render JavaScript; that does not make every client-rendered implementation equally robust. For public pages, inspect what a request actually returns. Confirm that the service description, article text and ordinary links are present or reliably rendered. Verify a real unknown URL returns a 404 instead of serving a successful application shell for everything. Keep customer-specific data behind authentication regardless of rendering mode. ## What changes for AEO and GEO? Answer engine optimization, or AEO, focuses on making a page's answer easy to find and understand. Generative engine optimization, or GEO, is commonly used for visibility in AI-generated responses. Neither changes the fact that a useful page needs to answer a real question. For example, a heading such as “Can this developer integrate an existing API?” should be followed by a concrete answer, supported by relevant work. A paragraph listing unrelated keywords gives a reader little reason to trust it. Google says its [AI search features do not require special AI markup or new machine-readable files](https://developers.google.com/search/docs/appearance/ai-features). My practical recommendation is to spend implementation time on accessible content and evidence before adding speculative AI search features. Other engines have their own retrieval rules, and no rendering mode guarantees a citation. ## Which stack fits three common projects? **A developer portfolio with articles:** Next.js is a reasonable default when project case studies, services and a growing blog belong in one application. This portfolio's [SEO checklist](/blog/nextjs-seo-checklist) covers the metadata and content concerns that follow that decision. **A private CRM:** React with Vite and an Express API can keep the architecture direct when the application mainly runs behind login. [Atlass CRM](/projects/atlass-crm) is a relevant example of the kind of product involved. Its public marketing pages can have a separate rendering strategy. **A web product with AI features:** Either approach can work. The model API call, credentials and validation should run on a trusted backend. Read the [RAG vs fine-tuning guide](/blog/rag-vs-fine-tuning) if the feature needs private documents or specialized behavior. ## What should you check before launching? 1. Fetch a public page and verify that its main content is accessible. 2. Check each page's title, description, canonical URL and response status. 3. Follow internal links without relying on a search box or a click handler. 4. Compare structured data with the text readers can actually see. 5. Test loading, keyboard navigation and layout stability on a phone. 6. Inspect representative URLs in Search Console after deployment. Choose the framework that makes those checks easier for your team to maintain. If you need help scoping the public site and application together, see my [MERN and Next.js development service](/services/mern-stack-developer). ### Is Next.js better than React for SEO? Next.js supplies rendering and metadata tools that make public, content-heavy sites easier to maintain. React can also support SEO with an appropriate rendering setup. Search visibility depends on the delivered page and content, not the framework name. ### Can a React single-page app rank on Google? Yes. Google can render JavaScript, but rendering introduces dependencies on scripts and correct routing. Deliver important public content in initial HTML where practical, and verify the rendered output in Search Console. ### Does Next.js guarantee citations in AI answers? No. A framework cannot guarantee AI citations. Accessible text, useful answers, clear authorship and crawlable pages support discovery, while each search or answer engine decides what to retrieve and cite. ### Should an internal dashboard use Next.js or Vite? React with Vite can be a good fit for an authenticated dashboard backed by an existing API. Choose Next.js when its server rendering, integrated routing or server-side data access solves a specific project need. --- # Article: n8n Webhooks in Production: Authentication, Retries and Duplicate Events URL: https://www.gaurav-sharma.in/blog/n8n-webhook-production-guide Author: Gaurav Sharma Published: 2026-11-02 Updated: 2026-11-02 A production n8n webhook should authenticate the sender, validate the payload, durably record the event and handle retries without repeating business actions. Use the production URL for live events, acknowledge only after reliable acceptance, and give failed jobs a recovery path. A demo workflow often works like this: receive a lead, add it to a CRM and send a welcome message. The first real failure changes the problem. The CRM may succeed while the messaging service times out; the sender may then retry the original event. Without a record of what already happened, the workflow can create a second lead and send a second message. This guide proposes an architecture for that situation. It is a design pattern to implement and test, rather than a claim that every n8n deployment supplies these guarantees automatically. ## How do n8n test and production URLs differ? The Webhook node exposes separate URLs for development and live use. A test webhook listens when you start the test session. The production webhook is registered when the workflow is published, and production runs can be inspected in Executions. The [official Webhook documentation](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.webhook) explains the URL and response options. After testing, copy the production URL into the sending service. Confirm the HTTP method, public HTTPS address and authentication settings. A successful editor test does not prove that the sender can reach your deployed instance through a reverse proxy. ## What should the event contain? Give each event an identity that remains stable across retries. For a hypothetical lead integration, the useful fields might be: ```json { "eventId": "evt_demo_1042", "type": "lead.created", "occurredAt": "2026-11-02T10:00:00Z", "lead": { "externalId": "lead_demo_82", "email": "person@example.com" } } ``` Here, the event ID identifies the delivery's business event, while the external lead ID identifies the CRM entity. Reusing an email address as the event ID could incorrectly suppress a later, legitimate event involving the same person. Validate required fields, accepted event types and payload size before calling downstream APIs. Derive workspace ownership from trusted server-side configuration and authenticated credentials. A caller-controlled workspace field should not decide where sensitive data is written. ## How should you authenticate a webhook? For an integration you control, use the authentication mechanism supported by the sender and receiving endpoint. For providers that sign deliveries, follow their signature-verification specification, including the original request bytes and any timestamp or replay checks they require. If verification needs code that is awkward to implement in the workflow, place a small trusted gateway before n8n. Store credentials in server-side configuration or the platform's credential store. A hard-to-guess URL alone is a weak substitute for sender authentication. Reject invalid requests before storing executable jobs. Keep logs useful without copying credentials or entire customer payloads into every failure report. ## How do you handle duplicate events safely? Use durable storage with a unique key such as `(integration_id, event_id)`. Make the initial claim atomic. Two simultaneous deliveries can both pass a “does this exist?” lookup, so the database constraint must enforce uniqueness. Track the event's state and the outcome of each external side effect: | State | Meaning | Recovery action | | --- | --- | --- | | Received | Event has been stored | Eligible for processing | | Processing | Worker holds a time-limited claim | Reclaim after a verified abandoned attempt | | Completed | Required actions succeeded | Acknowledge a repeated delivery without repeating actions | | Failed | Attempt stopped before completion | Retry or request investigation according to the error | A database row cannot make an external API call atomic. If a worker crashes after a CRM write but before recording success, a replay may still repeat the write. Prefer downstream idempotency keys or an upsert based on the external lead ID. Otherwise, reconcile the external result before retrying. ## When should the webhook send its response? For short synchronous jobs, waiting for completion may be acceptable. For slow workflows, use durable acceptance followed by asynchronous processing. The response should describe what actually happened: accepted for processing is different from completed successfully. Avoid acknowledging before the event has a reliable storage or queue boundary. Once the sender receives success, it may stop retrying. Also plan for the opposite edge case: storage succeeds but the response is lost, so the sender retries. That is why duplicate protection belongs alongside durable acceptance. ## How should retries and error workflows work? Separate temporary failures from invalid requests. Retry connection failures, rate limits and appropriate server errors with bounded backoff; respect the provider's retry guidance. A malformed payload or revoked credential usually needs intervention, not an unlimited loop. n8n supports [error workflows beginning with an Error Trigger](https://docs.n8n.io/build/flow-logic/handle-errors-gracefully.md). Use them to record a failure reference and notify the responsible operator. An alert should include an event ID, workflow execution reference and safe error summary, so recovery does not require searching through unrelated payloads. At higher volume, [n8n queue mode](https://docs.n8n.io/deploy/host-n8n/configure-n8n/scaling/enable-queue-mode.md) distributes executions to workers using Redis. More workers improve processing capacity; they do not replace application-level idempotency. ## What should you test before launch? 1. Deliver the same event twice, including two concurrent requests. 2. Send invalid credentials, malformed JSON and an unsupported event type. 3. Simulate a downstream rate limit and confirm retries stop at the limit you configured. 4. Fail after the first external write and verify replay does not create another record. 5. Interrupt processing and check that abandoned work can be recovered. 6. Confirm the failure alert contains enough information to replay the event safely. For an AI step in the workflow, also validate the model output before making external writes. The [AI content-agent guide](/blog/ai-content-agent-gemini-n8n) covers drafting and review. My [n8n automation service](/services/ai-automation-developer) covers the integration work around that pipeline. ### What is the difference between test and production webhook URLs in n8n? The test URL listens during a test session. The production URL is registered when the workflow is published. Configure the external sender with the production URL for ongoing events and inspect production runs in Executions. ### How do I stop duplicate webhook events creating duplicate records? Use a stable event ID and an atomic unique constraint in durable storage. Track processing status and make downstream writes idempotent where possible. A lookup followed by an insert without a unique constraint can still race. ### Should an n8n webhook respond before processing finishes? For long workflows, acknowledge after the event is durably accepted and process it asynchronously. Responding before durable acceptance can lose events; waiting for slow external services can exceed the sender's timeout. ### Does n8n queue mode guarantee exactly-once processing? No. Queue mode distributes workflow execution to workers; business-level duplicate protection still requires event IDs, durable state and safe handling of retries and partial failures. --- # Article: Flutter vs React Native: How to Choose for an iOS and Android App URL: https://www.gaurav-sharma.in/blog/flutter-vs-react-native Author: Gaurav Sharma Published: 2026-11-02 Updated: 2026-11-02 Choose Flutter when its Dart ecosystem and widget system fit your team and interface requirements. Choose React Native when React and TypeScript experience offers a practical head start and its native integrations meet your needs. Validate the hardest feature on iOS and Android before committing; neither framework is universally faster or cheaper. For an MVP, the most expensive mistake may be discovering too late that an essential camera, payment or background-location integration does not behave as expected. A framework comparison is useful only when it leads to a realistic test of your product's difficult parts. This guide is a decision framework, not a performance benchmark. It focuses on the work a team must maintain after the first screen is built. ## How do Flutter and React Native work? Flutter uses Dart and a composable widget system. Its engine handles much of the interface rendering, and platform integrations connect the application to operating-system capabilities. The [Flutter architecture overview](https://docs.flutter.dev/resources/architectural-overview) explains these layers and the platform-channel mechanism for calling native code. React Native uses React to describe mobile interfaces with JavaScript or TypeScript. Its architecture includes native rendering and native module integration. The [React Native architecture guide](https://reactnative.dev/architecture/landing-page) describes JSI and the move away from the older asynchronous bridge. Avoid comparisons that assume every current React Native app still uses that older design. Both approaches can call native APIs. Both can also require platform-specific code, tooling and debugging when a feature extends beyond the shared application layer. ## Flutter vs React Native: compare the project fit | Decision | Flutter | React Native | | --- | --- | --- | | Main language | Dart | JavaScript or TypeScript | | UI approach | Flutter widgets and rendering | React components backed by native platform rendering | | Existing web team | Requires learning Dart and Flutter conventions | React knowledge transfers, though mobile development is still different | | Custom interface | Widget composition provides extensive control | Components, styling and animation libraries provide control | | Native SDK integration | Check plugins and platform channels | Check native packages and module compatibility | | Long-term ownership | Needs Flutter, mobile and release skills | Needs React Native, mobile and release skills | The table is a starting point. Package support, product requirements and the team's actual experience should decide the outcome. ## Which is better for an existing React team? React Native can reduce the amount of unfamiliar application code for developers already comfortable with React and TypeScript. State management patterns, API client logic and data models may be reusable. The browser interface usually is not reusable as-is. A web page built from DOM elements and CSS does not become a mobile screen simply by changing its build command. Navigation, keyboard handling, touch targets and accessibility need mobile-specific attention. Before estimating the project, separate shared business logic from shared UI. If most of the proposed reuse is actually browser components, budget for a larger interface rewrite than the initial comparison suggests. ## When is Flutter a strong fit? Flutter is worth evaluating when the team is comfortable with Dart or wants a consistent widget system across its mobile screens. A product with a custom visual language may benefit from keeping much of that interface within one rendering approach. That does not eliminate platform differences. Camera views, maps, embedded web content and native SDKs still need integration testing. Check plugin maintenance and the behavior required by the specific product, rather than treating “supports iOS and Android” as the whole acceptance criterion. For a Flutter codebase that is growing beyond a prototype, the next decision is how to organize state and business logic. Read [Provider vs Bloc with MVVM](/blog/flutter-provider-vs-bloc-mvvm) for that separate architectural question. ## How should you compare performance? Define a workload before picking a winner. A content app might care about a long image feed and video startup. A field-service app might care more about maps, location updates and interrupted connectivity. A drawing tool has a different set of constraints again. Build the critical screen in release mode and test on a representative lower-end Android device as well as an iPhone. Record startup time, scrolling behavior, memory use and response to user input. Include network delays and large datasets instead of evaluating an empty screen on a development machine. Measure accessibility too. A screen that scrolls smoothly but fails with larger text or a screen reader is not ready for the users it needs to serve. ## Which native integrations should you verify first? List the features that depend on platform capabilities or third-party SDKs. Useful candidates include: - Sign-in callbacks and deep links from a cold start. - Push notifications while the app is open, backgrounded or closed. - Camera access, file selection and permission denial. - Purchases, subscription restoration and payment SDK callbacks. - Offline writes, synchronization and duplicate-submission handling. - Background work required by the product's actual use case. For each feature, identify a maintained package, confirm its compatibility with the framework version you plan to ship, and test failure states. React Native's [native platform documentation](https://reactnative.dev/docs/native-platform) is a useful starting point when a package does not cover the integration. ## What determines cost and release effort? Shared code can reduce duplicated feature work, but the total still includes design, backend integration, platform testing, signing, store review and maintenance. Neither framework can determine a reliable project price without scope. Write a short delivery plan: required screens, external services, offline behavior, supported devices and release responsibilities. Include account ownership and who handles a broken integration after launch. If automations sit behind the app, the [n8n webhook production guide](/blog/n8n-webhook-production-guide) covers duplicate events and safe retries at that boundary. ## A practical decision process for an MVP 1. Rank the product's essential features and identify the riskiest native integration. 2. Confirm which mobile skills the team can maintain after launch. 3. Prototype that integration and one representative screen. 4. Test release builds and error states on both operating systems. 5. Estimate the remaining work using the prototype's findings. Pick the framework after that evidence is available. If Flutter matches the project, my [Flutter app development service](/services/flutter-app-developer) describes the implementation scope for iOS and Android. ### What is the main difference between Flutter and React Native? Flutter uses Dart and its own widget and rendering system. React Native uses React with JavaScript or TypeScript and renders through native platform components. Both can share substantial application code across iOS and Android. ### Is Flutter faster than React Native? There is no universal winner. Performance depends on the screen, device, implementation and libraries. Compare release builds using representative scrolling, startup, animation and native integration workloads on target devices. ### Can I reuse a React website directly in React Native? Usually not its DOM-based interface. React concepts, types and some non-UI business logic can transfer, but mobile components, navigation, permissions and platform behavior need their own implementation. ### Does a cross-platform app still need separate iOS and Android testing? Yes. Test permissions, notifications, deep links, purchases, keyboard behavior, accessibility and store releases on both platforms. Shared source code does not make operating-system behavior identical. --- # Article: What Are Vector Embeddings? How They Work, Cosine Similarity and a Python Semantic Search Example URL: https://www.gaurav-sharma.in/blog/vector-embeddings-explained Author: Gaurav Sharma Published: 2026-10-25 Updated: 2026-10-25 A vector embedding is a list of numbers that represents the meaning of a piece of text (or an image, product or user). An embedding model is trained so that similar things get vectors that point in similar directions, which lets a computer measure "how related are these two things?" with simple arithmetic such as cosine similarity. That single trick powers semantic search, retrieval-augmented generation (RAG), recommendations, clustering and deduplication. ## Why do we need embeddings? Computers compare numbers well and words badly. To a string comparison, "reset your password" and "I forgot my login" share no words, so a keyword search says they are unrelated. A person knows they are about the same thing. Embeddings fix this by mapping each piece of text to a point in a high-dimensional space where **distance means difference in meaning**. "Reset your password" and "I forgot my login" land close together; "shipping times for international orders" lands far away. Once text is a point, every question about meaning becomes geometry: nearest neighbours, clusters, angles. The same idea works for anything you can train a model on: images, audio, code, products, users. ## What do the numbers in an embedding actually mean? An embedding for a sentence from a typical model looks like this: ```text [0.021, -0.113, 0.067, 0.004, ..., -0.059] # 384 to 3072 numbers ``` No single number has a human-readable meaning. There is no "dimension 17 = about food". Meaning is spread across the whole vector, and only the *relationships* between vectors are interpretable: which ones are near each other, and in which direction they differ. Two useful mental models: - **A location.** Each text is a point; related texts are neighbours. Searching is "find the points nearest to my query point". - **A direction.** Most models care about where a vector points, not how long it is. That is why cosine similarity (angle) is the usual measure, and why vectors are often normalised to length 1. Typical sizes: open-source sentence models such as `all-MiniLM-L6-v2` produce 384 dimensions; `bge-base` and similar produce 768; large hosted models produce 1024 to 3072. Bigger is not automatically better; it is more storage per vector and slower comparisons, in exchange for finer distinctions. ## How does an embedding model learn? Modern text embedding models are transformer encoders (BERT-style) trained with **contrastive learning**: 1. Take millions of pairs that should be close: a question and its answer, a title and its article, two paraphrases, a query and the result someone clicked. 2. Also take texts that should be far apart (random or hard negatives). 3. Adjust the model so that the pair's vectors move together and the negatives move apart, usually by pushing cosine similarity up for positives and down for negatives. After enough of this, the model's output space has the property we want: semantic closeness equals geometric closeness, even for sentences it has never seen. Older word-level methods (word2vec, GloVe) learned a vector per word from co-occurrence; sentence-transformer models embed a whole passage with context, which is what you want for search and RAG. ## How do you measure similarity between embeddings? | Measure | Formula | Range | Notes | | --- | --- | --- | --- | | Cosine similarity | (a · b) / (‖a‖ ‖b‖) | -1 to 1 | Direction only. The default for text | | Dot product | a · b | unbounded | Equals cosine when both vectors are unit length. Fastest | | Euclidean (L2) distance | ‖a − b‖ | 0 to ∞ | Smaller is closer. Equivalent ranking to cosine on normalised vectors | In practice: normalise every vector once when you create it, then use the dot product everywhere. It is the same ranking as cosine similarity and a single multiply-add per dimension. ```python import numpy as np def cosine(a, b): return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))) ``` What counts as "similar" depends on the model. For one model 0.8 may be a near-paraphrase and for another 0.6 may be; the absolute number is not comparable across models, only the ranking within one model is. ## Semantic search in Python in 20 lines This runs on a laptop CPU with an open-source model. Install with `pip install sentence-transformers numpy`. ```python from sentence_transformers import SentenceTransformer import numpy as np model = SentenceTransformer("all-MiniLM-L6-v2") # 384-dim, small, fast on CPU docs = [ "How to reset your password", "Refund policy for cancelled orders", "Setting up two-factor authentication", "Shipping times for international orders", "Changing the email address on your account", ] # Embed once; normalise so the dot product equals cosine similarity. doc_vecs = model.encode(docs, normalize_embeddings=True) # shape (5, 384) def search(query, k=3): q = model.encode([query], normalize_embeddings=True)[0] scores = doc_vecs @ q # one dot product per doc top = np.argsort(-scores)[:k] return [(round(float(scores[i]), 2), docs[i]) for i in top] for s, d in search("I forgot my login"): print(s, d) ``` Output (scores vary slightly by model version): ```text 0.58 How to reset your password 0.40 Changing the email address on your account 0.31 Setting up two-factor authentication ``` The query shares no words with the top result. That is the whole point of embeddings. Three details worth noticing: the documents were embedded **once** and reused; the query was embedded with the **same model**; and both were **normalised** so a plain matrix-vector product gives cosine similarity for every document at once. ## Where are embeddings used? | Use case | How embeddings help | | --- | --- | | Semantic search | Find documents by meaning, not keywords | | RAG | Retrieve the passages to put in an LLM's prompt; see [What is RAG?](/blog/what-is-rag-explained) | | Recommendations | Items near what a user liked; users near each other | | Clustering and topic discovery | Group support tickets, reviews or news by similarity | | Deduplication | Near-duplicate detection for documents, listings, questions | | Classification | Embed, then train a small classifier on the vectors, or compare to label embeddings (zero-shot) | | Anomaly detection | Items far from every cluster | | Multimodal search | Text-to-image search with CLIP-style models | ## Embeddings vs keyword search: use both Embedding search is not a replacement for keyword search; it is a complement. | | Keyword (BM25) | Embeddings | | --- | --- | --- | | "forgot my login" finds "reset password" | No | Yes | | Exact codes, SKUs, error strings, rare names | Excellent | Often misses them | | Needs a model at index and query time | No | Yes | | Explainable ("matched these words") | Yes | Not really | Production systems use **hybrid search**: run both, merge the ranked lists (reciprocal rank fusion is the common method), and optionally pass the top candidates through a **reranker**, a cross-encoder model that reads query and document together and scores them more accurately than a dot product can. ## Do you need a vector database? Only at scale. A rough guide: - **Up to ~50k vectors**: a NumPy array in memory and a dot product. Milliseconds. No infrastructure. - **Up to a few million**: an approximate nearest neighbour (ANN) index such as FAISS or HNSW (used by Chroma, Qdrant, Weaviate, pgvector). ANN trades a little recall for queries that stay fast as the collection grows. - **Already running PostgreSQL**: the pgvector extension keeps vectors next to your rows, with normal SQL filters and joins. - **Large, multi-tenant, or no ops team**: a managed service (Pinecone, Qdrant Cloud, Weaviate Cloud, MongoDB Atlas Vector Search). Whichever you pick, store the **original text and metadata** alongside each vector (source, title, date, permissions). You will need them to build the prompt, show citations and filter results. ## How to choose an embedding model - **Check a benchmark, then test on your data.** The MTEB leaderboard ranks models on retrieval, clustering and classification. Use it to shortlist, then evaluate on 50 to 100 real queries from your own domain; rankings shift between domains. - **Open source vs API.** Open models (`all-MiniLM`, `bge`, `e5`, `nomic-embed`, `gte`) run locally, cost nothing per call and keep data in-house. Hosted models (OpenAI, Google, Cohere, Voyage) are stronger on many benchmarks and zero-maintenance, but every embedding is a network call and a line on a bill. - **Dimensions and storage.** One million 1536-dimension float32 vectors is about 6 GB before any index. Smaller models, int8 quantisation or truncated dimensions cut this a lot. - **Context length.** Models truncate input past their limit (often 512 tokens for small models, 8k for larger ones). Anything beyond the limit is silently ignored, which is one reason documents are chunked. - **Language.** If your users write in Hindi or a mix of languages, pick a multilingual model and test it; English-only models degrade sharply. - **Query vs document prefixes.** Some models (e5, bge, nomic) expect a prefix such as `"query: "` or `"passage: "`. Skipping it costs real accuracy. ## Mistakes that quietly ruin embedding results - **Mixing models.** Vectors from two models, or two versions of one model, are not comparable. Re-embed everything when you switch. - **Not normalising** when using the dot product. Long texts get longer vectors in some models and win every search. - **Embedding whole documents.** A 30-page PDF squeezed into one vector matches everything a little and nothing well. Chunk into passages of a few hundred tokens. - **Chunks with no context.** A chunk that says "It defaults to 30 days" is unsearchable. Prepend the document title or section heading to each chunk before embedding. - **Trusting the score threshold.** A fixed cutoff like 0.7 means different things for different models and domains. Calibrate on labelled examples. - **Ignoring metadata filtering.** "Documents this user may see, from this year" should be a filter, not something you hope the vector encodes. - **No evaluation set.** Without labelled query-to-passage pairs you cannot tell whether a new model, chunk size or prefix helped. Before touching a vector database, embed a few hundred of your own documents with two candidate models, run 30 real queries, and look at the top 5 results for each by eye. Ten minutes of this tells you more than any leaderboard. ## Key takeaway An embedding is meaning turned into coordinates. Train a model so similar things point the same way, normalise the vectors, and a dot product tells you how related any two items are. Use embeddings for semantic search and retrieval, pair them with keyword search for exact matches, chunk documents sensibly, never mix models, and measure on your own queries. For how retrieval plugs into an LLM, read [What is RAG?](/blog/what-is-rag-explained); for the surrounding ML concepts on one page, download the free [AI/ML and GenAI handwritten notes](/placement/ai-ml-handwritten-notes). If you need semantic search or a RAG system built on your own data, see [AI engineering services](/services/ai-engineer). ### What is a vector embedding in simple terms? An embedding is a list of numbers (a vector) that represents the meaning of a piece of text, an image or any other item. An embedding model is trained so that items with similar meaning get vectors that point in similar directions. That turns the fuzzy question 'are these two things about the same thing?' into a number you can compute, which is what makes semantic search, recommendations and RAG possible. ### How many dimensions does an embedding have? It depends on the model: small open-source sentence models use 384 or 768 dimensions, while large commercial models use 1024 to 3072. More dimensions can capture finer distinctions but cost more storage and compute per comparison. Several recent models let you truncate the vector to a smaller size with only a small loss in quality. ### What is cosine similarity and why is it used for embeddings? Cosine similarity is the cosine of the angle between two vectors: 1 means they point the same way, 0 means unrelated, -1 means opposite. It ignores the vectors' lengths and compares only direction, which is what encodes meaning in most embedding models. If vectors are normalised to length 1, cosine similarity is simply their dot product, which is fast to compute at scale. ### What is the difference between embeddings and keyword search? Keyword search (like BM25) matches the exact words in the query, so 'forgot my login' will not find a document titled 'reset your password'. Embedding search compares meaning, so it finds that document. Keyword search is still better for exact identifiers, codes and rare names, which is why production systems usually combine both in hybrid search. ### Do I need a vector database to use embeddings? Not for small collections. Up to tens of thousands of vectors, a NumPy array and a dot product are fast enough. Beyond that, or when you need filtering, updates and persistence, use a vector index: FAISS or Chroma locally, pgvector inside PostgreSQL, or a managed service such as Pinecone, Qdrant or Weaviate. ### Can I compare embeddings from two different models? No. Each model has its own vector space, so a vector from model A means nothing next to a vector from model B, even if the dimensions match. Always embed the stored documents and the incoming queries with the same model and version, and re-embed everything if you switch models. ### Are embeddings only for text? No. Image models embed pictures, audio models embed sound, and multimodal models such as CLIP put text and images in the same space so you can search photos with a sentence. Recommendation systems also learn embeddings for users and products from behaviour alone, with no text involved. --- # Article: SQL Joins Explained with Examples: INNER, LEFT, RIGHT, FULL, CROSS and SELF JOIN URL: https://www.gaurav-sharma.in/blog/sql-joins-explained Author: Gaurav Sharma Published: 2026-10-25 Updated: 2026-10-25 A SQL join combines rows from two tables using a condition, usually a shared key. INNER JOIN keeps only matching rows; LEFT and RIGHT JOIN keep every row from one side and fill the other with NULL; FULL OUTER JOIN keeps everything from both; CROSS JOIN pairs every row with every row; a SELF JOIN joins a table to itself. The rest of this guide shows each one on the same two tables so you can see exactly which rows survive. ## The two tables used in every example Every example below uses the same data, so you can compare the output row by row. One employee has no department, and one department has no employees, because those are the cases that make the join types different. **employees** | id | name | dept_id | | --- | --- | --- | | 1 | Asha | 10 | | 2 | Ravi | 20 | | 3 | Meera | NULL | | 4 | Karan | 40 | **departments** | id | name | | --- | --- | | 10 | Engineering | | 20 | Sales | | 30 | HR | Notice: Meera has no department at all, Karan points at a department (40) that does not exist, and HR (30) has nobody in it. Only Asha and Ravi match on both sides. ```sql CREATE TABLE departments (id INT PRIMARY KEY, name VARCHAR(50)); CREATE TABLE employees (id INT PRIMARY KEY, name VARCHAR(50), dept_id INT); INSERT INTO departments VALUES (10, 'Engineering'), (20, 'Sales'), (30, 'HR'); INSERT INTO employees VALUES (1, 'Asha', 10), (2, 'Ravi', 20), (3, 'Meera', NULL), (4, 'Karan', 40); ``` ## What is an INNER JOIN? An INNER JOIN returns a row only when the ON condition is true for a pair of rows. Unmatched rows on either side are dropped. ```sql SELECT e.name, d.name AS department FROM employees e INNER JOIN departments d ON d.id = e.dept_id; ``` | name | department | | --- | --- | | Asha | Engineering | | Ravi | Sales | Meera (NULL department), Karan (department 40 does not exist) and HR (no employees) all disappear. `JOIN` on its own means `INNER JOIN`; the word INNER is optional. Use it when a row only makes sense if both sides exist: an order line and its product, a student and the course they enrolled in. ## What is a LEFT JOIN? A LEFT JOIN (also written LEFT OUTER JOIN) keeps **every row from the left table**, the one named before the JOIN keyword. When the right table has no match, its columns come back as NULL. ```sql SELECT e.name, d.name AS department FROM employees e LEFT JOIN departments d ON d.id = e.dept_id; ``` | name | department | | --- | --- | | Asha | Engineering | | Ravi | Sales | | Meera | NULL | | Karan | NULL | All four employees survive. Meera and Karan get NULL because nothing matched. HR is still missing because it is on the right side and nobody referenced it. This is the join you reach for in most reporting queries: "all customers, with their latest order if any", "all products, with their total sales even if zero". ## What is a RIGHT JOIN? A RIGHT JOIN keeps **every row from the right table** and fills the left with NULL. It is the exact mirror of LEFT JOIN. ```sql SELECT e.name, d.name AS department FROM employees e RIGHT JOIN departments d ON d.id = e.dept_id; ``` | name | department | | --- | --- | | Asha | Engineering | | Ravi | Sales | | NULL | HR | Now HR appears with no employee, while Meera and Karan are gone. The same result comes from swapping the table order and using LEFT JOIN, which is why many teams never write RIGHT JOIN at all: it is easier to read a query when the "keep all of these" table is always first. ```sql SELECT e.name, d.name AS department FROM departments d LEFT JOIN employees e ON e.dept_id = d.id; -- identical output ``` ## What is a FULL OUTER JOIN? A FULL OUTER JOIN keeps every row from **both** tables. Matching rows are merged; unmatched rows from either side are padded with NULL. ```sql SELECT e.name, d.name AS department FROM employees e FULL OUTER JOIN departments d ON d.id = e.dept_id; ``` | name | department | | --- | --- | | Asha | Engineering | | Ravi | Sales | | Meera | NULL | | Karan | NULL | | NULL | HR | PostgreSQL, SQL Server, Oracle and SQLite (3.39+) support it. **MySQL does not.** In MySQL you emulate it with a UNION of the LEFT and RIGHT joins; UNION removes the duplicate matched rows: ```sql SELECT e.name, d.name AS department FROM employees e LEFT JOIN departments d ON d.id = e.dept_id UNION SELECT e.name, d.name FROM employees e RIGHT JOIN departments d ON d.id = e.dept_id; ``` FULL OUTER JOIN is mostly used for reconciliation: comparing two lists and finding what is only in one of them. ## What is a CROSS JOIN? A CROSS JOIN has no ON condition. It pairs every row of the first table with every row of the second: the Cartesian product. 4 employees × 3 departments = 12 rows. ```sql SELECT e.name, d.name AS department FROM employees e CROSS JOIN departments d; ``` | name | department | | --- | --- | | Asha | Engineering | | Asha | Sales | | Asha | HR | | Ravi | Engineering | | … | … | It is useful on purpose for generating combinations (every size of every T-shirt, every day of a date range against every store). It happens by accident when you list two tables in FROM with a comma and forget the WHERE clause, which on a million-row table is a query that never finishes. ## What is a SELF JOIN? A self join is not a separate keyword. It is any join where both sides are the same table, under two different aliases. The classic case is a hierarchy stored in one table. ```sql CREATE TABLE staff (id INT PRIMARY KEY, name VARCHAR(50), manager_id INT); INSERT INTO staff VALUES (1, 'Priya', NULL), (2, 'Asha', 1), (3, 'Ravi', 1), (4, 'Karan', 2); SELECT s.name AS employee, m.name AS manager FROM staff s LEFT JOIN staff m ON m.id = s.manager_id; ``` | employee | manager | | --- | --- | | Priya | NULL | | Asha | Priya | | Ravi | Priya | | Karan | Asha | A LEFT JOIN is used so the top of the tree (Priya, who has no manager) is not dropped. Other self-join uses: finding duplicate rows, pairing each row with the previous one by date, or listing employees who share a department with a given person. ## The ON vs WHERE trap This is the single most common join bug, and a favourite interview question. Suppose you want **all** employees, and the department name only when the department is in a given building: ```sql -- WRONG: silently becomes an inner join SELECT e.name, d.name FROM employees e LEFT JOIN departments d ON d.id = e.dept_id WHERE d.name <> 'HR'; ``` The LEFT JOIN first produces NULL department rows for Meera and Karan. Then the WHERE clause evaluates `NULL <> 'HR'`, which is not true, so those rows are thrown away. The result has only Asha and Ravi, exactly as if you had written INNER JOIN. ```sql -- RIGHT: extra conditions on the outer table go in ON SELECT e.name, d.name FROM employees e LEFT JOIN departments d ON d.id = e.dept_id AND d.name <> 'HR'; ``` Rule of thumb: in an outer join, conditions that filter the **preserved** (left) table can go in WHERE; conditions on the **nullable** (right) table belong in ON. ## How many rows will a join return? Interviewers like to ask this because it shows whether you understand matching, not just syntax. | Join | Rows returned | | --- | --- | | INNER | One row per matching pair. Can be fewer than either table, or more if keys repeat on both sides | | LEFT | At least every left row. Left rows with several matches are repeated once per match | | RIGHT | At least every right row, same repetition rule | | FULL | Matched pairs + unmatched left + unmatched right | | CROSS | left rows × right rows | Two things to remember: - **NULL never matches NULL.** `NULL = NULL` is unknown, not true, so a row with a NULL key is never joined by an equality condition. That is why Meera is unmatched even if a department also had a NULL id. - **Duplicates multiply.** If an employee appears twice in a table and their department appears twice in the other, the join produces four rows for that pair. Unexpected row counts after a join almost always mean a key you thought was unique is not. ## Anti joins and semi joins Two patterns built on joins show up constantly in real queries. **Anti join: rows with no match.** Employees who are not in any existing department: ```sql SELECT e.* FROM employees e LEFT JOIN departments d ON d.id = e.dept_id WHERE d.id IS NULL; -- Meera, Karan ``` The same thing with `NOT EXISTS`, which many people find clearer and which the optimiser handles well: ```sql SELECT e.* FROM employees e WHERE NOT EXISTS (SELECT 1 FROM departments d WHERE d.id = e.dept_id); ``` Avoid `NOT IN (SELECT dept_id ...)` when the subquery can contain NULL: a single NULL in the list makes `NOT IN` return no rows at all. **Semi join: rows that have at least one match, without duplicating them.** Departments that have at least one employee: ```sql SELECT d.* FROM departments d WHERE EXISTS (SELECT 1 FROM employees e WHERE e.dept_id = d.id); -- Engineering, Sales ``` An INNER JOIN would give the same departments but repeated once per employee; EXISTS returns each department once. ## USING, NATURAL JOIN and joining more than two tables - `JOIN departments USING (dept_id)` works when both columns have the same name and merges them into one output column. Fine for quick queries. - `NATURAL JOIN` joins on **every** column with a matching name. Avoid it: adding a column called `name` or `created_at` to either table silently changes the join. - Joins chain left to right. Each JOIN clause joins the result so far with the next table, so with three tables you can mix types: `orders LEFT JOIN customers ... INNER JOIN products ...`. Read it one step at a time and ask what rows exist after each step. ## Joins and performance The optimiser decides how to execute a join (nested loop, hash join, merge join); you decide whether it has what it needs. - **Index the join columns.** Foreign keys such as `employees.dept_id` should be indexed; the primary key side already is. - **Filter early.** Put selective WHERE conditions on the driving table so fewer rows reach the join. - **Select only needed columns.** `SELECT *` across four tables drags wide rows through every step. - **Run EXPLAIN.** If you see a full table scan on the big table in a join, you are missing an index or a usable condition. When a join returns too many rows, do not add DISTINCT to hide it. Find the duplicated key: run SELECT key, COUNT(*) FROM table GROUP BY key HAVING COUNT(*) > 1 on each side. DISTINCT papers over a data problem and makes the query slower. ## SQL join interview questions 1. **INNER vs LEFT JOIN?** INNER keeps matches only; LEFT keeps all left rows with NULLs for missing right rows. 2. **Can a LEFT JOIN return fewer rows than the left table?** No. It returns at least one row per left row, and more when a left row matches several right rows. 3. **Why is my LEFT JOIN behaving like an INNER JOIN?** A WHERE condition on the right table drops the NULL-padded rows. Move it into ON. 4. **How do you get rows with no match?** LEFT JOIN with `WHERE right.key IS NULL`, or NOT EXISTS. 5. **What is the output size of a CROSS JOIN?** Rows in A × rows in B. 6. **How do you write FULL OUTER JOIN in MySQL?** UNION of a LEFT JOIN and a RIGHT JOIN. 7. **Do NULL keys match in a join?** Never with `=`. Use `IS NOT DISTINCT FROM` (PostgreSQL) or COALESCE if you really need NULL-safe matching. 8. **JOIN vs subquery?** Joins return columns from both tables and are usually what the optimiser prefers; EXISTS subqueries are better for "does a match exist" checks because they do not duplicate rows. ## Key takeaway Pick the join by asking one question: which table's rows must survive even without a match? Both sides must match: INNER. Keep the left side: LEFT. Keep both: FULL. Every combination: CROSS. Then put filters on the nullable table in ON, not WHERE, and check row counts against the key rules above. For the rest of DBMS (normalisation, indexes, transactions, the questions that follow joins in an interview), download the free [SQL handwritten notes](/placement/sql-handwritten-notes) and follow the [placement preparation roadmap](/blog/placement-preparation-roadmap-2026). ### What is the difference between INNER JOIN and LEFT JOIN? INNER JOIN returns only the rows where the join condition matches in both tables. LEFT JOIN returns every row from the left table, and fills the right table's columns with NULL when there is no match. Use INNER JOIN when both sides must exist, and LEFT JOIN when you want to keep the left rows that have nothing on the other side, such as customers with no orders. ### What is the difference between a LEFT JOIN and a RIGHT JOIN? They are mirror images. LEFT JOIN keeps all rows from the table written before the JOIN keyword; RIGHT JOIN keeps all rows from the table written after it. Any RIGHT JOIN can be rewritten as a LEFT JOIN by swapping the table order, which is why most codebases use LEFT JOIN only. ### What does a FULL OUTER JOIN return? All rows from both tables. Rows that match on the join condition are combined into one row; rows with no match on the other side are kept with NULLs in the missing columns. MySQL does not support FULL OUTER JOIN, so you emulate it with a UNION of a LEFT JOIN and a RIGHT JOIN. ### What is a CROSS JOIN? A CROSS JOIN pairs every row of the first table with every row of the second, producing the Cartesian product. With 4 rows and 3 rows you get 12 rows. It has no ON clause and is useful for generating combinations, such as every product in every size, but accidentally writing one on large tables is a classic performance bug. ### What is a SELF JOIN in SQL? A self join joins a table to itself using two aliases, usually to compare rows within the same table. The standard example is an employees table with a manager_id column: joining employees e to employees m ON e.manager_id = m.id lists each employee next to their manager's name. ### Why does my LEFT JOIN return the same rows as an INNER JOIN? Almost always because a condition on the right table was put in the WHERE clause instead of the ON clause. After the LEFT JOIN fills unmatched rows with NULL, a WHERE filter like right_table.column = 'x' throws those NULL rows away, which turns the join into an inner join. Move the condition into the ON clause to keep the unmatched left rows. ### How do you find rows in one table that have no match in another? Use an anti join: LEFT JOIN the second table and keep only the rows where the second table's key IS NULL. For example, SELECT c.* FROM customers c LEFT JOIN orders o ON o.customer_id = c.id WHERE o.id IS NULL returns customers who never ordered. NOT EXISTS with a correlated subquery gives the same result and is often clearer. --- # Article: JWT vs Session Authentication: How Each Works, When to Use Which (with Express Examples) URL: https://www.gaurav-sharma.in/blog/jwt-vs-session-authentication Author: Gaurav Sharma Published: 2026-10-25 Updated: 2026-10-25 Session authentication keeps the logged-in state on the server and gives the browser a cookie with a random session ID. JWT authentication puts the state inside a signed token that the client sends with every request, so the server verifies a signature instead of looking anything up. Sessions are simpler and easy to revoke; JWTs are stateless and scale across services but are hard to invalidate before they expire. Most single apps should start with sessions or short-lived JWTs in httpOnly cookies. ## Why does HTTP need authentication state at all? HTTP is stateless. The request that loads your dashboard carries no memory of the login request that came before it. So after a successful login, the server has to hand the client *something* it can present on every later request to prove "this is still the same logged-in user". The two mainstream answers are: - **A session ID**: a random string that means nothing by itself and is looked up on the server. - **A JSON Web Token (JWT)**: a self-contained, signed record of who the user is, verified by maths rather than by lookup. Everything else in this comparison follows from that one difference: *lookup* versus *verify*. ## How does session-based authentication work? 1. The user posts their email and password. The server checks the password hash (with bcrypt or argon2). 2. The server creates a session record, `{ userId: 42, createdAt, ... }`, in a session store (memory in development; Redis, PostgreSQL or MongoDB in production), keyed by a long random ID. 3. It sends that ID to the browser in a cookie: `Set-Cookie: sid=9f3c...; HttpOnly; Secure; SameSite=Lax`. 4. The browser automatically attaches the cookie to every later request to that domain. 5. On each request, the server reads the cookie, looks up the session, and now knows the user. 6. Logout deletes the session record. The cookie is instantly useless even if someone copied it. The cookie contains **no information**, only a reference. All the state lives on the server, which is why this is called *stateful* authentication. ### Minimal Express example with express-session ```js import express from "express"; import session from "express-session"; const app = express(); app.use(express.json()); app.use( session({ secret: process.env.SESSION_SECRET, // signs the cookie so it cannot be tampered with resave: false, saveUninitialized: false, cookie: { httpOnly: true, secure: true, sameSite: "lax", maxAge: 1000 * 60 * 60 * 24 }, // store: new RedisStore({ client }) in production; the default MemoryStore leaks and resets on restart }) ); app.post("/login", async (req, res) => { const user = await findUserAndVerifyPassword(req.body.email, req.body.password); if (!user) return res.status(401).json({ error: "Invalid credentials" }); req.session.userId = user.id; // state lives on the server res.json({ ok: true }); }); const requireAuth = (req, res, next) => req.session.userId ? next() : res.status(401).json({ error: "Not logged in" }); app.get("/me", requireAuth, async (req, res) => { res.json(await getUser(req.session.userId)); }); app.post("/logout", (req, res) => { req.session.destroy(() => res.json({ ok: true })); // instant revocation }); ``` ## How does JWT authentication work? A JWT is three base64url-encoded parts joined by dots: `header.payload.signature`. | Part | Example (decoded) | Purpose | | --- | --- | --- | | Header | `{"alg":"HS256","typ":"JWT"}` | Which algorithm signed it | | Payload | `{"sub":"42","role":"admin","iat":1761350400,"exp":1761351300}` | Claims: who, what, issued-at, expiry | | Signature | `HMAC-SHA256(header + "." + payload, secret)` | Proves the first two parts were not changed | The flow: 1. The user logs in; the server verifies the password. 2. The server builds the payload and signs it with a secret (HS256) or a private key (RS256). This is the token. 3. The client stores the token and sends it on every request, either as `Authorization: Bearer ` or in a cookie. 4. The server recomputes the signature and compares. If it matches and `exp` has not passed, the claims are trusted. **No database lookup is needed.** 5. "Logout" means the client throws the token away. The server cannot forget a token it never stored. The token carries the state, which is why this is called *stateless* authentication. It is also why a JWT is not secret: anyone holding it can base64-decode the payload and read every claim. The signature stops them changing it, not reading it. ### Minimal Express example with jsonwebtoken ```js import express from "express"; import jwt from "jsonwebtoken"; import cookieParser from "cookie-parser"; const app = express(); app.use(express.json()); app.use(cookieParser()); const ACCESS_TTL = "15m"; app.post("/login", async (req, res) => { const user = await findUserAndVerifyPassword(req.body.email, req.body.password); if (!user) return res.status(401).json({ error: "Invalid credentials" }); const token = jwt.sign({ sub: String(user.id), role: user.role }, process.env.JWT_SECRET, { algorithm: "HS256", expiresIn: ACCESS_TTL, }); // httpOnly cookie: JavaScript on the page cannot read it, so XSS cannot steal it res.cookie("access", token, { httpOnly: true, secure: true, sameSite: "lax", maxAge: 15 * 60 * 1000 }); res.json({ ok: true }); }); const requireAuth = (req, res, next) => { const token = req.cookies.access ?? req.headers.authorization?.replace("Bearer ", ""); if (!token) return res.status(401).json({ error: "Not logged in" }); try { req.user = jwt.verify(token, process.env.JWT_SECRET, { algorithms: ["HS256"] }); // pin the algorithm next(); } catch { res.status(401).json({ error: "Invalid or expired token" }); } }; app.get("/me", requireAuth, async (req, res) => { res.json(await getUser(req.user.sub)); }); app.post("/logout", (req, res) => { res.clearCookie("access"); // client-side only: a copied token stays valid until exp res.json({ ok: true }); }); ``` This is close to what I use in [Atlass CRM](/projects/atlass-crm) and [HireMate](/projects/hiremate): JWTs signed on login, passwords hashed with bcryptjs, and a `requireAuth` middleware in front of every protected route. ## JWT vs session: side-by-side comparison | | Sessions | JWT | | --- | --- | --- | | Where state lives | Server (session store) | Inside the token, on the client | | Per-request cost | One store lookup (fast in Redis) | One signature check, no I/O | | Logout / revocation | Instant: delete the session | Not possible without extra state; wait for expiry | | Scaling across servers | Needs a shared store (Redis) or sticky sessions | Any server with the secret or public key can verify | | Across services / domains | Awkward: every service must reach the store | Natural: pass the token along, verify anywhere | | Mobile and third-party API clients | Cookies are clumsy | Bearer header is the standard | | Payload visibility | Nothing on the client | Claims readable by anyone with the token | | Token size per request | ~32 bytes (the ID) | 200 bytes to several KB | | Changing a user's role | Takes effect immediately | Old token keeps old role until it expires | | Typical pitfalls | Default MemoryStore in production; missing cookie flags | localStorage storage; no expiry; weak secret; `alg` confusion | ## The revocation problem, and refresh tokens The biggest practical weakness of JWTs is that you cannot take one back. If a user logs out, changes their password, or is banned, any access token already issued keeps working until `exp`. The standard answer is **two tokens**: - An **access token**: a JWT with a short life (5 to 15 minutes). Sent on every request. If stolen, it is useful for minutes, not weeks. - A **refresh token**: long-lived (days to weeks), stored in an httpOnly cookie *and* recorded in the database. Used only on a `/refresh` endpoint to mint a new access token. Logout and password change now delete the refresh token row. The access token dies within minutes on its own. You get stateless verification on the hot path and real revocation on the slow path. If a product truly needs instant invalidation of access tokens (banking, admin consoles), keep a denylist of revoked token IDs (`jti` claim) in Redis with a TTL equal to the token's remaining life, and check it in `requireAuth`. At that point you have reintroduced a lookup, and plain sessions may have been simpler. ## Where to store a JWT in the browser This is where most JWT tutorials go wrong. - **localStorage / sessionStorage**: readable by any JavaScript on the page. One XSS bug (a vulnerable dependency, a markdown renderer, a browser extension) and the token is gone. Avoid. - **httpOnly cookie**: invisible to JavaScript. Immune to token theft via XSS. Needs CSRF protection because the browser attaches cookies automatically: use `SameSite=Lax` or `Strict`, and a CSRF token or origin check for state-changing requests from other sites. - **In memory only** (a variable in your SPA): safe from XSS reads, lost on reload. Pair it with a refresh token in an httpOnly cookie so the app can silently get a new access token on page load. Cookie flags you should always set: `HttpOnly`, `Secure`, `SameSite`, a `Max-Age`, and a tight `Path` if the API lives under one prefix. ## Security mistakes with JWTs - **Not pinning the algorithm.** Older libraries accepted `"alg": "none"` or let an attacker switch RS256 to HS256 and sign with the public key. Always pass `algorithms: ["HS256"]` (or `["RS256"]`) to `verify`. - **Weak or shared secrets.** HS256 secrets must be long and random (32+ bytes). If several services verify tokens, use RS256 so they only need the public key. - **No expiry.** A token without `exp` is a permanent password. Always set `expiresIn`. - **Sensitive data in the payload.** It is readable. Put the user ID and role in, not the email, address or anything regulated. - **Trusting claims that can go stale.** If `role` is in the token, a demoted admin stays admin until expiry. Keep sensitive authorization checks server-side when they must be instant. - **Logging tokens.** A bearer token in a log line is a credential in a log line. ## Which should you use? - **Server-rendered site or one app with one backend (most student and freelance projects):** sessions with Redis, or short-lived JWTs in httpOnly cookies. Both are fine; sessions are the simpler secure default. - **Several backend services, or a separate domain for API and frontend:** JWT access tokens plus refresh tokens, verified independently by each service. - **Mobile apps and public APIs:** JWT bearer tokens. - **Logging in with Google, GitHub, Auth0, Clerk, Firebase:** the provider issues JWTs (ID tokens); your job is to verify them with the provider's public keys. If you are deciding for a MERN project: a JWT in an httpOnly cookie with a 15-minute expiry and a refresh token stored in MongoDB is the pattern that satisfies interviewers, scales to a second service later, and does not leak tokens to XSS. It is about 40 lines of Express. ## Interview questions on JWT and sessions 1. **What are the three parts of a JWT?** Header (algorithm), payload (claims), signature (HMAC or RSA over the first two). 2. **Is a JWT encrypted?** No. It is signed. Anyone can decode the payload; only the signature proves it was not modified. 3. **Why are JWTs called stateless?** The server stores nothing per login; the token carries the state and is verified by signature. 4. **How do you revoke a JWT?** You cannot directly. Use short expiry plus server-stored refresh tokens, or a denylist of token IDs. 5. **Session ID vs JWT in a cookie, what is the difference?** The session ID is a lookup key; the JWT is self-describing. Both should be httpOnly, Secure and SameSite. 6. **What is CSRF and does JWT prevent it?** A cross-site request that the browser sends with your cookies attached. JWT in a header is immune (nothing is attached automatically); JWT in a cookie is not, so use SameSite and CSRF tokens. 7. **What goes in `sub`, `iat`, `exp`?** Subject (user ID), issued-at time, expiry time, all standard claims. 8. **Why not store the JWT in localStorage?** Any script on the page can read it, so a single XSS vulnerability steals every user's token. ## Key takeaway Sessions: the server remembers you, the cookie is just a key, logout is instant. JWTs: the token remembers you, the server only checks a signature, and revocation needs a refresh-token layer. Pick sessions for simplicity in a single app, JWTs for multiple services and non-browser clients, and in both cases put the credential in an httpOnly, Secure, SameSite cookie with an expiry. The Node and Express fundamentals behind this, including middleware and cookies, are in the free [Node.js handwritten notes](/placement/nodejs-handwritten-notes); if you need authentication built properly into a MERN app, see [MERN stack development services](/services/mern-stack-developer). ### What is the difference between JWT and session authentication? With sessions, the server stores the logged-in user's state and gives the browser a cookie containing only a random session ID; each request is checked by looking that ID up. With JWT, the server signs a token that contains the user's identity and expiry, and the client sends it back on each request; the server verifies the signature instead of looking anything up. Sessions are stateful and easy to revoke; JWTs are stateless and easy to scale but hard to revoke before they expire. ### Is JWT more secure than sessions? Neither is more secure by itself. A session ID in an httpOnly, Secure, SameSite cookie is a very safe default. JWTs add risks if misused: storing them in localStorage exposes them to XSS, long expiry makes stolen tokens valuable, and the payload is readable by anyone who has the token. Used with short expiry, httpOnly cookies and a strong secret, JWTs are fine; used carelessly, they are worse than sessions. ### Where should I store a JWT in the browser? In an httpOnly cookie, not localStorage. JavaScript cannot read httpOnly cookies, so a cross-site scripting bug cannot steal the token. Add Secure so it is only sent over HTTPS, and SameSite=Lax or Strict to limit cross-site request forgery. If you must send the token in an Authorization header from a single-page app, keep it in memory only and use a short-lived access token with a refresh token in an httpOnly cookie. ### How do you log out with JWT? You cannot invalidate a signed JWT on the server without state, so logout is usually: delete the token on the client, keep access tokens short-lived (5 to 15 minutes), and revoke the refresh token in the database. If you need instant revocation of access tokens, keep a denylist of token IDs in Redis until they expire, which reintroduces some server state. ### What is a refresh token? A long-lived credential stored securely (usually an httpOnly cookie and a database record) that is used only to obtain new short-lived access tokens. It lets the access token expire quickly, limiting the damage from theft, while the user stays logged in. Because the refresh token is stored server-side, it can be revoked on logout or password change. ### Can a JWT be decoded without the secret? Yes. The header and payload are only base64url-encoded, not encrypted, so anyone with the token can read every claim. The secret is needed only to create or verify the signature. Never put passwords, card numbers or anything private in a JWT payload. If the content itself must be hidden, use an encrypted token (JWE) or keep the data on the server. ### When should I use sessions instead of JWT? Use sessions for a traditional server-rendered website or a single app with its own backend, where you want instant logout, easy revocation and the simplest secure default. Use JWTs when several services or domains must verify identity without sharing a session store, for mobile or third-party API clients, or when an identity provider issues the tokens. --- # Article: What Is RAG? Retrieval-Augmented Generation Explained Simply (with Python) URL: https://www.gaurav-sharma.in/blog/what-is-rag-explained Author: Gaurav Sharma Published: 2026-10-22 Updated: 2026-10-22 RAG (retrieval-augmented generation) means searching your own data for the passages that answer a question, then giving those passages to a large language model along with the question. The model answers from that context instead of from memory, so it can use private, recent information and cite its sources, with no retraining. ## Why do LLMs need RAG? A language model only knows what was in its training data. That causes three problems in real applications: - **It doesn't know your data.** Your company wiki, product docs, contracts or support tickets were never in the training set. - **Its knowledge is frozen.** Anything that changed after the training cutoff is missing or out of date. - **It answers confidently anyway.** Ask about something it doesn't know and it may produce a fluent, wrong answer, often called a hallucination. You could paste every document into the prompt, but context windows are limited, long prompts cost more and get slower, and models attend less reliably to details buried in very long inputs. RAG solves this by sending only the few passages that matter for *this* question. Think of it as an open-book exam: the model is still the student writing the answer, but retrieval hands it the right pages first. ## How does a RAG pipeline work? A RAG system has two halves. **Ingestion** prepares your documents once (and again whenever they change). **Querying** runs on every question. | Stage | Step | What happens | | --- | --- | --- | | Ingest | Load | Read PDFs, web pages, docs, tickets; extract clean text and keep metadata (title, URL, date, permissions) | | Ingest | Chunk | Split text into passages of a few hundred tokens, usually with a small overlap | | Ingest | Embed | Turn each chunk into a vector with an embedding model | | Ingest | Store | Save vectors, chunk text and metadata in a vector index or database | | Query | Embed | Turn the user's question into a vector with the **same** embedding model | | Query | Retrieve | Find the top-k most similar chunks (often k = 3 to 10), optionally filtered by metadata | | Query | Rerank | Optionally re-score the candidates with a reranker model and keep the best few | | Query | Prompt | Put the chunks into the prompt with instructions: answer only from this context, cite sources | | Query | Generate | The LLM writes the answer and references the chunks it used | The quality of the final answer is capped by retrieval. If the right chunk is not in the prompt, no model can answer correctly from it, which is why most RAG work is really search work. ## How should you chunk documents? Chunking decides what a "passage" is, and it has more effect on answer quality than most people expect. | Choice | Typical starting point | Trade-off | | --- | --- | --- | | Chunk size | 300–800 tokens | Too small loses context; too large dilutes the match and wastes prompt space | | Overlap | 10–20% of the chunk | Keeps sentences that cross a boundary findable from both sides | | Split points | Headings, then paragraphs, then sentences | Splitting on structure keeps ideas together; fixed character cuts break them | | Metadata | Title, section, URL, date, access rights | Enables filters, citations and permission checks | Practical tips from building these systems: - **Prepend context to each chunk.** A chunk that says "It expires after 30 days" is useless alone. Store it as "Refund policy → Store credit: It expires after 30 days". - **Clean the text first.** Headers, footers, navigation menus and broken tables from PDF extraction add noise that ends up in the prompt. - **Keep tables and code blocks whole** where you can; splitting them mid-row produces chunks nobody can use. There is no universally best chunk size. Pick a sensible default, build a small test set of real questions, and adjust based on what retrieval actually returns. ## What are embeddings and vector databases? An **embedding** is a list of numbers (a vector) that represents the meaning of a piece of text. Texts with similar meaning get vectors that point in similar directions, so "How do I reset my password?" lands close to "Steps to change your login credentials" even though they share few words. Similarity is usually measured with **cosine similarity**: the cosine of the angle between two vectors, where 1 means same direction and values near 0 mean unrelated. A **vector database** stores those vectors and finds the nearest ones quickly. Exact search compares the question with every vector, which is fine for thousands of chunks. For millions, databases use approximate nearest neighbour (ANN) indexes such as HNSW, trading a tiny amount of accuracy for a large speed-up. Common options, with no single right answer: - **In-memory or a local library (for example Chroma or FAISS)**: prototypes and small datasets. - **pgvector**: a PostgreSQL extension, good when your app already uses Postgres and you want vectors next to your relational data and permissions. - **Managed vector databases (for example Pinecone, Weaviate, Qdrant)**: large collections, high query volume, or teams that do not want to operate the infrastructure. Always embed the question with the same embedding model you used for the chunks. Vectors from different models live in different spaces, and comparing them returns nonsense without any error. Many production systems also use **hybrid search**: combine vector similarity with keyword search (BM25) so exact terms such as product codes, error messages and names are not missed. ## How do you build a simple RAG pipeline in Python? Here is the whole idea in a few lines. `embed()` and `llm()` stand for whichever embedding model and LLM API you use; the retrieval logic is plain NumPy. ```python import numpy as np def embed(texts: list[str]) -> np.ndarray: """Call your embedding model; return one vector per text.""" ... def llm(prompt: str) -> str: """Call your chat model; return its reply.""" ... # --- Ingest (run once) --- chunks = [ "Refunds: items can be returned within 30 days of delivery.", "Refunds: store credit expires 12 months after it is issued.", "Shipping: orders over 999 rupees ship free within India.", ] vectors = embed(chunks) vectors = vectors / np.linalg.norm(vectors, axis=1, keepdims=True) # --- Query (run per question) --- def answer(question: str, k: int = 2) -> str: q = embed([question])[0] q = q / np.linalg.norm(q) scores = vectors @ q # cosine similarity top = np.argsort(scores)[::-1][:k] # best k chunks context = "\n".join(f"[{i + 1}] {chunks[j]}" for i, j in enumerate(top)) prompt = ( "Answer using only the context below. Cite sources like [1]. " "If the answer is not in the context, say you don't know.\n\n" f"Context:\n{context}\n\nQuestion: {question}" ) return llm(prompt) print(answer("How long do I have to return something?")) ``` Normalising every vector to length 1 makes the dot product equal to cosine similarity, so one matrix multiplication scores every chunk at once. Swap the NumPy array for a vector database when the collection grows; the shape of the code stays the same. ## RAG vs fine-tuning vs prompting: which should you use? | | Prompting | RAG | Fine-tuning | | --- | --- | --- | --- | | What it changes | The instructions and examples you send | The context you send, retrieved per question | The model's weights | | Best for | Format, tone, simple tasks | Facts from your own, changing data, with citations | A consistent style, output format or narrow skill | | Updating knowledge | Edit the prompt | Re-index the changed documents | Retrain | | Cost to start | Lowest | Moderate: ingestion and a vector store | Highest: data preparation and training runs | | Shows sources | No | Yes | No | Start with prompting. Add RAG when the model needs knowledge it doesn't have. Consider fine-tuning when prompting and RAG work but the model still does not follow your format or style reliably. They also combine: a fine-tuned model can still sit behind a RAG pipeline. ## How do you evaluate a RAG system? "It looked right in the demo" is not evaluation. Build a test set of 30 to 100 real questions with the answer and the source passage for each, and measure the two halves separately: | Metric | Measures | Question it answers | | --- | --- | --- | | Retrieval recall at k | Retrieval | Is the correct chunk in the top k results? | | Precision / MRR | Retrieval | Are the right chunks ranked near the top? | | Faithfulness (groundedness) | Generation | Is every claim in the answer supported by the retrieved context? | | Answer relevance | Generation | Does the answer actually address the question? | | Correctness | End to end | Does it match the expected answer? | Generation metrics are often scored by another LLM acting as a judge, with a human spot-checking a sample. Re-run the test set whenever you change chunking, the embedding model, k, the prompt or the LLM, so you know whether a change helped. ## What are common RAG failures and how do you fix them? | Symptom | Likely cause | Fix | | --- | --- | --- | | Right document exists, wrong chunks retrieved | Poor chunking or weak embeddings | Split on structure, add titles to chunks, try hybrid search or a better embedding model | | Exact names, codes or error messages missed | Pure vector search | Add keyword (BM25) search and merge the results | | Right chunks retrieved, wrong answer | Prompt too vague or too much noise | Fewer, reranked chunks; clearer instructions; ask for citations | | Confident answer that is not in the data | Model fills gaps from memory | Instruct it to say "I don't know"; check faithfulness | | Outdated answers | Index not refreshed | Re-ingest on change; store dates and prefer recent chunks | | Users see documents they should not | No access control in retrieval | Store permissions as metadata and filter before retrieval | When answers are wrong, look at what was retrieved before you touch the prompt. Log the question, the retrieved chunks and the answer for every request; most bugs are obvious once you see the chunks. ## What is agentic RAG? Basic RAG retrieves once and answers. **Agentic RAG** lets the model decide how to search: it can rewrite the question, split it into sub-questions, call retrieval as a tool several times, query different sources (a vector store, a SQL database, a web search), and check whether it has enough information before answering. It handles multi-step questions such as "Compare our refund policy with last year's" much better, at the cost of more LLM calls, higher latency and more ways to go wrong. Get simple retrieval working and measured first, then add agent behaviour where single-shot retrieval clearly falls short. ## Key takeaway RAG is search plus a language model: retrieve the passages that answer the question, put them in the prompt, and make the model answer only from them with citations. Spend your effort on clean text, sensible chunks, the right embedding model and a test set, because retrieval quality sets the ceiling for every answer. For a one-page visual of the pipeline and the surrounding ML and GenAI concepts, see the free [AI/ML and GenAI handwritten notes](/placement/ai-ml-handwritten-notes) (the RAG pipeline is on page 20), and brush up on the language with the [Python handwritten notes](/placement/python-handwritten-notes). If you want a RAG system or AI assistant built for your own data, see [AI engineering services](/services/ai-engineer). ### What is RAG in AI? RAG (retrieval-augmented generation) is a technique where an application first searches a knowledge source, such as company documents, for passages relevant to a question, then gives those passages to a large language model together with the question. The model writes its answer from that retrieved context, so it can use private or recent information and cite where the answer came from. ### What is the difference between RAG and fine-tuning? RAG adds knowledge at question time by retrieving documents and putting them in the prompt, so updating knowledge means updating the documents. Fine-tuning changes the model's weights by training it on examples, which is better for teaching a style, format or narrow skill than for adding facts. Most teams that need a model to know their data start with RAG. ### What are the steps in a RAG pipeline? Ingestion runs ahead of time: load documents, split them into chunks, turn each chunk into an embedding vector and store the vectors in a vector database. At query time: embed the question, retrieve the most similar chunks, optionally rerank them, put the best ones in the prompt and ask the LLM to answer only from that context, with citations. ### Which vector database should I use for RAG? For a small project, an in-memory index or a local library such as Chroma is enough. If you already run PostgreSQL, the pgvector extension keeps vectors next to your other data. Managed services such as Pinecone, Weaviate or Qdrant Cloud suit large collections or teams that do not want to run the infrastructure. Retrieval quality depends more on chunking and embeddings than on the database. ### Does RAG stop LLM hallucinations? It reduces them but does not remove them. If retrieval misses the right passage, the model may still guess, and it can misread a correct passage. Instruct the model to answer only from the context and to say it does not know otherwise, require citations, and measure faithfulness on a test set. --- # Article: Placement Preparation Roadmap 2026: What to Study, in What Order URL: https://www.gaurav-sharma.in/blog/placement-preparation-roadmap-2026 Author: Gaurav Sharma Published: 2026-10-22 Updated: 2026-10-22 Prepare for campus placements in this order: aptitude and DSA in one language first, then the core CS subjects (OOPs, DBMS and SQL, Operating Systems, Computer Networks), then one or two strong projects, and finally mock interviews and HR answers. Each step below links a free notes PDF. ## What are the rounds in a campus placement drive? Every company is different, but most drives follow a similar sequence: | Round | What it usually tests | Prepare with | | --- | --- | --- | | Online assessment | Aptitude, logical reasoning, 1–3 coding problems | [Aptitude notes](/placement/aptitude-handwritten-notes), [DSA notes](/placement/dsa-handwritten-notes) | | Technical interview 1 | DSA problems, your language, OOPs | DSA + [C](/placement/c-handwritten-notes) / [C++](/placement/cpp-handwritten-notes) / [Java](/placement/java-handwritten-notes) / [Python](/placement/python-handwritten-notes), [OOPs](/placement/oops-handwritten-notes) | | Technical interview 2 | Core CS, projects, sometimes design | [SQL & DBMS](/placement/sql-handwritten-notes), [OS](/placement/os-handwritten-notes), [Computer Networks](/placement/computer-networks-handwritten-notes) | | HR / managerial | Communication, motivation, fit | Practised answers about yourself and your projects | Product companies tend to go deeper on DSA and may add [System Design](/placement/system-design-handwritten-notes) basics; service companies often weigh aptitude and core subjects more. ## In what order should you study? 1. **Pick one language** (C++, Java or Python) and learn it well enough to write code without looking things up. 2. **Aptitude**, a little every day: percentages, profit and loss, time and work, speed and distance, probability, and reasoning puzzles. 3. **DSA by pattern**, not by random problems: arrays and hashing, two pointers, sliding window, binary search, linked lists, stacks, trees, graphs, then dynamic programming. 4. **OOPs**: the four pillars, abstract class vs interface, SOLID, with examples in your language. 5. **DBMS and SQL**: keys, normalization, transactions and ACID, indexing, and writing joins and GROUP BY queries by hand. 6. **Operating Systems**: processes vs threads, CPU scheduling, deadlocks, memory management and paging. 7. **Computer Networks**: OSI and TCP/IP layers, TCP vs UDP, HTTP and HTTPS, DNS, and what happens when you type a URL. 8. **Projects**: one or two you can explain end to end, pushed to GitHub ([Git notes](/placement/git-handwritten-notes)). For web roles, add [HTML and CSS](/placement/html-css-handwritten-notes), [JavaScript](/placement/javascript-handwritten-notes), [React](/placement/react-handwritten-notes), [Node.js](/placement/nodejs-handwritten-notes), [TypeScript](/placement/typescript-handwritten-notes) or [Next.js](/placement/nextjs-handwritten-notes); for mobile, [Flutter](/placement/flutter-handwritten-notes); for AI roles, [AI/ML and GenAI](/placement/ai-ml-handwritten-notes). 9. **Mock interviews and HR**: practise out loud with a friend or on video. Use the Top 50 interview question sets for [JavaScript](/placement/javascript-interview-questions), [C++](/placement/cpp-interview-questions) and [React](/placement/react-interview-questions): say the short answer first, then explain. Daily beats intense: 30 minutes of aptitude and two DSA problems every day for 12 weeks is about 170 problems and 40 hours of aptitude. Cramming the same amount into the last two weeks rarely sticks. ## A 12-week placement preparation plan | Weeks | Focus | Daily target | | --- | --- | --- | | 1–2 | Language basics, arrays, strings, hashing · aptitude basics | 2 problems + 30 min aptitude | | 3–4 | Two pointers, sliding window, binary search · OOPs | 2 problems + 1 OOPs topic | | 5–6 | Linked lists, stacks, queues, recursion · DBMS and SQL | 2 problems + 10 SQL queries | | 7–8 | Trees, BST, heaps · Operating Systems | 2 problems + 1 OS topic | | 9–10 | Graphs, greedy, dynamic programming · Computer Networks | 2 problems + 1 CN topic | | 11 | Project polish, resume, System Design basics | Explain each project in 2 minutes | | 12 | Mock tests and interviews, HR answers, revision cheat sheets | 1 timed mock per day | ## What do interviewers look for beyond correct answers? - **Thinking out loud.** Explain your approach and its time complexity before you code. - **Fundamentals over buzzwords.** Being able to explain a deadlock or a join clearly beats listing ten frameworks. - **Ownership of your projects.** Know why you chose each technology and what you would change. - **Honest answers.** "I don't know, but here is how I would find out" is better than guessing. ## How should you revise the night before? Use one-page summaries instead of new material. Every PDF in the [Placement Series](/placement) ends with a revision cheat sheet: go through the ones for the rounds you have next, redo two or three problems you got wrong earlier, and sleep. ## Key takeaway Study in the order the rounds come: aptitude and DSA for the online test, OOPs and core CS for the technical interviews, projects and communication for the final rounds. Keep it daily, keep it in one language, and revise from short notes. All 20 handwritten-style notes PDFs are free on the [Placement Series](/placement) page. ### What should I study first for campus placements? Start with aptitude and DSA in one programming language (C++, Java or Python), because online assessments usually test those first. Then cover the core CS subjects interviewers ask about: OOPs, DBMS and SQL, Operating Systems and Computer Networks. ### How many months does placement preparation take? Most students need about three to six months of steady practice. A focused 12-week plan covering aptitude, DSA patterns, core CS subjects, one strong project and mock interviews is enough for many service and product company drives if you practise daily. ### Which programming language is best for placements? Any one of C++, Java or Python. C++ and Java are the most common for DSA rounds, and Python is fine if you are comfortable with it. Pick one and use it for every coding round instead of switching. ### Do I need projects for campus placements? Yes. Interviewers almost always ask about your projects. One or two projects you built yourself and can explain in depth, including design choices and problems you solved, matter more than a long list. ### Where can I get free placement notes? The Placement Series on gaurav-sharma.in has free handwritten-style PDF notes for aptitude, DSA, C, C++, Java, Python, OOPs, SQL, OS, Computer Networks, System Design, Git, HTML and CSS, JavaScript, TypeScript, React, Node.js, Next.js, Flutter and AI/ML, with no sign-up. --- # Article: Next.js 16 proxy.ts vs middleware.ts: What Changed and How to Migrate URL: https://www.gaurav-sharma.in/blog/nextjs-16-middleware-to-proxy Author: Gaurav Sharma Published: 2026-10-22 Updated: 2026-10-22 In Next.js 16, middleware.ts is renamed to proxy.ts and its exported function from middleware to proxy. It still runs before a request reaches your routes, it now runs on the Node.js runtime, and you migrate with one codemod. ## What changed from middleware to proxy? | | Next.js 15 | Next.js 16 | | --- | --- | --- | | File | `middleware.ts` | `proxy.ts` (project root or `src/`) | | Export | `export function middleware()` | `export function proxy()` or a default export | | Runtime | Edge by default | Node.js (cannot be changed) | | Config flag | `skipMiddlewareUrlNormalize` | `skipProxyUrlNormalize` | | Status | Current | `middleware` deprecated | The behaviour is the same idea: code that runs **before** a request is matched to a route, so it can redirect, rewrite, or set headers and cookies. ## How do you migrate to proxy.ts? Run the official codemod from your project root: ```bash npx @next/codemod@canary middleware-to-proxy . ``` Or do it by hand: rename the file, rename the function, keep the `config` export. ```ts // proxy.ts import { NextResponse, type NextRequest } from "next/server"; export function proxy(request: NextRequest) { const session = request.cookies.get("session")?.value; if (!session && request.nextUrl.pathname.startsWith("/dashboard")) { return NextResponse.redirect(new URL("/login", request.url)); } return NextResponse.next(); } export const config = { matcher: ["/dashboard/:path*"], }; ``` ## How does the matcher work? The `matcher` decides which paths run the proxy. Skipping static files keeps it cheap: | Matcher | Runs on | | --- | --- | | `"/about/:path*"` | `/about` and everything under it | | `["/dashboard/:path*", "/account/:path*"]` | Several sections | | `"/((?!api\|_next/static\|_next/image\|.*\\.png$).*)"` | Everything except API routes, Next.js assets and PNGs | Matchers can also be objects with `source`, `has` and `missing` conditions, for example to run only when a header or cookie is present. ## What should proxy.ts be used for? | Good use | Avoid | | --- | --- | | Redirect logged-out users (cookie check) | Full authorization decisions | | A/B tests and rewrites (`NextResponse.rewrite`) | Slow database queries | | Locale or geo routing | Heavy work on every request | | Adding security or tracing headers | Relying on `fetch` cache options (they have no effect here) | `NextResponse.next()` continues to the route, `NextResponse.redirect(url)` sends the browser elsewhere, and `NextResponse.rewrite(url)` serves a different route while **keeping the URL** in the address bar. ## Why proxy is not your security layer Proxy is an **optimistic** check. A typo in the matcher, a new route, or a direct call to a Server Action can skip it entirely. Server Actions in particular are public POST endpoints. Treat proxy like the watchman at the gate: useful for turning people away early, but every room still needs its own lock. Verify the session again in Server Components, Server Actions and route handlers. ```ts "use server"; export async function deleteProject(id: string) { const session = await auth(); // real check, every time if (!session) throw new Error("Unauthorized"); await db.project.delete({ where: { id, ownerId: session.userId } }); } ``` ## Key takeaway Rename `middleware.ts` to `proxy.ts` (or run the codemod), keep the matcher narrow, and use proxy for fast redirects, rewrites and headers. Do real authorization next to the data. For everything else that changed in Next.js 16, see [Next.js 16 caching explained](/blog/nextjs-16-caching-use-cache) and the free [Next.js handwritten notes](/placement/nextjs-handwritten-notes). ### Is middleware.ts deprecated in Next.js 16? Yes. Starting with Next.js 16, Middleware is called Proxy. The middleware.ts file name and the middleware export are deprecated; rename the file to proxy.ts and export a function named proxy (or a default export). ### How do I migrate middleware.ts to proxy.ts? Run the official codemod with npx @next/codemod@canary middleware-to-proxy . in the project root, or rename middleware.ts to proxy.ts and rename the exported middleware function to proxy. The config and matcher stay the same. ### Which runtime does proxy.ts use in Next.js 16? Proxy runs on the Node.js runtime, and the runtime cannot be changed in the proxy file. Projects that need the edge runtime can keep using middleware for now. ### Should I do authentication in proxy.ts? Only an optimistic check, such as redirecting visitors without a session cookie away from /dashboard. Always verify the session again where data is read or changed: in Server Components, Server Actions and route handlers, because a matcher mistake or a new route can skip the proxy. --- # Article: Next.js 16 Caching Explained: use cache, cacheLife and updateTag vs revalidateTag URL: https://www.gaurav-sharma.in/blog/nextjs-16-caching-use-cache Author: Gaurav Sharma Published: 2026-10-22 Updated: 2026-10-22 In Next.js 16, caching is explicit: nothing is cached until you mark it with the 'use cache' directive. You set how long it lives with cacheLife, label it with cacheTag, and invalidate it with updateTag (immediately) or revalidateTag (in the background). ## What changed in Next.js 16 caching? Earlier versions of the App Router cached a lot implicitly, which made it hard to know why a page showed stale data. Next.js 16 flips the default with **Cache Components**: | | Before (Next.js 14–15) | Next.js 16 with Cache Components | | --- | --- | --- | | Default | Many fetches and routes cached implicitly | Nothing cached unless you say so | | How to cache | `fetch` options, `export const revalidate` | `'use cache'` + `cacheLife` | | Invalidate | `revalidateTag(tag)`, `revalidatePath` | `updateTag`, `revalidateTag(tag, profile)`, `revalidatePath` | | Static + dynamic in one page | Hard | Partial Prerendering by default | Turn it on in `next.config.ts` (new apps already have it): ```ts import type { NextConfig } from "next"; const nextConfig: NextConfig = { cacheComponents: true, }; export default nextConfig; ``` ## How do you use the 'use cache' directive? Put `'use cache'` at the top of a function, a component or a whole file. The function's **arguments** become part of the cache key, so `getProducts("shoes")` and `getProducts("bags")` are cached separately. ```ts import { cacheLife, cacheTag } from "next/cache"; export async function getProducts(category: string) { "use cache"; cacheLife("hours"); // how long it stays fresh cacheTag("products"); // a label to invalidate it later return db.product.findMany({ where: { category } }); } ``` A cached component works the same way: ```tsx export async function Footer() { "use cache"; const links = await getFooterLinks(); return {/* … */}; } ``` | Placement | What gets cached | | --- | --- | | Top of a file | Every export (they must all be async) | | Inside a component | Its rendered output | | Inside a function | Its return value | ## What do the cacheLife profiles mean? Each profile sets three times. **stale** is how long the browser may reuse data without asking; **revalidate** is when the server starts refreshing in the background; **expire** is when old data can no longer be served at all. | Profile | stale | revalidate | expire | | --- | --- | --- | --- | | `"seconds"` | 30 s | 1 s | 1 min | | `"minutes"` | 5 min | 1 min | 1 h | | `"hours"` | 5 min | 1 h | 1 day | | `"days"` | 5 min | 1 day | 1 week | | `"weeks"` | 5 min | 1 week | 30 days | | `"max"` | 5 min | 30 days | 1 year | You can also pass numbers in seconds, for example `cacheLife({ revalidate: 600 })`, or define named profiles under `cacheLife` in `next.config.ts`. ## updateTag vs revalidateTag: which one should you use? Both invalidate data you labelled with `cacheTag`. The difference is **when** users see fresh data. | | `updateTag("posts")` | `revalidateTag("posts", "max")` | | --- | --- | --- | | Effect | Expires immediately; next read waits for fresh data | Marks stale; old data served while fresh data loads | | Called from | Server Actions only | Server Actions and route handlers | | Use for | Read-your-own-writes: forms, settings, "I just posted this" | CMS webhooks, background jobs, data others can see a moment later | ```ts "use server"; import { updateTag } from "next/cache"; export async function createPost(formData: FormData) { await db.post.create({ data: { title: String(formData.get("title")) } }); updateTag("posts"); // the author sees the new post right away } ``` In Next.js 16, calling revalidateTag("posts") with one argument is deprecated. Always pass a profile as the second argument, usually "max". Two related helpers: `revalidatePath("/blog")` invalidates everything for a route, and `refresh()` (Server Actions only) re-renders the client router without touching cached data. ## How does Partial Prerendering fit in? With Cache Components, one page can be both static and dynamic. Cached parts are prerendered into a **static shell** that is served instantly, and parts that read request data (`cookies()`, `headers()`, `searchParams`) **stream in** at request time. Those dynamic parts must sit inside a `` boundary: ```tsx import { Suspense } from "react"; import { cookies } from "next/headers"; async function Cart() { const id = (await cookies()).get("cartId")?.value; // request-time data return ; } export default function ProductPage() { return ( <> {/* 'use cache' → static shell */} }> {/* streams in */} ); } ``` ## What are the common caching mistakes in Next.js 16? - **Reading cookies inside `'use cache'`.** A shared cache cannot depend on one user. Read the cookie outside and pass the value as an argument, or use `'use cache: private'`. - **Keeping old segment config.** `export const revalidate`, `dynamic`, `fetchCache` and `dynamicParams` error when Cache Components is on. - **Using `revalidateTag` where `updateTag` is needed.** If the user who made the change sees old data after submitting a form, switch to `updateTag`. - **Request-time data outside Suspense.** Wrap components that read cookies, headers or search params in `` so the rest of the page can still be prerendered. ## Key takeaway Cache on purpose. Add `'use cache'` where data is shared and changes rarely, pick a `cacheLife` profile that matches how fresh it must be, tag it, and invalidate with `updateTag` for the person who just changed it or `revalidateTag(tag, "max")` for everyone else. For a one-page summary of the rest of Next.js 16, see the free [Next.js handwritten notes](/placement/nextjs-handwritten-notes). ### Is fetch cached by default in Next.js 16? No. In Next.js 16 with Cache Components, fetch requests and database calls are not cached by default. You opt in by adding the 'use cache' directive to a function, a component or a whole file, and you control the lifetime with cacheLife. ### What is the difference between updateTag and revalidateTag in Next.js 16? updateTag expires a cache tag immediately, so the next request waits for fresh data; it can only be called from Server Actions and is meant for read-your-own-writes, such as showing a user the post they just created. revalidateTag(tag, 'max') marks the tag stale and serves the old data while fresh data loads in the background, which suits webhooks and background updates. ### How do I enable Cache Components in Next.js 16? Set cacheComponents: true in next.config.ts. New projects created with create-next-app in Next.js 16 have it enabled already. ### Can I use cookies() or headers() inside 'use cache'? No. A shared cache cannot depend on one user's request. Read cookies() or headers() outside the cached function and pass the value in as an argument, or use the 'use cache: private' variant, which caches per user in the browser. ### Do export const revalidate and export const dynamic still work in Next.js 16? Not when Cache Components is enabled. The route segment options dynamic, revalidate, fetchCache and dynamicParams cause an error with cacheComponents on; use 'use cache' with cacheLife and Suspense boundaries instead. They still work in apps that have not enabled Cache Components. --- # Article: JavaScript Event Loop Explained: Call Stack, Microtasks and Macrotasks (with Output Questions) URL: https://www.gaurav-sharma.in/blog/javascript-event-loop-explained Author: Gaurav Sharma Published: 2026-10-22 Updated: 2026-10-22 The JavaScript event loop runs your synchronous code on one call stack, and when the stack is empty it first runs every queued microtask (Promise callbacks, code after await), then lets the browser render, then runs one macrotask (a setTimeout callback, an event, I/O) and repeats. That is why a Promise callback always runs before a setTimeout(fn, 0) callback. ## What is the event loop in JavaScript? JavaScript runs on a **single thread** with a single **call stack**: one function runs at a time, to completion. Yet a page can wait for a network response, run a timer and react to clicks at the same time. The event loop is what makes that work. The pieces involved: | Piece | What it does | | --- | --- | | Call stack | Runs JavaScript, one frame at a time. Synchronous code lives here. | | Web APIs / Node APIs | The browser or Node.js handles timers, `fetch`, DOM events and file I/O outside the stack. | | Macrotask queue | Callbacks from timers, events, I/O and `postMessage` wait here. The HTML spec calls these **tasks**. | | Microtask queue | Promise reactions, code after `await`, `queueMicrotask` and `MutationObserver` callbacks wait here. | | Event loop | Moves callbacks from the queues to the stack when the stack is empty. | When you call `setTimeout(cb, 1000)`, JavaScript does not wait. The browser starts the timer, your code moves on, and after about a second `cb` is put into the macrotask queue. It only runs once the call stack is empty and the event loop picks it. ## How does one turn of the event loop work? Each turn follows the same steps: 1. Take the **oldest macrotask** from a task queue and run it to completion. The initial script counts as the first macrotask. 2. Run **every microtask** in the microtask queue, including microtasks added while doing this, until the queue is empty. 3. If it is time to paint, **update the rendering**: run `requestAnimationFrame` callbacks, recalculate styles and layout, and paint. 4. Go back to step 1. The rule that answers most interview questions: after any macrotask, the whole microtask queue is emptied before the next macrotask runs. One macrotask, then all microtasks. ## Microtask vs macrotask: what goes where? | Microtasks (high priority) | Macrotasks (one per turn) | | --- | --- | | `Promise.then`, `catch`, `finally` | `setTimeout`, `setInterval` | | Code after `await` in an async function | UI events: click, keydown, scroll | | `queueMicrotask(fn)` | Network and file I/O callbacks | | `MutationObserver` callbacks | `MessageChannel` and `postMessage` | | `process.nextTick` (Node.js, its own queue that runs first) | `setImmediate` (Node.js) | Note that the `Promise` constructor's executor function runs **synchronously**. Only the `then` callbacks are microtasks. ## Output question 1: setTimeout vs Promise order ```js console.log("A"); setTimeout(() => console.log("B"), 0); Promise.resolve().then(() => console.log("C")); console.log("D"); ``` **Output: A, D, C, B** - `A` and `D` are synchronous and print first. - The `then` callback is a microtask, so `C` runs as soon as the script ends. - The timer callback is a macrotask, so `B` waits for the next turn, even with a 0 ms delay. This is Q18 in the [Top 50 JavaScript interview questions](/placement/javascript-interview-questions), and it is asked in almost every frontend interview. ## Output question 2: how does async/await fit in? ```js async function first() { console.log("1"); await second(); console.log("2"); } async function second() { console.log("3"); } console.log("4"); setTimeout(() => console.log("5"), 0); first(); Promise.resolve().then(() => console.log("6")); console.log("7"); ``` **Output: 4, 1, 3, 7, 2, 6, 5** - An async function runs **synchronously until its first `await`**. So `first()` prints `1`, calls `second()` which prints `3`, and then pauses. - Everything after `await` becomes a microtask. Because `second()` has already returned a resolved promise, the continuation that prints `2` is queued right away, before the `then` that prints `6`. - `7` is synchronous. Then the microtasks run in order: `2`, `6`. The timer `5` comes last. Think of await x as "put the rest of this function in a then callback on x". The code before the first await is ordinary synchronous code. ## Output question 3: Promises inside setTimeout ```js setTimeout(() => { console.log("A"); Promise.resolve().then(() => console.log("B")); }, 0); setTimeout(() => console.log("C"), 0); Promise.resolve().then(() => { console.log("D"); setTimeout(() => console.log("E"), 0); }); ``` **Output: D, A, B, C, E** - After the script, the microtask prints `D` and schedules a third timer `E` at the back of the queue. - The first timer runs and prints `A`, and queues a microtask. - That microtask (`B`) runs **before** the second timer, because microtasks are drained after every macrotask. - Then `C`, then `E`. A common wrong answer is `D, A, C, B, E`. Browsers, and Node.js since version 11, both give `D, A, B, C, E`. ## Output question 4: chained Promises and queueMicrotask ```js Promise.resolve() .then(() => console.log(1)) .then(() => console.log(2)); Promise.resolve() .then(() => console.log(3)) .then(() => console.log(4)); queueMicrotask(() => console.log(5)); ``` **Output: 1, 3, 5, 2, 4** Only the first `then` of each chain is queued at the start, together with the `queueMicrotask` callback: `1`, `3`, `5`. A chained `then` is queued only when the previous one finishes, so `2` and `4` join the back of the queue afterwards. Chains interleave; they do not run one after another. ## Output question 5: why doesn't the red ever show? ```js button.addEventListener("click", () => { box.style.background = "red"; const end = Date.now() + 2000; while (Date.now() console.log("timeout"), 0); setImmediate(() => console.log("immediate")); Promise.resolve().then(() => console.log("promise")); process.nextTick(() => console.log("nextTick")); console.log("sync"); ``` **Output in a CommonJS file:** `sync`, `nextTick`, `promise`, then `timeout` and `immediate` in either order. - Node.js runs the `process.nextTick` queue before the Promise microtask queue. - Node's event loop has phases: **timers** (`setTimeout`), **poll** (I/O), **check** (`setImmediate`) and **close**. Whether `timeout` or `immediate` prints first in the main module depends on how fast the process starts, so the order is not guaranteed. Inside an I/O callback, `setImmediate` always runs first. - In an ES module (`.mjs` or `"type": "module"`), the module itself runs inside a Promise job, so `promise` can print before `nextTick`. Interviewers usually mean CommonJS. The [Node.js handwritten notes](/placement/nodejs-handwritten-notes) cover the event loop phases in more detail. ## What are the common event loop mistakes? - **Thinking `setTimeout(fn, 0)` runs immediately.** It runs after the current script and all microtasks, and browsers clamp nested timers to at least 4 ms after five levels of nesting. - **Thinking the delay is exact.** The delay is a minimum. A busy call stack pushes the callback later. - **Forgetting the Promise executor is synchronous.** In `new Promise(r => { console.log("x"); r(); })`, `x` prints immediately. - **Blocking the main thread.** Long loops, heavy JSON parsing or big sorts freeze clicks, timers and painting. Split the work, or move it to a Web Worker. - **Using `await` in a loop when the calls are independent.** Each iteration waits for the previous one. Start them together and use `Promise.all` instead. - **Infinite microtasks.** A `then` that keeps queuing another `then` starves rendering and timers, just like a `while (true)` loop. ## How do you explain the event loop in an interview? Keep it to four sentences, then offer an example: 1. JavaScript is single-threaded and runs code on one call stack. 2. Slow work such as timers, network and events is handed to the browser or Node.js, and the callbacks wait in queues. 3. When the stack is empty, the event loop runs all microtasks (Promise callbacks), lets the browser render, and then runs one macrotask (a timer or event). 4. That is why `Promise.then` runs before `setTimeout(fn, 0)`. Then write output question 1 on the board and walk through it. If the interviewer pushes further, mention that `await` splits a function into a microtask, and that Node.js adds `process.nextTick` and `setImmediate`. ## Key takeaway Synchronous code first, then every microtask, then render, then one macrotask, and repeat. Promise callbacks and code after `await` are microtasks; timers, events and I/O are macrotasks. With that one rule you can answer almost any event loop output question. To practise the rest of the topics that come up with it, such as closures, `this`, hoisting and Promise polyfills, work through the free [Top 50 JavaScript interview questions](/placement/javascript-interview-questions) PDF, and revise the basics from the [JavaScript handwritten notes](/placement/javascript-handwritten-notes). ### What is the event loop in JavaScript? The event loop is the mechanism that lets single-threaded JavaScript handle asynchronous work. JavaScript runs code on one call stack; timers, network requests and events are handled by the browser or Node.js, and their callbacks wait in queues. Whenever the call stack is empty, the event loop runs all pending microtasks, lets the browser render if needed, and then runs the next macrotask. ### What is the difference between a microtask and a macrotask? Microtasks are Promise callbacks (then, catch, finally), the code after await, queueMicrotask and MutationObserver callbacks. Macrotasks (called tasks in the HTML spec) are setTimeout, setInterval, I/O, UI events and message events. After every macrotask the event loop empties the whole microtask queue, including microtasks added along the way, before it takes the next macrotask. ### Why does a Promise callback run before setTimeout with 0 delay? Because a resolved Promise's then callback is a microtask and setTimeout's callback is a macrotask. When the current script finishes, the event loop drains the microtask queue first, so the Promise callback runs before the timer callback, even if the timer was created earlier and has a delay of 0. ### Is JavaScript single-threaded? The JavaScript engine runs your code on a single main thread with one call stack, so only one piece of JavaScript runs at a time. The browser and Node.js use other threads for timers, networking and file I/O, and Web Workers or worker_threads can run separate JavaScript threads that communicate by messages. ### What is the order of process.nextTick, Promise and setImmediate in Node.js? In a CommonJS script, synchronous code runs first, then process.nextTick callbacks, then Promise microtasks, then macrotasks such as setTimeout and setImmediate. The order between setTimeout 0 and setImmediate in the main module is not guaranteed, but inside an I/O callback setImmediate always runs first. In ES modules, Promise callbacks can run before nextTick callbacks. --- # Article: C++ vs Java vs Python: Best Programming Language for DSA and Placements in 2026 URL: https://www.gaurav-sharma.in/blog/best-programming-language-for-placements Author: Gaurav Sharma Published: 2026-10-22 Updated: 2026-10-22 For DSA and campus placements, choose C++ if you want speed and plan to do competitive programming, Java if you want strong OOP and collections depth for service and product company interviews, and Python if you value short, readable code or are aiming for AI and data roles. Learn C basics only as a foundation. The best language is the one you practise every problem in and can explain in depth. ## Does the language really matter for placements? Less than most students think. Interviewers judge your **problem-solving**: choosing the right data structure, explaining time and space complexity, and writing correct code without help. A hashmap is a hashmap in every language. The language still matters in three practical ways: 1. **Time in online assessments.** Shorter syntax and good built-in libraries let you finish more problems in a fixed time. 2. **Speed of the program.** Some assessments have strict time limits. A slower language can fail on large inputs even when the logic is correct. 3. **Follow-up questions.** Interviewers often ask about the language you chose. If you write C++, expect questions about pointers. If you write Java, expect questions about `HashMap` internals. So the real question is: which language can you use quickly **and** defend in depth? ## How do C++, Java and Python compare? | | C++ | Java | Python | | --- | --- | --- | --- | | Execution speed | Fastest of the three | Fast (JIT-compiled on the JVM) | Slowest; can time out on strict limits | | Code length | Medium | Longest (more boilerplate) | Shortest | | DSA library | STL: `vector`, `map`, `unordered_map`, `set`, `priority_queue`, `sort` | Collections: `ArrayList`, `HashMap`, `TreeMap`, `PriorityQueue`, `Deque` | Built-ins: `list`, `dict`, `set`, plus `heapq`, `collections`, `bisect` | | Memory control | Manual and explicit (pointers, references) | Automatic (garbage collector) | Automatic (garbage collector) | | OOP depth asked | Classes, virtual functions, constructors and destructors | Very deep: interfaces, abstract classes, inheritance rules, `equals`/`hashCode` | Lighter: classes, dunder methods, decorators | | Online-assessment support | Accepted almost everywhere | Accepted almost everywhere | Accepted almost everywhere | | Best fit | Competitive programming, product companies, systems roles | Service and product companies, backend and Android roles | AI/ML, data, scripting and backend roles | Two things stand out. **C++ wins on speed and STL power**, which is why it dominates competitive programming. **Java wins on OOP depth**, which many interview panels test after the coding round. **Python wins on writing speed** but loses on raw execution speed. ## What does the same problem look like in each language? Here is the classic **Two Sum** problem: return the indices of the two numbers that add up to a target. The best approach is the same everywhere: store each number's index in a hashmap and check whether `target - x` has been seen. It runs in O(n) time and O(n) space. ```cpp // C++ vector twoSum(vector& nums, int target) { unordered_map seen; // value -> index for (int i = 0; i seen = new HashMap<>(); // value -> index for (int i = 0; i index for i, x in enumerate(nums): if target - x in seen: return [seen[target - x], i] seen[x] = i return [] ``` The logic is identical. Python is the shortest, Java the most verbose, and C++ sits in between. In an interview, all three are correct answers. What differs is the follow-up: "Why `unordered_map` and not `map`?" for C++, "How does `HashMap` handle collisions?" for Java, and "What is the time complexity of `in` on a dict versus a list?" for Python. ## What do interviewers ask about each language? ### C++ - **Pointers and references**: the difference, null pointers, dangling pointers, pass by value versus by reference. - **Memory**: stack versus heap, `new`/`delete` versus `malloc`/`free`, memory leaks, smart pointers (`unique_ptr`, `shared_ptr`). - **OOP**: virtual functions and the vtable, why a base class needs a virtual destructor, copy constructors, the Rule of Three/Five. - **STL**: `map` versus `unordered_map` (balanced tree versus hash table), when iterators become invalid, `vector` growth. The [Top 50 C++ interview questions](/placement/cpp-interview-questions) cover these with short and detailed answers. ### Java - **JVM basics**: JDK versus JRE versus JVM, how bytecode runs, stack versus heap, garbage collection. - **Collections**: how `HashMap` works internally, `ArrayList` versus `LinkedList`, `HashMap` versus `TreeMap`, fail-fast iterators. - **OOP**: interfaces versus abstract classes, overloading versus overriding, why `equals` and `hashCode` must agree, immutability of `String`. - **Exceptions and threads**: checked versus unchecked exceptions, `synchronized`, basic multithreading. ### Python - **Built-in data structures**: list versus tuple versus set versus dict, and their time complexities. - **Language features**: list comprehensions, generators and `yield`, decorators, mutable default arguments. - **Performance**: the Global Interpreter Lock (GIL) and why threads do not speed up CPU-bound work, when to use `multiprocessing`. - **Memory model**: everything is an object, shallow versus deep copy, `is` versus `==`. Whichever you choose, be ready for these. Writing correct code is only half of the round. ## Should you learn C or C++ first? Many colleges teach C in the first year. That is useful: C teaches you how memory, arrays and pointers really work. But C has no built-in hashmap, dynamic array or sorting library you would want to use in an interview, so DSA code in C is long and error-prone. A practical path: 1. Learn **C basics** (variables, loops, functions, arrays, pointers, structs) until you are comfortable. The [C handwritten notes](/placement/c-handwritten-notes) cover exactly this. 2. Move to **C++** and learn the STL: `vector`, `string`, `unordered_map`, `set`, `stack`, `queue`, `priority_queue` and `sort`. 3. Solve every DSA problem in C++ from then on. Some service companies still ask C output questions (pointer arithmetic, `sizeof`, operator precedence) in written tests, so keep your C basics fresh even after you switch. ## How do you choose? A simple decision flow - **If** you enjoy competitive programming or want to target product companies with hard coding rounds, **then** choose **C++**. - **If** your college course is Java-based, or you are aiming for backend, Android or large service companies, **then** choose **Java**. - **If** you want AI, ML or data roles, or you find C++ and Java syntax slows you down, **then** choose **Python**, and practise writing efficient code. - **If** you have already solved 100 or more problems in one language, **then** stay with it. Switching now costs more than it gains. - **If** you are still unsure, **then** pick **C++ or Java** for DSA. Both are accepted everywhere and both teach you concepts interviewers ask about. ## Can I switch languages later? Yes. Arrays, hashmaps, two pointers, recursion and dynamic programming work the same in every language. Switching mainly means learning new syntax and library names, which takes a few weeks of practice. Two rules make switching painless: - **Switch early, not late.** A switch in your second or third year is fine. A switch two months before placements is risky. - **Re-solve problems you already know.** Rewriting 30–40 familiar problems in the new language is the fastest way to learn its library. Many developers end up using more than one language anyway: DSA in C++ or Java, and Python for scripts or AI work. ## What are the most common mistakes students make? - **Switching languages every month.** You stay a beginner in all of them. Pick one and stay with it for DSA. - **Learning syntax but not the library.** Writing your own sort or hashmap in an online test wastes time. Learn the STL, Java Collections or Python built-ins properly. - **Ignoring complexity of built-ins.** `list.remove(x)` in Python is O(n). `map` in C++ is O(log n) per operation, not O(1). Interviewers notice. - **Not knowing the language's own questions.** Choosing C++ and not being able to explain a virtual destructor, or choosing Java and not knowing how `HashMap` works, hurts in the technical round. - **Using Python on strict time limits without care.** Use fast input (`sys.stdin`) and avoid deep recursion, or the same algorithm may time out. ## Key takeaway There is no single best language for placements. There is a best language **for you**: C++ for speed and competitive programming, Java for OOP depth and broad company fit, Python for short code and AI roles, with C as the foundation if your college starts there. Pick one early, solve every problem in it, learn its standard library, and prepare for the questions interviewers ask about it. To get started, use the [DSA handwritten notes](/placement/dsa-handwritten-notes) for patterns, and the [C++](/placement/cpp-handwritten-notes), [Java](/placement/java-handwritten-notes) or [Python](/placement/python-handwritten-notes) notes for your chosen language. For the full plan, read the [placement preparation roadmap for 2026](/blog/placement-preparation-roadmap-2026). ### Which programming language is best for DSA and placements? For most CSE students in India, C++ or Java. C++ is the most common choice for competitive programming and fast online assessments because of its speed and the STL. Java is equally accepted in interviews and adds depth in OOP and collections, which service and product companies both ask about. Python is fine for coding rounds and is the natural pick for AI and data roles. ### Is Python good enough for coding interviews? Yes. Almost every online-assessment platform and interviewer accepts Python, and its short syntax saves time. Its main risk is speed: an O(n log n) solution can still time out on strict competitive-programming limits where the same logic in C++ passes. For interviews focused on correctness and explanation, Python works well. ### Should I learn C or C++ first? If your college course starts with C, learn C basics first: variables, loops, arrays, pointers and memory. Then move to C++ for DSA, because C++ keeps C's syntax and adds the STL, classes and references, which make DSA code far shorter. Do not spend months on C alone if your goal is placements. ### Can I switch from Java to C++ or Python later? Yes. DSA logic is the same in every language; only the syntax and library names change. Switching a few months before placements costs time, so pick one language early, solve all your practice problems in it, and only switch if you have a clear reason, such as moving into AI roles that use Python. ### Which language do companies prefer for placements? Most companies let you choose the language for coding rounds. What changes is the follow-up questions: interviewers ask about pointers and memory if you use C++, about the JVM, collections and OOP if you use Java, and about built-in data structures and performance if you use Python. Choose the language you can defend in depth. --- # Article: Building a Drag-and-Drop Kanban Board with dnd-kit, Express and MongoDB URL: https://www.gaurav-sharma.in/blog/react-kanban-dnd-kit-express-mongodb Author: Gaurav Sharma Published: 2026-10-20 Updated: 2026-10-20 A drag-and-drop Kanban board in React needs three pieces: dnd-kit droppable columns with sortable cards, a drag handler that moves cards between columns while dragging and reorders them on drop, and one backend endpoint that saves each card's column and position to MongoDB. ## What we are building [Atlass CRM](/projects/atlass-crm) has a deal pipeline with five stages: New, Qualified, Proposal, Won and Lost. Every lead is a card. Drag it to another column and its stage changes; drop it higher in a column and it moves up the list. Reload the page and everything is where you left it. | Concern | Where it lives | | --- | --- | | Drag and drop | `@dnd-kit/core` and `@dnd-kit/sortable` | | Board state | React state shaped as `{ stage: Lead[] }` | | Persistence | `PATCH /api/leads/reorder` on Express | | Storage | MongoDB `status` and `order` fields on each lead | ## Step 1: Store the column and the position Each lead keeps its stage and its position inside that stage. Nothing else is needed: ```js export const LEAD_STATUSES = ["New", "Qualified", "Proposal", "Won", "Lost"]; const leadSchema = new mongoose.Schema( { owner: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true, index: true }, name: { type: String, required: true, trim: true }, value: { type: Number, default: 0, min: 0 }, status: { type: String, enum: LEAD_STATUSES, default: "New", index: true }, order: { type: Number, default: 0 }, }, { timestamps: true }, ); ``` The list endpoint sorts by `order` first, so the board comes back in the saved order: ```js const leads = await Lead.find({ owner: req.user._id }).sort({ order: 1, createdAt: -1 }); ``` ## Step 2: Turn a flat list into a board The API returns one array. The board wants one array per column: ```js const PIPELINE_STAGES = ["New", "Qualified", "Proposal", "Won", "Lost"]; const toBoard = (leads) => { const board = Object.fromEntries(PIPELINE_STAGES.map((s) => [s, []])); for (const l of leads) (board[l.status] || board.New).push(l); return board; }; ``` The `|| board.New` fallback means a lead with an unknown status still shows up somewhere instead of vanishing. ## Step 3: Columns are droppable, cards are sortable Each column registers itself as a droppable with its stage name as the id. Inside it, a `SortableContext` makes the cards reorderable: ```jsx function Column({ stage, leads }) { const { setNodeRef, isOver } = useDroppable({ id: stage }); return ( l._id)} strategy={verticalListSortingStrategy}> {leads.map((lead) => )} {leads.length === 0 && Drop leads here} ); } ``` The droppable matters for **empty columns**. With no cards there is nothing to hover over, so without it you could never drop into "Won" for the first time. Each card uses `useSortable`, and the drag listeners go on a grip handle rather than the whole card, so buttons on the card still click normally: ```jsx function SortableCard({ lead }) { const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: lead._id }); return ( ); } ``` ## Step 4: Wire up the DndContext ```jsx const sensors = useSensors( useSensor(PointerSensor, { activationConstraint: { distance: 6 } }), ); const snapshot = useRef(null); // board before the drag, for rollback { snapshot.current = board; setActiveId(active.id); }} onDragOver={handleDragOver} onDragEnd={handleDragEnd} onDragCancel={() => setActiveId(null)} > {PIPELINE_STAGES.map((stage) => )} {activeLead ? : null} ``` Two choices worth copying: - **`activationConstraint: { distance: 6 }`** means a drag only starts after the pointer moves 6px. A plain click stays a click. - **`closestCorners`** works better than the default `rectIntersection` for stacked columns, because it picks the nearest card even when the dragged card overlaps two. `DragOverlay` renders the dragged card outside the scrolling column. It is not clipped by `overflow-x-auto`, it does not jump when the source list re-renders, and you can style it as lifted and slightly rotated. ## Step 5: Move between columns while dragging Both droppables (columns) and sortables (cards) can be the `over` target, so the first job is to find which column an id belongs to: ```js const findContainer = (id) => { if (id in board) return id; // a column id return PIPELINE_STAGES.find((s) => board[s].some((l) => l._id === id)); }; ``` `onDragOver` fires continuously. When the card crosses into another column, move it there right away, so the cards in the target column open up a gap under the pointer: ```js const handleDragOver = ({ active, over }) => { if (!over) return; const from = findContainer(active.id); const to = findContainer(over.id); if (!from || !to || from === to) return; setBoard((prev) => { const fromItems = prev[from].filter((l) => l._id !== active.id); const moved = { ...prev[from].find((l) => l._id === active.id), status: to }; const toItems = [...prev[to]]; const overIdx = toItems.findIndex((l) => l._id === over.id); toItems.splice(overIdx === -1 ? toItems.length : overIdx, 0, moved); return { ...prev, [from]: fromItems, [to]: toItems }; }); }; ``` Hovering a card inserts above it; hovering the empty part of a column appends to the end. ## Step 6: Reorder on drop, then save By the time `onDragEnd` runs, the card is already in the right column. All that is left is the final position inside it, which `arrayMove` handles: ```js const handleDragEnd = ({ active, over }) => { setActiveId(null); if (!over) return; const stage = findContainer(over.id); if (!stage) return; const items = board[stage]; const oldIdx = items.findIndex((l) => l._id === active.id); const newIdx = items.findIndex((l) => l._id === over.id); const next = { ...board, [stage]: oldIdx !== -1 && newIdx !== -1 ? arrayMove(items, oldIdx, newIdx) : items, }; setBoard(next); const updates = PIPELINE_STAGES.flatMap((s) => next[s].map((l, order) => ({ id: l._id, status: s, order })), ); leadsApi.reorder(updates).catch(() => { setBoard(snapshot.current); toast.error("Could not save pipeline"); }); }; ``` `snapshot.current` is the board saved during `onDragStart`. If the save fails, the board snaps back instead of showing an order the server never accepted. The payload is simply "every card's stage and index". That keeps the server dumb and the client the single source of truth for order. ## Step 7: One Express endpoint saves the whole board ```js router.use(protect); router.patch("/reorder", reorderLeads); // must be registered before "/:id" ``` ```js export const reorderLeads = asyncHandler(async (req, res) => { const { updates } = req.body; if (!Array.isArray(updates)) throw new ApiError(400, "updates must be an array"); if (updates.some((u) => !LEAD_STATUSES.includes(u.status))) throw new ApiError(400, "Invalid status"); await Lead.bulkWrite( updates.map((u) => ({ updateOne: { filter: { _id: u.id, owner: req.user._id }, update: { $set: { status: u.status, order: u.order } }, }, })), ); res.json({ success: true }); }); ``` Three details matter: - **Filter by `owner`.** The client sends ids; the server must make sure they belong to the signed-in user. - **Validate `status` yourself.** Mongoose `updateOne` skips schema validators by default, so the `enum` will not catch a bad stage. - **Route order.** `PATCH /reorder` sits above `/:id`, or Express would treat `reorder` as a lead id. ## What I would change next The first version of Atlass CRM saved updates with one `updateOne` per lead inside `Promise.all`, and called the API from inside a `setState` updater. Both work, but: - **`bulkWrite` is one round trip** instead of one query per card, which adds up on a board with hundreds of deals. - **Side effects do not belong in state updaters.** React Strict Mode runs updaters twice in development, which sends the save request twice. Compute the next board, set it, then call the API, as shown above. - **Send only the columns that changed.** A drag touches at most two columns; the other three do not need rewriting. - **Add a `KeyboardSensor`** with `sortableKeyboardCoordinates` so the board works without a mouse, and give the grip handle a real label such as "Move Acme deal". ## Key takeaways - Store a `status` for the column and an `order` for the position. - Columns are droppables, cards are sortables; that is what makes empty columns work. - Move across columns in `onDragOver`, reorder in `onDragEnd`. - Use `DragOverlay` for a smooth, unclipped preview. - Save the whole board through one owner-scoped `bulkWrite`, and roll back on failure. Want a pipeline, dashboard or internal tool like this? I build them as a [freelance MERN stack developer](/services/mern-stack-developer). ### How do you build a Kanban board in React? Group items into an object keyed by column, render each column as a dnd-kit droppable with a SortableContext inside, make each card sortable with useSortable, move cards between columns in onDragOver, reorder them in onDragEnd, and save the new column and position of every card to the backend. ### Is dnd-kit better than react-beautiful-dnd? For new projects, yes. react-beautiful-dnd is no longer maintained, while dnd-kit is actively maintained, lightweight, works with React 18 and 19, and supports pointer, touch and keyboard sensors. ### How do you save Kanban card order in MongoDB? Store a status field for the column and a numeric order field for the position. After a drop, send the status and order of the affected cards to one endpoint and apply them with a single bulkWrite, filtered by the current user, then sort queries by order. ### Why use DragOverlay in dnd-kit? DragOverlay renders the dragged card outside the scrolling columns, so it is not clipped by overflow, does not jump when the source list re-renders, and can be styled differently, for example lifted and slightly rotated. --- # Article: Building a Real-Time Chat App with Socket.IO, Express and MongoDB URL: https://www.gaurav-sharma.in/blog/socketio-realtime-chat-express-mongodb Author: Gaurav Sharma Published: 2026-10-19 Updated: 2026-10-19 A real-time chat app on the MERN stack needs four things: authenticated Socket.IO connections, one room per conversation, a save-then-emit flow with acknowledgements, and paginated message history from MongoDB. This is the structure I used for PingChat. ## The architecture in one paragraph Express serves the REST API (conversations, message history, uploads). Socket.IO runs on the **same HTTP server** and handles only live events: joining conversations, sending messages, typing indicators. MongoDB stores every message. The React client loads history over REST once, then listens on the socket for anything new. | Concern | Where it lives | | --- | --- | | Sign-in, sessions | Clerk (token verified on every socket) | | Live delivery | Socket.IO rooms | | Message history | MongoDB via Mongoose, REST endpoint | | Client state | Zustand store | ## Step 1: Share one server between Express and Socket.IO ```ts import express from "express"; import { createServer } from "node:http"; import { Server } from "socket.io"; const app = express(); const server = createServer(app); export const io = new Server(server, { cors: { origin: process.env.CLIENT_URL, credentials: true }, }); server.listen(process.env.PORT ?? 4000); ``` Calling `app.listen()` would create a second server that Socket.IO knows nothing about. Create the HTTP server yourself and hand it to both. ## Step 2: Authenticate the socket, not just the page A logged-in page does not mean a trusted socket. Verify a token during the handshake and keep the user id on `socket.data`: ```ts import { verifyToken } from "@clerk/backend"; io.use(async (socket, next) => { try { const token = socket.handshake.auth.token as string; const { sub } = await verifyToken(token, { secretKey: process.env.CLERK_SECRET_KEY! }); socket.data.userId = sub; next(); } catch { next(new Error("unauthorized")); } }); ``` On the client, pass the token as a function so reconnects always send a fresh one: ```ts import { io } from "socket.io-client"; export const socket = io(import.meta.env.VITE_API_URL, { autoConnect: false, auth: async (cb) => cb({ token: await getToken() }), }); ``` ## Step 3: One room per conversation Rooms keep broadcasting cheap and private. Check membership in the database before joining, because the client can send any id it likes: ```ts io.on("connection", (socket) => { socket.on("conversation:join", async (conversationId: string, ack) => { const member = await Conversation.exists({ _id: conversationId, members: socket.data.userId }); if (!member) return ack({ ok: false }); socket.join(`conv:${conversationId}`); ack({ ok: true }); }); }); ``` ## Step 4: Save, then emit, then acknowledge ```ts socket.on("message:send", async ({ conversationId, text, clientId }, ack) => { if (!socket.rooms.has(`conv:${conversationId}`)) return ack({ ok: false, error: "not a member" }); const message = await Message.create({ conversation: conversationId, sender: socket.data.userId, text }); socket.to(`conv:${conversationId}`).emit("message:new", message); ack({ ok: true, clientId, message }); }); ``` Three details matter here: - **Save first.** If MongoDB rejects the write, nobody receives a message that does not exist. - **`socket.to(...)` skips the sender.** The sender gets the saved message back through the acknowledgement instead. - **`clientId` links the optimistic copy** on the sender's screen to the saved document, so the UI can swap one for the other. ## Step 5: Optimistic UI with Zustand The sender should see the message instantly, marked as pending until the server confirms it: ```ts send: (conversationId, text) => { const clientId = crypto.randomUUID(); set((s) => ({ messages: [...s.messages, { clientId, text, status: "pending" }] })); socket.emit("message:send", { conversationId, text, clientId }, (res) => { set((s) => ({ messages: s.messages.map((m) => m.clientId === clientId ? (res.ok ? { ...res.message, status: "sent" } : { ...m, status: "failed" }) : m, ), })); }); }, ``` ## Step 6: Paginate history by cursor, not by page number New messages arrive constantly, so `skip`-based pages shift under the user. Use the oldest loaded timestamp as a cursor, backed by a compound index: ```ts messageSchema.index({ conversation: 1, createdAt: -1 }); app.get("/api/conversations/:id/messages", requireAuth, async (req, res) => { const before = req.query.before ? new Date(String(req.query.before)) : new Date(); const messages = await Message.find({ conversation: req.params.id, createdAt: { $lt: before } }) .sort({ createdAt: -1 }) .limit(30); res.json(messages.reverse()); }); ``` ## Production checklist - **Scale out with the Redis adapter** (`@socket.io/redis-adapter`) once you run more than one server instance. - **Rate-limit `message:send`** per socket so one client cannot flood a room. - **Re-join rooms on reconnect.** Listen for the client `connect` event and join active conversations again. - **Upload media over REST,** not the socket. PingChat sends images through Multer to ImageKit and only emits the resulting URL. - **Make the UI accessible.** PingChat uses React Aria Components so the message list and composer work with a keyboard and screen reader. ## Key takeaways - One HTTP server, shared by Express and Socket.IO. - Verify a token on every socket connection and every room join. - Save to MongoDB, then emit, then acknowledge. - Load history over REST with cursor pagination. Need real-time features in your app? I build them as a [freelance MERN stack developer](/services/mern-stack-developer). ### How do you build a real-time chat app with Socket.IO and MongoDB? Run Socket.IO on the same HTTP server as Express, authenticate each socket in an io.use middleware, put each conversation in its own room, save every message to MongoDB first and then emit it to the room, and load older history over a paginated REST endpoint. ### Should chat messages be saved before or after emitting them? Save first, then emit. If the database write fails, nobody sees a message that does not exist, and the saved document gives every client the same id and timestamp. ### How do you authenticate Socket.IO connections? Send a token in the handshake auth payload from the client, verify it in an io.use middleware on the server, store the user id on socket.data, and reject the connection with an error if verification fails. ### Is Socket.IO good for production chat apps? Yes. Socket.IO adds rooms, acknowledgements, automatic reconnection and fallbacks on top of WebSockets. For more than one server instance, add the Redis adapter so events reach sockets connected to other instances. --- # Article: Provider vs Bloc in Flutter: When I Use Each in an MVVM App URL: https://www.gaurav-sharma.in/blog/flutter-provider-vs-bloc-mvvm Author: Gaurav Sharma Published: 2026-10-19 Updated: 2026-10-19 Use Provider with a ChangeNotifier view model when a screen's state is simple and local. Use Bloc when a feature has many events, async steps and states that must stay predictable and testable. In an MVVM Flutter app you can, and often should, use both. ## The example app Throughout this post the example is an EdTech-style Flutter app: course modules, video playback and quizzes, backed by Firebase and REST APIs, structured with MVVM and using **both** Provider and Bloc. The question is never "which one wins", it is "which one fits this feature". ## MVVM in 30 seconds | Layer | Flutter piece | Job | | --- | --- | --- | | Model | Repositories, data classes | Talk to Firebase or the REST API | | ViewModel | ChangeNotifier, Cubit or Bloc | Hold state, run logic | | View | Widgets | Render state, send user actions | Widgets never call the API directly. They talk to a view model, and the view model talks to a repository. ## Provider: the simple view model A quiz screen is a good fit. The state is local, the actions are obvious, and nothing outside the screen cares: ```dart class QuizViewModel extends ChangeNotifier { QuizViewModel(this.questions); final List questions; int _index = 0; int _score = 0; bool get isFinished => _index == questions.length; Question get current => questions[_index]; // read only while !isFinished int get score => _score; void answer(int option) { if (isFinished) return; if (option == current.correctOption) _score++; _index++; notifyListeners(); } } ``` ```dart ChangeNotifierProvider( create: (_) => QuizViewModel(questions), child: const QuizScreen(), ); // Inside QuizScreen.build final vm = context.watch(); if (vm.isFinished) return ResultView(score: vm.score); return QuestionView(question: vm.current, onAnswer: vm.answer); ``` **Why Provider here:** one class, no boilerplate, easy to read. Adding Bloc would mean events and states for what is really three fields and one method. ## Bloc: the predictable async feature Loading a course is different. It can be loading, loaded, empty or failed, it can be retried, and other parts of the app react to it. That is where Bloc's explicit events and states earn their extra lines: ```dart sealed class CourseEvent {} final class CourseRequested extends CourseEvent { CourseRequested(this.courseId); final String courseId; } sealed class CourseState {} final class CourseLoading extends CourseState {} final class CourseLoaded extends CourseState { CourseLoaded(this.course); final Course course; } final class CourseFailed extends CourseState { CourseFailed(this.message); final String message; } class CourseBloc extends Bloc { CourseBloc(this._repo) : super(CourseLoading()) { on((event, emit) async { emit(CourseLoading()); try { emit(CourseLoaded(await _repo.fetchCourse(event.courseId))); } catch (_) { emit(CourseFailed('Could not load this course. Try again.')); } }); } final CourseRepository _repo; } ``` With Dart 3 sealed classes, the view can switch over every state and the compiler complains if one is missing: ```dart BlocBuilder( builder: (context, state) => switch (state) { CourseLoading() => const Center(child: CircularProgressIndicator()), CourseLoaded(:final course) => CourseView(course: course), CourseFailed(:final message) => RetryView( message: message, onRetry: () => context.read().add(CourseRequested(courseId)), ), }, ); ``` **Why Bloc here:** every transition is an event you can log and test, and no screen can end up in a half-loaded state nobody planned for. ## How I decide | Signal | Provider (ChangeNotifier) | Bloc / Cubit | | --- | --- | --- | | State lives on one screen | ✅ | | | A few fields, synchronous updates | ✅ | | | Several async steps (load, page, retry) | | ✅ | | Many user events that change state | | ✅ | | Other features react to this state | | ✅ | | You need to unit-test every transition | Possible | ✅ Easiest | A middle option worth knowing: **Cubit** (from the bloc package) keeps Bloc's explicit states but replaces events with plain methods. It is a good step up when a ChangeNotifier starts to feel messy. ## Mistakes to avoid - **Calling the API from a widget.** Put it in a repository so both Provider and Bloc view models can reuse it. - **One giant app-wide ChangeNotifier.** Every `notifyListeners()` rebuilds everything listening. Keep view models per feature. - **Bloc for everything.** A text field toggle does not need three classes. - **Ignoring `context.read` vs `context.watch`.** Use `watch` in `build` to rebuild, `read` in callbacks to call methods. ## Key takeaways - MVVM first: widgets talk to view models, view models talk to repositories. - Provider for simple, local screen state. - Bloc (or Cubit) for async, event-heavy features that must be predictable. - Mixing both in one app is normal, not a compromise. Building a Flutter app for iOS and Android? I take this on as a [Flutter app developer](/services/flutter-app-developer). ### Should I use Provider or Bloc in Flutter? Use Provider with ChangeNotifier view models for screens with simple, local state such as forms, toggles and quizzes. Use Bloc when a feature has many events, async flows or states that must be predictable and testable, such as loading, paging and retrying data from an API. ### Can you use Provider and Bloc in the same Flutter app? Yes. Provider handles dependency injection and simple view models, while Bloc handles complex features. flutter_bloc itself is built on top of Provider, so the two fit together naturally. ### What is MVVM in Flutter? MVVM separates the Model (data and repositories), the View (widgets) and the ViewModel (state and logic the view binds to). In Flutter the ViewModel is usually a ChangeNotifier exposed with Provider, or a Bloc or Cubit. ### Is Bloc overkill for small Flutter apps? Often, yes. For a screen with a few fields and one API call, a ChangeNotifier view model with Provider is less code and just as clear. Reach for Bloc when the number of events and states starts to grow. --- # Article: How to Build an AI Content Agent That Writes Daily Social Posts URL: https://www.gaurav-sharma.in/blog/ai-content-agent-gemini-n8n Author: Gaurav Sharma Published: 2026-10-19 Updated: 2026-10-19 An AI content agent is a scheduled pipeline, not a chatbot: a trigger fires, the agent gathers context, an LLM such as Gemini drafts posts for each platform as structured JSON, a schema validates them, and a human approves them before publishing. ## Why build one At Garage Collective I built and deployed an AI content-generation agent that produces daily Instagram, LinkedIn and blog content. It reduced manual content-creation effort by roughly 40%. This post walks through the architecture pattern behind that kind of agent, so you can build your own. The 40% did not come from skipping humans. It came from removing the blank-page step: people review and edit drafts instead of writing from scratch. ## The pipeline | Stage | Job | Tool options | | --- | --- | --- | | 1. Trigger | Run every morning | n8n Schedule node, node-cron | | 2. Context | Topic, brand voice, recent posts | Database, Google Sheet, CMS | | 3. Draft | One post per platform | Gemini or Groq | | 4. Validate | Lengths, fields, banned words | Zod | | 5. Review | Approve, edit or reject | Slack, email, dashboard | | 6. Publish | Post or schedule | Platform APIs, scheduler | ## Step 1: Describe the output before the prompt Each platform has different rules, so define them as a schema. This is the same idea I used for [reliable Gemini JSON in HireMate](/blog/gemini-structured-output-zod): ```ts import { z } from "zod"; export const DailyContent = z.object({ topic: z.string(), linkedin: z.object({ post: z.string().min(200).max(2800) }), instagram: z.object({ caption: z.string().max(2200), hashtags: z.array(z.string()).min(3).max(15) }), blog: z.object({ title: z.string().max(70), outline: z.array(z.string()).min(3), draft: z.string().min(600) }), }); export type DailyContent = z.infer; ``` ## Step 2: Give the model the context a writer would need Generic prompts give generic posts. Feed the model what a human writer would ask for: ```ts const prompt = ` You write social content for ${brand.name}. Audience: ${brand.audience} Voice: ${brand.voice} Never use: ${brand.bannedPhrases.join(", ")} Today's topic: ${topic} Avoid repeating these recent posts: ${recent.map((p) => p.summary).join(" | ")} Return JSON with keys linkedin, instagram and blog, following the rules for each platform. `; ``` The "recent posts" line matters more than it looks. Without it, a daily agent repeats itself within a week. ## Step 3: Generate, validate, retry ```ts import { GoogleGenAI } from "@google/genai"; const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY }); export async function draftDailyContent(prompt: string, attempts = 2): Promise { const res = await ai.models.generateContent({ model: "gemini-2.5-flash", contents: prompt, config: { responseMimeType: "application/json" }, }); const parsed = DailyContent.safeParse(JSON.parse(res.text ?? "{}")); if (parsed.success) return parsed.data; if (attempts > 0) return draftDailyContent(prompt, attempts - 1); throw new Error(`Draft failed validation: ${parsed.error.message}`); } ``` ## Step 4: Schedule it **Option A: plain Node.js with node-cron.** ```ts import cron from "node-cron"; cron.schedule("0 7 * * 1-5", async () => { const context = await loadContext(); const draft = await draftDailyContent(buildPrompt(context)); await saveForReview(draft); await notifyReviewers(draft.topic); }, { timezone: "Asia/Kolkata" }); ``` **Option B: n8n.** A Schedule Trigger node, a node that reads the topic list, an HTTP Request node that calls a small `/draft` endpoint wrapping the function above, then Slack or email for review. Non-developers can change the schedule, the topic source or the reviewers without touching code. Both work. n8n wins on visibility and easy changes; code wins on testing and prompt versioning. Using n8n for orchestration and a Node.js endpoint for the LLM step gets you both. ## Step 5: Keep a human in the loop Store each draft with a status (`pending`, `approved`, `rejected`) and send reviewers a link. Track how often drafts are approved without edits. That number tells you whether the prompt is improving, and when a low-risk format is ready to publish automatically. ## What goes wrong (and the fix) - **Same post, new day.** Pass recent post summaries into the prompt. - **Invalid JSON or overlong captions.** Validate with Zod and retry once or twice. - **Off-brand tone.** Add one or two real example posts to the prompt. - **Silent failures.** Alert someone when a run fails, so a missing post is never discovered at 6 p.m. - **API keys in the workflow.** Keep them in environment variables or n8n credentials, never in node parameters. ## Key takeaways - An AI agent is a scheduled pipeline with an LLM step, not a chat window. - Define the output schema per platform before writing the prompt. - Validate every draft, retry on failure, and alert on errors. - Keep human review, and measure how often drafts ship unedited. Want an agent like this for your team? I build them as an [AI automation developer](/services/ai-automation-developer). ### What is an AI content agent? An AI content agent is an automated workflow that gathers inputs such as topics, product updates or brand guidelines, uses a large language model to draft platform-specific posts, validates the output, and queues it for review or publishing on a schedule. ### Should AI-generated social posts be published automatically? Start with a human review step. Let the agent draft and queue posts, and have a person approve them. Remove the review step only for low-risk formats once the output has been consistently good. ### n8n or custom code for an AI content workflow? n8n is faster for wiring triggers, APIs and approvals visually, and is easy for non-developers to adjust. Custom Node.js code with node-cron gives more control over prompts, validation and testing. Many teams use n8n for orchestration and call a small Node.js service for the LLM step. ### How do you keep AI content on brand? Put the brand voice, audience, banned phrases and one or two example posts in the prompt, ask for structured JSON per platform, validate length and required fields with a schema, and keep a human approval step. --- # Article: How to Get Reliable JSON from the Gemini API with Zod URL: https://www.gaurav-sharma.in/blog/gemini-structured-output-zod Author: Gaurav Sharma Published: 2026-09-20 Updated: 2026-09-20 To get reliable JSON from Google Gemini, request JSON output with a response schema, then parse and validate every response with Zod on your server before your app uses it. Retry on failure instead of trusting raw model output. ## The problem In HireMate, my AI resume checker, the model returns a skill-gap analysis, a preparation plan, and interview questions. The UI expects a precise shape. If one field is missing or a list comes back as a string, the page breaks. ## Step 1: Define the shape once with Zod ```ts import { z } from "zod"; export const Analysis = z.object({ matchScore: z.number().min(0).max(100), missingSkills: z.array(z.string()).min(1), prepPlan: z.array(z.object({ step: z.string(), resources: z.array(z.string()) })), interviewQuestions: z.array( z.object({ type: z.enum(["technical", "behavioral"]), question: z.string(), answer: z.string() }), ), }); export type Analysis = z.infer; ``` ## Step 2: Ask Gemini for JSON ```ts import { GoogleGenAI } from "@google/genai"; const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY }); const res = await ai.models.generateContent({ model: "gemini-2.5-flash", contents: buildPrompt(resume, jobDescription), config: { responseMimeType: "application/json" }, }); ``` ## Step 3: Validate, then retry ```ts async function analyse(input: Input, attempts = 2): Promise { const raw = await callGemini(input); const parsed = Analysis.safeParse(JSON.parse(raw)); if (parsed.success) return parsed.data; if (attempts > 0) return analyse(input, attempts - 1); throw new Error("The AI response could not be validated."); } ``` ## Key takeaways - **Define the schema once** and reuse it for validation and TypeScript types. - **Never trust raw model output.** Validate on the server. - **Retry on failure** and show a friendly message if retries run out. ### How do I get JSON output from the Gemini API? Ask for JSON in the prompt, set the response MIME type to application/json, provide a response schema, and then validate the parsed result in your own code with a schema library such as Zod before using it. ### Why validate LLM output with Zod if the model already uses a schema? Model-side schemas reduce errors but do not guarantee business rules such as minimum lengths, allowed values, or non-empty arrays. Zod validation on your server catches anything malformed and gives you typed data in TypeScript. ### What should happen when LLM output fails validation? Retry the request once or twice, optionally including the validation error in the prompt, and fall back to a friendly error message if it still fails. Never render unvalidated model output directly. --- # Article: The Next.js SEO, AEO & GEO Checklist for 2026 URL: https://www.gaurav-sharma.in/blog/nextjs-seo-checklist Author: Gaurav Sharma Published: 2026-05-03 Updated: 2026-05-03 To rank in search and get cited by AI engines, a Next.js site needs pre-rendered HTML, complete metadata, structured data, answer-first content, and machine-readable summaries such as llms.txt. ## SEO: the technical foundation - **Pre-render everything you can.** Static HTML is fast and fully crawlable. - **Use the Metadata API** for unique titles, descriptions, and canonical URLs on every page. - **Generate `sitemap.xml` and `robots.txt`** from code so they never drift from your routes. - **Ship dynamic Open Graph images** with `opengraph-image.tsx` for every page. - **Hit Core Web Vitals:** LCP under 2.5s, INP under 200ms, CLS under 0.1. ## AEO: be the answer - **Lead with the answer.** Put a one- or two-sentence direct answer at the top of each page. - **Use question-shaped headings** that match how people search. - **Add `FAQPage` JSON-LD** for genuine questions and answers. - **Prefer lists and tables** for steps and comparisons, which are easy to extract. ## GEO: be citable by AI - **Publish `llms.txt`** with a summary and links to your key pages. - **Build a strong entity.** Consistent `Person` or `Organization` schema with `sameAs` links to your profiles. - **Include specific numbers and sources.** Concrete, verifiable claims are cited more often than vague ones. - **Allow AI crawlers** such as GPTBot, ClaudeBot, and PerplexityBot in `robots.txt` if you want to be cited. - **Show freshness** with visible published and updated dates. ## Key takeaway **Great SEO, AEO, and GEO share one principle: make the page easy for both people and machines to understand.** ### What is the difference between SEO, AEO, and GEO? SEO (search engine optimisation) helps pages rank in traditional search results. AEO (answer engine optimisation) structures content so it is chosen as a direct answer or featured snippet. GEO (generative engine optimisation) makes content easy for AI models like ChatGPT and Perplexity to understand, trust, and cite. ### Is Next.js good for SEO? Yes. Next.js pre-renders pages to static HTML, has a built-in Metadata API for titles, canonical URLs and Open Graph tags, and generates sitemaps, robots.txt, and social images from code. ### What is llms.txt? llms.txt is a plain-text Markdown file at the root of a website that summarises the site and links to its key pages, so large language models can understand it quickly without parsing complex HTML.