<?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: nishchal singh</title>
    <description>The latest articles on DEV Community by nishchal singh (@nishchaldev).</description>
    <link>https://dev.to/nishchaldev</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%2F1231797%2F0c243537-17d9-431b-b323-f81531f96741.jpg</url>
      <title>DEV Community: nishchal singh</title>
      <link>https://dev.to/nishchaldev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nishchaldev"/>
    <language>en</language>
    <item>
      <title>I Built AI Streaming With Too Many Layers. Here’s What Broke</title>
      <dc:creator>nishchal singh</dc:creator>
      <pubDate>Mon, 14 Sep 2026 12:16:34 +0000</pubDate>
      <link>https://dev.to/nishchaldev/i-built-ai-streaming-with-too-many-layers-heres-what-broke-1m5g</link>
      <guid>https://dev.to/nishchaldev/i-built-ai-streaming-with-too-many-layers-heres-what-broke-1m5g</guid>
      <description>&lt;p&gt;I was working on the AI assistant for an NGO application when I ran into a streaming problem that took me through a few different layers of the system.&lt;/p&gt;

&lt;p&gt;The chat worked locally.&lt;/p&gt;

&lt;p&gt;In production, it didn't.&lt;/p&gt;

&lt;p&gt;Then I fixed a platform timeout and found another timeout. After that, I found something even stranger: OpenRouter was returning &lt;code&gt;200&lt;/code&gt;, but my application was receiving &lt;strong&gt;zero usable streaming events&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Eventually, I realized the bigger problem wasn't one broken request.&lt;/p&gt;

&lt;p&gt;I had made the streaming architecture more complicated than it needed to be.&lt;/p&gt;

&lt;p&gt;This is how I found it, what I changed, and what I'm still investigating.&lt;/p&gt;




&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;The application uses Next.js App Router, React, TypeScript, MongoDB/Mongoose, Clerk, TanStack Query, Cloudinary and OpenRouter.&lt;/p&gt;

&lt;p&gt;The AI assistant is available at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://www.pssmumbai.org/ai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The public chat endpoint is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /api/ai/chat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The assistant uses reviewed application knowledge to answer questions around PSS teachings, meditation and related topics.&lt;/p&gt;

&lt;p&gt;There is quite a bit happening before and after the model call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Authentication
Rate limiting
Quota
Conversation history
Knowledge retrieval
AI response
Conversation persistence
Usage tracking
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the model interaction, I use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openai/gpt-5-mini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;through OpenRouter.&lt;/p&gt;

&lt;p&gt;I wanted the response to stream to the browser rather than waiting for the complete answer.&lt;/p&gt;

&lt;p&gt;That's where my architecture had become unnecessarily complicated.&lt;/p&gt;




&lt;h2&gt;
  
  
  The streaming setup I had built
&lt;/h2&gt;

&lt;p&gt;The application already had an AI SDK implementation using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;streamText()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@openrouter/ai-sdk-provider
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there was also an older custom streaming implementation.&lt;/p&gt;

&lt;p&gt;The older path used an OpenAI-compatible wrapper in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/lib/openai.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That wrapper made its own request to OpenRouter and requested:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Accept: text/event-stream
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API route then manually handled the provider response.&lt;/p&gt;

&lt;p&gt;It had to read chunks, parse SSE events, extract token deltas, detect completion and usage, accumulate the response, and eventually convert the result into our own NDJSON format.&lt;/p&gt;

&lt;p&gt;The browser then had another custom parser to consume that NDJSON stream.&lt;/p&gt;

&lt;p&gt;So the flow was roughly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser
  ↓
fetch()
  ↓
Custom NDJSON parser
  ↓
Next.js API route
  ↓
Custom OpenRouter wrapper
  ↓
Custom SSE parser
  ↓
OpenRouter
  ↓
GPT-5 Mini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpow7n71qms4a95gxa6qt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpow7n71qms4a95gxa6qt.png" alt="Original AI streaming architecture with custom SSE and NDJSON parsing in a Next.js application" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There was also an AI SDK path sitting alongside it.&lt;/p&gt;

&lt;p&gt;That was the first thing I should have questioned.&lt;/p&gt;

&lt;p&gt;The system had multiple layers that understood the same stream.&lt;/p&gt;




&lt;h2&gt;
  
  
  Then production failed
&lt;/h2&gt;

&lt;p&gt;The first error I saw in the browser was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unexpected token 'A', "An error o"... is not valid JSON
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first, I thought I had a JSON/API response problem.&lt;/p&gt;

&lt;p&gt;Maybe the server was returning an unexpected response.&lt;/p&gt;

&lt;p&gt;Maybe the frontend parser was wrong.&lt;/p&gt;

&lt;p&gt;Maybe the error response itself wasn't valid JSON.&lt;/p&gt;

&lt;p&gt;So I opened the Network tab.&lt;/p&gt;

&lt;p&gt;The important part was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /api/ai/chat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;returned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;504 Gateway Timeout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The JSON error was only a symptom.&lt;/p&gt;

&lt;p&gt;The actual request wasn't completing.&lt;/p&gt;

&lt;p&gt;This was a good reminder that browser errors don't always tell you where the failure started. Sometimes you have to follow the request one layer deeper.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Vercel timeout
&lt;/h2&gt;

&lt;p&gt;The Vercel logs made the first problem much clearer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FUNCTION_INVOCATION_TIMEOUT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The execution was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10.37s / 10s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function was being terminated before the AI request could complete.&lt;/p&gt;

&lt;p&gt;I checked the repository for anything that might have configured this limit.&lt;/p&gt;

&lt;p&gt;There was no:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vercel.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There was no route-level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;maxDuration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and no runtime override that I had intentionally added.&lt;/p&gt;

&lt;p&gt;So I checked the Vercel project settings.&lt;/p&gt;

&lt;p&gt;Fluid Compute was disabled.&lt;/p&gt;

&lt;p&gt;I enabled it and redeployed.&lt;/p&gt;

&lt;p&gt;The function now had a much larger execution window.&lt;/p&gt;

&lt;p&gt;That fixed the platform-level timeout.&lt;/p&gt;

&lt;p&gt;But it also exposed another problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Fixing the timeout didn't fix the request
&lt;/h2&gt;

&lt;p&gt;After the deployment, the application started reaching its own timeout instead.&lt;/p&gt;

&lt;p&gt;The response was now a controlled application error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI_TIMEOUT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The AI service took too long to respond. Please try again.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application-level timeout was around:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;20 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This was actually useful.&lt;/p&gt;

&lt;p&gt;The first problem had been:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Platform timeout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I was looking at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application/provider streaming latency
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Increasing the available function duration hadn't made the streaming implementation correct.&lt;/p&gt;

&lt;p&gt;It had simply allowed the request to get further.&lt;/p&gt;

&lt;p&gt;So I added more timing and streaming logs.&lt;/p&gt;




&lt;h2&gt;
  
  
  The strange part: OpenRouter returned 200
&lt;/h2&gt;

&lt;p&gt;This was the most interesting trace.&lt;/p&gt;

&lt;p&gt;The request successfully passed the application stages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;auth_end
rate_limit_end
quota_reserve_end
conversation_lookup_end
retrieve_context_end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openrouter_request_start
streaming=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And OpenRouter responded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openrouter_stream_headers
status=200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That sounds good.&lt;/p&gt;

&lt;p&gt;But immediately after that, the stream counters told a very different story:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chunkCount=0
parsedEventCount=0
deltaCount=0
accumulatedChars=0
sawFinishReason=false
sawUsage=false
sawDone=false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eventually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openrouter_stream_unexpected_eof
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API eventually returned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /api/ai/chat 200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but the browser received:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The AI service disconnected before completing the response.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So I had an HTTP &lt;code&gt;200&lt;/code&gt; from the provider, but no usable streamed content made it through my custom streaming path.&lt;/p&gt;

&lt;p&gt;That was the clue I needed.&lt;/p&gt;

&lt;p&gt;I couldn't reasonably conclude that OpenRouter itself was broken.&lt;/p&gt;

&lt;p&gt;The evidence pointed me toward the path I had built around the provider.&lt;/p&gt;




&lt;h2&gt;
  
  
  Instead of patching the parser, I made a smaller test
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4dzsu8yf6hojpmowud22.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4dzsu8yf6hojpmowud22.png" alt="Debugging a production AI streaming failure from browser JSON error to Vercel timeout and zero stream events" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, I could have kept modifying the custom SSE parser.&lt;/p&gt;

&lt;p&gt;But I wanted a simpler answer first:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can the AI SDK receive a stream from OpenRouter correctly?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So I created an isolated test using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI SDK v6
+
@openrouter/ai-sdk-provider
+
OpenRouter
+
openai/gpt-5-mini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test successfully produced streamed deltas.&lt;/p&gt;

&lt;p&gt;The result included things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;success: true
model: openai/gpt-5-mini
deltasCount: 4
accumulatedChars: 21
finishReason: stop
usage present
providerRequestId present
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I wouldn't rely on the exact timing from that isolated test because the instrumentation lifecycle around it wasn't reliable enough.&lt;/p&gt;

&lt;p&gt;But the important result was much simpler:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The AI SDK + OpenRouter combination could successfully receive streamed output.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That changed how I looked at the problem.&lt;/p&gt;

&lt;p&gt;I didn't necessarily need to find the exact line where my custom parser was failing.&lt;/p&gt;

&lt;p&gt;I needed to ask whether I should have that parser in the first place.&lt;/p&gt;




&lt;h2&gt;
  
  
  The actual architectural problem
&lt;/h2&gt;

&lt;p&gt;Looking back, I was solving too much myself.&lt;/p&gt;

&lt;p&gt;The application had custom code handling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Provider streaming
SSE parsing
Transport conversion
Client stream parsing
Message accumulation
Cancellation
Completion handling
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there was already a mature abstraction available for the model streaming part.&lt;/p&gt;

&lt;p&gt;The problem wasn't that custom streaming code is always wrong.&lt;/p&gt;

&lt;p&gt;The problem was that I had &lt;strong&gt;multiple layers responsible for the same thing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The browser understood one streaming protocol.&lt;/p&gt;

&lt;p&gt;The API route translated between protocols.&lt;/p&gt;

&lt;p&gt;The OpenRouter wrapper understood another streaming protocol.&lt;/p&gt;

&lt;p&gt;The SSE parser interpreted provider events.&lt;/p&gt;

&lt;p&gt;And the AI SDK had its own streaming abstraction.&lt;/p&gt;

&lt;p&gt;That creates more places where a response can be transformed, misunderstood or dropped.&lt;/p&gt;

&lt;p&gt;It also makes debugging harder because the error you see may be several layers away from where the problem started.&lt;/p&gt;




&lt;h2&gt;
  
  
  The change: one authoritative streaming path
&lt;/h2&gt;

