<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Devanshu Biswas</title>
    <description>The latest articles on DEV Community by Devanshu Biswas (@dev48v).</description>
    <link>https://dev.clauneck.workers.dev/dev48v</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3929385%2F75a3696c-143d-4252-ba59-6ed4083ca827.jpg</url>
      <title>DEV Community: Devanshu Biswas</title>
      <link>https://dev.clauneck.workers.dev/dev48v</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.clauneck.workers.dev/feed/dev48v"/>
    <language>en</language>
    <item>
      <title>OrderHub Day 5: Clean Error Handling With RFC-7807 ProblemDetail (Spring Boot)</title>
      <dc:creator>Devanshu Biswas</dc:creator>
      <pubDate>Wed, 24 Jun 2026 14:54:38 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/dev48v/orderhub-day-5-clean-error-handling-with-rfc-7807-problemdetail-spring-boot-156m</link>
      <guid>https://dev.clauneck.workers.dev/dev48v/orderhub-day-5-clean-error-handling-with-rfc-7807-problemdetail-spring-boot-156m</guid>
      <description>&lt;p&gt;OrderHub Day 5: stop returning ugly, inconsistent errors. Today every failure — validation, not-found, bad state, or an unexpected crash — comes back in ONE standard, machine-readable shape: RFC-7807 ProblemDetail. One @RestControllerAdvice does it all.&lt;/p&gt;

&lt;p&gt;🚧 &lt;strong&gt;See every error shape:&lt;/strong&gt; &lt;a href="https://dev48v.infy.uk/orderhub/day5-exception-handling.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/orderhub/day5-exception-handling.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with scattered try/catch
&lt;/h2&gt;

&lt;p&gt;Handle errors in each controller and you get inconsistent JSON, leaked stack traces, and duplicated code. Centralize it instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  One advice, RFC-7807 everywhere
&lt;/h2&gt;

&lt;p&gt;Spring Boot 3 has &lt;code&gt;ProblemDetail&lt;/code&gt; built in. A single &lt;code&gt;@RestControllerAdvice&lt;/code&gt; maps exceptions to a consistent envelope (&lt;code&gt;type&lt;/code&gt;, &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;status&lt;/code&gt;, &lt;code&gt;detail&lt;/code&gt;, &lt;code&gt;instance&lt;/code&gt;, + extensions):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;MethodArgumentNotValidException&lt;/code&gt; → &lt;strong&gt;400&lt;/strong&gt; + an &lt;code&gt;errors&lt;/code&gt; field→message map&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OrderNotFoundException&lt;/code&gt; → &lt;strong&gt;404&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IllegalStateException&lt;/code&gt; (confirming an already-confirmed order) → &lt;strong&gt;409 Conflict&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;any other &lt;code&gt;Exception&lt;/code&gt; → &lt;strong&gt;500&lt;/strong&gt; with a &lt;em&gt;generic&lt;/em&gt; message — never leak the stack trace&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Let exceptions flow
&lt;/h2&gt;

&lt;p&gt;The trick: don't swallow errors in controllers. The service throws a domain exception (&lt;code&gt;OrderNotFoundException&lt;/code&gt;), it propagates up, and the advice turns it into the right status. Controllers stay clean; the web layer owns HTTP, the service owns domain rules.&lt;/p&gt;

&lt;p&gt;🔨 Full walkthrough (@RestControllerAdvice → ProblemDetail → 400/404/409/500, no leaks) on the page: &lt;a href="https://dev48v.infy.uk/orderhub/day5-exception-handling.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/orderhub/day5-exception-handling.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OrderHub — a production-grade Spring Boot backend, one feature a day.&lt;br&gt;
🌐 &lt;a href="https://dev48v.infy.uk" rel="noopener noreferrer"&gt;https://dev48v.infy.uk&lt;/a&gt; · Code: &lt;a href="https://github.com/dev48v/order-hub-from-zero" rel="noopener noreferrer"&gt;https://github.com/dev48v/order-hub-from-zero&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>spring</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>RAG Explained: Give an LLM Your Own Knowledge</title>
      <dc:creator>Devanshu Biswas</dc:creator>
      <pubDate>Wed, 24 Jun 2026 14:53:55 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/dev48v/rag-explained-give-an-llm-your-own-knowledge-388h</link>
      <guid>https://dev.clauneck.workers.dev/dev48v/rag-explained-give-an-llm-your-own-knowledge-388h</guid>
      <description>&lt;p&gt;An LLM doesn't know your company's docs, last week's news, or your private data — and it'll confidently make things up. RAG fixes that: retrieve the relevant facts, put them in the prompt, then generate. It's the backbone of almost every real LLM app. Here's the full pipeline, live.&lt;/p&gt;

