<?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: Samuel Oyerinde</title>
    <description>The latest articles on DEV Community by Samuel Oyerinde (@sam4rano).</description>
    <link>https://dev.to/sam4rano</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%2F209861%2F948c409e-6272-4f1b-823f-b41d66423cb6.jpeg</url>
      <title>DEV Community: Samuel Oyerinde</title>
      <link>https://dev.to/sam4rano</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sam4rano"/>
    <language>en</language>
    <item>
      <title>Reflections on OpenAI's Scaling Laws for Neural Language Models: Why Models Improve, Why Compute Matters, and What It Means for Africa</title>
      <dc:creator>Samuel Oyerinde</dc:creator>
      <pubDate>Thu, 02 Jul 2026 04:24:22 +0000</pubDate>
      <link>https://dev.to/sam4rano/reflections-on-openais-scaling-laws-for-neural-language-models-why-models-improve-why-compute-4cod</link>
      <guid>https://dev.to/sam4rano/reflections-on-openais-scaling-laws-for-neural-language-models-why-models-improve-why-compute-4cod</guid>
      <description>&lt;p&gt;I recently took the time to read one of the most influential papers in modern AI:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scaling Laws for Neural Language Models (OpenAI, 2020)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;📄 Paper: &lt;a href="https://arxiv.org/abs/2001.08361" rel="noopener noreferrer"&gt;Scaling Laws for Neural Language Models&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Despite being published several years ago, it remains one of the most insightful papers I've read in a long time.&lt;/p&gt;

&lt;p&gt;What struck me most wasn't just the mathematics behind scaling. It was how many questions I've been asking over the years were already being investigated by researchers long before the current AI boom.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Questions I've Been Asking
&lt;/h2&gt;

&lt;p&gt;As someone working across speech AI, NLP, and low-resource languages, I've always been curious about why AI systems continue to improve so dramatically across different domains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Text generation&lt;/li&gt;
&lt;li&gt;Speech recognition&lt;/li&gt;
&lt;li&gt;Speech synthesis&lt;/li&gt;
&lt;li&gt;Computer vision&lt;/li&gt;
&lt;li&gt;Multimodal systems&lt;/li&gt;
&lt;li&gt;Coding assistants&lt;/li&gt;
&lt;li&gt;Domain-specific AI applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The questions that kept coming up were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is AI getting better simply because engineering is improving?&lt;/li&gt;
&lt;li&gt;Is the main driver more training data?&lt;/li&gt;
&lt;li&gt;Is compute the real secret?&lt;/li&gt;
&lt;li&gt;Do larger parameter counts matter most?&lt;/li&gt;
&lt;li&gt;How important are architecture choices such as width and depth?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It turns out these were exactly the questions the paper set out to answer.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Scaling Laws Actually Tell Us
&lt;/h2&gt;

&lt;p&gt;One of the paper's most important findings is surprisingly simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Model performance improves predictably as we increase model size, dataset size, and compute.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These three variables are deeply interconnected.&lt;/p&gt;

&lt;p&gt;A larger model can learn more sophisticated patterns, but only if it has access to enough data and enough compute to fully utilize its capacity.&lt;/p&gt;

&lt;p&gt;Likewise:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More data alone is not enough.&lt;/li&gt;
&lt;li&gt;More parameters alone are not enough.&lt;/li&gt;
&lt;li&gt;More compute alone is not enough.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The gains come from balancing all three.&lt;/p&gt;

&lt;p&gt;The paper demonstrated that loss curves follow remarkably consistent power-law relationships across a wide range of model scales.&lt;/p&gt;

&lt;p&gt;In other words:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AI improvement is not random. It follows surprisingly predictable trends.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For me, this provided a useful framework for understanding why each generation of AI systems often feels significantly more capable than the one before it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Scaling Triangle
&lt;/h2&gt;

&lt;p&gt;A useful way to think about scaling laws is as a triangle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                Compute
                   ▲
                   │
                   │
                   │
                   │
                   │
Data ◄─────────────┼─────────────► Model Size
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each corner influences the others.&lt;/p&gt;

&lt;p&gt;If one side becomes a bottleneck, overall performance suffers.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Large Model + Small Dataset
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Huge capacity
Little knowledge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Overfitting&lt;/li&gt;
&lt;li&gt;Poor generalization&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Large Dataset + Small Model
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Massive knowledge
Limited capacity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Under-utilization of data&lt;/li&gt;
&lt;li&gt;Missed patterns&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Large Model + Large Dataset + Limited Compute
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Potential exists
Training never fully converges
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wasted capacity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scaling laws showed that optimal performance emerges when these factors grow together.&lt;/p&gt;




&lt;h2&gt;
  
  
  Looking at Today's Models
&lt;/h2&gt;

&lt;p&gt;Fast-forward a few years, and we can see these ideas playing out in practice.&lt;/p&gt;

&lt;p&gt;Some of today's most influential open-weight models include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/deepseek-ai/DeepSeek-V3" rel="noopener noreferrer"&gt;DeepSeek-V3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/Qwen" rel="noopener noreferrer"&gt;Qwen 3 Family&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/nvidia" rel="noopener noreferrer"&gt;NVIDIA Nemotron&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/THUDM" rel="noopener noreferrer"&gt;GLM Models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/MiniMaxAI" rel="noopener noreferrer"&gt;MiniMax Models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/moonshotai" rel="noopener noreferrer"&gt;Kimi Models&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each generation tends to improve through a combination of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Larger effective model capacity&lt;/li&gt;
&lt;li&gt;More training data&lt;/li&gt;
&lt;li&gt;Greater compute budgets&lt;/li&gt;
&lt;li&gt;Better architectures&lt;/li&gt;
&lt;li&gt;Improved post-training&lt;/li&gt;
&lt;li&gt;Alignment and reinforcement learning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What makes modern AI fascinating is that progress rarely comes from a single factor.&lt;/p&gt;

&lt;p&gt;The gains are usually cumulative.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Growing Opacity of Frontier Models
&lt;/h2&gt;

&lt;p&gt;Something else stood out while reflecting on the paper.&lt;/p&gt;

&lt;p&gt;During earlier generations of AI research, it was common to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parameter counts&lt;/li&gt;
&lt;li&gt;Dataset sizes&lt;/li&gt;
&lt;li&gt;Compute budgets&lt;/li&gt;
&lt;li&gt;Training methodologies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Today, that transparency has largely disappeared.&lt;/p&gt;

&lt;p&gt;Organizations such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenAI&lt;/li&gt;
&lt;li&gt;Anthropic&lt;/li&gt;
&lt;li&gt;Google DeepMind&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;increasingly keep these details private for proprietary reasons&lt;br&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%2Fyzfhvge6vt4891kq1ywv.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%2Fyzfhvge6vt4891kq1ywv.png" alt=" " width="800" height="640"&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As a result, direct comparisons between frontier systems have become much more difficult than they were just a few years ago.&lt;/p&gt;

&lt;p&gt;We often observe the outputs.&lt;/p&gt;

&lt;p&gt;The inputs that created them are becoming less visible.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Elephant in the Room: Compute
&lt;/h2&gt;

&lt;p&gt;The deeper I went into the paper, the more I realized something important.&lt;/p&gt;

&lt;p&gt;The AI conversation often focuses on models.&lt;/p&gt;

&lt;p&gt;But the real bottleneck is usually compute.&lt;/p&gt;

&lt;p&gt;And compute is an entirely different beast.&lt;/p&gt;

&lt;p&gt;When we hear about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google building AI-focused data centers&lt;/li&gt;
&lt;li&gt;Meta investing tens of billions into infrastructure&lt;/li&gt;
&lt;li&gt;NVIDIA becoming one of the world's most valuable companies&lt;/li&gt;
&lt;li&gt;xAI building massive GPU clusters&lt;/li&gt;
&lt;li&gt;Anthropic securing large-scale compute partnerships&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;we're seeing where a significant portion of the AI race is actually being fought.&lt;/p&gt;

&lt;p&gt;Not at the model layer.&lt;/p&gt;

&lt;p&gt;At the infrastructure layer.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Hidden Stack Behind Every AI Model
&lt;/h2&gt;

&lt;p&gt;Most people interact with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ChatGPT
Claude
Gemini
DeepSeek
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What they don't see is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Massive GPU clusters
Data centers
High-speed networking
Storage systems
Power infrastructure
Cooling systems
Distributed training frameworks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model is the visible product.&lt;/p&gt;

&lt;p&gt;The compute infrastructure is what makes the product possible.&lt;/p&gt;

&lt;p&gt;This is one reason why AI development has become increasingly capital-intensive.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Open-Weight Models Matter
&lt;/h2&gt;

&lt;p&gt;This is where open-weight models become incredibly important.&lt;/p&gt;

&lt;p&gt;Organizations such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/meta-llama" rel="noopener noreferrer"&gt;Meta Llama Models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/deepseek-ai" rel="noopener noreferrer"&gt;DeepSeek Models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/Qwen" rel="noopener noreferrer"&gt;Alibaba Qwen Models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/mistralai" rel="noopener noreferrer"&gt;Mistral AI Models&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;have dramatically lowered the barrier to entry.&lt;/p&gt;