&lt;p&gt;I decided to stop using the legacy custom streaming path for the public chat route.&lt;/p&gt;

&lt;p&gt;The new flow is much simpler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser
  ↓
POST /api/ai/chat
  ↓
Authentication
  ↓
Rate limiting
  ↓
Quota
  ↓
Conversation lookup
  ↓
Knowledge retrieval
  ↓
streamText()
  ↓
@openrouter/ai-sdk-provider
  ↓
OpenRouter
  ↓
GPT-5 Mini
  ↓
Stream back to browser
  ↓
Save completed response
  ↓
Persist usage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frmhfey5ec5kqctru8e0i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frmhfey5ec5kqctru8e0i.png" alt="Simplified Next.js AI streaming architecture using AI SDK, OpenRouter and GPT-5 Mini" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The public route no longer calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;getOpenAIClient().chat.completions.stream()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and it no longer manually parses OpenRouter's raw SSE response.&lt;/p&gt;

&lt;p&gt;The existing OpenAI-compatible wrapper wasn't removed completely because other non-streaming/admin functionality still uses it.&lt;/p&gt;

&lt;p&gt;The change was specifically about the public streaming path.&lt;/p&gt;

&lt;p&gt;The important architectural decision was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;There should be one authoritative implementation responsible for the model stream.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  I didn't change the frontend at the same time
&lt;/h2&gt;

&lt;p&gt;There was another problem I wanted to avoid.&lt;/p&gt;

&lt;p&gt;The frontend already understood our NDJSON protocol:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"delta"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"done"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I could have changed the server transport, frontend parser and message handling in one large refactor.&lt;/p&gt;

&lt;p&gt;I didn't.&lt;/p&gt;

&lt;p&gt;For the first change, I kept the existing browser contract and replaced the provider-side streaming implementation.&lt;/p&gt;

&lt;p&gt;So temporarily, the architecture became:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI SDK
  ↓
AI SDK stream
  ↓
Small compatibility layer
  ↓
Existing NDJSON client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This wasn't intended to be the final architecture.&lt;/p&gt;

&lt;p&gt;It was a way to change one layer at a time and reduce the number of variables involved in the debugging.&lt;/p&gt;

&lt;p&gt;The longer-term plan is to move the frontend away from custom &lt;code&gt;fetch()&lt;/code&gt; + NDJSON parsing and eventually use the AI SDK's React transport.&lt;/p&gt;

&lt;p&gt;But that can happen separately.&lt;/p&gt;




&lt;h2&gt;
  
  
  The first successful end-to-end test
&lt;/h2&gt;

&lt;p&gt;After changing the public route, I tested the actual chat with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Guide me through a 5-minute mindful meditation.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser successfully streamed the response.&lt;/p&gt;

&lt;p&gt;The application produced the expected answer, including the guided practice and knowledge sources.&lt;/p&gt;

&lt;p&gt;The logs now showed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ai_stream_selected
stream_path = ai_sdk_openrouter

stream_started

stream_first_text
firstDeltaMs = 10568
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response was then persisted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;conversation_save:
~472 ms

usage persistence:
~166 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the request completed with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;stream_finished

POST /api/ai/chat 200 in 18584ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just as important, the old streaming failure events were gone.&lt;/p&gt;

&lt;p&gt;There was no:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openrouter_stream_unexpected_eof
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openrouter_stream_error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the browser didn't show the disconnect message.&lt;/p&gt;

&lt;p&gt;That gave me the first proper end-to-end confirmation that the new path was working.&lt;/p&gt;




&lt;h2&gt;
  
  
  But it's still too slow
&lt;/h2&gt;

&lt;p&gt;This is where I want to be careful about the conclusion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The streaming problem is fixed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The performance problem isn't.&lt;/p&gt;

&lt;p&gt;The successful request took approximately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;First text: ~10.568s
Total request: ~18.584s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's still too much waiting before the user sees the first useful text.&lt;/p&gt;

&lt;p&gt;I don't want to hide that behind a nicer loading animation.&lt;/p&gt;

&lt;p&gt;The next question is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is the first text taking around 10.5 seconds?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's now a performance investigation rather than a streaming correctness problem.&lt;/p&gt;

&lt;p&gt;I'm looking at things such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Model reasoning configuration
OpenRouter/provider routing
Prompt size
Conversation history size
Retrieved context size
Duplicated instructions/context
Work happening before the provider call
AI SDK/provider configuration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model remains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openai/gpt-5-mini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm not planning to switch models just because another model might produce a nicer benchmark.&lt;/p&gt;

&lt;p&gt;First I want to understand where the time is actually going.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I learned from this
&lt;/h2&gt;

&lt;p&gt;The biggest lesson wasn't that I should always use the AI SDK.&lt;/p&gt;

&lt;p&gt;It's this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If a mature library already handles a difficult infrastructure problem, think twice before rebuilding that responsibility yourself.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The application still needs to own plenty of things.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Authentication
Permissions
Quota
Rate limiting
Knowledge retrieval
Source filtering
Conversation persistence
Business rules
Observability
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those are application concerns.&lt;/p&gt;

&lt;p&gt;The model streaming abstraction doesn't need to know how the application's quota works or where its knowledge comes from.&lt;/p&gt;

&lt;p&gt;Likewise, the application doesn't need to understand every detail of the provider's streaming protocol.&lt;/p&gt;

&lt;p&gt;That separation makes the system easier to reason about.&lt;/p&gt;




&lt;h2&gt;
  
  
  Another lesson: don't change everything at once
&lt;/h2&gt;

&lt;p&gt;One thing I'm glad I didn't do was rewrite the entire streaming system in one go.&lt;/p&gt;

&lt;p&gt;The frontend already had a working NDJSON contract.&lt;/p&gt;

&lt;p&gt;So I kept it temporarily.&lt;/p&gt;

&lt;p&gt;That gave me a smaller change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Old provider streaming
        ↓
New AI SDK provider streaming
        ↓
Existing browser contract
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once that worked, I had a known-good baseline.&lt;/p&gt;

&lt;p&gt;I can now replace the client transport separately.&lt;/p&gt;

&lt;p&gt;This is especially useful when debugging systems with several moving parts.&lt;/p&gt;

&lt;p&gt;If you change the provider integration, API response format, client parser and UI state management at the same time, a successful result doesn't tell you much about which change actually mattered.&lt;/p&gt;

&lt;p&gt;Smaller changes give you better evidence.&lt;/p&gt;




&lt;h2&gt;
  
  
  Working and fast are two different problems
&lt;/h2&gt;

&lt;p&gt;This distinction is probably the most useful thing I'll carry forward from this work.&lt;/p&gt;

&lt;p&gt;The first successful test answered:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does the stream work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes.&lt;/p&gt;

&lt;p&gt;It did not answer:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is the stream fast enough?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not yet.&lt;/p&gt;

&lt;p&gt;Those are different engineering problems.&lt;/p&gt;

&lt;p&gt;The next stage is to measure time to first text, completion time and the work happening before the provider request.&lt;/p&gt;

&lt;p&gt;I also want better request-level observability around:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;request ID
stream start
first text
completion
abort
failure
latency
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That should make the next performance investigation much less dependent on guesswork.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;There are a few things I want to improve from here.&lt;/p&gt;

&lt;p&gt;First, I want to understand the roughly 10-second first-text delay.&lt;/p&gt;

&lt;p&gt;Then I'll look at the prompt, conversation history and retrieved context sizes, along with the model and provider configuration.&lt;/p&gt;

&lt;p&gt;On the frontend, I eventually want to remove the custom NDJSON transport and move to the AI SDK React transport rather than maintaining our own client-side streaming state machine.&lt;/p&gt;

&lt;p&gt;There is also UX work to do.&lt;/p&gt;

&lt;p&gt;The current chat works, but the preparing/generating state still needs improvement. I'd like it to feel more natural while the application is waiting for the first response, without turning the interface into a collection of animations.&lt;/p&gt;

&lt;p&gt;But that's separate from the architecture fix.&lt;/p&gt;

&lt;p&gt;For now, the important part is that the stream itself is working again.&lt;/p&gt;




&lt;h2&gt;
  
  
  The part I'd change if I built it again
&lt;/h2&gt;

&lt;p&gt;I wouldn't start with a pile of streaming infrastructure.&lt;/p&gt;

&lt;p&gt;I'd first decide which layer should own the stream.&lt;/p&gt;

&lt;p&gt;For this application, that means keeping the responsibilities roughly separated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application
→ auth, quota, retrieval, persistence, business rules

AI SDK
→ model streaming and stream lifecycle

Provider
→ OpenRouter/model communication

UI
→ displaying and interacting with the response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The mistake wasn't writing custom code.&lt;/p&gt;

&lt;p&gt;The mistake was allowing several layers to take responsibility for the same problem.&lt;/p&gt;

&lt;p&gt;Once I removed that overlap, the system became much easier to understand.&lt;/p&gt;

&lt;p&gt;And that's probably the part I'll remember from this debugging session:&lt;/p&gt;

&lt;p&gt;Sometimes the useful architectural change isn't adding another layer.&lt;/p&gt;

&lt;p&gt;It's deciding which layer doesn't need to be there. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>The NGO App's AI Worked Locally. Then Vercel Gave Me a 504.</title>
      <dc:creator>nishchal singh</dc:creator>
      <pubDate>Wed, 09 Sep 2026 01:49:08 +0000</pubDate>
      <link>https://dev.to/nishchaldev/the-ngo-apps-ai-worked-locally-then-vercel-gave-me-a-504-3ied</link>
      <guid>https://dev.to/nishchaldev/the-ngo-apps-ai-worked-locally-then-vercel-gave-me-a-504-3ied</guid>
      <description>&lt;p&gt;I was testing the AI assistant locally, and everything was working.&lt;/p&gt;

&lt;p&gt;Then I deployed it.&lt;/p&gt;

&lt;p&gt;I opened the production app and asked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;how start meditation. im a beginner&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of an answer, I got:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unexpected token 'A', "An error o"... is not valid JSON
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first, I thought I had broken something in the frontend.&lt;/p&gt;

&lt;p&gt;I hadn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The error was hiding the actual problem
&lt;/h2&gt;

&lt;p&gt;I checked the browser Network tab.&lt;/p&gt;

&lt;p&gt;The request was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /api/ai/chat
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the response was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;504 Gateway Timeout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the JSON error wasn't the actual problem. The frontend was trying to parse an error response as JSON, while the request itself had already timed out.&lt;/p&gt;

&lt;p&gt;That changed my debugging path.&lt;/p&gt;

&lt;p&gt;Instead of looking at the JSON parser, I needed to find out &lt;strong&gt;why the server request was timing out&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  But it worked locally
&lt;/h2&gt;

&lt;p&gt;This was the confusing part.&lt;/p&gt;

