<?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>OpenRouter Returned 200, But My Next.js AI Stream Was Empty</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;&lt;strong&gt;My AI chat was working locally. In production, Vercel gave me a &lt;code&gt;504&lt;/code&gt;. After fixing that, OpenRouter returned &lt;code&gt;200&lt;/code&gt; — and I still received nothing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That was the point where I stopped looking for one broken line and started looking at the whole streaming path.&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%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;The eventual problem was simpler than I expected:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I had too many layers handling the same stream.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's how I found it.&lt;/p&gt;




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

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Next.js App Router
React
TypeScript
MongoDB / Mongoose
Clerk
TanStack Query
Cloudinary
OpenRouter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;It uses reviewed application knowledge to answer questions around PSS teachings, meditation and related topics.&lt;/p&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 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;The model is:&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;There is quite a bit happening around the model 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
Conversation history
Knowledge retrieval
AI response
Conversation persistence
Usage tracking
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I wanted the response to stream to the browser instead of waiting for the entire answer.&lt;/p&gt;

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




&lt;h2&gt;
  
  
  The streaming architecture 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:&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;&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;It had to read chunks, parse SSE events, extract token deltas, detect completion and usage, accumulate the response, and convert everything into our own NDJSON format.&lt;/p&gt;

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

&lt;p&gt;So the flow looked roughly like this:&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;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;&lt;strong&gt;Multiple layers understood the same stream.&lt;/strong&gt;&lt;/p&gt;




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

&lt;p&gt;The first thing 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 problem.&lt;/p&gt;

&lt;p&gt;Maybe the API was returning something unexpected.&lt;/p&gt;

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

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

&lt;p&gt;So I opened the 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;That changed the investigation.&lt;/p&gt;

&lt;p&gt;The JSON error wasn't the root problem.&lt;/p&gt;

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




&lt;h2&gt;
  
  
  Vercel was killing the function
&lt;/h2&gt;

&lt;p&gt;The Vercel 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;FUNCTION_INVOCATION_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;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 finish.&lt;/p&gt;

&lt;p&gt;I checked the repository for anything that might have configured this.&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;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;&lt;strong&gt;Fluid Compute was disabled.&lt;/strong&gt;&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;The platform timeout was fixed.&lt;/p&gt;

&lt;p&gt;But the request still wasn't working.&lt;/p&gt;




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

&lt;p&gt;After the deployment, the application started reaching its own timeout:&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;That was useful information.&lt;/p&gt;

&lt;p&gt;The problem had 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;Platform timeout
&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;Application/provider streaming latency
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Increasing the function duration hadn't fixed the stream.&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;
  
  
  Then OpenRouter returned &lt;code&gt;200&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;This was the part that really confused me.&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;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;So far, so good.&lt;/p&gt;

&lt;p&gt;Except the stream counters said:&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 itself 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 OpenRouter, but &lt;strong&gt;zero usable streaming events&lt;/strong&gt; reached my application.&lt;/p&gt;

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

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

&lt;p&gt;The evidence pointed toward the streaming path I had built around it.&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%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;h2&gt;
  
  
  I stopped patching the parser
&lt;/h2&gt;

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

&lt;p&gt;Instead, I wanted to answer one smaller question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can the AI SDK receive an OpenRouter stream 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:&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 around it wasn't reliable enough.&lt;/p&gt;

&lt;p&gt;But I had enough evidence to move forward:&lt;/p&gt;

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

&lt;p&gt;That changed the question.&lt;/p&gt;

&lt;p&gt;Instead of asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which line in my parser is broken?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I started asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why am I maintaining this parser at all?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




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

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

&lt;p&gt;The application had custom code for:&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;None of those things are impossible to build.&lt;/p&gt;

&lt;p&gt;The problem was that &lt;strong&gt;multiple layers had responsibility for the same stream&lt;/strong&gt;.&lt;/p&gt;

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

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

&lt;p&gt;The OpenRouter wrapper understood the provider stream.&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;More layers meant more places where data could be transformed, misunderstood or lost.&lt;/p&gt;

&lt;p&gt;And when something failed, it wasn't immediately obvious which layer was responsible.&lt;/p&gt;




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

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

&lt;p&gt;The new flow is:&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 for the public streaming path.&lt;/p&gt;

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

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




&lt;h2&gt;
  
  
  I didn't rewrite the frontend
&lt;/h2&gt;

&lt;p&gt;I also didn't want to change everything at once.&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 provider, server transport, frontend parser and UI state management together.&lt;/p&gt;

&lt;p&gt;That would have made the debugging harder.&lt;/p&gt;

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

&lt;p&gt;For the moment, the flow 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;It's not the final architecture.&lt;/p&gt;

&lt;p&gt;The longer-term plan is to move the frontend away from custom:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fetch() + NDJSON parsing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and eventually use the AI SDK's React transport.&lt;/p&gt;

&lt;p&gt;But that can be a separate change.&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 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 streamed the response successfully.&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;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 finished 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;The old failure events were gone.&lt;/p&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_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 no longer showed the disconnect error.&lt;/p&gt;

&lt;p&gt;The streaming path was working again.&lt;/p&gt;




&lt;h2&gt;
  
  
  But it was still slow
&lt;/h2&gt;

&lt;p&gt;This is where the story gets more interesting.&lt;/p&gt;

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

&lt;p&gt;The performance problem wasn'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;Ten seconds before the first useful text is still too long.&lt;/p&gt;

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

&lt;p&gt;Now the 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 a different investigation.&lt;/p&gt;

&lt;p&gt;I'm 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;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 changing the model just to get a better-looking number.&lt;/p&gt;

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




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

&lt;p&gt;This distinction became pretty important during this debugging session.&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 didn't 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 two different engineering problems.&lt;/p&gt;

&lt;p&gt;So I'm now measuring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request start
Stream start
First text
Completion
Abort
Failure
Total latency
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also want a request ID that follows the request through the important stages.&lt;/p&gt;

&lt;p&gt;That should make the next performance investigation much easier than piecing unrelated log lines together.&lt;/p&gt;




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

&lt;p&gt;I wouldn't start by building 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, the responsibilities are roughly:&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 own the same problem.&lt;/p&gt;

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

&lt;p&gt;And that's probably the most useful thing I got from this debugging session:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sometimes the fix isn't adding another layer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's deciding which layer doesn't need to be there.&lt;/strong&gt;&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>