&lt;p&gt;📚 &lt;strong&gt;See it answer from a private knowledge base:&lt;/strong&gt; &lt;a href="https://dev48v.infy.uk/ai/days/day15-rag.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/ai/days/day15-rag.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Retrieve → Augment → Generate
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Embed the question&lt;/strong&gt; into a vector (last two posts: embeddings + vector DBs).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retrieve&lt;/strong&gt; the top-k most similar chunks from your knowledge base.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Augment&lt;/strong&gt; the prompt: system instructions + the retrieved chunks as context + the question.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generate&lt;/strong&gt; — the model answers &lt;em&gt;grounded in those chunks&lt;/em&gt;, and can cite them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the demo, flip RAG off and the bare model hallucinates or refuses — it never saw your data. Flip it on and the answer is correct and sourced.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two pipelines
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Offline (indexing):&lt;/strong&gt; chunk your docs → embed → store in a vector DB.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Online (querying):&lt;/strong&gt; embed question → search → build prompt → generate.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  RAG vs fine-tuning
&lt;/h2&gt;

&lt;p&gt;RAG adds &lt;em&gt;knowledge&lt;/em&gt; (fresh, private, citable) without retraining. Fine-tuning changes &lt;em&gt;behavior/style&lt;/em&gt;. Most teams reach for RAG first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it breaks
&lt;/h2&gt;

&lt;p&gt;Bad retrieval → bad answer. That's why reranking, HyDE, and Corrective-RAG (earlier posts) exist — they all make the &lt;em&gt;retrieve&lt;/em&gt; step better.&lt;/p&gt;

&lt;p&gt;🔨 Build it (chunk → embed → upsert → retrieve top-k → augment → generate + cite) on the page: &lt;a href="https://dev48v.infy.uk/ai/days/day15-rag.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/ai/days/day15-rag.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Part of AIFromZero. 🌐 &lt;a href="https://dev48v.infy.uk" rel="noopener noreferrer"&gt;https://dev48v.infy.uk&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>llm</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Diffusion Models Explained: Turning Noise Into Images</title>
      <dc:creator>Devanshu Biswas</dc:creator>
      <pubDate>Wed, 24 Jun 2026 14:53:13 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/dev48v/diffusion-models-explained-turning-noise-into-images-1dcd</link>
      <guid>https://dev.clauneck.workers.dev/dev48v/diffusion-models-explained-turning-noise-into-images-1dcd</guid>
      <description>&lt;p&gt;GANs (yesterday) make images with two networks fighting. Diffusion models — what actually powers Stable Diffusion, DALL·E, and Midjourney — do it differently and far more stably: they learn to turn noise into images, one denoising step at a time. Here's the process, visualized.&lt;/p&gt;

&lt;p&gt;🌫️ &lt;strong&gt;Scrub the noise → image chain:&lt;/strong&gt; &lt;a href="https://dev48v.infy.uk/dl/day15-diffusion.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/dl/day15-diffusion.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Two processes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Forward (fixed, no learning):&lt;/strong&gt; take a real image and add a little Gaussian noise, over and over, for T steps — until it's pure static.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reverse (the learned part):&lt;/strong&gt; train a network to undo one noise step. Run it backward from pure noise and an image emerges.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What the network actually predicts
&lt;/h2&gt;

&lt;p&gt;Not the image — the &lt;strong&gt;noise&lt;/strong&gt; that was added at each step. Subtract the predicted noise, repeat. The training loss is just MSE between predicted and actual noise. That simplicity is why diffusion trains so much more stably than GANs (no adversarial game, no mode collapse).&lt;/p&gt;

&lt;h2&gt;
  
  
  How you steer it
&lt;/h2&gt;