&lt;p&gt;The same AI request worked on my local machine.&lt;/p&gt;

&lt;p&gt;The local terminal showed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /api/ai/chat 200 in 21994ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The logs showed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI context retrieved
model: openai/gpt-5-mini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI completion itself took around &lt;strong&gt;17.76 seconds&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The usage was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;promptTokens: 1663
completionTokens: 1500
totalTokens: 3163
finishReason: "length"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the complete local request was taking roughly &lt;strong&gt;22 seconds&lt;/strong&gt;, but it still succeeded.&lt;/p&gt;

&lt;p&gt;That was an important clue.&lt;/p&gt;

&lt;p&gt;The model wasn't simply broken.&lt;/p&gt;

&lt;p&gt;OpenRouter wasn't obviously unreachable.&lt;/p&gt;

&lt;p&gt;The application could make the request and receive a response.&lt;/p&gt;

&lt;p&gt;Something was different in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  Vercel gave me the useful error
&lt;/h2&gt;

&lt;p&gt;I checked the Vercel production logs.&lt;/p&gt;

&lt;p&gt;This time, the error was much more useful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FUNCTION_INVOCATION_TIMEOUT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there was a number that immediately stood out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Execution Duration / Maximum
10.37s / 10s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The logs also showed that parts of the request had already completed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Clerk authentication succeeded
AI context retrieval succeeded
POST request to OpenRouter was made
AI completion did not return before the function was terminated
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the function wasn't failing immediately.&lt;/p&gt;

&lt;p&gt;It was running out of time while waiting for the AI completion.&lt;/p&gt;

&lt;p&gt;That explained the 504.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6fu56xi92a7jztic7u5o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6fu56xi92a7jztic7u5o.png" alt="Vercel settings fluid" width="799" height="193"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where was that 10-second limit coming from?
&lt;/h2&gt;

&lt;p&gt;I checked the repository first.&lt;/p&gt;

&lt;p&gt;There was no:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vercel.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There was no route-level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;maxDuration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There was no runtime override.&lt;/p&gt;

&lt;p&gt;And there wasn't a Next.js configuration setting a 10-second function duration.&lt;/p&gt;

&lt;p&gt;So I hadn't configured this timeout in the application code.&lt;/p&gt;

&lt;p&gt;I checked the Vercel project settings next.&lt;/p&gt;

&lt;p&gt;That's where I found it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fluid Compute was disabled.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Screenshot: Vercel Functions settings showing Fluid Compute disabled&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That was the missing piece.&lt;/p&gt;




&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;p&gt;I enabled &lt;strong&gt;Fluid Compute&lt;/strong&gt; in the Vercel project settings and redeployed the application.&lt;/p&gt;

&lt;p&gt;After the redeployment, the execution numbers changed from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10.37s / 10s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;26.31s / 5m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI request could now finish.&lt;/p&gt;

&lt;p&gt;The browser displayed the generated response instead of the 504.&lt;/p&gt;

&lt;p&gt;The production logs also showed the rest of the request completing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;conversation_save_start
conversation_save_end
usage_persist_start
usage_persist_end
ai_chat_request_end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application recorded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;totalElapsedMs: 25384
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vercel reported approximately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;26.31s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the API returned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Screenshot: successful production request / Vercel execution metrics&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So the first production problem was fixed.&lt;/p&gt;




&lt;h2&gt;
  
  
  One important clarification
&lt;/h2&gt;

&lt;p&gt;I don't want to turn this into the wrong Vercel lesson.&lt;/p&gt;

&lt;p&gt;I'm &lt;strong&gt;not&lt;/strong&gt; saying:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Vercel cannot run AI functions longer than 10 seconds."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's not what I observed.&lt;/p&gt;

&lt;p&gt;What I observed was that &lt;strong&gt;this deployment was running with a 10-second maximum while Fluid Compute was disabled&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;After enabling Fluid Compute and redeploying, the same function was allowed to run for up to &lt;strong&gt;5 minutes&lt;/strong&gt;, and the request completed.&lt;/p&gt;

&lt;p&gt;The fix wasn't making OpenRouter faster.&lt;/p&gt;

&lt;p&gt;It removed the execution limit that was killing the request before the AI response could return.&lt;/p&gt;




&lt;h2&gt;
  
  
  But then I noticed something else
&lt;/h2&gt;

&lt;p&gt;The 504 was gone.&lt;/p&gt;

&lt;p&gt;The AI was working in production.&lt;/p&gt;

&lt;p&gt;So I could have stopped there.&lt;/p&gt;

&lt;p&gt;But the successful request was still taking around &lt;strong&gt;25–26 seconds&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The local request was around &lt;strong&gt;22 seconds&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So fixing one problem exposed another one.&lt;/p&gt;

&lt;p&gt;I don't know the cause yet, and I don't want to guess.&lt;/p&gt;

&lt;p&gt;Instead, I added temporary timing logs around different parts of the request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;authentication
rate limiting
quota reservation
database connection
conversation lookup/create
AI context retrieval
OpenRouter request start
OpenRouter response headers
OpenRouter full response
conversation save
usage persistence
total request duration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I'm measuring each part instead of assuming where the time is going.&lt;/p&gt;

&lt;p&gt;That's the next problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I learned from this
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Don't trust the first error
&lt;/h3&gt;

&lt;p&gt;The browser showed a JSON parsing error.&lt;/p&gt;

&lt;p&gt;The actual problem was a 504.&lt;/p&gt;

&lt;p&gt;The Network tab gave me the next clue.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local success doesn't guarantee production success
&lt;/h3&gt;

&lt;p&gt;Locally, the request took around 22 seconds and worked.&lt;/p&gt;

&lt;p&gt;Production was terminating it after 10 seconds.&lt;/p&gt;

&lt;p&gt;The application code wasn't the only thing that mattered. The execution environment mattered too.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check the platform before changing your code
&lt;/h3&gt;

&lt;p&gt;There was no 10-second timeout configured in my repository.&lt;/p&gt;

&lt;p&gt;The useful information was in the Vercel runtime logs and project settings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't immediately blame the AI provider
&lt;/h3&gt;

&lt;p&gt;The request reached OpenRouter, and the same model worked locally.&lt;/p&gt;

&lt;p&gt;There wasn't enough evidence to blame the provider.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't blindly increase timeouts
&lt;/h3&gt;

&lt;p&gt;First find out &lt;strong&gt;which layer is timing out&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this case, the function itself was being terminated before the AI completion could return.&lt;/p&gt;

&lt;h3&gt;
  
  
  Measure again after every fix
&lt;/h3&gt;

&lt;p&gt;Enabling Fluid Compute fixed the 504.&lt;/p&gt;

&lt;p&gt;It also made the next problem visible:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is the request still taking ~25 seconds?&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Measure first. Change second.
&lt;/h2&gt;

&lt;p&gt;That's probably the simplest way I can describe this debugging session.&lt;/p&gt;

&lt;p&gt;I started with a strange frontend error.&lt;/p&gt;

&lt;p&gt;Then I checked the Network tab.&lt;/p&gt;

&lt;p&gt;Then the production logs.&lt;/p&gt;

&lt;p&gt;Then the repository configuration.&lt;/p&gt;

&lt;p&gt;Then the Vercel project settings.&lt;/p&gt;

&lt;p&gt;Each step removed another assumption.&lt;/p&gt;

&lt;p&gt;Eventually, the 504 made sense.&lt;/p&gt;

&lt;p&gt;The actual fix was only one setting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finding that setting was the debugging work.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The application is live here if you want to have a look:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pssmumbai.org/" rel="noopener noreferrer"&gt;https://www.pssmumbai.org/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 2: Why is the AI still taking ~25 seconds?
&lt;/h2&gt;

&lt;p&gt;The timeout is fixed.&lt;/p&gt;

&lt;p&gt;The request now completes successfully in production.&lt;/p&gt;

&lt;p&gt;But waiting 25+ seconds for an AI response isn't something I want to leave alone.&lt;/p&gt;

&lt;p&gt;So now I'm trying to find out where those seconds are actually going.&lt;/p&gt;

&lt;p&gt;Is it the AI request?&lt;/p&gt;

&lt;p&gt;Context retrieval?&lt;/p&gt;

&lt;p&gt;Database work?&lt;/p&gt;

&lt;p&gt;Something else?&lt;/p&gt;

&lt;p&gt;I don't know yet.&lt;/p&gt;

&lt;p&gt;That's what I'm measuring now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 2 will be about finding that answer.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>vercel</category>
      <category>ai</category>
      <category>debugging</category>
    </item>
    <item>
      <title>I Spent $5 on OpenRouter While Building AI Features for an NGO App</title>
      <dc:creator>nishchal singh</dc:creator>
      <pubDate>Thu, 03 Sep 2026 13:01:15 +0000</pubDate>
      <link>https://dev.to/nishchaldev/i-spent-5-on-openrouter-while-building-ai-features-for-a-nextjs-app-566b</link>
      <guid>https://dev.to/nishchaldev/i-spent-5-on-openrouter-while-building-ai-features-for-a-nextjs-app-566b</guid>
      <description>&lt;p&gt;I've been working on the PSS website for quite some time, and recently a lot of my work went into its AI features.&lt;/p&gt;

&lt;p&gt;The application already handles sessions, events, staff, blog posts, gallery, testimonials, donations, settings, and an admin CMS.&lt;/p&gt;

&lt;p&gt;For the AI work, I wanted two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PSS-specific information available to the user-facing AI&lt;/li&gt;
&lt;li&gt;AI-assisted content creation inside the admin CMS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The stack is &lt;strong&gt;Next.js, React, TypeScript, MongoDB, Mongoose, Clerk, Cloudinary, Tailwind CSS, shadcn/ui, TanStack Query and OpenRouter&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;During development, my OpenRouter dashboard reached about &lt;strong&gt;$4.99 in total spend&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The $5 isn't the interesting part.&lt;/p&gt;

&lt;p&gt;What happened while building the features is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Giving the AI PSS-specific knowledge
&lt;/h2&gt;

&lt;p&gt;I didn't want the AI to answer PSS-related questions only from its general knowledge.&lt;/p&gt;

&lt;p&gt;I needed information that the application could control and update.&lt;/p&gt;

&lt;p&gt;So I built a knowledge flow around approved PSS content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Approved PSS knowledge
        ↓
     Chunking
        ↓
    Embeddings
        ↓
     MongoDB
        ↓
Relevant knowledge retrieved
        ↓
    AI context
        ↓
 Response / content generation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The stored knowledge includes the content plus details such as its source, authority, status and visibility.&lt;/p&gt;

&lt;p&gt;That also gives me a way to separate public knowledge from internal AI guidance and policies.&lt;/p&gt;