&lt;p&gt;Without open-weight models, many startups, researchers, and independent developers would have little practical access to state-of-the-art AI capabilities.&lt;/p&gt;

&lt;p&gt;For many parts of the world, open-weight models are not simply convenient.&lt;/p&gt;

&lt;p&gt;They are foundational.&lt;/p&gt;

&lt;p&gt;They enable adaptation of AI systems to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local languages&lt;/li&gt;
&lt;li&gt;Local cultures&lt;/li&gt;
&lt;li&gt;Local businesses&lt;/li&gt;
&lt;li&gt;Specialized industries&lt;/li&gt;
&lt;li&gt;Emerging modalities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;without requiring billions of dollars in training costs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where Does Africa Fit Into This Story?
&lt;/h2&gt;

&lt;p&gt;Reading the paper eventually led me to a different question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Where does Africa fit into the future of AI?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From a business perspective, supply generally follows demand.&lt;/p&gt;

&lt;p&gt;Companies invest where markets are large and where purchasing power is strongest.&lt;/p&gt;

&lt;p&gt;AI ecosystems often follow similar dynamics.&lt;/p&gt;

&lt;p&gt;Africa possesses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exceptional talent&lt;/li&gt;
&lt;li&gt;Rich linguistic diversity&lt;/li&gt;
&lt;li&gt;Large populations&lt;/li&gt;
&lt;li&gt;Important problems worth solving&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What we often lack are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Large-scale compute infrastructure&lt;/li&gt;
&lt;li&gt;Frontier hardware access&lt;/li&gt;
&lt;li&gt;Research funding&lt;/li&gt;
&lt;li&gt;Venture capital at comparable scale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates a structural challenge.&lt;/p&gt;

&lt;p&gt;Not because capability is lacking.&lt;/p&gt;

&lt;p&gt;But because modern AI increasingly depends on computational resources.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I'm Still Optimistic
&lt;/h2&gt;

&lt;p&gt;Despite these challenges, I remain optimistic.&lt;/p&gt;

&lt;p&gt;The rise of open-weight AI has fundamentally changed what is possible.&lt;/p&gt;

&lt;p&gt;Today, researchers can build meaningful systems without training trillion-parameter models from scratch.&lt;/p&gt;

&lt;p&gt;Instead, they can focus on adaptation.&lt;/p&gt;

&lt;p&gt;For African AI researchers, this shift is enormously important.&lt;/p&gt;

&lt;p&gt;The opportunity is no longer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Build the next frontier model.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The opportunity is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Adapt frontier capabilities to local problems.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  My Experience with Yorùbá Speech AI
&lt;/h2&gt;

&lt;p&gt;Over the past few years, I've explored this idea through research in Yorùbá speech and language technologies.&lt;/p&gt;

&lt;p&gt;Some of my projects include:&lt;/p&gt;

&lt;h3&gt;
  
  
  Research Repository
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/sam4rano/academic-research-repo" rel="noopener noreferrer"&gt;Academic Research Repository&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Yorùbá OmniTTS
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/sam4rano/yor_tts_omnivoice" rel="noopener noreferrer"&gt;Yorùbá OmniTTS Project&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These projects leverage existing foundation models and adapt them for a low-resource language context.&lt;/p&gt;

&lt;p&gt;Without open-weight ecosystems, work like this would be significantly more difficult.&lt;/p&gt;

&lt;p&gt;Open-weight AI allows researchers to spend less time rebuilding foundational infrastructure and more time solving real-world problems.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Scaling Laws Mean for Low-Resource Languages
&lt;/h2&gt;

&lt;p&gt;One lesson from scaling laws is often overlooked.&lt;/p&gt;

&lt;p&gt;The paper is not only about larger models.&lt;/p&gt;

&lt;p&gt;It's also about where future opportunities exist.&lt;/p&gt;

&lt;p&gt;For many low-resource languages, including African languages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The foundation models already exist.&lt;/li&gt;
&lt;li&gt;The architectures already exist.&lt;/li&gt;
&lt;li&gt;The training recipes largely exist.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The missing pieces are often:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High-quality datasets&lt;/li&gt;
&lt;li&gt;Evaluation benchmarks&lt;/li&gt;
&lt;li&gt;Domain adaptation&lt;/li&gt;
&lt;li&gt;Fine-tuning&lt;/li&gt;
&lt;li&gt;Deployment infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This changes the nature of the challenge.&lt;/p&gt;

&lt;p&gt;The question becomes less about competing with frontier labs and more about leveraging their advances effectively.&lt;/p&gt;




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

&lt;p&gt;Reading &lt;em&gt;Scaling Laws for Neural Language Models&lt;/em&gt; helped me understand why AI systems continue to improve so consistently.&lt;/p&gt;

&lt;p&gt;But it also highlighted a deeper reality.&lt;/p&gt;

&lt;p&gt;The future of AI is not determined solely by better models.&lt;/p&gt;

&lt;p&gt;It is also shaped by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compute&lt;/li&gt;
&lt;li&gt;Capital&lt;/li&gt;
&lt;li&gt;Infrastructure&lt;/li&gt;
&lt;li&gt;Research ecosystems&lt;/li&gt;
&lt;li&gt;Access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scaling laws explain how models improve.&lt;/p&gt;

&lt;p&gt;Compute explains who gets to participate.&lt;/p&gt;

&lt;p&gt;For regions such as Africa, the immediate opportunity may not be building the next frontier model tomorrow.&lt;/p&gt;

&lt;p&gt;The opportunity is leveraging today's open-weight models to build solutions for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local languages&lt;/li&gt;
&lt;li&gt;Education&lt;/li&gt;
&lt;li&gt;Healthcare&lt;/li&gt;
&lt;li&gt;Agriculture&lt;/li&gt;
&lt;li&gt;Finance&lt;/li&gt;
&lt;li&gt;Government services&lt;/li&gt;
&lt;li&gt;Knowledge preservation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rise of open-weight AI has already lowered the barrier.&lt;/p&gt;

&lt;p&gt;The question now is whether it can lower it enough to make advanced AI truly global.&lt;/p&gt;




&lt;h3&gt;
  
  
  Further Reading
&lt;/h3&gt;

&lt;p&gt;📄 OpenAI Scaling Laws Paper&lt;/p&gt;

&lt;p&gt;&lt;a href="https://arxiv.org/abs/2001.08361" rel="noopener noreferrer"&gt;Scaling Laws for Neural Language Models&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#AI
#MachineLearning
#DeepLearning
#LLM
#ScalingLaws
#OpenSourceAI
#OpenWeights
#SpeechAI
#Yoruba
#Africa
#NLP
#Research
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ai</category>
      <category>huggingface</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Fine-Tuning OmniVoice for Yoruba Zero-Shot Voice Cloning: Lessons from 9.6 Hours of Speech Data</title>
      <dc:creator>Samuel Oyerinde</dc:creator>
      <pubDate>Thu, 02 Jul 2026 03:56:55 +0000</pubDate>
      <link>https://dev.to/sam4rano/fine-tuning-omnivoice-for-yoruba-zero-shot-voice-cloning-lessons-from-96-hours-of-speech-data-2nam</link>
      <guid>https://dev.to/sam4rano/fine-tuning-omnivoice-for-yoruba-zero-shot-voice-cloning-lessons-from-96-hours-of-speech-data-2nam</guid>
      <description>&lt;p&gt;However, when you move beyond high-resource languages and start working with &lt;strong&gt;low-resource, tonal languages like Yoruba&lt;/strong&gt;, many of the assumptions behind standard TTS pipelines begin to fail.&lt;/p&gt;

&lt;p&gt;Over the past week, I fine-tuned &lt;strong&gt;OmniVoice&lt;/strong&gt; for Yoruba using approximately &lt;strong&gt;9.6 hours of speech data&lt;/strong&gt; collected from &lt;strong&gt;156 speakers&lt;/strong&gt;. The goal was to build a model capable of &lt;strong&gt;zero-shot voice cloning&lt;/strong&gt; while preserving the tonal characteristics that are fundamental to Yoruba speech.&lt;/p&gt;

&lt;p&gt;This article documents the dataset construction process, the engineering decisions that mattered, why some popular multilingual baselines struggle with Yoruba, and how I evaluated synthesis quality.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Yoruba is Different
&lt;/h2&gt;

&lt;p&gt;Unlike English, Yoruba is a &lt;strong&gt;tonal language&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Words that appear similar can have completely different meanings depending on tone:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Word&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ọkọ&lt;/td&gt;
&lt;td&gt;husband&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;òkò&lt;/td&gt;
&lt;td&gt;hoe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ọ̀kọ̀&lt;/td&gt;
&lt;td&gt;vehicle&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For humans, tone is obvious.&lt;/p&gt;

&lt;p&gt;For TTS models, tone must be learned through the interaction between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Text representations&lt;/li&gt;
&lt;li&gt;Acoustic patterns&lt;/li&gt;
&lt;li&gt;Prosodic modeling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A model that ignores tonal information will often generate speech that is intelligible acoustically but semantically incorrect.&lt;/p&gt;