&lt;p&gt;Text-to-image conditions the denoiser on a prompt (via cross-attention), and "latent diffusion" runs the whole thing in a compressed latent space for speed — that's the Stable Diffusion recipe.&lt;/p&gt;

&lt;h2&gt;
  
  
  GANs vs diffusion
&lt;/h2&gt;

&lt;p&gt;GANs: fast to sample, tricky to train. Diffusion: stable to train, slower to sample (many steps) — though that gap keeps closing.&lt;/p&gt;

&lt;p&gt;🔨 Full picture (forward noising → train to predict noise → sample by denoising) on the page: &lt;a href="https://dev48v.infy.uk/dl/day15-diffusion.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/dl/day15-diffusion.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Part of DeepLearningFromZero. 🌐 &lt;a href="https://dev48v.infy.uk" rel="noopener noreferrer"&gt;https://dev48v.infy.uk&lt;/a&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>deeplearning</category>
      <category>ai</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Gradient Boosting From Scratch: Weak Trees Fixing Each Other</title>
      <dc:creator>Devanshu Biswas</dc:creator>
      <pubDate>Wed, 24 Jun 2026 14:52:32 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/dev48v/gradient-boosting-from-scratch-weak-trees-fixing-each-other-12b4</link>
      <guid>https://dev.clauneck.workers.dev/dev48v/gradient-boosting-from-scratch-weak-trees-fixing-each-other-12b4</guid>
      <description>&lt;p&gt;Random forests build many trees in parallel and average them. Gradient boosting builds trees one at a time, each one fixing the previous trees' mistakes — and it's what wins most Kaggle competitions on tabular data. Here it is, fitting residuals live.&lt;/p&gt;

&lt;p&gt;🌲 &lt;strong&gt;Watch it boost (add trees one by one):&lt;/strong&gt; &lt;a href="https://dev48v.infy.uk/ml/day15-gradient-boosting.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/ml/day15-gradient-boosting.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The core loop
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Start with a constant prediction (the mean).&lt;/li&gt;
&lt;li&gt;Compute the &lt;strong&gt;residuals&lt;/strong&gt; — how far off you are at each point.&lt;/li&gt;
&lt;li&gt;Fit a small, shallow tree to those residuals.&lt;/li&gt;
&lt;li&gt;Add it to the ensemble, scaled by a &lt;strong&gt;learning rate&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Repeat. Each tree chips away at the remaining error.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the demo you watch the prediction curve bend toward the data and the residual bars shrink while the MSE drops every round.&lt;/p&gt;

&lt;h2&gt;
  
  
  Forest vs boosting
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Random forest:&lt;/strong&gt; independent trees, built in parallel, averaged. Reduces variance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Boosting:&lt;/strong&gt; dependent trees, built sequentially, summed. Reduces bias by correcting errors.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Learning rate = shrinkage
&lt;/h2&gt;

&lt;p&gt;Small steps (e.g. 0.1) generalize better than big ones — but need more trees. Too many trees / too high a rate → overfitting, so use early stopping.&lt;/p&gt;