&lt;p&gt;The idea I ended up using is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The knowledge base decides what PSS teaches. The model decides how to communicate it.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That became much more important once I started checking the generated content.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI inside the admin CMS
&lt;/h2&gt;

&lt;p&gt;The admin CMS also has AI-assisted blog creation.&lt;/p&gt;

&lt;p&gt;AI can help generate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;title/context&lt;/li&gt;
&lt;li&gt;tags&lt;/li&gt;
&lt;li&gt;SEO title&lt;/li&gt;
&lt;li&gt;SEO description&lt;/li&gt;
&lt;li&gt;excerpt&lt;/li&gt;
&lt;li&gt;full article&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I didn't want one button to generate an entire blog post from nothing.&lt;/p&gt;

&lt;p&gt;For smaller fields, the admin can run individual AI actions. Full article generation is a separate flow.&lt;/p&gt;

&lt;p&gt;The article generation can use the information already entered in the editor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Title
Category
Tags
SEO title
SEO description
Excerpt
Writing instruction
Relevant PSS knowledge
        ↓
     AI model
        ↓
 Generated article
        ↓
   Article editor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is much more useful than sending something generic like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Write a blog post about meditation."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application already has context. The AI should use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The first problem: the article stopped halfway
&lt;/h2&gt;

&lt;p&gt;My first full-article generation didn't finish.&lt;/p&gt;

&lt;p&gt;The logs showed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model: openai/gpt-5-mini
task: full_article
promptTokens: 1013
completionTokens: 1800
finishReason: length
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application reported:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI generation reached the model's output limit.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I increased:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI_CONTENT_MAX_TOKENS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;from &lt;code&gt;1800&lt;/code&gt; to &lt;code&gt;2000&lt;/code&gt;, and after testing again, the generation completed.&lt;/p&gt;

&lt;p&gt;It was a small configuration issue, but it reminded me that an AI feature has limits that a normal API call doesn't have.&lt;/p&gt;

&lt;p&gt;The request can succeed while the output is still incomplete.&lt;/p&gt;

&lt;p&gt;The application needs to detect and handle that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then I found a bigger problem
&lt;/h2&gt;

&lt;p&gt;The generated article looked good.&lt;/p&gt;

&lt;p&gt;That was actually the problem.&lt;/p&gt;

&lt;p&gt;When I compared it with the approved PSS knowledge, I found some contradictions.&lt;/p&gt;

&lt;p&gt;The approved information included specific guidance around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;clasped/interlaced hands&lt;/li&gt;
&lt;li&gt;closed eyes&lt;/li&gt;
&lt;li&gt;natural breathing&lt;/li&gt;
&lt;li&gt;avoiding breath manipulation&lt;/li&gt;
&lt;li&gt;other PSS-specific meditation instructions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The generated article introduced more general meditation advice, including things like resting the hands in the lap or on the knees, allowing the eyes to remain open, and suggesting specific practice durations.&lt;/p&gt;

&lt;p&gt;Those suggestions may sound reasonable for meditation in general.&lt;/p&gt;

&lt;p&gt;But the website isn't publishing generic meditation advice.&lt;/p&gt;

&lt;p&gt;It represents PSS.&lt;/p&gt;

&lt;p&gt;So the output can be well written and still be wrong &lt;strong&gt;for the application&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That was the most useful thing I found during testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  RAG became more than a search problem
&lt;/h2&gt;

&lt;p&gt;Before this work, I mostly thought of retrieval as a way to give the model better information.&lt;/p&gt;

&lt;p&gt;Now I also see it as a way to keep the application's content under control.&lt;/p&gt;

&lt;p&gt;The embeddings help find relevant information, but the application still needs to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the information approved?&lt;/li&gt;
&lt;li&gt;Is it public?&lt;/li&gt;
&lt;li&gt;Where did it come from?&lt;/li&gt;
&lt;li&gt;Who is the authority?&lt;/li&gt;
&lt;li&gt;Is the document active?&lt;/li&gt;
&lt;li&gt;Should this information be used for this AI workflow?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So it isn't simply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;documents → embeddings → model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is an application around it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The admin UI mattered too
&lt;/h2&gt;

&lt;p&gt;Getting the backend generation working wasn't enough.&lt;/p&gt;

&lt;p&gt;While using the admin workflow, I also found that the AI actions needed to behave like normal application features.&lt;/p&gt;

&lt;p&gt;I worked on things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;clearer generation states&lt;/li&gt;
&lt;li&gt;disabling relevant fields while generation is running&lt;/li&gt;
&lt;li&gt;loading/progress feedback&lt;/li&gt;
&lt;li&gt;better AI action buttons&lt;/li&gt;
&lt;li&gt;separate actions for smaller fields&lt;/li&gt;
&lt;li&gt;clearer error messages&lt;/li&gt;
&lt;li&gt;keeping the writing instruction separate from generated content&lt;/li&gt;
&lt;li&gt;putting generated content into the article editor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Adding AI doesn't remove normal UX problems.&lt;/p&gt;

&lt;p&gt;It gives you a few more.&lt;/p&gt;

&lt;h2&gt;
  
  
  What did the $4.99 actually show?
&lt;/h2&gt;

&lt;p&gt;My OpenRouter dashboard showed approximately:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Total spend:&lt;/strong&gt; $4.99&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Requests:&lt;/strong&gt; ~1K&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token volume:&lt;/strong&gt; 73.5M&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache hit rate:&lt;/strong&gt; 94.7%&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blended cost:&lt;/strong&gt; $0.07 / 1M&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The dashboard also showed usage from &lt;strong&gt;GPT-5.4, GPT-5 Mini and Text Embedding 3 Small&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One clarification: 73.5M is the &lt;strong&gt;token-volume metric shown by the dashboard&lt;/strong&gt;. I wouldn't describe it as 73.5M tokens of generated text.&lt;/p&gt;

&lt;p&gt;Most of this usage came from development, testing AI flows, model calls and embeddings.&lt;/p&gt;

&lt;p&gt;The useful part wasn't getting a lot of AI work done for $5.&lt;/p&gt;

&lt;p&gt;It was being able to see what experimentation actually costs.&lt;/p&gt;

&lt;p&gt;The 94.7% cache hit rate also made me think more about repeated context and what these costs could look like with more traffic.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'm checking now
&lt;/h2&gt;

&lt;p&gt;I'm trying not to judge an AI feature only by whether the API returns a successful response.&lt;/p&gt;

&lt;p&gt;I also need to ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the generated content use the right knowledge?&lt;/li&gt;
&lt;li&gt;Can it introduce unsupported information?&lt;/li&gt;
&lt;li&gt;Can it contradict approved information?&lt;/li&gt;
&lt;li&gt;What happens when the output limit is reached?&lt;/li&gt;
&lt;li&gt;Does the UI clearly show that generation is running?&lt;/li&gt;
&lt;li&gt;What happens when generation fails or hits a rate limit?&lt;/li&gt;
&lt;li&gt;Should a person review generated content before publishing?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of these are things I've already encountered during development. Others are areas I still want to make more systematic with testing.&lt;/p&gt;

&lt;p&gt;The AI system isn't finished.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd do earlier next time
&lt;/h2&gt;

&lt;p&gt;If I started this part of the project again, I'd think about the knowledge and failure cases earlier.&lt;/p&gt;

&lt;p&gt;Not only:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Which model should I use?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But also:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What information should the AI use?

What information should it never use?

What happens when there is no relevant information?

What happens when the model doesn't finish?

How do I know the generated content is acceptable?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model is only one part of the feature.&lt;/p&gt;

&lt;p&gt;The rest is application engineering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final takeaway
&lt;/h2&gt;

&lt;p&gt;The biggest thing I learned wasn't about a particular model.&lt;/p&gt;

&lt;p&gt;It was that adding AI to an existing application means dealing with a lot more than an API call:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;knowledge retrieval&lt;/li&gt;
&lt;li&gt;embeddings&lt;/li&gt;
&lt;li&gt;prompt context&lt;/li&gt;
&lt;li&gt;content generation&lt;/li&gt;
&lt;li&gt;token limits&lt;/li&gt;
&lt;li&gt;model selection&lt;/li&gt;
&lt;li&gt;caching&lt;/li&gt;
&lt;li&gt;cost&lt;/li&gt;
&lt;li&gt;admin UX&lt;/li&gt;
&lt;li&gt;error handling&lt;/li&gt;
&lt;li&gt;validation&lt;/li&gt;
&lt;li&gt;testing&lt;/li&gt;
&lt;li&gt;human review&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The AI can generate a very good-looking article.&lt;/p&gt;

&lt;p&gt;I still have to ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Is this actually what we want the application to say?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For this project, that question matters more than whether the model produced a polished paragraph.&lt;/p&gt;

&lt;p&gt;You can see the application here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pssmumbai.org/" rel="noopener noreferrer"&gt;https://www.pssmumbai.org/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're building AI into an existing application, I'd be interested to hear what surprised you after the first successful API response.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>ai</category>
      <category>rag</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Why Your Nextjs UI Flickers: TanStack Query vs useEffect</title>
      <dc:creator>nishchal singh</dc:creator>
      <pubDate>Wed, 13 May 2026 03:04:49 +0000</pubDate>
      <link>https://dev.to/nishchaldev/why-your-nextjs-ui-flickers-tanstack-query-vs-useeffect-1a2o</link>
      <guid>https://dev.to/nishchaldev/why-your-nextjs-ui-flickers-tanstack-query-vs-useeffect-1a2o</guid>
      <description>&lt;p&gt;A page can load quickly and still feel unstable.&lt;/p&gt;

&lt;p&gt;That usually happens when the initial render strategy is fine, but client-side data updates are handled poorly.&lt;/p&gt;

&lt;p&gt;In this article, we’ll compare two common approaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A basic &lt;code&gt;useEffect&lt;/code&gt; fetch&lt;/li&gt;
&lt;li&gt;A production-ready pattern using TanStack Query&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both fetch the same API under the same network conditions.&lt;/p&gt;

&lt;p&gt;One flickers.&lt;/p&gt;

&lt;p&gt;The other stays smooth.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5yitw1hpedb8uhzyb8ok.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5yitw1hpedb8uhzyb8ok.png" alt="Overview of how TanStack Query keeps previous data visible while naive useEffect fetching causes UI flicker in Next.js" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Experiment
&lt;/h2&gt;

&lt;p&gt;I built a small &lt;strong&gt;Next.js Rendering Lab&lt;/strong&gt; to visualize:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSR&lt;/li&gt;
&lt;li&gt;CSR&lt;/li&gt;
&lt;li&gt;SSG&lt;/li&gt;
&lt;li&gt;ISR&lt;/li&gt;
&lt;li&gt;Hydration&lt;/li&gt;
&lt;li&gt;Cached background refetching&lt;/li&gt;
&lt;li&gt;UI flicker caused by naive fetching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;call the same endpoint&lt;/li&gt;
&lt;li&gt;refetch every few seconds&lt;/li&gt;
&lt;li&gt;run under throttled network conditions&lt;/li&gt;
&lt;li&gt;display live telemetry&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Naive &lt;code&gt;useEffect&lt;/code&gt; Fetching
&lt;/h2&gt;