&lt;p&gt;This creates unique challenges for text normalization, tokenization, and model training.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dataset Construction
&lt;/h2&gt;

&lt;p&gt;To create a balanced Yoruba speech corpus, I merged two complementary datasets:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Google Yoruba Speech Dataset (OpenSLR 86)
&lt;/h3&gt;

&lt;p&gt;A collection of high-quality studio recordings with clean acoustic conditions.&lt;/p&gt;

&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consistent microphone setup&lt;/li&gt;
&lt;li&gt;Minimal background noise&lt;/li&gt;
&lt;li&gt;Reliable pronunciation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. IroyinSpeech
&lt;/h3&gt;

&lt;p&gt;A crowd-sourced Yoruba speech dataset containing diverse accents and speaking styles.&lt;/p&gt;

&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Greater speaker diversity&lt;/li&gt;
&lt;li&gt;Real-world recording conditions&lt;/li&gt;
&lt;li&gt;More representative pronunciation variation&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Dataset Statistics
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Total Utterances&lt;/td&gt;
&lt;td&gt;6,989&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total Duration&lt;/td&gt;
&lt;td&gt;~9.6 Hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total Speakers&lt;/td&gt;
&lt;td&gt;156&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sample Rate&lt;/td&gt;
&lt;td&gt;24 kHz&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Channels&lt;/td&gt;
&lt;td&gt;Mono&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The idea was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use studio-quality recordings to establish acoustic stability while using crowd-sourced speech to improve speaker diversity and robustness.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Data Pipeline
&lt;/h2&gt;

&lt;p&gt;The preprocessing pipeline looked 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;Google OpenSLR 86 (Studio)
          +
IroyinSpeech (Crowd)
          │
          ▼
     24 kHz Mono WAV
          │
          ▼
 Discrete Audio Tokenization
 (HiggsAudio 8-Codebook VQ)
          │
          ▼
     OmniVoice Training
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rather than feeding raw waveforms directly into the language model, OmniVoice operates on &lt;strong&gt;discrete audio tokens&lt;/strong&gt; generated through vector quantization.&lt;/p&gt;

&lt;p&gt;For this project, I used the &lt;strong&gt;HiggsAudio 8-Codebook VQ tokenizer&lt;/strong&gt;, which converts continuous speech into sequences of discrete acoustic symbols that can be modeled autoregressively.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding the Zero-Shot Paradigm
&lt;/h2&gt;

&lt;p&gt;One common misconception about fine-tuning voice cloning models is that fine-tuning teaches the model a single voice.&lt;/p&gt;

&lt;p&gt;That is &lt;strong&gt;not&lt;/strong&gt; what happens here.&lt;/p&gt;

&lt;p&gt;Even after fine-tuning, the model remains a &lt;strong&gt;zero-shot voice cloning system&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The architecture consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Qwen3-0.6B&lt;/strong&gt; as the autoregressive language model&lt;/li&gt;
&lt;li&gt;Discrete audio tokens as targets&lt;/li&gt;
&lt;li&gt;Reference audio for speaker conditioning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;During training, the model learns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Yoruba Text
     +
Audio Tokens
     ↓
Speech Generation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At inference time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Text Prompt
     +
5–10 Second Reference Clip
     ↓
Cloned Speaker Output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reference clip provides speaker identity dynamically.&lt;/p&gt;

&lt;p&gt;This means the model can synthesize speech in voices it has never seen before, provided there is a short reference sample.&lt;/p&gt;




&lt;h2&gt;
  
  
  Diacritics Are Acoustic Features, Not Formatting
&lt;/h2&gt;

&lt;p&gt;This was arguably the most important lesson from the project.&lt;/p&gt;

&lt;p&gt;Many NLP pipelines treat diacritics as optional formatting.&lt;/p&gt;

&lt;p&gt;For Yoruba TTS, this assumption is catastrophic.&lt;/p&gt;

&lt;p&gt;Characters such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ẹ
ọ
ṣ
à
á
ì
ó
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;are not stylistic variations.&lt;/p&gt;

&lt;p&gt;They encode phonological and tonal information directly tied to pronunciation.&lt;/p&gt;

&lt;p&gt;Removing diacritics forces the model to map identical text sequences to multiple conflicting acoustic realizations.&lt;/p&gt;

&lt;p&gt;The result is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tone confusion&lt;/li&gt;
&lt;li&gt;Prosody degradation&lt;/li&gt;
&lt;li&gt;Lower intelligibility&lt;/li&gt;
&lt;li&gt;Inconsistent synthesis&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Safeguard #1: Unicode NFC Normalization
&lt;/h2&gt;

&lt;p&gt;Before training, all transcripts were normalized using &lt;strong&gt;Unicode Normalization Form C (NFC)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Without normalization:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;can be represented as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;e + U+0323
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of a single Unicode codepoint.&lt;/p&gt;

&lt;p&gt;This can silently break tokenization and create inconsistent text representations.&lt;/p&gt;

&lt;p&gt;Using NFC ensured that all Yoruba characters were encoded consistently across the corpus.&lt;/p&gt;




&lt;h2&gt;
  
  
  Safeguard #2: Tokenizer Vocabulary Audit
&lt;/h2&gt;

&lt;p&gt;Before launching training, I audited the tokenizer vocabulary to verify that Yoruba characters existed as native tokens.&lt;/p&gt;

&lt;p&gt;Specifically, I checked support for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ẹ
ọ
ṣ
à
á
è
é
ì
í
ò
ó
ù
ú
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The objective was to ensure that none of these characters were being mapped to:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Unknown-token substitutions would effectively erase tonal information before the model even saw the text.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Meta's MMS Struggles with Modern Yoruba
&lt;/h2&gt;

&lt;p&gt;Meta's Massive Multilingual Speech (MMS) project is one of the most significant contributions to multilingual speech technology.&lt;/p&gt;

&lt;p&gt;However, it exposes an important issue that affects many low-resource languages:&lt;/p&gt;

&lt;h2&gt;
  
  
  Domain Mismatch
&lt;/h2&gt;

&lt;p&gt;A substantial portion of publicly available Yoruba speech data originates from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bible readings&lt;/li&gt;
&lt;li&gt;Religious recordings&lt;/li&gt;
&lt;li&gt;Formal narration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These datasets are valuable linguistically but represent a narrow style of speech.&lt;/p&gt;

&lt;p&gt;As a result, models trained primarily on such data often produce speech that sounds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Formal&lt;/li&gt;
&lt;li&gt;Archaic&lt;/li&gt;
&lt;li&gt;Unnaturally scripted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When generating contemporary Yoruba conversations, this mismatch becomes noticeable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why OpenSLR + IroyinSpeech Helped
&lt;/h2&gt;

&lt;p&gt;The datasets used in this project contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;News content&lt;/li&gt;
&lt;li&gt;Modern writing&lt;/li&gt;
&lt;li&gt;Everyday language patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This broader linguistic coverage produced synthesis that sounded substantially closer to modern spoken Yoruba.&lt;/p&gt;

&lt;p&gt;The improvement was especially noticeable in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prosody&lt;/li&gt;
&lt;li&gt;Phrase rhythm&lt;/li&gt;
&lt;li&gt;Conversational flow&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ASR-in-the-Loop Evaluation
&lt;/h2&gt;

&lt;p&gt;Evaluating TTS remains one of the hardest problems in speech research.&lt;/p&gt;

&lt;p&gt;The gold standard remains:&lt;/p&gt;

&lt;h2&gt;
  
  
  Mean Opinion Score (MOS)
&lt;/h2&gt;

&lt;p&gt;Human listeners rate speech quality and naturalness.&lt;/p&gt;

&lt;p&gt;The downside:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expensive&lt;/li&gt;
&lt;li&gt;Slow&lt;/li&gt;
&lt;li&gt;Difficult to scale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To obtain a faster quantitative signal, I implemented an &lt;strong&gt;ASR-in-the-loop evaluation pipeline&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Text Prompt
      │
      ▼
[ Fine-Tuned OmniVoice ]
      │
      ▼
Synthesized Audio
      │
      ▼
[ Fine-Tuned Yoruba ASR ]
      │
      ▼
Word Error Rate (WER)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ASR model used was:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ccibeekeocwhisper-small-yoruba-07-17&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;The synthesized speech achieved:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Normalized WER ≈ 11.5%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not a replacement for MOS evaluation.&lt;/p&gt;

&lt;p&gt;However:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If an independent, diacritic-aware Yoruba ASR system can accurately recover the original text from synthesized speech, that provides strong evidence that the speech is intelligible and linguistically faithful.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For rapid iteration, this evaluation loop proved extremely useful.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;After training and evaluation, three conclusions stood out:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Data Quality Matters More Than Model Size
&lt;/h3&gt;

&lt;p&gt;The combination of studio recordings and crowd-sourced diversity provided stronger gains than simply increasing parameter count.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Diacritics Must Be Preserved End-to-End
&lt;/h3&gt;