&lt;p&gt;The "gradient" part: fitting residuals is just gradient descent on squared error; swap the loss and it generalizes (that's XGBoost / LightGBM / CatBoost).&lt;/p&gt;

&lt;p&gt;🔨 Built from scratch (mean → residuals → tree → add lr×tree → repeat) on the page: &lt;a href="https://dev48v.infy.uk/ml/day15-gradient-boosting.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/ml/day15-gradient-boosting.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Part of MachineLearningFromZero. 🌐 &lt;a href="https://dev48v.infy.uk" rel="noopener noreferrer"&gt;https://dev48v.infy.uk&lt;/a&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>ai</category>
      <category>datascience</category>
      <category>beginners</category>
    </item>
    <item>
      <title>I Built a JSON Formatter &amp; Validator in the Browser (No Library)</title>
      <dc:creator>Devanshu Biswas</dc:creator>
      <pubDate>Wed, 24 Jun 2026 14:51:50 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/dev48v/i-built-a-json-formatter-validator-in-the-browser-no-library-4p4n</link>
      <guid>https://dev.clauneck.workers.dev/dev48v/i-built-a-json-formatter-validator-in-the-browser-no-library-4p4n</guid>
      <description>&lt;p&gt;A JSON formatter sounds like a weekend project — and it is, because the browser does the hard part. Here's a live formatter + validator with syntax highlighting and real error locations, no library.&lt;/p&gt;

&lt;p&gt;🧾 &lt;strong&gt;Try it (paste JSON):&lt;/strong&gt; &lt;a href="https://dev48v.infy.uk/solve/day15-json-formatter.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/solve/day15-json-formatter.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Format = parse then re-stringify
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;          &lt;span class="c1"&gt;// validate (throws if invalid)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pretty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// 2-space indent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the entire formatter. &lt;code&gt;JSON.stringify(obj)&lt;/code&gt; with no third arg gives you minify for free.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validation is "did parse throw?"
&lt;/h2&gt;

&lt;p&gt;Wrap &lt;code&gt;JSON.parse&lt;/code&gt; in try/catch. On failure, the error message often includes a position — turn that into a line/column and show the offending snippet, so the user sees &lt;em&gt;where&lt;/em&gt; it broke (trailing comma, single quotes, unquoted key — the usual suspects).&lt;/p&gt;

&lt;h2&gt;
  
  
  Syntax highlighting
&lt;/h2&gt;

&lt;p&gt;Tokenize the pretty output with a regex and wrap keys / strings / numbers / booleans / null in colored spans. ~15 lines.&lt;/p&gt;

&lt;h2&gt;
  
  
  One safety rule
&lt;/h2&gt;

&lt;p&gt;Never &lt;code&gt;eval()&lt;/code&gt; JSON. &lt;code&gt;JSON.parse&lt;/code&gt; is safe; &lt;code&gt;eval&lt;/code&gt; runs arbitrary code.&lt;/p&gt;

&lt;p&gt;🔨 Full build (parse → stringify → highlight → minify → error position) on the page: &lt;a href="https://dev48v.infy.uk/solve/day15-json-formatter.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/solve/day15-json-formatter.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Part of SolveFromZero. 🌐 &lt;a href="https://dev48v.infy.uk" rel="noopener noreferrer"&gt;https://dev48v.infy.uk&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>json</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Chain-of-Verification: Make an LLM Fact-Check Itself</title>
      <dc:creator>Devanshu Biswas</dc:creator>
      <pubDate>Wed, 24 Jun 2026 14:51:07 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/dev48v/chain-of-verification-make-an-llm-fact-check-itself-4k68</link>
      <guid>https://dev.clauneck.workers.dev/dev48v/chain-of-verification-make-an-llm-fact-check-itself-4k68</guid>
      <description>&lt;p&gt;LLMs state wrong facts with total confidence. Chain-of-Verification (CoVe) is a prompting pattern that makes the model catch its own mistakes — by drafting, then fact-checking each claim independently, then revising. Here's a live walkthrough.&lt;/p&gt;

&lt;p&gt;🔬 &lt;strong&gt;Watch it catch a wrong fact:&lt;/strong&gt; &lt;a href="https://dev48v.infy.uk/prompt/day15-chain-of-verification.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/prompt/day15-chain-of-verification.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Four stages
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Draft&lt;/strong&gt; — the model answers normally (e.g. "5 politicians born in NYC"). One entry is subtly wrong.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan&lt;/strong&gt; — it generates one verification question per claim ("Was X born in NYC?").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify independently&lt;/strong&gt; — it answers each question &lt;em&gt;in a fresh context&lt;/em&gt;. This independence is the whole trick: if it re-checked while staring at its draft, it'd just repeat the error ("snowballing").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revise&lt;/strong&gt; — it regenerates the answer, dropping/fixing whatever failed verification.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why it works
&lt;/h2&gt;

&lt;p&gt;Splitting one big claim into small, isolated checks turns "sound confident" into "answer this single fact." Small factual questions are much easier to get right, so the revision is grounded in verified pieces.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cost
&lt;/h2&gt;

&lt;p&gt;Several LLM calls per answer — worth it for fact- and list-heavy responses, overkill for casual chat.&lt;/p&gt;

&lt;p&gt;🔨 Full pattern (draft → plan questions → answer independently → revise) on the page: &lt;a href="https://dev48v.infy.uk/prompt/day15-chain-of-verification.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/prompt/day15-chain-of-verification.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Part of PromptFromZero. 🌐 &lt;a href="https://dev48v.infy.uk" rel="noopener noreferrer"&gt;https://dev48v.infy.uk&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>rag</category>
      <category>beginners</category>
    </item>
    <item>
      <title>I Built a Drag-and-Drop Kanban Board With Zero Libraries</title>
      <dc:creator>Devanshu Biswas</dc:creator>
      <pubDate>Wed, 24 Jun 2026 14:50:25 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/dev48v/i-built-a-drag-and-drop-kanban-board-with-zero-libraries-4o8b</link>
      <guid>https://dev.clauneck.workers.dev/dev48v/i-built-a-drag-and-drop-kanban-board-with-zero-libraries-4o8b</guid>
      <description>&lt;p&gt;Trello, Linear, Jira — they all have the same draggable board. You can build it with zero libraries using the browser's native HTML5 Drag and Drop API. Here's a live Kanban with cards you drag between columns.&lt;/p&gt;

&lt;p&gt;🗂️ &lt;strong&gt;Try it (drag the cards):&lt;/strong&gt; &lt;a href="https://dev48v.infy.uk/design/day15-kanban-board.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/design/day15-kanban-board.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The native DnD lifecycle
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Mark a card &lt;code&gt;draggable="true"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;On &lt;strong&gt;&lt;code&gt;dragstart&lt;/code&gt;&lt;/strong&gt;, stash the card's id in &lt;code&gt;dataTransfer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;On the column's &lt;strong&gt;&lt;code&gt;dragover&lt;/code&gt;&lt;/strong&gt;, call &lt;code&gt;preventDefault()&lt;/code&gt; — this is the #1 gotcha: without it, the element is &lt;em&gt;not&lt;/em&gt; a valid drop target and nothing happens.&lt;/li&gt;
&lt;li&gt;On &lt;strong&gt;&lt;code&gt;drop&lt;/code&gt;&lt;/strong&gt;, read the id, move the DOM node into that column, and update your model.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  State vs DOM
&lt;/h2&gt;

&lt;p&gt;Move the node for instant feedback, but keep a small data model (which card is in which column) as the source of truth — then re-render counts from it and persist to &lt;code&gt;localStorage&lt;/code&gt;. Don't let the DOM &lt;em&gt;be&lt;/em&gt; your database.&lt;/p&gt;

&lt;h2&gt;
  
  
  The caveats
&lt;/h2&gt;

&lt;p&gt;Native DnD has no touch support (mobile needs Pointer Events or a lib like dnd-kit) and weak accessibility — fine for learning the mechanics, reach for a library in production.&lt;/p&gt;

&lt;p&gt;🔨 Full build (draggable → dragstart/dataTransfer → dragover preventDefault → drop → persist) on the page: &lt;a href="https://dev48v.infy.uk/design/day15-kanban-board.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/design/day15-kanban-board.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Part of DesignFromZero. 🌐 &lt;a href="https://dev48v.infy.uk" rel="noopener noreferrer"&gt;https://dev48v.infy.uk&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>css</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>I Built Doodle Jump in Vanilla JS (the Endless Bouncer)</title>
      <dc:creator>Devanshu Biswas</dc:creator>
      <pubDate>Wed, 24 Jun 2026 14:49:43 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/dev48v/i-built-doodle-jump-in-vanilla-js-the-endless-bouncer-4jad</link>
      <guid>https://dev.clauneck.workers.dev/dev48v/i-built-doodle-jump-in-vanilla-js-the-endless-bouncer-4jad</guid>
      <description>&lt;p&gt;Doodle Jump is the classic "go up forever" game — and it teaches one idea every platformer needs: instead of moving the player up, you move the world down. Here's a playable build in vanilla JS + canvas.&lt;/p&gt;

&lt;p&gt;🦘 &lt;strong&gt;Play it (←/→ to steer):&lt;/strong&gt; &lt;a href="https://dev48v.infy.uk/game/day15-doodle-jump.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/game/day15-doodle-jump.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The bounce is automatic
&lt;/h2&gt;

&lt;p&gt;There's no jump button. Every time the character lands on a platform (detected only while falling, &lt;code&gt;vy &amp;gt; 0&lt;/code&gt;), you set its velocity to a fixed upward value. Gravity pulls it back down, it lands, it springs again. Your only job is steering left/right — with screen-edge wrap.&lt;/p&gt;

&lt;h2&gt;
  
  
  The camera trick
&lt;/h2&gt;

&lt;p&gt;The player never actually rises past the middle of the screen. When it climbs above a threshold, you scroll &lt;strong&gt;everything else down&lt;/strong&gt; by that amount and add the distance to the score. It feels like flying up; really the world is sliding down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Endless platforms
&lt;/h2&gt;

&lt;p&gt;As platforms scroll off the bottom you remove them, and you spawn fresh ones above with slightly random spacing (wider as the score grows = harder). Miss them all, fall off the bottom → game over.&lt;/p&gt;

&lt;p&gt;🔨 Full build (loop → gravity/bounce → collision-on-descent → camera scroll → spawn/cull → score) on the page: &lt;a href="https://dev48v.infy.uk/game/day15-doodle-jump.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/game/day15-doodle-jump.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Part of GameFromZero. 🌐 &lt;a href="https://dev48v.infy.uk" rel="noopener noreferrer"&gt;https://dev48v.infy.uk&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>gamedev</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>OrderHub Day 4: Bean Validation + Clean DTOs (Spring Boot)</title>
      <dc:creator>Devanshu Biswas</dc:creator>
      <pubDate>Tue, 23 Jun 2026 06:17:34 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/dev48v/orderhub-day-4-bean-validation-clean-dtos-spring-boot-1f58</link>
      <guid>https://dev.clauneck.workers.dev/dev48v/orderhub-day-4-bean-validation-clean-dtos-spring-boot-1f58</guid>
      <description>&lt;p&gt;OrderHub Day 4: never trust the client. Today the backend gets proper &lt;strong&gt;Bean Validation&lt;/strong&gt; — bad requests are rejected at the edge with a clear 400, long before they reach the business logic. And it's all declarative.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Try the validating form (see the 400 body):&lt;/strong&gt; &lt;a href="https://dev48v.infy.uk/orderhub/day4-validation.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/orderhub/day4-validation.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Three DTOs, three jobs
&lt;/h2&gt;

&lt;p&gt;A common beginner mistake is using one class everywhere. OrderHub keeps them separate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Request DTO&lt;/strong&gt; (&lt;code&gt;CreateOrderRequest&lt;/code&gt;) — what the client sends, and where validation lives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain/Entity&lt;/strong&gt; (&lt;code&gt;Order&lt;/code&gt;) — the internal model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response DTO&lt;/strong&gt; (&lt;code&gt;OrderResponse&lt;/code&gt;) — what the API returns, so internal fields never leak.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Validation is just annotations
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;CreateOrderRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="nd"&gt;@NotBlank&lt;/span&gt; &lt;span class="nd"&gt;@Size&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nd"&gt;@CleanText&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nd"&gt;@NotBlank&lt;/span&gt; &lt;span class="nd"&gt;@Size&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nd"&gt;@CleanText&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nd"&gt;@Min&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nd"&gt;@Max&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add &lt;code&gt;@Valid @RequestBody&lt;/code&gt; on the controller and Spring checks every rule before your method runs. Break one and it throws &lt;code&gt;MethodArgumentNotValidException&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A custom constraint + clean errors
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;@CleanText&lt;/code&gt; is a custom &lt;code&gt;ConstraintValidator&lt;/code&gt; (rejects blank-after-trim + a small blocklist) — you can write your own rules, not just the built-ins. A &lt;code&gt;@RestControllerAdvice&lt;/code&gt; turns validation failures into a tidy 400 with a field→message map. (Day 5 upgrades this to full RFC-7807 ProblemDetail.)&lt;/p&gt;

&lt;p&gt;🔨 Full walkthrough (constraints → &lt;a class="mentioned-user" href="https://dev.clauneck.workers.dev/valid"&gt;@valid&lt;/a&gt; → custom validator → 400 handler) on the page: &lt;a href="https://dev48v.infy.uk/orderhub/day4-validation.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/orderhub/day4-validation.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OrderHub — a production-grade Spring Boot backend, one feature a day.&lt;br&gt;
🌐 &lt;a href="https://dev48v.infy.uk" rel="noopener noreferrer"&gt;https://dev48v.infy.uk&lt;/a&gt; · Code: &lt;a href="https://github.com/dev48v/order-hub-from-zero" rel="noopener noreferrer"&gt;https://github.com/dev48v/order-hub-from-zero&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>spring</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Vector Databases: Search by Meaning, at Scale</title>
      <dc:creator>Devanshu Biswas</dc:creator>
      <pubDate>Tue, 23 Jun 2026 06:16:52 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/dev48v/vector-databases-search-by-meaning-at-scale-2mfn</link>
      <guid>https://dev.clauneck.workers.dev/dev48v/vector-databases-search-by-meaning-at-scale-2mfn</guid>
      <description>&lt;p&gt;Embeddings turn meaning into vectors (last post). But if you have a million of them, how do you find the right ones for a query — fast? That's what a vector database does, and it's the retrieval engine behind every RAG app. Here's a live semantic search demo.&lt;/p&gt;

&lt;p&gt;🗂️ &lt;strong&gt;Search by meaning (not keywords):&lt;/strong&gt; &lt;a href="https://dev48v.infy.uk/ai/days/day14-vector-databases.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/ai/days/day14-vector-databases.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Search becomes "find the nearest vectors"
&lt;/h2&gt;

&lt;p&gt;Embed your query into the same space as your documents, then find the document vectors closest to it (by cosine similarity). Because closeness = meaning, the query "how do I reset my password" matches a doc about "recovering account access" — even with &lt;strong&gt;zero shared keywords&lt;/strong&gt;. The demo shows this beating a keyword search that returns nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why you need a database, not a for-loop
&lt;/h2&gt;

&lt;p&gt;Comparing your query to every vector (brute-force kNN) is fine for hundreds, hopeless for millions. Vector DBs use &lt;strong&gt;ANN&lt;/strong&gt; (approximate nearest neighbour) indexes like HNSW to find the closest vectors in milliseconds — trading a tiny bit of accuracy for huge speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a vector DB actually stores
&lt;/h2&gt;

&lt;p&gt;Vectors + the original text + metadata, behind an ANN index. Pipeline: chunk your docs → embed → upsert. Query: embed the question → search top-k → (often) filter by metadata or combine with keyword search (hybrid).&lt;/p&gt;

&lt;p&gt;This is the retrieval half of RAG. Real options: Pinecone, Weaviate, Chroma, pgvector, FAISS.&lt;/p&gt;

&lt;p&gt;🔨 Build it (embed → upsert → similarity search → top-k → RAG) on the page: &lt;a href="https://dev48v.infy.uk/ai/days/day14-vector-databases.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/ai/days/day14-vector-databases.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Part of AIFromZero. 🌐 &lt;a href="https://dev48v.infy.uk" rel="noopener noreferrer"&gt;https://dev48v.infy.uk&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>database</category>
      <category>beginners</category>
    </item>
    <item>
      <title>GANs Explained: Two Networks That Make Fakes Real</title>
      <dc:creator>Devanshu Biswas</dc:creator>
      <pubDate>Tue, 23 Jun 2026 06:16:11 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/dev48v/gans-explained-two-networks-that-make-fakes-real-3kj8</link>
      <guid>https://dev.clauneck.workers.dev/dev48v/gans-explained-two-networks-that-make-fakes-real-3kj8</guid>
      <description>&lt;p&gt;Before diffusion models, GANs were how AI learned to generate realistic images. The idea is a game between two networks — and you can watch it reach its eerie equilibrium on a 2D scatter. Here's a live GAN-training demo.&lt;/p&gt;

&lt;p&gt;🎭 &lt;strong&gt;Watch the fakes become real:&lt;/strong&gt; &lt;a href="https://dev48v.infy.uk/dl/day14-gans.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/dl/day14-gans.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Two networks, one game
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Generator&lt;/strong&gt; turns random noise into fake data, trying to mimic the real distribution.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Discriminator&lt;/strong&gt; is a detective: given a sample, is it real or fake?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They train against each other. The generator wants to fool the discriminator; the discriminator wants to catch fakes. Forger vs. detective.&lt;/p&gt;

&lt;h2&gt;
  
  
  The equilibrium
&lt;/h2&gt;

&lt;p&gt;At first the fakes are obvious noise and the discriminator nails them (~90% accuracy). As the generator improves, its fakes drift onto the real distribution — until the discriminator can't do better than a coin flip (&lt;strong&gt;~50%&lt;/strong&gt;). That stalemate means the fakes are indistinguishable from real. In the demo, the rose "fake" cloud morphs onto the teal "real" ring while the accuracy bar slides to 50%.&lt;/p&gt;

&lt;h2&gt;
  
  
  The catch
&lt;/h2&gt;

&lt;p&gt;GANs are famously unstable to train — &lt;strong&gt;mode collapse&lt;/strong&gt; (the generator outputs one thing), oscillation, sensitive hyperparameters. Variants like DCGAN and StyleGAN tamed it (StyleGAN's faces went viral). Today, diffusion models have largely taken over image generation — but the adversarial idea is foundational.&lt;/p&gt;

&lt;p&gt;🔨 Full build (G and D nets → sample noise → train D on real+fake → train G to fool D) on the page: &lt;a href="https://dev48v.infy.uk/dl/day14-gans.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/dl/day14-gans.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Part of DeepLearningFromZero. 🌐 &lt;a href="https://dev48v.infy.uk" rel="noopener noreferrer"&gt;https://dev48v.infy.uk&lt;/a&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>deeplearning</category>
      <category>ai</category>
      <category>beginners</category>
    </item>
    <item>
      <title>PCA From Scratch: Compress Data, Keep the Signal</title>
      <dc:creator>Devanshu Biswas</dc:creator>
      <pubDate>Tue, 23 Jun 2026 06:15:29 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/dev48v/pca-from-scratch-compress-data-keep-the-signal-mlh</link>
      <guid>https://dev.clauneck.workers.dev/dev48v/pca-from-scratch-compress-data-keep-the-signal-mlh</guid>
      <description>&lt;p&gt;Got 100 features and can't visualize or train fast? PCA finds the few directions that carry most of the information and throws away the rest — and you can watch it happen on a 2D scatter. Here's PCA computed for real in the browser.&lt;/p&gt;

&lt;p&gt;📉 &lt;strong&gt;See the principal axes (drag the correlation slider):&lt;/strong&gt; &lt;a href="https://dev48v.infy.uk/ml/day14-pca.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/ml/day14-pca.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The idea: rotate to where the variance is
&lt;/h2&gt;

&lt;p&gt;PCA finds new axes — &lt;strong&gt;principal components&lt;/strong&gt; — pointing along the directions your data spreads the most. PC1 is the longest spread, PC2 the next (perpendicular to it), and so on. Keep the top few and you've compressed the data with minimal loss.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it's actually computed
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Center&lt;/strong&gt; the data (subtract the mean).&lt;/li&gt;
&lt;li&gt;Build the &lt;strong&gt;covariance matrix&lt;/strong&gt; (how features vary together).&lt;/li&gt;
&lt;li&gt;Find its &lt;strong&gt;eigenvectors&lt;/strong&gt; (the component directions) and &lt;strong&gt;eigenvalues&lt;/strong&gt; (how much variance each holds).&lt;/li&gt;
&lt;li&gt;Sort by eigenvalue, keep the top-k, &lt;strong&gt;project&lt;/strong&gt; onto them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The demo draws PC1/PC2 through the cloud and shows the "variance explained" percentages — collapse to PC1 and watch how much information survives.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to reach for it
&lt;/h2&gt;

&lt;p&gt;Visualization (high-dim → 2D), compression, denoising, speeding up training. Scale your features first; remember it only captures &lt;em&gt;linear&lt;/em&gt; structure.&lt;/p&gt;

&lt;p&gt;🔨 Built from scratch (center → covariance → eigen → project) on the page: &lt;a href="https://dev48v.infy.uk/ml/day14-pca.html" rel="noopener noreferrer"&gt;https://dev48v.infy.uk/ml/day14-pca.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Part of MachineLearningFromZero. 🌐 &lt;a href="https://dev48v.infy.uk" rel="noopener noreferrer"&gt;https://dev48v.infy.uk&lt;/a&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>ai</category>
      <category>datascience</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