&lt;p&gt;A common pattern looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works, but on every refetch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;loading state resets&lt;/li&gt;
&lt;li&gt;content disappears&lt;/li&gt;
&lt;li&gt;layout shifts&lt;/li&gt;
&lt;li&gt;charts blink&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The data may arrive quickly, but the interface feels unstable.&lt;/p&gt;




&lt;h2&gt;
  
  
  TanStack Query
&lt;/h2&gt;

&lt;p&gt;TanStack Query handles updates differently.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;keeps previous data visible&lt;/li&gt;
&lt;li&gt;fetches in the background&lt;/li&gt;
&lt;li&gt;updates only changed values&lt;/li&gt;
&lt;li&gt;avoids unnecessary loading states&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is a much smoother experience.&lt;/p&gt;

&lt;p&gt;Users continue seeing the existing UI while fresh data is being fetched.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fytzbbhazt24kmhl2mcxb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fytzbbhazt24kmhl2mcxb.png" alt="Side-by-side comparison of TanStack Query cached background refetching versus useEffect loading and UI resets" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Rendering Strategy vs Data Strategy
&lt;/h2&gt;

&lt;p&gt;These are two separate concerns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rendering Strategy
&lt;/h3&gt;

&lt;p&gt;Determines how the page initially loads.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSR&lt;/li&gt;
&lt;li&gt;SSG&lt;/li&gt;
&lt;li&gt;ISR&lt;/li&gt;
&lt;li&gt;CSR&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Data Strategy
&lt;/h3&gt;

&lt;p&gt;Determines how the UI behaves after hydration.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;useEffect&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;TanStack Query&lt;/li&gt;
&lt;li&gt;SWR&lt;/li&gt;
&lt;li&gt;caching&lt;/li&gt;
&lt;li&gt;background refetching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A page can be server-rendered and still flicker if data updates are handled poorly.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3k8wsx6cnfu6k9yke4mk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3k8wsx6cnfu6k9yke4mk.png" alt="Diagram showing the difference between Next.js rendering strategies like SSR and CSR and data strategies like TanStack Query" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;This becomes obvious in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dashboards&lt;/li&gt;
&lt;li&gt;analytics tools&lt;/li&gt;
&lt;li&gt;admin panels&lt;/li&gt;
&lt;li&gt;live metrics&lt;/li&gt;
&lt;li&gt;stock tickers&lt;/li&gt;
&lt;li&gt;collaborative applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Users may not understand hydration or caching, but they notice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;flicker&lt;/li&gt;
&lt;li&gt;disappearing content&lt;/li&gt;
&lt;li&gt;layout shifts&lt;/li&gt;
&lt;li&gt;unstable interfaces&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Good frontend UX is often about preserving visual stability.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try the Rendering Lab
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Live Demo:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://nextjs-rendering-lab-phi.vercel.app/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Next.js Rendering Lab&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source Code:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/nishchal27/next.js_rendering_lab?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Watch the YouTube Short
&lt;/h2&gt;

&lt;p&gt;I also recorded a short visual comparison showing both patterns side by side under Slow 4G throttling.&lt;/p&gt;


&lt;div&gt;
    &lt;iframe src="https://www.youtube.com/embed/uqI_wAg8a84"&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;





&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The biggest lesson from this experiment:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Performance is not only about speed. It is also about stability.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Two apps can fetch data at almost the same speed but feel completely different depending on how updates are handled.&lt;/p&gt;

&lt;p&gt;TanStack Query does not make your API faster.&lt;/p&gt;

&lt;p&gt;It makes your UI behave better.&lt;/p&gt;

&lt;p&gt;And users notice that immediately.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>performance</category>
      <category>react</category>
      <category>ui</category>
    </item>
    <item>
      <title>Why Date and Time Bugs Happen in JavaScript (And How Apps Actually Get It Right)</title>
      <dc:creator>nishchal singh</dc:creator>
      <pubDate>Tue, 10 Feb 2026 11:46:37 +0000</pubDate>
      <link>https://dev.to/nishchaldev/why-date-and-time-bugs-happen-in-javascript-and-how-apps-actually-get-it-right-hjh</link>
      <guid>https://dev.to/nishchaldev/why-date-and-time-bugs-happen-in-javascript-and-how-apps-actually-get-it-right-hjh</guid>
      <description>&lt;h2&gt;
  
  
  If you’ve ever seen reminders fire early, late, or on the wrong day,
&lt;/h2&gt;

&lt;p&gt;this post is for you.&lt;/p&gt;

&lt;p&gt;I used to think date and time bugs were just edge cases.&lt;/p&gt;

&lt;p&gt;They’re not.&lt;/p&gt;

&lt;p&gt;Most of the time, they come from a slightly wrong mental model of how&lt;br&gt;
time actually works in JavaScript. The problem only becomes visible&lt;br&gt;
when an app starts dealing with real users, real schedules, and real&lt;br&gt;
expectations.&lt;/p&gt;

&lt;p&gt;This post explains why these bugs happen so often, how JavaScript really&lt;br&gt;
handles date and time, and how production apps avoid them.&lt;/p&gt;

&lt;p&gt;No heavy theory.&lt;br&gt;
No library comparisons.&lt;br&gt;
Just the parts that matter.&lt;/p&gt;


&lt;h2&gt;
  
  
  The illusion: “I used &lt;code&gt;Date()&lt;/code&gt;, so time should be correct”
&lt;/h2&gt;

&lt;p&gt;Most developers start with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It prints a date and time that looks correct, so we assume everything&lt;br&gt;
underneath is local and intuitive.&lt;/p&gt;

&lt;p&gt;That assumption is where many bugs begin.&lt;/p&gt;

&lt;p&gt;JavaScript dates are not stored as local time.&lt;/p&gt;

&lt;p&gt;Internally, they are stored as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Milliseconds since January 1, 1970 (UTC)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Local time, timezone, and formatting are applied only when the date is&lt;br&gt;
read or displayed.&lt;/p&gt;

&lt;p&gt;This sounds like a small detail.&lt;br&gt;
In real apps, it isn’t.&lt;/p&gt;


&lt;h2&gt;
  
  
  What JavaScript is actually doing
&lt;/h2&gt;

&lt;p&gt;A useful mental model is this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript stores one number&lt;/li&gt;
&lt;li&gt;That number represents a moment in UTC&lt;/li&gt;
&lt;li&gt;Local time is calculated only at display or formatting time&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-02-10T09:00:00&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This does not mean “9am in my timezone”.&lt;/p&gt;

&lt;p&gt;It means “9am UTC, converted to the user’s local timezone”.&lt;/p&gt;

&lt;p&gt;If your app does not control that context explicitly, time slowly drifts.&lt;/p&gt;




&lt;h2&gt;
  
  
  The three most common time mistakes
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw02rwrm9tjh42b8drtyy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw02rwrm9tjh42b8drtyy.png" alt="The three most common time mistakes in JavaScript" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Assuming &lt;code&gt;Date()&lt;/code&gt; is local internally
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Date&lt;/code&gt; behaves like a local clock, but it is not one.&lt;/p&gt;

&lt;p&gt;It is a UTC timestamp with a local view layered on top.&lt;/p&gt;

&lt;p&gt;This becomes a problem when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;users are in different timezones&lt;/li&gt;
&lt;li&gt;servers run in UTC&lt;/li&gt;
&lt;li&gt;background jobs don’t share locale information&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2. Mixing server time and client time
&lt;/h3&gt;

&lt;p&gt;A very common pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;server schedules something&lt;/li&gt;
&lt;li&gt;client displays or adjusts it&lt;/li&gt;
&lt;li&gt;background job runs later&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If these layers don’t agree on what “now” means, reminders drift.&lt;/p&gt;

&lt;p&gt;This is especially dangerous for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;recurring schedules&lt;/li&gt;
&lt;li&gt;weekly reminders&lt;/li&gt;
&lt;li&gt;“tomorrow at 9am” logic&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  3. Generating dates without context
&lt;/h3&gt;

&lt;p&gt;Any logic that generates dates needs to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;today’s date&lt;/li&gt;
&lt;li&gt;the user’s timezone&lt;/li&gt;
&lt;li&gt;daylight saving rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without this context, it’s easy to generate reminders:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;in the past&lt;/li&gt;
&lt;li&gt;on the wrong day&lt;/li&gt;
&lt;li&gt;in the wrong year&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why this gets worse in PWAs
&lt;/h2&gt;

&lt;p&gt;These problems become much more visible in Progressive Web Apps.&lt;/p&gt;

&lt;p&gt;Browsers are not designed to guarantee precise scheduling.&lt;br&gt;
They optimize for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;battery life&lt;/li&gt;
&lt;li&gt;performance&lt;/li&gt;
&lt;li&gt;security&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;background execution is delayed&lt;/li&gt;
&lt;li&gt;service workers wake unpredictably&lt;/li&gt;
&lt;li&gt;scheduled logic runs in time windows, not exact moments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6qwxvaiflf3hnw9tkcup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6qwxvaiflf3hnw9tkcup.png" alt="Why scheduling is unreliable in PWAs" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I ran into this while building a productivity app where reminders and&lt;br&gt;
check-ins were core features.&lt;/p&gt;

&lt;p&gt;Notifications worked.&lt;br&gt;
Nothing crashed.&lt;br&gt;
But timing was unreliable.&lt;/p&gt;

&lt;p&gt;I wrote about that experience here:&lt;/p&gt;

&lt;p&gt;When Notifications Matter, PWAs Start to Show Their Limits&lt;br&gt;&lt;br&gt;
&lt;a href="https://dev.to/nishchaldev/when-notifications-matter-pwas-start-to-show-their-limits-5ebl"&gt;https://dev.to/nishchaldev/when-notifications-matter-pwas-start-to-show-their-limits-5ebl&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That post explains where things broke.&lt;br&gt;
This post explains why.&lt;/p&gt;




&lt;h2&gt;
  
  
  How mature apps avoid time bugs
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdey4v3z6iv841j5fjpja.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdey4v3z6iv841j5fjpja.png" alt="How mature apps avoid time bugs" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once I looked at how established reminder apps work, a clear pattern&lt;br&gt;
emerged.&lt;/p&gt;

&lt;h3&gt;
  
  
  One clear definition of “now”
&lt;/h3&gt;

&lt;p&gt;There is exactly one source of truth for current time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;based on the device timezone&lt;/li&gt;
&lt;li&gt;or an explicit user setting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No guessing.&lt;br&gt;
No hidden defaults.&lt;/p&gt;