&lt;p&gt;For Yoruba TTS:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Diacritics are acoustic features.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Treating them as optional formatting introduces ambiguity the model cannot reliably resolve.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Domain Coverage Matters
&lt;/h3&gt;

&lt;p&gt;Modern conversational datasets produce noticeably more natural synthesis than corpora dominated by religious or formal speech.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;With the TTS pipeline stable, the next step is building the reverse direction:&lt;/p&gt;

&lt;h3&gt;
  
  
  Streaming Yoruba ASR
&lt;/h3&gt;

&lt;p&gt;The current roadmap includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Low-latency transcription&lt;/li&gt;
&lt;li&gt;WebSocket streaming&lt;/li&gt;
&lt;li&gt;Silero VAD&lt;/li&gt;
&lt;li&gt;Real-time inference&lt;/li&gt;
&lt;li&gt;Code-switch handling&lt;/li&gt;
&lt;li&gt;Speaker diarization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The long-term goal is a production-grade speech platform supporting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Yoruba ASR&lt;/li&gt;
&lt;li&gt;Yoruba TTS&lt;/li&gt;
&lt;li&gt;Voice cloning&lt;/li&gt;
&lt;li&gt;Conversational AI&lt;/li&gt;
&lt;li&gt;Educational speech applications&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Model
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://huggingface.co/Sam4rano/omnivoice-yoruba-tts" rel="noopener noreferrer"&gt;Sam4rano/omnivoice-yoruba-tts&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Repository
&lt;/h3&gt;

&lt;p&gt;Search for:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  Tags
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#Yoruba
#TTS
#SpeechSynthesis
#VoiceCloning
#ASR
#MachineLearning
#DeepLearning
#NLP
#SpeechAI
#OpenSource
#LowResourceLanguages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;If you're working on speech technology for African or other low-resource languages, I'd be interested in hearing how you're handling tone preservation, tokenizer design, and evaluation beyond traditional WER and MOS metrics.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>gpt3</category>
    </item>
    <item>
      <title>🚀 Master VS Code on Mac: The Ultimate Keyboard Shortcuts Guide for Next.js &amp; Python Developers</title>
      <dc:creator>Samuel Oyerinde</dc:creator>
      <pubDate>Mon, 30 Jun 2025 07:29:29 +0000</pubDate>
      <link>https://dev.to/sam4rano/master-vs-code-on-mac-the-ultimate-keyboard-shortcuts-guide-for-nextjs-python-developers-2iee</link>
      <guid>https://dev.to/sam4rano/master-vs-code-on-mac-the-ultimate-keyboard-shortcuts-guide-for-nextjs-python-developers-2iee</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://dev.to"&gt;dev.to&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As a developer working with Next.js and Python on macOS, I've discovered that mastering VS Code keyboard shortcuts is one of the fastest ways to supercharge your productivity. Instead of constantly reaching for your mouse, these shortcuts will have you navigating, editing, and debugging code like a seasoned pro.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quick Mac Tip&lt;/strong&gt;: Most VS Code shortcuts replace &lt;code&gt;Ctrl&lt;/code&gt; with &lt;code&gt;Cmd&lt;/code&gt; and &lt;code&gt;Alt&lt;/code&gt; with &lt;code&gt;Option&lt;/code&gt; on Mac. I'll highlight any exceptions as we go!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why Keyboard Shortcuts Matter
&lt;/h2&gt;

&lt;p&gt;Before we dive in, let's be honest—learning shortcuts feels tedious at first. But once they become muscle memory, you'll wonder how you ever coded without them. The time you save adds up quickly, especially when you're deep in a coding flow state.&lt;/p&gt;

&lt;h2&gt;
  
  
  📝 Basic Text Editing: Your Daily Drivers
&lt;/h2&gt;