&lt;h3&gt;
  
  
  Store in UTC, schedule in local time
&lt;/h3&gt;

&lt;p&gt;This is the most important rule.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store timestamps in UTC&lt;/li&gt;
&lt;li&gt;Convert to local time for display&lt;/li&gt;
&lt;li&gt;Schedule alarms using local context&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;daylight saving bugs&lt;/li&gt;
&lt;li&gt;timezone drift&lt;/li&gt;
&lt;li&gt;unexpected early or late triggers&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Let the OS handle scheduling
&lt;/h3&gt;

&lt;p&gt;On native platforms, reminders are scheduled using system services.&lt;/p&gt;

&lt;p&gt;The operating system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reschedules after reboots&lt;/li&gt;
&lt;li&gt;adjusts for timezone changes&lt;/li&gt;
&lt;li&gt;guarantees delivery timing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JavaScript logic does not need to stay alive.&lt;/p&gt;




&lt;h2&gt;
  
  
  The shift that fixed my app
&lt;/h2&gt;

&lt;p&gt;After understanding these patterns, I changed the architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the web app handles dashboards and planning&lt;/li&gt;
&lt;li&gt;the native layer handles scheduling and notifications&lt;/li&gt;
&lt;li&gt;the backend stores everything in UTC&lt;/li&gt;
&lt;li&gt;time context is always explicit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same product logic runs everywhere, but time-sensitive&lt;br&gt;
responsibilities live where they belong.&lt;/p&gt;

&lt;p&gt;The app is still evolving, but the difference is noticeable.&lt;/p&gt;

&lt;p&gt;Live app:&lt;br&gt;&lt;br&gt;
&lt;a href="https://wio-dev.vercel.app" rel="noopener noreferrer"&gt;https://wio-dev.vercel.app&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  A simple rule that helps
&lt;/h2&gt;

&lt;p&gt;If you remember only one thing, remember this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Time is not a utility. It’s a product feature.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If your app depends on time being correct:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;model it deliberately&lt;/li&gt;
&lt;li&gt;pass context explicitly&lt;/li&gt;
&lt;li&gt;let the platform handle scheduling&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Closing thought
&lt;/h2&gt;

&lt;p&gt;JavaScript dates are not broken.&lt;br&gt;
Browsers are not broken.&lt;/p&gt;

&lt;p&gt;Most time bugs come from assumptions that feel reasonable until real&lt;br&gt;
users and real schedules expose them.&lt;/p&gt;

&lt;p&gt;Once your mental model matches how time actually works, things become&lt;br&gt;
much simpler.&lt;/p&gt;




&lt;h2&gt;
  
  
  A question for you
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Have you run into confusing date or timezone bugs?&lt;/li&gt;
&lt;li&gt;How are you handling reminders or schedules today?&lt;/li&gt;
&lt;li&gt;Did this explanation match what you’ve seen in practice?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’d genuinely love to hear how others are dealing with this.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>javascript</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>When notifications matter, PWAs start to show their limits</title>
      <dc:creator>nishchal singh</dc:creator>
      <pubDate>Sat, 07 Feb 2026 08:37:57 +0000</pubDate>
      <link>https://dev.to/nishchaldev/when-notifications-matter-pwas-start-to-show-their-limits-5ebl</link>
      <guid>https://dev.to/nishchaldev/when-notifications-matter-pwas-start-to-show-their-limits-5ebl</guid>
      <description>&lt;h2&gt;
  
  
  I was getting notifications at &lt;strong&gt;3am&lt;/strong&gt;.
&lt;/h2&gt;

&lt;p&gt;Users were confused.&lt;br&gt;&lt;br&gt;
I hadn’t changed anything.&lt;/p&gt;

&lt;p&gt;That’s when I realized something uncomfortable:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PWAs don’t really understand time the way we expect them to.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Nothing was “broken” in the obvious sense.&lt;br&gt;&lt;br&gt;
Reminders worked. Notifications appeared. Logs looked fine.&lt;/p&gt;

&lt;p&gt;But for a productivity app — where reminders and check-ins &lt;em&gt;are the product&lt;/em&gt; —&lt;br&gt;&lt;br&gt;
“mostly works” isn’t good enough.&lt;/p&gt;

&lt;p&gt;This post is about what went wrong, why it wasn’t actually a bug, and why I eventually stopped relying on a pure PWA setup for time-critical notifications.&lt;/p&gt;




&lt;h2&gt;
  
  
  When PWAs work great (and when they don’t)
&lt;/h2&gt;

&lt;p&gt;If your app needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;in-app banners
&lt;/li&gt;
&lt;li&gt;occasional push notifications
&lt;/li&gt;
&lt;li&gt;background sync &lt;em&gt;when possible&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PWAs are an excellent choice.&lt;/p&gt;

&lt;p&gt;They’re fast to build, easy to ship, and good enough for many products.&lt;/p&gt;

&lt;p&gt;But reminders are different.&lt;/p&gt;

&lt;p&gt;A reminder isn’t just a notification.&lt;br&gt;&lt;br&gt;
It’s a &lt;strong&gt;promise about time&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And time is where PWAs start to show their limits.&lt;/p&gt;




&lt;h2&gt;
  
  
  How PWA notifications really behave
&lt;/h2&gt;

&lt;p&gt;When a PWA is open:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript is running
&lt;/li&gt;
&lt;li&gt;the user’s local time is known
&lt;/li&gt;
&lt;li&gt;scheduling logic is predictable
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Things feel solid.&lt;/p&gt;

&lt;p&gt;The problems start once the app is closed or backgrounded.&lt;/p&gt;

&lt;p&gt;At that point:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the browser decides when background work runs
&lt;/li&gt;
&lt;li&gt;service workers wake up only under certain conditions
&lt;/li&gt;
&lt;li&gt;push delivery is best-effort
&lt;/li&gt;
&lt;li&gt;timing happens in &lt;em&gt;windows&lt;/em&gt;, not exact moments
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A “scheduled” notification often looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a backend job checks reminder time
&lt;/li&gt;
&lt;li&gt;timezone logic runs on the server
&lt;/li&gt;
&lt;li&gt;a web push is sent
&lt;/li&gt;
&lt;li&gt;the browser decides when (or if) to wake the service worker
&lt;/li&gt;
&lt;li&gt;the OS eventually shows the notification
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each step makes sense on its own.&lt;/p&gt;

&lt;p&gt;Together, they introduce uncertainty.&lt;/p&gt;

&lt;p&gt;This isn’t bad engineering.&lt;br&gt;&lt;br&gt;
It’s how browsers are designed.&lt;/p&gt;

&lt;p&gt;Browsers optimize for battery life, performance, and security —&lt;br&gt;&lt;br&gt;
&lt;strong&gt;not precise scheduling guarantees.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmeruqf7l5u97d4oq0rz9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmeruqf7l5u97d4oq0rz9.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where things actually broke for me
&lt;/h2&gt;

&lt;p&gt;At first, I assumed this was just a PWA limitation.&lt;/p&gt;

&lt;p&gt;Then I wrapped the app with a native Android container and refactored the notification flow.&lt;/p&gt;

&lt;p&gt;Some issues still showed up.&lt;/p&gt;

&lt;p&gt;That’s when it became clear:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Notification reliability isn’t just about platform choice.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
It’s also about how your app understands &lt;em&gt;time itself&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Looking at how mature reminder apps work made the gaps obvious.&lt;/p&gt;




&lt;h2&gt;
  
  
  What real reminder apps get right
&lt;/h2&gt;

&lt;p&gt;Apps like &lt;strong&gt;Google Calendar&lt;/strong&gt;, &lt;strong&gt;TickTick&lt;/strong&gt;, and &lt;strong&gt;Any.do&lt;/strong&gt; all follow the same principles.&lt;/p&gt;




&lt;h3&gt;
  
  
  One clear definition of “now”
&lt;/h3&gt;

&lt;p&gt;There is a single authoritative source of current time —&lt;br&gt;&lt;br&gt;
based on device timezone or an explicit user setting.&lt;/p&gt;

&lt;p&gt;No guessing.&lt;br&gt;&lt;br&gt;
No hidden defaults.&lt;/p&gt;




&lt;h3&gt;
  
  
  Store in UTC, schedule in local time
&lt;/h3&gt;

&lt;p&gt;Events are stored in UTC.&lt;br&gt;&lt;br&gt;
They’re converted to local time only for display and scheduling.&lt;/p&gt;

&lt;p&gt;This avoids slow, painful bugs around daylight saving and timezone changes.&lt;/p&gt;




&lt;h3&gt;
  
  
  OS-level scheduling
&lt;/h3&gt;

&lt;p&gt;Reminders are scheduled using system services (for example, &lt;code&gt;AlarmManager&lt;/code&gt; on Android).&lt;/p&gt;

&lt;p&gt;They’re automatically rescheduled when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the device restarts
&lt;/li&gt;
&lt;li&gt;the timezone changes
&lt;/li&gt;
&lt;li&gt;daylight saving rules shift
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The OS owns delivery — not JavaScript.&lt;/p&gt;




&lt;h3&gt;
  
  
  No dates without context
&lt;/h3&gt;

&lt;p&gt;Any AI planner or automation that generates dates is explicitly told:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Today is YYYY-MM-DD in this timezone.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Without this, it’s surprisingly easy to generate reminders in the past or wrong year without noticing.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomy1i56msmyni8viw3vi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomy1i56msmyni8viw3vi.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The real issues in my app
&lt;/h2&gt;

&lt;p&gt;Once I stepped back, the problems were surprisingly basic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;timezone defaulting to UTC instead of user locale
&lt;/li&gt;
&lt;li&gt;AI planner not receiving current date and timezone explicitly
&lt;/li&gt;
&lt;li&gt;weekly reminders drifting due to timezone conversion
&lt;/li&gt;
&lt;li&gt;limited control over notification channels and sounds
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aren’t exotic bugs.&lt;/p&gt;

&lt;p&gt;They’re the kind that appear only after real users and real time collide.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Android behaves more predictably
&lt;/h2&gt;

&lt;p&gt;On Android, the mental model is simpler:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the app schedules the reminder locally
&lt;/li&gt;
&lt;li&gt;the OS owns the timing
&lt;/li&gt;
&lt;li&gt;the notification fires when expected
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the app is closed
&lt;/li&gt;
&lt;li&gt;the process is killed
&lt;/li&gt;
&lt;li&gt;the device restarts
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notifications are first-class system features.&lt;/p&gt;

&lt;p&gt;That’s why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sound and vibration are consistent
&lt;/li&gt;
&lt;li&gt;notification channels behave correctly
&lt;/li&gt;
&lt;li&gt;widgets are possible
&lt;/li&gt;
&lt;li&gt;background behavior is predictable
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn’t about Android being “better”.&lt;/p&gt;

&lt;p&gt;It’s about using the platform for what it was designed to do.&lt;/p&gt;




&lt;h2&gt;
  
  
  The setup that finally made sense
&lt;/h2&gt;

&lt;p&gt;For this app, reminders and check-ins aren’t optional.&lt;/p&gt;

&lt;p&gt;They &lt;strong&gt;are&lt;/strong&gt; the product.&lt;/p&gt;

&lt;p&gt;So the architecture that aligned best was:&lt;/p&gt;

&lt;h3&gt;
  
  
  Web app (desktop)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;dashboards
&lt;/li&gt;
&lt;li&gt;insights
&lt;/li&gt;
&lt;li&gt;planning and review
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Android app (Capacitor wrapper)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;native scheduling
&lt;/li&gt;
&lt;li&gt;OS-level notifications
&lt;/li&gt;
&lt;li&gt;background reliability
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same backend.&lt;br&gt;&lt;br&gt;
Same database.&lt;br&gt;&lt;br&gt;
Same product logic.&lt;/p&gt;

&lt;p&gt;Different delivery mechanisms — matched to platform strengths.&lt;/p&gt;




&lt;h2&gt;
  
  
  A simple rule of thumb
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;If notifications are a nice-to-have → PWAs are usually fine
&lt;/li&gt;
&lt;li&gt;If notifications are a core promise → let the OS handle timing
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That distinction would have saved me weeks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;PWAs aren’t unreliable.&lt;/p&gt;

&lt;p&gt;They’re just not designed to guarantee time.&lt;/p&gt;

&lt;p&gt;Native platforms are.&lt;/p&gt;

&lt;p&gt;Once you align product expectations with what a platform can realistically promise, a lot of confusion — and frustration — disappears.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick question for you
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Have you faced random notification timings in PWAs?
&lt;/li&gt;
&lt;li&gt;How are you handling scheduled reminders today?
&lt;/li&gt;
&lt;li&gt;Would you still choose a PWA if notifications were critical?
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m genuinely curious how others are solving this.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Live app (still evolving):&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
👉 &lt;a href="https://wio-dev.vercel.app" rel="noopener noreferrer"&gt;https://wio-dev.vercel.app&lt;/a&gt;&lt;/p&gt;

</description>
      <category>android</category>
      <category>mobile</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Object Cloning in Javascript</title>
      <dc:creator>nishchal singh</dc:creator>
      <pubDate>Fri, 01 Mar 2024 05:43:13 +0000</pubDate>
      <link>https://dev.to/nishchaldev/object-cloning-in-javascript-636</link>
      <guid>https://dev.to/nishchaldev/object-cloning-in-javascript-636</guid>
      <description>&lt;p&gt;While coding in Javascript have you ever encountered a situation where you needed to copy an object? and when you try to copy an object, you face some issues like all of the properties are not cloned, or when changing the copied object somehow the original object is changed, leaving you without the desired results. Well, In this article we'll explore some simple solutions to these issues.&lt;/p&gt;

&lt;p&gt;First thing that came to your mind is that why not simply use 🟰 to copy objects, but it'll not work b'coz Javascript objects are reference type values. worry not, there are 3 basic ways of object cloning:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originalObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Using Spread Operator (...)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spread_Cloned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;originalObject&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Using Object.assign() Method&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;assign_Cloned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="nx"&gt;originalObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Using JSON.stringify() and JSON.parse() &lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cloned_JSON&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;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;originalObject&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spread_Cloned&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// { name: 'John', age: 30 }&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;assign_Cloned&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// { name: 'John', age: 30 }&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cloned_JSON&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// { name: 'John', age: 30 }&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;If you're dealing with tricky data setups, making exact copies, or just want to keep things from changing unexpectedly, copying objects can be super helpful in JavaScript. This article is all about diving into object cloning in JavaScript. We'll check out different ways to do it and figure out when and why it's important. By the time you finish reading, you'll totally get how to clone objects and be ready to use it in your own coding projects.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Shallow Clone vs Deep Clone
&lt;/h2&gt;

&lt;p&gt;When you shallow clone something in JavaScript, you're basically making a copy that only goes skin-deep. It means you get a new object with the same basic stuff as the original, but if those basic things include other objects, those aren't copied – they're just referenced. Now, deep cloning is like making a photocopy of everything. You get a brand-new object where every little thing, even the stuff inside other stuff, gets copied over completely. So, you end up with a totally separate copy of everything from the original.&lt;br&gt;
&lt;br&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Techniques for Object Cloning
&lt;/h1&gt;




&lt;h2&gt;
  
  
  Using Spread Operator (...)
&lt;/h2&gt;

&lt;p&gt;The spread operator in JavaScript is a concise and efficient way to clone objects. It allows us to create a copy of an object, including all its enumerable properties, into a new object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originalObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clonedObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;originalObject&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clonedObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// { name: 'John', age: 30 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Very simple syntax&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supports cloning both Shallow and moderately nested objects&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cannot handle deeply nested objects&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does not clone non-enumerable properties or methods&lt;br&gt;
&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using Object.assign() Method
&lt;/h2&gt;

&lt;p&gt;The Object.assign() method is another powerful technique to clone objects. It copies the values of all enumerable properties from one or more source objects into a target object, returning the target object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originalObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clonedObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;originalObject&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clonedObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// { name: 'John', age: 30 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handles cloning of non-enumerable properties and methods&lt;/li&gt;
&lt;li&gt;Supports cloning moderately nested objects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cannot clone deeply nested objects directly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Overwrites properties if they already exist in the target object&lt;br&gt;
&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using JSON.stringify() and JSON.parse()
&lt;/h2&gt;

&lt;p&gt;The combination of JSON.stringify() and JSON.parse() methods can be used as a workaround for cloning complex objects. By converting the object to a JSON string and then parsing it back into an object, we can achieve a Deep Clone of the original object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originalObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clonedObject&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;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;originalObject&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clonedObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// { name: 'John', age: 30 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supports cloning deeply nested objects&lt;/li&gt;
&lt;li&gt;Can be used to clone objects with circular references&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Does not preserve non-enumerable properties or methods&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;May not preserve certain data types (e.g., dates, regular expressions) during cloning&lt;br&gt;
.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using Third-party Library
&lt;/h2&gt;

&lt;p&gt;Lodash is a popular JavaScript utility library that provides a powerful method called cloneDeep() for object cloning. It performs a deep copy of the entire object hierarchy, ensuring accurate replication of the original object's structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originalObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clonedObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cloneDeep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originalObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clonedObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// { name: 'John', age: 30 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can handle cloning of any level of object nesting&lt;/li&gt;
&lt;li&gt;Preserves non-enumerable properties and methods&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adds a dependency on an external library (Lodash)&lt;/li&gt;
&lt;li&gt;May have performance implications for large objects due to deep copying&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you don't want to use any third-party library, there is an alternate solution: using a custom deep cloning function we'll discuss it further in this article. Both have their advantages and limitations.&lt;br&gt;
&lt;br&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Shallow Cloning
&lt;/h2&gt;

&lt;p&gt;Shallow cloning is the simplest form of object cloning. It creates a new object with the same top-level properties as the original object. However, if those properties are themselves objects, they are still references to the original objects. Shallow cloning is a quick and easy way to duplicate objects when there's no need to clone nested objects.&lt;/p&gt;

&lt;p&gt;Shallow Clone Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originalObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;hobbies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;swimming&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clonedObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;originalObject&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the spread operator (...) creates a shallow clone of originalObject. Although clonedObject appears to be an identical copy, modifying the hobbies property in either object will affect both, as they still share a reference to the same array.&lt;/p&gt;

&lt;p&gt;We can fix this issue by Deep Cloning.&lt;br&gt;
&lt;br&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Deep Cloning
&lt;/h2&gt;

&lt;p&gt;Deep cloning is a more thorough form of object cloning. It creates a new object and recursively clones all nested properties and their descendants, ensuring each object is an independent copy. Deep cloning is indispensable when working with complex data structures and avoiding unintended side effects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using JSON.stringify() and JSON.parse():
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//Deep Clone Using JSON.stringify() and JSON.parse()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originalObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="c1"&gt;// Nested object&lt;/span&gt;
  &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;New York&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;NY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="c1"&gt;// Method&lt;/span&gt;
  &lt;span class="na"&gt;doAction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; is walking in &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clonedObject&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;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;originalObject&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clonedObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="c1"&gt;// { name: 'John', age: 30, address: { city: 'New York', state: 'NY' } }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see in the above example we are losing our data, the method "doAction" is not cloned b'coz it does not preserve non-enumerable properties or methods. The solution for this issue is given below.&lt;br&gt;
&lt;br&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Custom Recursive Function:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Deep Clone Using Custom Recursive Function&lt;/span&gt;
&lt;span class="c1"&gt;// Custom Recursive Function &lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;deepClone&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="nx"&gt;visited&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WeakMap&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Handle non-object types and null&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Handle circular references&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;visited&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&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="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;visited&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&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="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Handle dates&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Handle regular expressions&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&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="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Handle arrays&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cloneArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="nx"&gt;visited&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&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="nx"&gt;cloneArray&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="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;cloneArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deepClone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;visited&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cloneArray&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Handle objects&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cloneObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="nx"&gt;visited&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&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="nx"&gt;cloneObj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&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="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;cloneObj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deepClone&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="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;visited&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cloneObj&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clonedObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deepClone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originalObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clonedObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="cm"&gt;/*{
  name: 'John',
  age: 30,
  address: { city: 'New York', state: 'NY' },
  doAction: [Function: doAction]
}*/&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clonedObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;doAction&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// John is walking in New York&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, deepClone is a recursive function that clones all properties and nested objects of originalObject. The resulting clonedObject is a deep copy, ensuring no changes made to original one and no object will impact the other.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We use a WeakMap to keep track of visited objects to handle circular references.&lt;/li&gt;
&lt;li&gt;We add support for cloning Date objects and RegExp objects.&lt;/li&gt;
&lt;li&gt;We handle cloning of arrays and objects separately to ensure correct cloning and handling of circular references.&lt;/li&gt;
&lt;li&gt;We use Object.prototype.hasOwnProperty.call(obj, key) to ensure that properties from the object's prototype chain are not mistakenly cloned.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This deepClone function can handle a wider range of data types and scenarios.&lt;/p&gt;