&lt;p&gt;These are the shortcuts you'll use every single day:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Essential Copy/Paste Operations&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Cmd + X&lt;/code&gt; - Cut selected text (or entire line if nothing's selected)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + C&lt;/code&gt; - Copy selected text (or entire line if nothing's selected)
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + V&lt;/code&gt; - Paste from clipboard&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + A&lt;/code&gt; - Select all content in file&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Undo/Redo &amp;amp; Comments&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Z&lt;/code&gt; - Undo last action&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Shift + Z&lt;/code&gt; - Redo (Mac's version of Ctrl+Y)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + /&lt;/code&gt; - Toggle line comment (works on multiple selected lines too!)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⚡ Advanced Text Editing: Level Up Your Game
&lt;/h2&gt;

&lt;p&gt;Once you're comfortable with the basics, these shortcuts will make you feel like a coding wizard:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smart Selection &amp;amp; Autocomplete&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Space&lt;/code&gt; - Trigger autocomplete suggestions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + .&lt;/code&gt; - Quick fix for errors/warnings under cursor&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + D&lt;/code&gt; - Select word under cursor, then select next occurrence&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Line Manipulation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Shift + K&lt;/code&gt; - Delete current line (without copying to clipboard)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Enter&lt;/code&gt; - Insert new line below cursor&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Shift + Enter&lt;/code&gt; - Insert new line above cursor&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Option + Up/Down&lt;/code&gt; - Move current line up/down&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Code Folding &amp;amp; Indentation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Tab&lt;/code&gt; - Indent line&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + ]&lt;/code&gt; - Increase indentation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Option + [&lt;/code&gt; - Collapse code block&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Option + ]&lt;/code&gt; - Expand code block&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Shift + Option + A&lt;/code&gt; - Block comment selected code&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🗂️ Tab Management: Stay Organized
&lt;/h2&gt;

&lt;p&gt;Managing multiple files efficiently is crucial for larger projects:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Opening &amp;amp; Closing Tabs&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Shift + T&lt;/code&gt; - Reopen last closed tab&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + W&lt;/code&gt; - Close current tab&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + K, Cmd + W&lt;/code&gt; - Close all tabs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Navigation Between Tabs&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + Tab&lt;/code&gt; - Show recent tabs list (note: &lt;code&gt;Ctrl&lt;/code&gt;, not &lt;code&gt;Cmd&lt;/code&gt;!)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + Shift + Tab&lt;/code&gt; - Show tabs in reverse order&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Panel Management&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Option + Left/Right&lt;/code&gt; - Move tab to left/right panel&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + 1/2/3&lt;/code&gt; - Switch focus between panels&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🎛️ Panel &amp;amp; Sidebar Control
&lt;/h2&gt;

&lt;p&gt;Maximize your screen real estate and access tools quickly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal &amp;amp; Panels&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + ~&lt;/code&gt; - Toggle terminal (remember: &lt;code&gt;Ctrl&lt;/code&gt; not &lt;code&gt;Cmd&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + Shift + ~&lt;/code&gt; - Open new terminal&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Shift + M&lt;/code&gt; - Open problems panel&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Shift + U&lt;/code&gt; - Open output panel&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Sidebar Navigation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Cmd + B&lt;/code&gt; - Toggle sidebar&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Shift + E&lt;/code&gt; - Focus Explorer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + P&lt;/code&gt; - Quick file search&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Shift + P&lt;/code&gt; - Command Palette (your best friend!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Settings &amp;amp; Shortcuts&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Cmd + ,&lt;/code&gt; - Open settings&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + K, Cmd + S&lt;/code&gt; - View/edit keyboard shortcuts&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔍 Find, Replace &amp;amp; Symbol Navigation
&lt;/h2&gt;

&lt;p&gt;These shortcuts are game-changers when working with large codebases:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Search Operations&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Cmd + F&lt;/code&gt; - Find in current file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Shift + F&lt;/code&gt; - Global search across project&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Option + F&lt;/code&gt; - Find and replace in file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Shift + H&lt;/code&gt; - Global find and replace&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Symbol Navigation&lt;/strong&gt; (Perfect for Next.js components and Python functions!)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;F2&lt;/code&gt; - Rename symbol everywhere&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Shift + F12&lt;/code&gt; - Show all references inline&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Shift + Option + F12&lt;/code&gt; - Open references in side panel&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Option + F12&lt;/code&gt; - Peek definition&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;F12&lt;/code&gt; - Go to definition&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Click&lt;/code&gt; - Go to definition (mouse + keyboard combo)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Symbol Search&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Shift + O&lt;/code&gt; - Search symbols in current file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + T&lt;/code&gt; - Search symbols globally&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🎯 Advanced Selection &amp;amp; Multi-Cursor Magic
&lt;/h2&gt;

&lt;p&gt;Multi-cursor editing is where VS Code really shines:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Text Selection&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Shift + Arrow Keys&lt;/code&gt; - Select character by character&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Option + Left/Right&lt;/code&gt; - Jump by word&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Shift + Option + Left/Right&lt;/code&gt; - Select by word&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + Shift + Left/Right&lt;/code&gt; - Expand selection to logical blocks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Multi-Cursor Mastery&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Option + Click&lt;/code&gt; - Add cursor at click position&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + U&lt;/code&gt; - Undo last cursor placement&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Option + Up/Down&lt;/code&gt; - Add cursor above/below&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Box Selection&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Shift + Option + Drag&lt;/code&gt; - Select rectangular text block&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Shift + Option + Arrows&lt;/code&gt; - Adjust box selection&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🐛 Debugging Shortcuts
&lt;/h2&gt;

&lt;p&gt;Essential for troubleshooting your Next.js apps and Python scripts:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debug Control&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;F5&lt;/code&gt; - Start debugging / Continue execution&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Shift + F5&lt;/code&gt; - Stop debugger&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;F9&lt;/code&gt; - Toggle breakpoint&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Shift + F9&lt;/code&gt; - Add inline breakpoint&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step Through Code&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;F11&lt;/code&gt; - Step into function
&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%2Fx1y69c4um6i747p0hl55.png" alt="Image description" width="800" height="800"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;F10&lt;/code&gt; - Step over function&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Shift + F11&lt;/code&gt; - Step out of function&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💡 Pro Tips for Maximum Efficiency
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Start Small&lt;/strong&gt;: Pick 5-10 shortcuts that match your most common actions and practice them for a week.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use the Command Palette&lt;/strong&gt;: &lt;code&gt;Cmd + Shift + P&lt;/code&gt; is your gateway to discovering new features and their shortcuts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Customize When Needed&lt;/strong&gt;: Access &lt;code&gt;Cmd + K, Cmd + S&lt;/code&gt; to modify shortcuts that don't feel natural.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Practice with Real Projects&lt;/strong&gt;: The best way to memorize shortcuts is by using them in your actual Next.js and Python development work.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  📚 Additional Resources
&lt;/h2&gt;

&lt;p&gt;Want to dive deeper? Check out these helpful resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/docs/getstarted/keybindings" rel="noopener noreferrer"&gt;Official VS Code Keyboard Shortcuts Reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/shortcuts/keyboard-shortcuts-macos.pdf" rel="noopener noreferrer"&gt;VS Code Keyboard Shortcuts PDF (Mac version)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/docs/getstarted/tips-and-tricks" rel="noopener noreferrer"&gt;VS Code Tips and Tricks Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/docs/getstarted/keybindings#_customizing-shortcuts" rel="noopener noreferrer"&gt;Customizing Keyboard Shortcuts Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🎯 Your Next Steps
&lt;/h2&gt;

&lt;p&gt;The journey to keyboard shortcut mastery doesn't happen overnight, but every shortcut you learn is a small investment in your future productivity. Start with the basic text editing shortcuts, then gradually work your way up to the advanced multi-cursor and debugging features.&lt;/p&gt;

&lt;p&gt;Which shortcuts are you most excited to try? Drop a comment below and let me know how these shortcuts have improved your development workflow!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Found this helpful? Give it a ❤️ and share it with your fellow developers. Happy coding! 🚀&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags&lt;/strong&gt;: #vscode #productivity #macos #nextjs #python #shortcuts #webdev #developer&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>python</category>
      <category>vscode</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Next.js Performance Optimization with Real-World Example</title>
      <dc:creator>Samuel Oyerinde</dc:creator>
      <pubDate>Sat, 12 Apr 2025 14:25:09 +0000</pubDate>
      <link>https://dev.to/sam4rano/explaining-nextjs-performance-optimization-with-real-world-example-j5</link>
      <guid>https://dev.to/sam4rano/explaining-nextjs-performance-optimization-with-real-world-example-j5</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;Building a performant web application involves balancing static and dynamic content effectively. Next.js offers a suite of features to achieve this balance, including &lt;strong&gt;Streaming React Server Components (RSC)&lt;/strong&gt;, &lt;strong&gt;Partial Prerendering (PPR)&lt;/strong&gt;, &lt;strong&gt;Incremental Static Regeneration (ISR)&lt;/strong&gt;, &lt;strong&gt;Server-Side Rendering (SSR)&lt;/strong&gt;, &lt;strong&gt;Static Site Generation (SSG)&lt;/strong&gt;, caching, prefetching, and suspense boundaries. Let's explore these concepts through a real-world example: a blog website with a mix of static and dynamic content.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario: Blog Homepage
&lt;/h3&gt;

&lt;p&gt;Our blog homepage will display:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Static Header and Blog Posts&lt;/strong&gt;: These are mostly static, updated occasionally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic "Latest Comments" Section&lt;/strong&gt;: This updates frequently.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step-by-Step Implementation
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Step 1: Project Setup
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Directory Structure&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   /app
     /layout.tsx         # Root layout for the app
     /page.tsx           # Homepage route
     /components
       /BlogPostList.tsx # Component for rendering the blog post list
       /LatestComments.tsx # Component for rendering latest comments
     /lib
       /data.ts         # Functions to fetch blog posts and comments
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Mock Data Source&lt;/strong&gt;: Use a JSON file or API for blog posts and comments.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Step 2: Define Data Fetching Functions
&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;/lib/data.ts&lt;/code&gt;, create functions to fetch blog posts and comments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/data.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getBlogPosts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Simulate delay&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&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;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Blog Post 1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is the first post.&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="na"&gt;id&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;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Blog Post 2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is the second post.&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="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getLatestComments&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1500&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Simulate delay&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&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;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Great post!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User1&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="na"&gt;id&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;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Thanks for sharing!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User2&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 3: Create Components
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;BlogPostList Component&lt;/strong&gt;: Use &lt;strong&gt;SSG with ISR&lt;/strong&gt; for blog posts.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;   &lt;span class="c1"&gt;// components/BlogPostList.tsx&lt;/span&gt;
   &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getBlogPosts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../lib/data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;BlogPostList&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;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getBlogPosts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

     &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;

         &lt;span class="nx"&gt;Blog&lt;/span&gt; &lt;span class="nx"&gt;Posts&lt;/span&gt;

           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;post&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
               &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&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;ol&gt;
&lt;li&gt;
&lt;strong&gt;LatestComments Component&lt;/strong&gt;: Use &lt;strong&gt;SSR&lt;/strong&gt; with a suspense boundary for dynamic comments.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;   &lt;span class="c1"&gt;// components/LatestComments.tsx&lt;/span&gt;
   &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getLatestComments&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../lib/data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;LatestComments&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;comments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getLatestComments&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

     &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;

         &lt;span class="nx"&gt;Latest&lt;/span&gt; &lt;span class="nx"&gt;Comments&lt;/span&gt;

           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;comment&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&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;h4&gt;
  
  
  Step 4: Build the Homepage
&lt;/h4&gt;

&lt;p&gt;Combine static and dynamic content using &lt;strong&gt;Streaming SSR&lt;/strong&gt; and &lt;strong&gt;Suspense&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/page.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Suspense&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;BlogPostList&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../components/BlogPostList&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;LatestComments&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../components/LatestComments&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;revalidate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Enable ISR&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Home&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="p"&gt;(&lt;/span&gt;

      &lt;span class="nx"&gt;My&lt;/span&gt; &lt;span class="nx"&gt;Blog&lt;/span&gt;

      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Static Blog Posts with SSG + ISR */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Dynamic Comments with Streaming SSR and Suspense */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;Loading&lt;/span&gt; &lt;span class="nx"&gt;latest&lt;/span&gt; &lt;span class="nx"&gt;comments&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 5: Optimize Caching and Prefetching
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Prefetching&lt;/strong&gt;: Use &lt;code&gt;prefetch={true}&lt;/code&gt; in links for faster navigation.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;   &lt;span class="c1"&gt;// components/BlogPostList.tsx (updated)&lt;/span&gt;
   &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/link&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getBlogPosts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../lib/data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;BlogPostList&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;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getBlogPosts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

     &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;

         &lt;span class="nx"&gt;Blog&lt;/span&gt; &lt;span class="nx"&gt;Posts&lt;/span&gt;

           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;post&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


               &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&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;ol&gt;
&lt;li&gt;
&lt;strong&gt;Cache Headers for Static Assets&lt;/strong&gt;: Set cache headers in &lt;code&gt;next.config.js&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="c1"&gt;// next.config.js&lt;/span&gt;
   &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;headers&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="p"&gt;[&lt;/span&gt;
         &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/:path*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="na"&gt;headers&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="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cache-Control&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;public, max-age=31536000, immutable&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Cache static assets for 1 year&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;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;h3&gt;
  
  
  Explanation of Rendering Strategies
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SSG with ISR for BlogPostList&lt;/strong&gt;: Pre-rendered at build time, revalidated every 10 minutes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streaming SSR with PPR for LatestComments&lt;/strong&gt;: Dynamic content is streamed as it becomes available.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Suspense Boundary&lt;/strong&gt;: Ensures a smooth loading experience by showing a fallback UI.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fast Initial Load&lt;/strong&gt;: Static content loads immediately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Updates&lt;/strong&gt;: Fresh data is fetched at request time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved UX&lt;/strong&gt;: Suspense boundaries prevent page blocking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching&lt;/strong&gt;: Reduces server requests on repeat visits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefetching&lt;/strong&gt;: Enhances navigation speed.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Tags:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;#NextJS&lt;/code&gt; &lt;code&gt;#React&lt;/code&gt; &lt;code&gt;#WebDevelopment&lt;/code&gt; &lt;code&gt;#PerformanceOptimization&lt;/code&gt; &lt;code&gt;#StreamingRSC&lt;/code&gt; &lt;code&gt;#ISR&lt;/code&gt; &lt;code&gt;#SSG&lt;/code&gt; &lt;code&gt;#SSR&lt;/code&gt; &lt;code&gt;#SuspenseBoundary&lt;/code&gt; &lt;code&gt;#Caching&lt;/code&gt; &lt;code&gt;#Prefetching&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This approach ensures a fast and user-friendly experience by leveraging Next.js's advanced features to balance static and dynamic content effectively.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building an API with Express.js and Connecting It to the Frontend</title>
      <dc:creator>Samuel Oyerinde</dc:creator>
      <pubDate>Thu, 27 Mar 2025 09:47:56 +0000</pubDate>
      <link>https://dev.to/sam4rano/building-an-api-with-expressjs-and-connecting-it-to-the-frontend-3cfb</link>
      <guid>https://dev.to/sam4rano/building-an-api-with-expressjs-and-connecting-it-to-the-frontend-3cfb</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Building an API with Express.js and Connecting It to the Frontend&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When building modern web applications, APIs serve as the bridge between the backend (server-side logic) and the frontend (user interface). In this blog post, we’ll break down how an Express.js-based API works, its key components, and how it connects to a frontend application.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. What is a Router in Express.js?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;router&lt;/strong&gt; in Express.js is a way to organize API endpoints into modular and reusable components. Think of it as a "sub-application" that groups related routes together.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Why Use Routers?&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Keeps code clean and modular.&lt;/li&gt;
&lt;li&gt;Allows you to separate concerns (e.g., authentication routes in &lt;code&gt;auth.js&lt;/code&gt;, product routes in &lt;code&gt;products.js&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&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;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Define routes&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/register&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="nx"&gt;req&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="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="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Register endpoint&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="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/login&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="nx"&gt;req&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="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="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Login endpoint&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;// Export the router&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This router can then be mounted in the main app:&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;authRouter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./routes/auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;authRouter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;2. Backend API Workflow&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Here’s how a typical authentication API works:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;a. POST &lt;code&gt;/api/auth/register&lt;/code&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Registers a new user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steps&lt;/strong&gt;:

&lt;ol&gt;
&lt;li&gt;Check if the email already exists in the database.&lt;/li&gt;
&lt;li&gt;Hash the password using &lt;code&gt;bcrypt&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Save the user to the database.&lt;/li&gt;
&lt;li&gt;Return a JWT token for future authenticated requests.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;b. POST &lt;code&gt;/api/auth/login&lt;/code&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Logs in an existing user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steps&lt;/strong&gt;:

&lt;ol&gt;
&lt;li&gt;Verify if the email exists.&lt;/li&gt;
&lt;li&gt;Compare the provided password with the hashed password stored in the database.&lt;/li&gt;
&lt;li&gt;If valid, return a JWT token.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;c. GET &lt;code&gt;/api/auth/user&lt;/code&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Fetches data of the logged-in user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steps&lt;/strong&gt;:

&lt;ol&gt;
&lt;li&gt;Validate the JWT token using middleware.&lt;/li&gt;
&lt;li&gt;Return user data, excluding sensitive information like passwords.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Code Example for &lt;code&gt;/register&lt;/code&gt;:&lt;/strong&gt;&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;bcrypt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bcrypt&lt;/span&gt;&lt;span class="dl"&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;jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jsonwebtoken&lt;/span&gt;&lt;span class="dl"&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;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./models/User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Mongoose model&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/register&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Check if user exists&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;existingUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;email&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="nx"&gt;existingUser&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User already exists&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Hash password&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hashedPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Save user to database&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newUser&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;User&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;hashedPassword&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Generate JWT token&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;secretKey&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="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1h&lt;/span&gt;&lt;span class="dl"&gt;'&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="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&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="nx"&gt;token&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;h3&gt;
  
  
  &lt;strong&gt;3. Connecting the Backend to the Frontend&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The frontend communicates with this API through HTTP requests.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Step 1: Registration/Login&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The frontend sends a &lt;code&gt;POST&lt;/code&gt; request to &lt;code&gt;/api/auth/register&lt;/code&gt; or &lt;code&gt;/api/auth/login&lt;/code&gt; with user credentials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example Frontend Code:&lt;/strong&gt;&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;// Register a user&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&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="s1"&gt;/api/auth/register&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="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&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;Content-Type&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;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&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="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;123456&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&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="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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// JWT token&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Step 2: Storing JWT Token&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;After receiving the JWT token, store it securely (e.g., in &lt;code&gt;localStorage&lt;/code&gt; or cookies):&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="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;token&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Step 3: Making Authenticated Requests&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;For protected routes like &lt;code&gt;/api/auth/user&lt;/code&gt;, include the JWT token in the request headers:&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;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;token&lt;/span&gt;&lt;span class="dl"&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&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="s1"&gt;/api/auth/user&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="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;userData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&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="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;userData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;4. Key Components of an Express API&lt;/strong&gt;
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Express Router&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Organizes routes into modules for cleaner code.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bcrypt&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hashes passwords securely before storing them in a database.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;JWT (JSON Web Token)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Generates tokens for authenticating users across sessions.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mongoose Models&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Defines schemas for MongoDB collections (e.g., users).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auth Middleware&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Validates JWT tokens for protected routes like &lt;code&gt;/api/auth/user&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Summary: Frontend vs Backend Roles&lt;/strong&gt;
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Frontend&lt;/th&gt;
&lt;th&gt;Backend&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sends HTTP requests to API endpoints.&lt;/td&gt;
&lt;td&gt;Handles requests and sends responses with data/logic.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stores and uses tokens for auth.&lt;/td&gt;
&lt;td&gt;Generates and validates tokens using JWTs.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Displays user data (e.g., profile).&lt;/td&gt;
&lt;td&gt;Fetches and secures data from databases like MongoDB.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why This Matters&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Security:&lt;/strong&gt; Passwords are hashed, and JWT ensures only authenticated users access protected routes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability:&lt;/strong&gt; Modular routing and middleware make it easier to grow your application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separation of Concerns:&lt;/strong&gt; The frontend focuses on UI/UX while the backend handles logic and data.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach forms the backbone of most modern web apps, enabling seamless communication between frontend interfaces and backend systems.&lt;/p&gt;




&lt;h3&gt;
  
  
  Tags:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;#NodeJS&lt;/code&gt; &lt;code&gt;#ExpressJS&lt;/code&gt; &lt;code&gt;#API&lt;/code&gt; &lt;code&gt;#Authentication&lt;/code&gt; &lt;code&gt;#WebDevelopment&lt;/code&gt; &lt;code&gt;#FrontendBackendIntegration&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Citations:&lt;br&gt;
[1] &lt;a href="https://rapidapi.com/blog/nodejs-express-rest-api-example/" rel="noopener noreferrer"&gt;https://rapidapi.com/blog/nodejs-express-rest-api-example/&lt;/a&gt;&lt;br&gt;
[2] &lt;a href="https://www.freecodecamp.org/news/the-express-handbook/" rel="noopener noreferrer"&gt;https://www.freecodecamp.org/news/the-express-handbook/&lt;/a&gt;&lt;br&gt;
[3] &lt;a href="https://dev.to/mrrishimeena/understanding-expressjs-router-nodejs-a-comprehensive-guide-59o8"&gt;https://dev.to/mrrishimeena/understanding-expressjs-router-nodejs-a-comprehensive-guide-59o8&lt;/a&gt;&lt;br&gt;
[4] &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction&lt;/a&gt;&lt;br&gt;
[5] &lt;a href="https://dev.to/reiallenramos/create-an-express-api-static-and-dynamic-routes-33lb"&gt;https://dev.to/reiallenramos/create-an-express-api-static-and-dynamic-routes-33lb&lt;/a&gt;&lt;br&gt;
[6] &lt;a href="https://www.codecademy.com/article/what-is-express-js" rel="noopener noreferrer"&gt;https://www.codecademy.com/article/what-is-express-js&lt;/a&gt;&lt;br&gt;
[7] &lt;a href="https://www.youtube.com/watch?v=1XxQBXl4Lv8" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=1XxQBXl4Lv8&lt;/a&gt;&lt;br&gt;
[8] &lt;a href="https://www.freecodecamp.org/news/rest-api-design-best-practices-build-a-rest-api/" rel="noopener noreferrer"&gt;https://www.freecodecamp.org/news/rest-api-design-best-practices-build-a-rest-api/&lt;/a&gt;&lt;br&gt;
[9] &lt;a href="https://www.topcoder.com/thrive/articles/routing-in-express-js" rel="noopener noreferrer"&gt;https://www.topcoder.com/thrive/articles/routing-in-express-js&lt;/a&gt;&lt;br&gt;
[10] &lt;a href="https://kinsta.com/knowledgebase/what-is-express-js/" rel="noopener noreferrer"&gt;https://kinsta.com/knowledgebase/what-is-express-js/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>node</category>
      <category>api</category>
      <category>express</category>
    </item>
    <item>
      <title>Automated Download Folder Organization with python</title>
      <dc:creator>Samuel Oyerinde</dc:creator>
      <pubDate>Fri, 14 Mar 2025 10:03:27 +0000</pubDate>
      <link>https://dev.to/sam4rano/automated-download-folder-organization-with-python-1cd2</link>
      <guid>https://dev.to/sam4rano/automated-download-folder-organization-with-python-1cd2</guid>
      <description>&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;Lately, my Downloads folder had become a chaotic mess. Finding a single file meant endless scrolling and searching—frustrating and time-consuming. But then, I stumbled upon an article on Dev.to about Python automation, which sparked an idea. After some research, I wrote a script that automates the organization of my Downloads folder.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Solution
&lt;/h3&gt;

&lt;p&gt;The script performs the following tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scans&lt;/strong&gt; my Downloads folder&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identifies&lt;/strong&gt; file types (e.g., PDFs, images, videos, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Moves&lt;/strong&gt; each file into its designated folder&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a visual representation of how the organized folder structure looks:&lt;/p&gt;

&lt;p&gt;Image description&lt;/p&gt;

&lt;h3&gt;
  
  
  The Code
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Step 1: Check Folder Existence and Create Folders
&lt;/h4&gt;

&lt;p&gt;First, we need to ensure the specified Downloads folder exists and create the necessary subfolders if they don't already exist.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;shutil&lt;/span&gt;

&lt;span class="c1"&gt;# Define file types and their corresponding folders
&lt;/span&gt;&lt;span class="n"&gt;FILE_TYPES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Documents&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.pdf&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.docx&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.txt&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Images&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.jpg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.gif&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Videos&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.mp4&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.mkv&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.avi&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Other&lt;/span&gt;&lt;span class="sh"&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;# Default folder for unknown file types
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;organize_downloads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;download_folder&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Check if the folder exists
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;download_folder&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The folder &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;download_folder&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; does not exist.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="c1"&gt;# Create folders if they don't exist
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;FILE_TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;folder_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;download_folder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;folder_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makedirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;folder_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 2: Organize Files
&lt;/h4&gt;

&lt;p&gt;Next, we iterate through all files in the Downloads folder, identify their types, and move them to their respective folders.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="c1"&gt;# Iterate through files in the download folder
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;download_folder&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;file_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;download_folder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Skip directories
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="n"&gt;file_extension&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&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="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c1"&gt;# Find the right folder for the file
&lt;/span&gt;        &lt;span class="n"&gt;destination_folder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Other&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;extensions&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;FILE_TYPES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;file_extension&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;destination_folder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;

        &lt;span class="c1"&gt;# Move the file to the appropriate folder
&lt;/span&gt;        &lt;span class="n"&gt;destination_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;download_folder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;destination_folder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;shutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;destination_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Moved &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; to &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;destination_folder&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Call and run the script
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;download_folder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Enter the path to your downloads folder: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;organize_downloads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;download_folder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Download folder organized successfully!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What’s Next?
&lt;/h3&gt;

&lt;p&gt;I’m now working on enhancing this script to run automatically based on specific triggers (e.g., time intervals or folder size). The goal is to make file organization completely hands-off, so my system stays organized without any manual intervention.&lt;/p&gt;

&lt;h3&gt;
  
  
  Share Your Thoughts!
&lt;/h3&gt;

&lt;p&gt;If you’re curious about the code or want to try it out yourself, feel free to adapt it to your needs or suggest improvements—I’d love to hear your thoughts! You can find the code on GitHub: &lt;a href="https://github.com/sam4rano/python-automation" rel="noopener noreferrer"&gt;https://github.com/sam4rano/python-automation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>automation</category>
      <category>python</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Decoupling Hoisting In React</title>
      <dc:creator>Samuel Oyerinde</dc:creator>
      <pubDate>Thu, 23 Mar 2023 19:58:10 +0000</pubDate>
      <link>https://dev.to/sam4rano/decoupling-hoisting-in-react-1420</link>
      <guid>https://dev.to/sam4rano/decoupling-hoisting-in-react-1420</guid>
      <description>&lt;p&gt;**Table Of Content&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Brief overview of hoisting in JavaScript&lt;/li&gt;
&lt;li&gt;Explanation of how hoisting works in ReactJS&lt;/li&gt;
&lt;li&gt;Hoisting in ReactJS&lt;/li&gt;
&lt;li&gt;Benefits of using hoisting in ReactJS&lt;/li&gt;
&lt;li&gt;Examples of hoisting in ReactJS&lt;/li&gt;
&lt;li&gt;Best Practices for Hoisting in ReactJS&lt;/li&gt;
&lt;li&gt;Tips for optimizing performance with hoisting in ReactJS&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;li&gt;Reference**&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Brief overview of hoisting in JavaScript&lt;/strong&gt;&lt;br&gt;
Hoisting is a JavaScript mechanism where variables and function declarations are moved to the top of their respective scope before the code is executed. This means that you can use a variable or function before it has been declared in your code. However, only the declaration is hoisted, not the initialization, which means that if you try to access a variable before it has been assigned a value, it will be undefined. Hoisting can be a powerful tool, but it can also lead to unexpected results if not used properly.&lt;/p&gt;

&lt;p&gt;Variable declarations are hoisted to the top of their respective function or global scope. &lt;/p&gt;

&lt;p&gt;a. &lt;em&gt;For example, consider the following code&lt;/em&gt;&lt;br&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%2Ffhvsozza1juh1wlj4p60.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%2Ffhvsozza1juh1wlj4p60.png" alt="Javascript code" width="796" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even though the console.log(x) statement appears before the declaration of the x variable, the code still runs without error because the declaration is hoisted to the top of the function scope.&lt;br&gt;
b. Function declarations are also hoisted to the top of their respective function or global scope. For example, consider the following code:&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%2Fw0jzuzwq2kl3mizo1php.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%2Fw0jzuzwq2kl3mizo1php.png" alt="Image 2" width="796" height="552"&gt;&lt;/a&gt;&lt;br&gt;
Even though the example() function is called before it is declared, the code still runs without error because the function declaration is hoisted to the top of the global scope.&lt;/p&gt;

&lt;p&gt;Note: It's important to note that while variable and function declarations are hoisted, any assignments or initializations are not hoisted. &lt;br&gt;
&lt;strong&gt;For example, consider the following code:&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%2F8nxiyo0ax3n35hbiht9l.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%2F8nxiyo0ax3n35hbiht9l.png" alt="Var hoisting" width="540" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this code, the declaration of the x variable is hoisted to the top of the global scope, but the initialization of x is not hoisted. As a result, the console.log(x) statement will output undefined because x has not yet been assigned a value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explanation of how Hoisting works in React&lt;/strong&gt;&lt;br&gt;
In ReactJS, hoisting works in a similar way to how it works in regular JavaScript. React components are defined as functions, and just like any other JavaScript function, the function declaration is hoisted to the top of its scope. This means that you can use the component before it has been defined in your code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hoisting in React&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;For example, consider the following React code:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//1. Hoisting a function component
renderMyComponent();

function renderMyComponent() {
  ReactDOM.render(&amp;lt;MyComponent /&amp;gt;, document.getElementById('root'));
}

function MyComponent() {
  return &amp;lt;h1&amp;gt;Hello, world!&amp;lt;/h1&amp;gt;;
}

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

&lt;/div&gt;



&lt;p&gt;In this example, the MyComponent function component is declared after the renderMyComponent function. However, because the function declaration is hoisted to the top of the scope, &lt;br&gt;
the renderMyComponent function can still call the MyComponent component and render it to the DOM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits of using hoisting in ReactJS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;a. Improved code organization: Hoisting allows you to declare variables and functions at the top of a code block, which can make your code more organized and easier to read.&lt;/p&gt;

&lt;p&gt;b. Faster execution: Hoisting can improve the performance of your code by allowing the JavaScript engine to pre-process function and variable declarations before executing the rest of the code.&lt;/p&gt;

&lt;p&gt;c. Avoiding errors: Hoisting can prevent errors caused by using variables or functions before they are declared, which can be especially helpful in large ReactJS projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example of Hoisting In React&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// 2. Hoisting a state variable
import {useState} from 'react';

const MyComponent = () =&amp;gt; {
  const [count, setCount] = useState(0);

  const handleClick = () =&amp;gt; {
    setCount(count + 1);
  }

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Count: {count}&amp;lt;/h1&amp;gt;
      &amp;lt;button onClick={handleClick}&amp;gt;Increment&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
export default MyComponent;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the count state variable is declared and initialized using the useState hook. Even though count is declared after the handleClick function that uses it, &lt;br&gt;
the function can still access count because the declaration is hoisted to the top of the component function scope.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect } from "react";
const MyComponent = () =&amp;gt; {
  const [count, setCount] = useState(0);

  const handleClick = () =&amp;gt; {
    setCount(count + 1);
  }

  useEffect(() =&amp;gt; {
    // do some side effect
  }, []);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Count: {count}&amp;lt;/h1&amp;gt;
      &amp;lt;button onClick={handleClick}&amp;gt;Increment&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
export default MyComponent;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the handleClick function is declared below the useState hook, but it can still be called in the JSX element because of hoisting. This improves the organization and readability of the code because related code is grouped together.&lt;/p&gt;

&lt;p&gt;Similarly, the useState hook is declared above the handleClick function, but it can still be used in the function because of hoisting. &lt;br&gt;
This allows for more flexible placement of code &lt;br&gt;
and can improve performance by allowing the JavaScript engine to pre-process the hook before executing the rest of the code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best practices for Hoisting in React&lt;/strong&gt;&lt;br&gt;
a. Declare state hooks and other hooks at the top of the component, before any other logic or functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect } from "react";

const MyComponent = () =&amp;gt; {
  const [count, setCount] = useState(0);

  useEffect(() =&amp;gt; {
    // do some side effect
  }, []);

  const handleClick = () =&amp;gt; {
    setCount(count + 1);
  }

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Count: {count}&amp;lt;/h1&amp;gt;
      &amp;lt;button onClick={handleClick}&amp;gt;Increment&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
export default MyComponent;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;b. Declare variables and functions before using them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from "react";

const MyComponent = () =&amp;gt; {
  const [count, setCount] = useState(0);

  // Good: Declare handleClick before using it in JSX
  const handleClick = () =&amp;gt; {
    setCount(count + 1);
  }

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Count: {count}&amp;lt;/h1&amp;gt;
      &amp;lt;button onClick={handleClick}&amp;gt;Increment&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
export default MyComponent;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;c. Declare functions that use hooks below the hooks they depend on&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect } from "react";

const MyComponent = () =&amp;gt; {
  const [count, setCount] = useState(0);

  useEffect(() =&amp;gt; {
    // do some side effect
  }, []);

  const handleClick = ()  {
    setCount(count + 1);
  }

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Count: {count}&amp;lt;/h1&amp;gt;
      &amp;lt;button onClick={handleClick}&amp;gt;Increment&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default MyComponent;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;d. Avoid declaring functions and hooks inside other functions, as this can make it harder to reason about the code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect } from "react";

const MyComponent = () =&amp;gt; {
  const [count, setCount] = useState(0);

  const handleClick = () =&amp;gt; {
    const innerFunction = () =&amp;gt; {
      setCount(count + 1); // This won't work as expected
    }

    innerFunction();
  }

  useEffect(() =&amp;gt; {
    // do some side effect
  }, []);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Count: {count}&amp;lt;/h1&amp;gt;
      &amp;lt;button onClick={handleClick}&amp;gt;Increment&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
export default MyComponent;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tips for optimizing performance with hoisting in ReactJS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use hoisting with caution and only when necessary to avoid overcomplicating your code.&lt;/p&gt;

&lt;p&gt;Be mindful of the order in which your code is executed to avoid unexpected behavior.&lt;/p&gt;

&lt;p&gt;Use profiling tools to identify performance issues and optimize your code accordingly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Hoisting is an important concept in ReactJS that can improve code organization and performance when used properly. It is important to understand the best practices and pitfalls of hoisting to avoid errors and optimize code performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reference&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://facebook.github.io/react/docs/thinking-in-react.html" rel="noopener noreferrer"&gt;https://facebook.github.io/react/docs/thinking-in-react.html&lt;/a&gt;&lt;br&gt;
&lt;a href="https://facebook.github.io/react/docs/lifting-state-up.html" rel="noopener noreferrer"&gt;https://facebook.github.io/react/docs/lifting-state-up.html&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.digitalocean.com/community/tutorials/understanding-hoisting-in-javascript" rel="noopener noreferrer"&gt;https://www.digitalocean.com/community/tutorials/understanding-hoisting-in-javascript&lt;/a&gt;&lt;br&gt;
&lt;a href="https://react.dev/blog/2023/03/16/introducing-react-dev" rel="noopener noreferrer"&gt;https://react.dev/blog/2023/03/16/introducing-react-dev&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Fibonacci Sequence: Algorithm and Python implementation simplified</title>
      <dc:creator>Samuel Oyerinde</dc:creator>
      <pubDate>Fri, 22 Jul 2022 17:16:00 +0000</pubDate>
      <link>https://dev.to/sam4rano/fibonacci-sequence-algorithm-and-python-implementation-simplified-2n96</link>
      <guid>https://dev.to/sam4rano/fibonacci-sequence-algorithm-and-python-implementation-simplified-2n96</guid>
      <description>&lt;h2&gt;
  
  
  1.1 The Fibonacci Sequence
&lt;/h2&gt;

&lt;p&gt;The Fibonacci numbers, sometimes known as Fn, create a series in which each number is the sum &lt;br&gt;
of the two numbers before it. Although some authors ignore the initial words and begin the sequence &lt;br&gt;
from 1 and 1 or from 1 and 2, the pattern typically starts from 0 and 1.&lt;br&gt;
The following values follow 0 and 1 in the sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34,...&lt;/p&gt;

&lt;h2&gt;
  
  
  1.2 The previous two digits are combined to yield the following number:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; The 1 is found by adding the two numbers that precede it (0+1), &lt;/li&gt;
&lt;li&gt;The 2 by adding the two numbers that come before it (1+1), &lt;/li&gt;
&lt;li&gt;The 3 by adding the two numbers that come before it (1+2), &lt;/li&gt;
&lt;li&gt;The 5 by adding the two numbers that come before it (2+3), and so on!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1.3 Mathematically, Fibonacci can be represented by:
&lt;/h2&gt;

&lt;p&gt;F(1) = 1&lt;br&gt;
F(2) = 1&lt;br&gt;
F(n) = F(n − 1) + F(n − 2)&lt;/p&gt;

&lt;h2&gt;
  
  
  1.4 pictorial representation
&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%2F1qp3vs1d082zqt3b6130.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%2F1qp3vs1d082zqt3b6130.PNG" alt="Image description" width="800" height="133"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2 Fibonacci Algorithm
&lt;/h2&gt;

&lt;p&gt;2.1 Non-Recursive Iterative Algorithm for Fibonacci&lt;br&gt;
Procedures or subroutines written in a programming language that do not refer to themselves&lt;br&gt;
are known as non-recursive functions.&lt;/p&gt;

&lt;h2&gt;
  
  
  2.1.1 Algorithm non-recursive Fibonacci
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Procedure Iterative_Fibonacci(n):
    int f0, f1, fib
    f0 = 0
    f1 = 1
    display f0, f1
    for int i:= 1 to n:
        fib := f0 + f1   
        f0 := f1
        f1 := fib
        display fib
    END for loop
END Iterative_Fibonacci
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2.1.2 Python implementation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;num_terms = int(input("Number of terms? "))

# first two terms
f1, f2 = 0, 1
count = 0

# checking for the validity of the number of terms
if num_terms &amp;lt;= 0:
   print("Enter a positive integer")
# if there is only one term, return f1
elif num_terms == 1:
   print("Fibonacci sequence to",num_terms,":")
   print(f1)
# generate fibonacci sequence
else:
   print("Fibonacci sequence:")
   while count &amp;lt; num_terms:
       print(f1)
       nths = f1 + f2
       # update values
       f1 = f2
       f2 = nths
       count += 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2.2 Recursive implementation of the Fibonacci sequence
&lt;/h2&gt;

&lt;p&gt;Recursion is a powerful programming concept that provides an effective way to solve large problems by&lt;br&gt;
breaking them down into simpler subproblems, using this approach, it's often possible to unravel&lt;br&gt;
seemingly complex problems via repeated application of very simple solutions to the subproblems.&lt;br&gt;
When we speak about recursion in programming, we are simply talking about recursive functions.&lt;br&gt;
A recursive function is a function that calls itself somewhere in its definition, The function is defined in terms of itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  2.2.1 Properties of Recursion
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;There must be a reachable base case where the function stops calling itself otherwise infinite loop will occur&lt;/li&gt;
&lt;li&gt;The argument of the function must be modified with each call.&lt;/li&gt;
&lt;li&gt;Performing the identical operations multiple times with different inputs.&lt;/li&gt;
&lt;li&gt;For each step, we apply smaller inputs to reduce the complexity of the problem.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  2.2.2 Algorithm of Recursive Fibonacci
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;START
Procedure Fibonacci(n)
   declare f0, f1, fib, loop 

   set f0 to 0
   set f1 to 1

   display f0, f1

   for loop ← 1 to n

      fib ← f0 + f1   
      f0 ← f1
      f1 ← fib

      display fib
   end for

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  2.2.3 Python implementation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def fibo(n):
   if n &amp;lt;= 1:
       return n
   else:
       return(fibo(n-1) + fibo(n-2))

nterms = int(input('enter an integer? '))

# check if the number of terms is valid
if nterms &amp;lt;= 0:
   print("Please enter a positive integer")
else:
   print("Fibonacci sequence:")
   for i in range(nterms):
       print(recur_fibo(i))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks for reading, kindly follow for more interesting content on Data structure and Algorithm&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