&lt;p&gt;Let's see another example of 'deepClone' function with different data types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Define an object with various data types including arrays, objects, dates, and regular expressions&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;originalObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;array&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;b&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="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;regexp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/test/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Add circular reference&lt;/span&gt;
&lt;span class="nx"&gt;originalObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;circular&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;originalObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Clone the original object&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clonedObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deepClone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originalObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Modify the cloned object&lt;/span&gt;
&lt;span class="nx"&gt;clonedObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Modified&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;clonedObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;456&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;clonedObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;clonedObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Log both original and cloned objects&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Original Object:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;originalObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cm"&gt;/*Original Object: &amp;lt;ref *1&amp;gt; {
  string: 'Hello',
  number: 123,
  boolean: true,
  array: [ 1, 2, 3 ],
  object: { a: 1, b: 2 },
  date: 2024-02-23T13:18:38.521Z,
  regexp: /test/g,
  circular: [Circular *1]
}*/&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cloned Object:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;clonedObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cm"&gt;/*Cloned Object: &amp;lt;ref *1&amp;gt; {
  string: 'Modified',
  number: 456,
  boolean: true,
  array: [ 1, 2, 3, 4 ],
  object: { a: 1, b: 2, c: 3 },
  date: 2024-02-23T13:18:38.521Z,
  regexp: /test/g,
  circular: [Circular *1]
}*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in this example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We define an originalObject containing various data types including arrays, objects, dates, and regular expressions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We add a circular reference to the originalObject.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We then clone the originalObject using the deepClone function.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We modify some properties of the cloned object to demonstrate &lt;br&gt;
that the original object remains unaffected by the modifications to the clone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, we log both the original and cloned objects to see the differences.&lt;br&gt;
&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The deepClone function has several advantages and limitations:
&lt;/h2&gt;

&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deep Cloning: The function can recursively clone nested objects and arrays, ensuring a deep copy of the original object.&lt;/li&gt;
&lt;li&gt;Support for Various Data Types: It supports cloning of various data types including objects, arrays, dates, and regular expressions, making it versatile for different use cases.&lt;/li&gt;
&lt;li&gt;Handling Circular References: It can handle circular references gracefully by keeping track of visited objects using a WeakMap, preventing infinite recursion.&lt;/li&gt;
&lt;li&gt;Maintains Object Structure: It maintains the structure of the original object, including nested objects and arrays, ensuring the cloned object has the same structure.&lt;/li&gt;
&lt;li&gt;Flexible and Customizable: It can be extended to support additional data types or custom cloning logic based on specific requirements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performance: Deep cloning can be computationally expensive, especially for large and deeply nested objects, potentially leading to performance issues.&lt;/li&gt;
&lt;li&gt;Prototype Chain: It does not preserve the prototype chain of objects. Cloned objects will lose their original prototype chain and inherit from Object.prototype.&lt;/li&gt;
&lt;li&gt;Non-Clonable Properties: Certain properties like non-enumerable properties or properties with getters/setters may not be cloned accurately.&lt;/li&gt;
&lt;li&gt;External References: If the original object contains references to external resources or mutable shared state, the cloned object will still reference the same external resources, potentially leading to unintended side effects.&lt;/li&gt;
&lt;li&gt;Memory Consumption: The use of a WeakMap for handling circular references may consume additional memory, especially for large datasets with many circular references.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, while the deepClone function provides a robust solution for deep copying objects, it's important to be aware of its limitations and potential impact on performance and memory usage, especially in scenarios involving large or complex data structures.&lt;br&gt;
&lt;br&gt;
&lt;/p&gt;

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

&lt;p&gt;Remember, when cloning objects, it's crucial to choose the appropriate method based on your specific needs. Whether you opt for native JavaScript techniques or leverage external libraries like Lodash or Immer, object cloning is a valuable tool for maintaining data integrity and preventing unintended side effects.&lt;/p&gt;

&lt;p&gt;So, the next time you find yourself needing to duplicate an object in JavaScript, don't go down the path of manual copying and mutation. Instead, harness the power of object cloning and unlock a world of possibilities.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Object cloning in JavaScript is the key to maintaining data integrity and avoiding unintended side effects."&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>object</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Overview of ReactJs</title>
      <dc:creator>nishchal singh</dc:creator>
      <pubDate>Tue, 12 Dec 2023 14:14:59 +0000</pubDate>
      <link>https://dev.to/nishchaldev/overview-of-reactjs-3cik</link>
      <guid>https://dev.to/nishchaldev/overview-of-reactjs-3cik</guid>
      <description>&lt;p&gt;Whenever the development community talks about modern web development stacks, the word "ReactJS" is often mentioned. It's one of the widely used tech stacks for web development, In this article, we'll take an overview of ReactJS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is ReactJs?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ReactJS, or simply React, is like a superhero or supertool for building websites and web applications. It's a special set of tools and rules that helps people create websites that are not only really cool but also super fast and easy to work with.&lt;/p&gt;

&lt;p&gt;React is a JavaScript-based front-end library used for UI(user interface) development. It's used to create modular user interfaces and promotes the development of reusable UI components that display dynamic data. React is often used to build single-page applications (SPAs).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Concept of ReactJS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frd4i3yhyw1ocj40kghz3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frd4i3yhyw1ocj40kghz3.png" alt=" " width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;his is Hashnode's homepage as we can see here a react application is made from independent components that together make a whole web application. The search bar in the top header is a reusable component. the same search bar component is used in the other sections of this app.&lt;/p&gt;

&lt;p&gt;Key concepts and principles of ReactJS include:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Component-Based Architecture:&lt;/strong&gt; React is built around the idea of breaking down user interfaces into reusable, self-contained components. These components can range from simple elements like buttons or form inputs to complex parts of the user interface like navigation bars or entire pages. By building UIs as components, development becomes modular, maintainable, and scalable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Virtual DOM (Document Object Model):&lt;/strong&gt; React introduced the concept of a Virtual DOM which is like a lightweight copy of the actual DOM. virtual DOM is an abstract representation of the actual DOM in the browser. When data in a React application changes, React doesn't directly manipulate the real DOM. Instead, it creates a virtual representation of the changes and efficiently updates only the parts of the real DOM that need to change. This approach minimizes browser reflows and enhances performance.&lt;/p&gt;

&lt;p&gt;The image below is a visual representation of the concept of the virtual DOM:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg3kc3r71fahhf7ozhfu6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg3kc3r71fahhf7ozhfu6.png" alt=" " width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unidirectional Data Flow:&lt;/strong&gt; React follows a unidirectional data flow, where data moves in one direction, usually from parent components to child components. Child components cannot send data back to their parent components. This design minimizes errors and gives us greater control over our code.&lt;/p&gt;

&lt;p&gt;As shown in the diagram below, data can only flow from top to bottom:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flzstclqdqv73m8brl3t8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flzstclqdqv73m8brl3t8.png" alt=" " width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Component Lifecycle:&lt;/strong&gt; React components have a lifecycle that includes various methods such as componentDidMount, componentDidUpdate, and componentWillUnmount. These lifecycle methods allow developers to hook into different stages of a component's existence and perform actions like data fetching, DOM manipulation, or cleanup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State in React:&lt;/strong&gt; In ReactJS, "state" refers to a built-in feature that allows you to manage and store data within a component. State represents the internal data of a component that can change during the component's lifecycle, and when it does change, React will automatically re-render the component to reflect the updated state.&lt;/p&gt;

&lt;p&gt;State acts as a storage space for data essential for a component's functioning. It's versatile, capable of holding different data types like numbers, strings, arrays, or objects. Unlike props, which are unchangeable and flow from parent to child components, state is changeable. Components have the power to modify their own state through React's setState method.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reactivity:&lt;/strong&gt; React encourages a reactive approach to UI development. When the state or props of a component change, React automatically re-renders the component to reflect those changes. This reactivity simplifies UI updates and ensures that the UI always matches the application's data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State Management:&lt;/strong&gt; React components can effectively handle their internal state using either the useState hook for functional components or class-based state for class components. These approaches allow components to store and update data within themselves.&lt;/p&gt;

&lt;p&gt;For more intricate applications, developers often turn to state management libraries like Redux or Mobx. These libraries centralize and manage state across the entire application, making it easier to handle complex data interactions.&lt;/p&gt;

&lt;p&gt;For instance, consider a web application with dynamic notification functionality. State management ensures that notifications can be added, removed, and displayed in real-time without the need for complex manual updates. Similarly, in an online shopping cart, managing the dynamic count of items and their state helps ensure a seamless and responsive user experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JSX (JavaScript XML):&lt;/strong&gt; JSX, which stands for JavaScript XML, is a powerful feature in React. It's like a special language that React developers use to describe how a component should look. Imagine it as a blend of HTML and JavaScript that makes building user interfaces more intuitive.&lt;/p&gt;

&lt;p&gt;With JSX, you can write your user interface code in a way that closely resembles HTML. This not only makes it easier to understand but also helps you visualize your UI components. However, under the hood, JSX gets converted into regular JavaScript using tools like Babel before it's shown in the browser.&lt;/p&gt;

&lt;p&gt;One of the cool things about JSX is that you can embed JavaScript expressions within curly braces {}. This means you can include dynamic content, variables, and calculations right alongside your JSX code. It's a flexible way to create dynamic and interactive user interfaces in React.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';

function Greeting(props) {
  const name = props.name;
  const isLoggedIn = props.isLoggedIn;

  // Define a JavaScript function to conditionally render a greeting message
  function getGreeting(name) {
    if (isLoggedIn) {
      return &amp;lt;p&amp;gt;Hello, {name}!&amp;lt;/p&amp;gt;;
    } else {
      return &amp;lt;p&amp;gt;Please log in.&amp;lt;/p&amp;gt;;
    }
  }
  return (
    &amp;lt;div&amp;gt;
      {/* Embed JavaScript expression to render the greeting message */}
      {getGreeting(name)}
    &amp;lt;/div&amp;gt;
  );
}
export default Greeting;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Community and Ecosystem:&lt;/strong&gt; React has a vast and active community, resulting in a rich ecosystem of third-party libraries, tools, and extensions. These resources make it easier for developers to build feature-rich and performant applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How Does ReactJS Work?&lt;/strong&gt;&lt;br&gt;
ReactJS works by utilizing a component-based architecture to build user interfaces efficiently. It uses a Virtual DOM to optimize updates, enforces a unidirectional data flow for predictable behavior, and allows developers to define UI components using JSX, which is transpiled into JavaScript. React updates the actual DOM efficiently, making it ideal for creating dynamic and interactive web applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
ReactJS stands as a powerful and pivotal force in modern web development. Its component-based architecture, Virtual DOM, and unidirectional data flow provide developers with a robust toolkit to create dynamic and responsive user interfaces. React's flexibility, combined with a thriving community and extensive ecosystem, makes it a top choice for building web applications that are not only efficient and maintainable but also user-friendly. As we've explored in this overview, ReactJS empowers developers to bring their web projects to life with elegance and precision, setting new standards for web development in the digital age. Whether you're a seasoned developer or just beginning your journey, ReactJS remains a technology worth exploring and mastering.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>dom</category>
      <category>props</category>
    </item>
  </channel>
</rss>
