<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[wolz CODElife - Joel Adewole]]></title><description><![CDATA[Joel is an accomplished Technical Writer and DevRel Engineer with extensive industry experience and background in full-stack web development.]]></description><link>https://blog.wolzcodelife.com</link><generator>RSS for Node</generator><lastBuildDate>Wed, 22 Apr 2026 09:08:54 GMT</lastBuildDate><atom:link href="https://blog.wolzcodelife.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Going Serverless: Pros And Cons Of Serverless Architecture]]></title><description><![CDATA[From startups to enterprise-level organizations, serverless computing has gained significant traction due to its promise of scalability, cost-efficiency, and simplified infrastructure management. The rise of serverless architecture has been nothing s...]]></description><link>https://blog.wolzcodelife.com/going-serverless-pros-and-cons-of-serverless-architecture</link><guid isPermaLink="true">https://blog.wolzcodelife.com/going-serverless-pros-and-cons-of-serverless-architecture</guid><category><![CDATA[serverless]]></category><category><![CDATA[Devops]]></category><category><![CDATA[infrastructure]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Thu, 04 Sep 2025 23:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1758745649429/a8198108-986e-4d54-ad2d-a255b311ba83.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>From startups to enterprise-level organizations, serverless computing has gained significant traction due to its promise of scalability, cost-efficiency, and simplified infrastructure management. The rise of serverless architecture has been nothing short of remarkable.</p>
<p>For example, a streaming giant like <a target="_blank" href="https://www.netflix.com/">Netflix</a> handles millions of requests per second. Managing such a massive infrastructure can be daunting and resource-intensive. However, Netflix realized the transformative power of going serverless with AWS. By leveraging serverless architecture, they were able to offload the burden of infrastructure management and focus on delivering an exceptional streaming experience. This move allowed them to scale seamlessly and optimize costs, leading to improved performance and user satisfaction.</p>
<p>In this article, we will explore the pros and cons of serverless architecture. We will point out the benefits it offers, such as effortless scalability, reduced operational overhead, and pay-per-use pricing models. Also, we will address the potential challenges and limitations, including vendor lock-in, cold start latency, and restricted control over the underlying infrastructure. By examining both sides of the serverless coin, we aim to provide valuable insights that will empower software developers and architects to make informed decisions when considering serverless architecture for their projects.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before diving into the pros and cons of serverless architecture, it is essential to have a basic understanding of cloud computing and its relationship to serverless computing.</p>
<p>To grasp the concept of serverless architecture, two fundamental components need to be understood: Function as a Service (FaaS) and Backend as a Service (BaaS). Here are the key points:</p>
<ul>
<li><p><strong>Function as a Service (FaaS)</strong>: FaaS is a cloud computing model where developers write code in the form of individual functions that run in response to specific events or triggers.<br />  These functions are short-lived and stateless, executing only when required, and scaling automatically based on the incoming workload.<br />  Examples of FaaS platforms include <a target="_blank" href="https://aws.amazon.com/lambda/">AWS Lambda</a>, <a target="_blank" href="https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview?pivots=programming-language-csharp">Azure Functions</a>, and <a target="_blank" href="https://cloud.google.com/functions">Google Cloud Functions</a>.</p>
</li>
<li><p><strong>Backend as a Service (BaaS)</strong>: BaaS is a cloud computing service that provides pre-built backend functionalities for applications, such as databases, user authentication, and push notifications.<br />  This allows developers to focus on the front end and application logic, offloading backend infrastructure management to the BaaS provider.<br />  BaaS platforms include Firebase, AWS Amplify, and Azure Mobile Apps.</p>
</li>
</ul>
<h2 id="heading-what-is-serverless-architecture">What is Serverless Architecture</h2>
<p>Serverless architecture, also known as Function as a Service (FaaS), is a revolutionary approach to cloud computing that simplifies the development and deployment of applications such that developers can focus solely on writing code for individual functionalities, which are triggered by specific events or requests. These functions execute in a stateless and ephemeral environment, scaling automatically to accommodate workload fluctuations.</p>
<p>By adopting a serverless architecture, developers can shift their attention from managing servers to crafting efficient and scalable code. The underlying infrastructure, including server provisioning, scaling, and maintenance, is abstracted away by the cloud provider. This allows developers to focus on delivering business value and accelerating the development process.</p>
<p>We can use the illustration below to visualize the structure of a serverless architecture.</p>
<p><img src="https://io.dropinblog.com/uploaded/blogs/34251246/files/serverless-architecture-zezjr.png" alt="Serverless architecture" /></p>
<p>In this diagram, the client (browser) interacts with various components of the serverless architecture. The Authentication service handles user authentication and authorization. The API gateway acts as a bridge between the client and other serverless functions such as the Purchase function and the Search function which are triggered by specific events. The Purchase function communicates with the Purchase database to process purchase requests, while the Search function interacts with the Product database to fetch relevant information. This decoupled and event-driven nature of serverless architecture enables flexible and scalable application development.</p>
<h2 id="heading-pros-of-serverless-architecture">Pros of Serverless Architecture</h2>
<p>Serverless architecture offers numerous benefits that make it an attractive choice for software development projects. Here are the key advantages of adopting a serverless architecture:</p>
<ul>
<li><p><strong>Scalability</strong>: Serverless architecture excels in handling variable workloads. With traditional architectures, scaling infrastructure to accommodate fluctuating demand can be challenging and time-consuming. In contrast, serverless platforms automatically scale the execution environment based on the incoming workload. This elastic scalability ensures that applications can handle sudden spikes in traffic without compromising performance or incurring additional costs.</p>
</li>
<li><p><strong>Automatic Scaling</strong>: Serverless platforms automatically handle the scaling of resources based on demand. As the workload increases, additional instances of functions are provisioned to handle the increased traffic. Conversely, during periods of low or no traffic, the platform automatically scales down resources, ensuring optimal resource allocation and cost savings. This automatic scaling feature simplifies capacity planning and eliminates the need for manual intervention.</p>
</li>
<li><p><strong>Reduced Infrastructure Management:</strong> Serverless architecture eliminates the need for developers to manage servers or worry about infrastructure provisioning and maintenance. This frees up valuable time and resources that can be redirected towards focusing on core application logic and business functionality. Developers can simply focus on writing and deploying functions, allowing for greater agility and faster time-to-market.</p>
</li>
<li><p><strong>Cost Optimization</strong>: One of the significant advantages of serverless architecture is its cost-effectiveness. With traditional infrastructure, developers need to anticipate and provision resources to handle peak loads, which can lead to underutilization and unnecessary expenses during periods of low demand. In a serverless model, developers only pay for the actual execution time of their functions, resulting in cost savings and improved cost efficiency.</p>
</li>
</ul>
<p>These advantages enable organizations to build efficient and scalable applications while focusing on delivering value to their users.</p>
<h2 id="heading-cons-of-serverless-architecture">Cons of Serverless Architecture</h2>
<p>While serverless architecture offers many benefits, it is important to consider the potential drawbacks associated with it. Here are some of the key challenges that developers and organizations may face when using serverless architecture:</p>
<ul>
<li><p><strong>Vendor Lock-In</strong>: One significant concern with serverless architecture is the risk of vendor lock-in. Each cloud provider offers its own serverless platform with unique features and limitations. Once an application is built on a specific serverless platform, it becomes tightly coupled to that provider's ecosystem. Moving to a different provider or transitioning to a different architecture can be complex and time-consuming. It is crucial to carefully evaluate the long-term implications of vendor lock-in and consider the portability of applications built on serverless platforms.</p>
</li>
<li><p><strong>Cold Start Latency</strong>: Serverless functions have an inherent startup time, known as cold start latency, which occurs when a function is invoked for the first time or after a period of inactivity. During cold starts, the serverless platform provisions resources and initializes the environment, which can introduce delays in application response time. While the subsequent invocations benefit from low latency, the initial latency may impact real-time or latency-sensitive applications. It is important to evaluate the specific use cases and performance requirements to determine the impact of cold start latency on the application's overall user experience.</p>
</li>
<li><p><strong>Limited Control Over Infrastructure</strong>: Serverless architectures abstract away much of the infrastructure management, providing simplicity and ease of use. However, this abstraction can also limit fine-grained control over the underlying infrastructure. Developers have less control over the underlying hardware, networking, and system-level configurations. Customization and fine-tuning may be restricted, which can be a concern for applications with specific performance, security, or compliance requirements. It is essential to assess the level of control needed for the application and evaluate whether serverless architecture aligns with those requirements.</p>
</li>
</ul>
<p>It is crucial to weigh the benefits against the limitations and evaluate whether the trade-offs align with the specific needs and goals of the project.</p>
<h2 id="heading-addressing-misconceptions">Addressing Misconceptions</h2>
<p>Serverless architecture has gained popularity, but it is not without its share of misconceptions. Let's address some common myths associated with serverless architecture:</p>
<ol>
<li><p>**Myth: Serverless architecture is always cost-effective.  </p>
<p> Reality**: While serverless architecture can offer cost savings, it is not universally cost-effective in all scenarios. The pay-per-use pricing model can be advantageous for applications with variable workloads. However, for applications with consistently high traffic or long-running processes, a traditional infrastructure approach may be more cost-effective. It is crucial to analyze the specific requirements and usage patterns to determine the cost-effectiveness of serverless architecture.</p>
</li>
<li><p>**Myth: Serverless architecture always provides superior performance.   </p>
<p> Reality**: Serverless architecture offers automatic scaling and resource allocation, which can enhance performance for certain workloads. However, cold start latency and dependency on external services may introduce performance overhead. It is essential to assess the performance requirements of the application and evaluate whether serverless architecture aligns with those needs. Performance optimization techniques, such as function optimization and warm-up strategies, can help mitigate these concerns.</p>
</li>
<li><p>**Myth: Serverless architecture eliminates DevOps or infrastructure management.   </p>
<p> Reality:** While serverless architecture abstracts away much of the infrastructure management, it does not eliminate the need for DevOps entirely. DevOps practices, such as continuous integration and deployment, monitoring, and troubleshooting, are still crucial for managing and optimizing serverless applications. Additionally, understanding the underlying infrastructure and architecture remains important for effective development and debugging.</p>
</li>
</ol>
<p>By busting these misconceptions and understanding the reality, we can start making informed decisions about adopting serverless architecture. It is crucial to consider the specific requirements, challenges, and trade-offs associated with serverless architecture to determine its suitability for the intended use cases.</p>
<h2 id="heading-top-serverless-architecture-providers">Top Serverless Architecture Providers</h2>
<p>When considering serverless architecture, it's important to explore the top providers that offer the necessary infrastructure and services. </p>
<p><img src="https://io.dropinblog.com/uploaded/blogs/34251246/files/top-serverless-architecture-providers-javte.png" alt="top serverless architecture providers" /></p>
<p>These providers specialize in delivering serverless capabilities, enabling developers to focus on writing code and building applications without the need to manage underlying servers. Here are some of the leading serverless architecture providers:</p>
<ol>
<li><p><strong>AWS Lambda</strong>: As part of <a target="_blank" href="https://aws.amazon.com/lambda/">Amazon Web Services (AWS), Lambda</a> is a popular choice for serverless computing. It offers a wide range of integrations, scalability, and flexible pricing options. Lambda supports a variety of programming languages and provides seamless integration with other AWS services, making it a preferred choice for many developers.</p>
</li>
<li><p><strong>Microsoft Azure Functions</strong>: <a target="_blank" href="https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview?pivots=programming-language-csharp">Azure Functions</a> is Microsoft's serverless computing offering. It provides a fully managed platform for running event-driven applications and supports multiple programming languages. With Azure Functions, developers can easily integrate with other Azure services and take advantage of Microsoft's extensive cloud ecosystem.</p>
</li>
<li><p><strong>Google Cloud Functions</strong>: <a target="_blank" href="https://cloud.google.com/functions">Google Cloud Functions</a> allows developers to build and deploy serverless functions on the Google Cloud Platform. It supports multiple languages, provides automatic scaling, and integrates well with other Google Cloud services. Google Cloud Functions offers a reliable infrastructure and extensive monitoring capabilities.</p>
</li>
<li><p><strong>IBM Cloud Functions</strong>: <a target="_blank" href="https://cloud.ibm.com/functions/">IBM Cloud Functions</a>, based on the open-source Apache OpenWhisk project, provides a serverless computing platform that supports multiple programming languages. It offers seamless integration with other IBM Cloud services and provides flexible deployment options.</p>
</li>
<li><p><strong>Cloudflare Workers</strong>: <a target="_blank" href="https://workers.cloudflare.com/">Cloudflare Workers</a> is a serverless platform that runs JavaScript applications on Cloudflare's global network of edge servers. It enables developers to build serverless functions and deploy them close to the end-users, improving performance and reducing latency.</p>
</li>
<li><p><strong>Netlify Functions</strong>: <a target="_blank" href="https://www.netlify.com/products/functions/">Netlify Functions</a> is a serverless computing platform integrated with Netlify's static site hosting. It allows developers to create serverless functions using JavaScript or TypeScript, providing a seamless workflow for deploying serverless applications alongside static websites.</p>
</li>
<li><p><strong>Vercel Functions</strong>: <a target="_blank" href="https://vercel.com/docs/concepts/functions/serverless-functions">Vercel Functions</a>, powered by the Next.js framework, is a serverless computing platform designed for modern frontend applications. It supports serverless functions written in Node.js, providing easy deployment and integration with Vercel's hosting platform.</p>
</li>
</ol>
<p>Each provider has its own unique features, pricing models, and integrations, so it's important to evaluate and choose the one that best aligns with the specific requirements and goals of the project.</p>
<h2 id="heading-real-world-use-cases-and-success-stories">Real-World Use Cases and Success Stories</h2>
<p>Serverless architecture has gained traction across various industries, with organizations leveraging its benefits to solve specific challenges and achieve notable outcomes. Here are some real-world use cases and success stories:</p>
<ul>
<li><p><strong>Netflix</strong>: Netflix, the popular streaming platform, adopted serverless architecture to optimize its content encoding pipeline. By breaking down the encoding process into smaller functions, they achieved significant improvements in scalability, cost-efficiency, and reduced time-to-market for new features. Serverless allowed Netflix to handle fluctuating workloads efficiently, ensuring a seamless streaming experience for millions of users.</p>
</li>
<li><p><strong>Coca-Cola</strong>: Coca-Cola, the global beverage giant, implemented serverless architecture to enhance its marketing campaigns. By utilizing serverless functions, they developed interactive and personalized experiences for consumers, such as dynamic content delivery, targeted promotions, and real-time analytics. Serverless enabled Coca-Cola to handle high traffic volumes during campaign periods while keeping costs low and ensuring smooth user experiences.</p>
</li>
<li><p><strong>NASA</strong>: NASA, the space exploration agency, leveraged serverless architecture to process and analyze vast amounts of data from satellites and space missions. With serverless functions, they achieved scalable data processing, real-time event-driven workflows, and seamless integration with their existing infrastructure. Serverless allowed NASA to focus on scientific research and analysis, rather than managing complex server infrastructure.</p>
</li>
<li><p><strong>Airtable</strong>: Airtable, a collaborative work management platform, leveraged serverless functions to enable real-time collaboration and data synchronization across their user base. Serverless allowed them to handle concurrent requests efficiently and ensure data consistency without managing server infrastructure. This architecture choice contributed to improved user experience and seamless collaboration.</p>
</li>
<li><p><strong>Amazon Prime Video</strong>: While other organizations have succeeded using serverless infrastructure, the Video Quality Analysis (VQA) team at Prime Video initially used a distributed system architecture with serverless components such as AWS Step Functions and AWS Lambda which worked fine. However, they encountered scaling bottlenecks and high costs and needed to scale. To address these issues, they decided to rearchitect their infrastructure and migrate to a monolith application. In the new architecture, all components of the VQA service were packed into a single process. This allowed data transfer to happen within the memory, reducing costs associated with passing video frames between components. By moving to a monolith application, the VQA team was able to reduce infrastructure costs by over 90% and increase scaling capabilities. They were able to handle thousands of streams and still had the capacity for further scaling. </p>
</li>
</ul>
<p>These examples demonstrate how organizations have successfully leveraged serverless architecture to solve specific challenges and achieve remarkable results. Organizations have successfully utilized serverless to address scalability, cost optimization, real-time processing, and agility in delivering innovative solutions.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, serverless architecture offers numerous advantages such as scalability, reduced infrastructure management, and automatic scaling, making it an attractive option for many organizations. However, it is crucial to also acknowledge the drawbacks, such as vendor lock-in, cold start latency, and limited control over the infrastructure.</p>
<p>As you evaluate whether serverless architecture is suitable for your projects, you should carefully consider the requirements, scalability needs, and resource constraints of the project. While serverless architecture may not be a one-size-fits-all solution, it can be a powerful tool in the right context. By understanding the trade-offs and conducting proper due diligence, developers and businesses can harness the benefits of serverless architecture while mitigating its limitations.</p>
<p>Ultimately, the decision to go serverless should be based on a thorough analysis of the specific project requirements and goals. By considering the pros and cons discussed in this article, readers can make informed decisions that align with their objectives, optimize resource usage, and drive innovation in their software development.</p>
]]></content:encoded></item><item><title><![CDATA[How To Choose The Language And Framework For Your Startup]]></title><description><![CDATA[Introduction
As a startup founder or CTO who is eager to bring an innovative idea to life, you have a talented team, a solid business plan, and the drive to succeed. But before you can start building your product, you're faced with a critical decisio...]]></description><link>https://blog.wolzcodelife.com/how-to-choose-the-language-and-framework-for-your-startup</link><guid isPermaLink="true">https://blog.wolzcodelife.com/how-to-choose-the-language-and-framework-for-your-startup</guid><category><![CDATA[startup]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Thu, 07 Aug 2025 23:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1758745434447/957a0bba-54b4-45de-b051-186d2a2c01a6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction">Introduction</h3>
<p>As a startup founder or CTO who is eager to bring an innovative idea to life, you have a talented team, a solid business plan, and the drive to succeed. But before you can start building your product, you're faced with a critical decision: <strong>choosing the right programming language and framework for your startup</strong>. This choice is crucial because it will not only impact your team's productivity and the quality of your product but also determine how quickly you can bring your idea to market and scale your business.</p>
<p>Selecting the ideal programming language and framework can be a daunting task, especially with the ever-growing number of options available in the technology landscape. Startup founders, CTOs, and developers often struggle to find the perfect fit for their specific needs, taking into account factors such as team expertise, time to market, and long-term scalability.</p>
<p>This article aims to guide you through the process of choosing the best language and framework for your startup, providing expert advice and insights tailored to your unique requirements. We will delve into the essential selection criteria, including team strength, industry standards, and trends while comparing popular frontend, backend, and mobile app development technologies. Additionally, we will touch on blockchain development languages and frameworks and explore the challenges of migrating between technologies, should the need arise.</p>
<p>By the end of this article, you will have a comprehensive understanding of the key factors to consider when choosing a programming language and framework, empowering you to make informed decisions that set your startup on the path to success.</p>
<h2 id="heading-prerequisite">Prerequisite</h2>
<p>Before diving into the process of selecting the ideal programming language and framework for your startup, it's essential to have a solid foundation in some key concepts. This article assumes that you have a basic understanding of programming languages and frameworks, as well as familiarity with software development processes. If you're new to these topics, we recommend brushing up on the following areas:</p>
<ol>
<li><p><strong>Programming languages</strong>: Grasp the fundamental concepts of programming languages, such as syntax, data types, control structures, and object-oriented programming. Being familiar with popular languages like Python, JavaScript, Java, and Ruby will be beneficial when comparing different options.</p>
</li>
<li><p><strong>Frameworks</strong>: Understand the role of frameworks in software development and how they simplify and speed up the development process by providing reusable code, libraries, and tools. Learn about some of the widely-used frameworks, such as Django for Python, Ruby on Rails for Ruby, or Angular for JavaScript.</p>
</li>
<li><p><strong>Software development concepts</strong>: Familiarize yourself with essential software development concepts like version control, software architecture, design patterns, and testing. This will help you appreciate the benefits and drawbacks of various languages and frameworks in different development scenarios.</p>
</li>
<li><p><strong>Web and mobile app development</strong>: Gain a basic understanding of frontend and backend development for web applications and the process of creating mobile apps. This knowledge will be valuable when comparing languages and frameworks specifically designed for these platforms.</p>
</li>
<li><p><strong>Development methodologies</strong>: Be aware of common development methodologies like Agile, Scrum, and DevOps, as they can influence the choice of language and framework to some extent.</p>
</li>
</ol>
<p>By having a foundational understanding of these topics, you'll be better equipped to make informed decisions when choosing the best programming language and framework for your startup. This article is designed to be comprehensive and accessible for all experience levels, so don't worry if you're not an expert—our goal is to provide you with the practical advice you need to succeed.</p>
<h2 id="heading-what-are-languages-and-frameworks">What Are Languages And Frameworks?</h2>
<p>To make informed decisions about the best programming language and framework for your startup, it's essential to understand what these terms mean and the roles they play in software development. Let’s take a closer look.</p>
<h3 id="heading-programming-languages">Programming languages</h3>
<p><img src="https://lh6.googleusercontent.com/sTLgSfw-QW0poLHT7U9vtzRRWDc16SlDVbhxw_2jxb11gqvW-oM5raHOIRjHqAh7Bx6NoE90IfMWsz9VYmC8NhVnylDT1h8SDtI1fqI_l63VU42KJAtQufm9YK5YZbHyE3ShWsjPNPqWu9HnbNJfOtM" alt="programming languages for startup" /></p>
<p>A programming language is a set of instructions, commands, and syntax used to create software programs. Developers write code in a programming language to communicate with computers and instruct them on how to perform specific tasks. There are numerous programming languages, each with its strengths and weaknesses, and they can be broadly classified into high-level languages (e.g., Python, JavaScript, Java, Ruby) and low-level languages (e.g., C, C++, Assembly). High-level languages are more human-readable and easier to learn, while low-level languages offer greater control over hardware and are often used for system-level programming.</p>
<h3 id="heading-frameworks">Frameworks</h3>
<p><img src="https://lh6.googleusercontent.com/KNzadsmFRdg8eDvQywwMEPgjlzzhS0NsYjMS63mvr-xA0agMUjJucE4SHcohviYLqu52zj08eEO3x3X9BmzQc9Oud9LgJgNhMZ50scDw28oVuxAzsN835hbBaYhyIjkri1XJsnrFiocm_BtjwqkFd3A" alt="frameworks for startups" /></p>
<p>A framework is a collection of pre-written code libraries, tools, and templates that simplifies and accelerates software development by providing a structure and reusable components. Frameworks are designed for specific programming languages(e.g., Django for Python, Angular for JavaScript) and help developers adhere to best practices while reducing the amount of repetitive code they need to write. By using a framework, developers can focus more on implementing unique features and functionality of their applications rather than reinventing the wheel.</p>
<h3 id="heading-differences-between-languages-and-frameworks">Differences between languages and frameworks</h3>
<p>While programming languages provide the fundamental building blocks for creating software, frameworks offer a structured environment and tools to streamline the development process. The choice of programming language determines the syntax and core features available to developers, while the framework dictates the development workflow, design patterns, and overall structure of the project. It's essential to understand that a framework is built on top of a programming language and cannot exist independently. Hence, choosing the right programming language and framework combination is crucial for efficient software development.</p>
<h2 id="heading-what-are-the-selection-criteria">What Are The Selection Criteria?</h2>
<p>When choosing the right programming language and framework for your startup, several crucial factors come into play. By considering the following selection criteria, you'll be better equipped to make an informed decision that best suits your project's unique needs:</p>
<ol>
<li><p><strong>Team strength</strong>: The skills and expertise of your development team play a significant role in determining the best technology choice. Evaluate your team's proficiency in various programming languages and frameworks, taking into account their learning curve and the potential need for additional training or hiring new talent.</p>
</li>
<li><p><strong>Time to market</strong>: In the competitive startup landscape, getting your product to market quickly is essential. Consider the development and deployment speed offered by different languages and frameworks, including their learning curve, the ease of setting up a development environment, and the availability of pre-built modules and components.</p>
</li>
<li><p><strong>Open-source resources</strong>: The presence of a robust open-source ecosystem can be a game-changer for startups. Assess the availability of open-source tools, libraries, and community support for each language and framework under consideration. Open-source resources can significantly reduce development time and costs while providing access to a wealth of knowledge and expertise.</p>
</li>
<li><p><strong>Industry standards and trends</strong>: Analyze popular choices within your industry, as they can offer valuable insights into what works best for your specific use case. Staying aligned with industry trends can make it easier to find skilled developers, integrate with other tools and services, and receive community support.</p>
</li>
<li><p><strong>Scalability</strong>: As your startup grows, so will your technical requirements. Ensure that the chosen language and framework can support the growth of your business by evaluating their performance, ability to handle increasing loads, and ease of maintaining and updating the codebase.</p>
</li>
</ol>
<p>These selection criteria will guide you to choose the programming language and framework that best align with your startup's goals, resources, and technical requirements, setting the stage for your success in the competitive market.</p>
<h2 id="heading-frontend-web-development-languages-and-frameworks">Frontend Web Development Languages And Frameworks</h2>
<p>Frontend web development focuses on creating the user interface and user experience of a web application. It involves designing the layout, visuals, and interactivity of a website or web app. When choosing frontend languages and frameworks for your startup, consider the following popular options and their best use cases:</p>
<p><strong>Popular frontend languages</strong>:</p>
<ul>
<li><p><strong>HTML (HyperText Markup Language)</strong>: A markup language used to structure content on the web, HTML is essential for creating the basic layout of web pages. It's typically combined with CSS and JavaScript for styling and interactivity.</p>
</li>
<li><p><strong>CSS (Cascading Style Sheets)</strong>: A stylesheet language used for describing the look and formatting of a document written in HTML, CSS is responsible for the visual appearance of web pages, including layout, colors, and typography.</p>
</li>
<li><p><strong>JavaScript</strong>: A versatile programming language used for adding interactivity to web pages, JavaScript can manipulate HTML and CSS, enabling dynamic content and responsive designs. It can be used with TypeScript for improved type safety and maintainability.</p>
</li>
<li><p><strong>TypeScript</strong>: A superset of JavaScript that adds optional static typing, TypeScript can catch errors at compile time, making it easier to maintain and scale large codebases. It's often used in conjunction with popular front-end frameworks.</p>
</li>
</ul>
<p><strong>Popular frontend frameworks</strong>:</p>
<ul>
<li><p><strong>React</strong>: Developed by Facebook, React is a popular JavaScript library for building user interfaces. It uses a component-based architecture and a virtual DOM for optimized performance. React can be combined with Redux for state management and works well with TypeScript.</p>
</li>
<li><p><strong>Angular</strong>: A comprehensive framework developed by Google, Angular uses TypeScript as its primary language and offers a complete solution for building large-scale web applications, including dependency injection, routing, and form validation.</p>
</li>
<li><p><strong>Vue.js</strong>: A lightweight and flexible JavaScript framework, Vue.js is easy to learn and integrates well with existing projects. Its component-based architecture and reactive data binding make it ideal for building modern user interfaces.</p>
</li>
<li><p><strong>Svelte</strong>: A newer, compiler-based JavaScript framework, Svelte shifts the work from runtime to compile time, resulting in faster performance and smaller bundle sizes. It's an excellent choice for startups focused on performance optimization.</p>
</li>
<li><p><strong>Nuxt.js</strong>: A framework built on top of Vue.js that helps you create server-side rendered (SSR) and statically generated applications. It provides a convention-based setup and allows you to quickly scaffold a Vue.js application with server-side rendering capabilities. Nuxt.js simplifies the development of universal or isomorphic Vue.js applications and offers features like automatic routing, code splitting, and server-side rendering out of the box.</p>
</li>
<li><p><strong>Next.js</strong>: A framework for React that enables server-side rendering, static site generation, and client-side rendering all in one. It provides an opinionated setup for building modern web applications with React. Next.js offers features like server-side rendering (SSR), automatic code splitting, and API routes, making it suitable for building dynamic and performant web applications. It can be used with external servers or deployed as a standalone serverless application.</p>
</li>
</ul>
<p>Based on your startup's specific needs, you can select the best combination that will deliver a seamless and engaging user experience for your web application.</p>
<h2 id="heading-backend-web-development-languages-and-frameworks">Backend Web Development Languages And Frameworks</h2>
<p>Backend web development focuses on server-side logic, data storage, and communication between the front end and back end. It is responsible for processing user requests, interacting with databases, and ensuring the overall performance and security of a web application. When selecting backend languages and frameworks for your startup, consider these popular options and their best use cases:</p>
<p><strong>Popular backend languages</strong>:</p>
<ul>
<li><p><strong>Python</strong>: A versatile, high-level programming language, Python is known for its readability, simplicity, and extensive library support. It's suitable for a wide range of applications, including web development, data analysis, and machine learning.</p>
</li>
<li><p><strong>Ruby</strong>: An object-oriented, dynamic programming language, Ruby is prized for its elegant syntax and readability. It's an excellent choice for startups focused on rapid web development and ease of use.</p>
</li>
<li><p><strong>Java</strong>: A widely used, platform-independent programming language, Java offers high performance, scalability, and extensive libraries. It's ideal for building large-scale enterprise applications and web services.</p>
</li>
<li><p><strong>JavaScript</strong>: Node.js is a JavaScript runtime built on Chrome's V8 engine. Node.js enables developers to write server-side code using JavaScript. It's well-suited for scalable and high-performance web applications, particularly when combined with popular front-end JavaScript frameworks.</p>
</li>
<li><p><strong>PHP</strong>: A popular server-side scripting language specifically designed for web development. It has a large user base and extensive community support. PHP is known for its simplicity, ease of integration with HTML, and compatibility with various databases. It's a good choice for startups focusing on building dynamic and database-driven websites or web applications.</p>
</li>
<li><p><strong>Go (GoLang)</strong>: A statically typed, compiled programming language developed by Google. It emphasizes simplicity, performance, and concurrency. Go is well-suited for building scalable, efficient, and reliable server-side applications. It has a strong standard library and excellent support for concurrent programming, making it a good choice for high-performance web services and microservices architectures.</p>
</li>
<li><p><strong>Rust</strong>: A systems programming language that is known for its focus on memory safety, performance, and concurrency. It provides strong guarantees about memory management and has a strict compile-time checking system that prevents many common programming errors. Rust is often used for building highly reliable and secure backend systems, such as web servers and network services, where performance and safety are critical. Although it is usually recommended for most early-stage startups to use Rust (because it might affect the time to market).</p>
</li>
<li><p><a target="_blank" href="http://asp.net/"><strong>ASP.NET</strong></a>: A web development framework developed by Microsoft. It enables developers to build robust and scalable web applications using multiple programming languages, such as C# and Visual Basic. <a target="_blank" href="http://asp.net/">ASP.NET</a> provides various tools, libraries, and frameworks for building web APIs, web services, and web applications. It is well-suited for developing enterprise-level applications and integrates well with other Microsoft technologies.</p>
</li>
</ul>
<p><strong>Popular backend frameworks</strong>:</p>
<ul>
<li><p><strong>Django</strong>: A powerful Python web framework, Django follows the "batteries-included" philosophy, offering a comprehensive set of built-in features for rapid web development. It's known for its robustness, security, and scalability, making it an excellent choice for startups.</p>
</li>
<li><p><strong>Flask</strong>: A Python microframework that emphasizes simplicity and minimalism. It provides the basics for web development and allows developers to choose and integrate additional libraries based on their specific needs. Flask is lightweight and flexible, making it a popular choice for building small to medium-sized web applications.</p>
</li>
<li><p><strong>FastAPI</strong>: A modern, high-performance Python framework for building APIs with Python 3.7+ type hints. It combines the ease of use of Python with the speed of Node.js, making it a compelling choice for building robust and efficient backend APIs. FastAPI leverages asynchronous programming to provide excellent performance and is suitable for building microservices and high-performance web applications.</p>
</li>
<li><p><strong>Ruby on Rails</strong>: Often referred to as "Rails," this popular Ruby framework follows the "convention over configuration" paradigm, allowing for fast and efficient web development. Rails is particularly suitable for startups looking to build MVPs and prototypes quickly.</p>
</li>
<li><p><strong>Spring Boot</strong>: A Java-based framework, Spring Boot simplifies the creation of stand-alone, production-grade Spring applications. It offers a wide range of built-in features, including dependency injection, security, and data access, making it a powerful choice for enterprise-level applications.</p>
</li>
<li><p><strong>Express.js</strong>: A minimalist Node.js framework, Express.js simplifies the development of web applications and RESTful APIs using JavaScript. It's an excellent choice for developers already familiar with JavaScript and those seeking a unified language for both frontend and backend development.</p>
</li>
<li><p><strong>Laravel</strong>: A PHP web framework that is known for its elegance and expressive syntax. It follows the MVC (Model-View-Controller) pattern and provides a rich set of features for web application development, including routing, database ORM (Object-Relational Mapping), caching, and authentication. Laravel is widely used for building scalable and maintainable web applications.</p>
</li>
<li><p><strong>Symfony</strong>: A flexible and highly modular PHP framework that emphasizes code reusability and extensibility. It offers a wide range of components and tools to speed up development and ensure best practices. Symfony is suitable for both small and large-scale projects and provides excellent support for creating APIs.</p>
</li>
<li><p><strong>CodeIgniter</strong>: A lightweight PHP framework known for its simplicity and speed. It's easy to learn and offers a straightforward approach to building web applications. CodeIgniter has a small footprint and requires minimal configuration, making it a suitable choice for startups looking for a lightweight framework with good performance.</p>
</li>
<li><p><strong>Gin</strong>: A lightweight web framework for Go (GoLang). It offers a fast and efficient routing engine and provides essential middleware functionality. Gin is well-suited for building high-performance web applications and RESTful APIs in Go, with a focus on simplicity and minimalism.</p>
</li>
<li><p><strong>Echo</strong>: Another lightweight web framework for Go (GoLang) that emphasizes simplicity, performance, and productivity. It provides a straightforward API for building web applications and APIs and offers features like routing, middleware, and template rendering. Echo is a good choice for startups looking for a fast and flexible framework in Go.</p>
</li>
<li><p><strong>Fiber</strong>: A web framework for Go (GoLang) inspired by Express.js. It focuses on speed and efficiency, utilizing fast HTTP routing and middleware processing. Fiber offers an easy-to-use API for building web applications and APIs in Go, making it suitable for startups that prioritize performance and productivity.</p>
</li>
<li><p><strong>Actix</strong>: A high-performance, actor-based web framework for Rust. It provides a robust foundation for building concurrent and efficient web applications. Actix is known for its scalability, speed, and safety, making it suitable for building highly concurrent systems and network services.</p>
</li>
<li><p><strong>Rocket</strong>: A web framework for Rust that focuses on simplicity, ease of use, and developer productivity. It aims to provide a delightful web development experience while leveraging the performance and safety benefits of Rust. Rocket simplifies tasks like routing, request handling, and parameter parsing, making it an attractive choice for startups looking to build web applications in Rust.</p>
</li>
</ul>
<p>Considering these backend web development languages and frameworks based on your startup's specific requirements will ensure that you select the most suitable combination to power the server-side logic and functionality of your web application. Resulting in efficient processing, secure data storage, and seamless communication between frontend and backend components.</p>
<h2 id="heading-mobile-app-development-languages-and-frameworks">Mobile App Development Languages And Frameworks</h2>
<p>As mobile app usage continues to grow, startups must consider the right programming languages and frameworks for developing their apps. Let’s look at some popular mobile app development languages and frameworks to help you make an informed decision for your startup's needs.</p>
<p><strong>Popular mobile app development languages</strong>:</p>
<ul>
<li><p><strong>Dart</strong>: Dart is designed for building high-performance mobile, web, and server apps. Its best use case is creating cross-platform applications with a single codebase.</p>
</li>
<li><p><strong>Objective-C</strong>: An object-oriented programming language, Objective-C is a primary language for iOS development. It's known for its strong typing and dynamic runtime, best used for developing iOS and macOS applications.</p>
</li>
<li><p><strong>Swift</strong>: Developed by Apple, Swift is a powerful, easy-to-learn language for building iOS and macOS applications. It offers fast performance, strong typing, and modern syntax, making it an excellent choice for startups targeting the Apple ecosystem.</p>
</li>
<li><p><strong>Java</strong>: A universal, platform-independent programming language, Java is widely used for Android app development. Its broad library support, strong community, and proven reliability make it a popular choice for many startups.</p>
</li>
<li><p><strong>Kotlin</strong>: A more modern alternative to Java, Kotlin is fully interoperable with Java and has become a preferred language for Android app development. Its concise, expressive syntax and built-in safety features make it an attractive option for startups.</p>
</li>
<li><p><strong>C++</strong>: A highly efficient, general-purpose language, C++ is well-suited for resource-constrained environments, such as mobile app development, gaming, and embedded systems.</p>
</li>
<li><p><strong>JavaScript</strong>: When paired with the right frameworks like React Native, JavaScript enables cross-platform mobile app development, allowing developers to write code that works on multiple platforms.</p>
</li>
<li><p><strong>Python</strong>: Although not primarily a mobile app development language, Python can be used in combination with tools like Kivy or BeeWare to build cross-platform applications.</p>
</li>
</ul>
<p><strong>Popular mobile app development frameworks:</strong></p>
<ul>
<li><p><strong>React Native</strong>: Developed by Facebook, React Native is a popular framework for building cross-platform mobile apps using JavaScript and the React library. It allows developers to write native-like applications for iOS and Android with a single codebase, significantly reducing development time and cost for startups.</p>
</li>
<li><p><strong>Flutter</strong>: An open-source UI toolkit from Google, Flutter enables developers to create natively compiled, visually appealing mobile applications for iOS, Android, and other platforms using the Dart programming language. Its hot-reload feature and rich set of pre-built widgets make it a popular choice for fast, iterative development.</p>
</li>
<li><p><strong>Ionic</strong>: A hybrid mobile app development framework, Ionic combines web technologies like HTML, CSS, and JavaScript to create platform-independent applications. It's best used for creating simple, cost-effective apps that can be easily deployed across multiple platforms.</p>
</li>
<li><p><strong>Xamarin</strong>: A cross-platform mobile app development framework from Microsoft, Xamarin enables developers to build native iOS, Android, and Windows apps using a shared C# codebase. With access to native APIs and performance optimizations, Xamarin is an excellent choice for startups seeking to leverage the power and familiarity of the .NET ecosystem.</p>
</li>
</ul>
<p>By evaluating these languages and frameworks, you can choose the right combination for your startup's specific requirements. Considering factors such as platform support, performance, and development efficiency will help ensure the success of your mobile app in the competitive marketplace.</p>
<h2 id="heading-blockchain-development-languages-and-frameworks">Blockchain Development Languages And Frameworks</h2>
<p>Choosing the right language and framework for blockchain development plays a crucial role in ensuring robustness, security, and efficiency. Let’s look at some popular blockchain development languages and frameworks to guide you in selecting the most suitable ones for your startup.</p>
<p><strong>Popular blockchain development languages</strong>:</p>
<ul>
<li><p><strong>Solidity</strong>: A contract-oriented language specifically designed for developing smart contracts on Ethereum. It is best used for creating decentralized applications (DApps) and custom tokens looking to leverage the power and popularity of the Ethereum network.</p>
</li>
<li><p><strong>Vyper</strong>: A security-focused language for writing Ethereum smart contracts. Vyper prioritizes simplicity and audibility, making it ideal for creating secure and easy-to-understand contracts.</p>
</li>
<li><p><strong>Rust</strong>: A fast, reliable, and safe systems language, Rust is becoming increasingly popular in the blockchain space. Its memory safety features make it suitable for creating secure, high-performance blockchain platforms.</p>
</li>
<li><p><strong>C++</strong>: As a high-performance language, C++ is used in the development of various blockchain platforms, such as Bitcoin and Ethereum. Its versatility and efficiency make it ideal for creating resource-intensive blockchain applications.</p>
</li>
<li><p><strong>C#</strong>: A popular language in the Microsoft ecosystem, C# is often used to build blockchain applications on platforms like Stratis and NEO.</p>
</li>
<li><p><strong>JavaScript</strong>: A versatile language used for various blockchain applications, JavaScript can be utilized for developing DApps and interacting with blockchain platforms through APIs and libraries.</p>
</li>
<li><p><strong>Python</strong>: Known for its simplicity and readability, Python is widely used for creating blockchain prototypes and interacting with blockchain networks.</p>
</li>
<li><p><strong>Golang</strong>: A modern language developed by Google, Golang offers excellent performance and simplicity. It is used for creating high-performance blockchain platforms like Cosmos and Tendermint.</p>
</li>
<li><p><strong>Java</strong>: A versatile and popular language, Java is used for developing blockchain applications on platforms like Corda and Hyperledger Fabric.</p>
</li>
</ul>
<p>Although JavaScript, Python, Golang and Java were not designed specifically for blockchain, they have been used to write blockchain and smart contract code, primarily due to their versatility, large developer communities, and the availability of supporting libraries.</p>
<p><strong>Popular blockchain development frameworks</strong>:</p>
<ul>
<li><p><strong>Ethereum</strong>: The leading smart contract platform, Ethereum enables developers to create decentralized applications using Solidity or Vyper. It has a large developer community and extensive resources.</p>
</li>
<li><p><strong>Hyperledger Fabric</strong>: A permissioned, modular blockchain platform that supports smart contracts in multiple languages like JavaScript, Go, and Java. It is suitable for building private, enterprise-grade blockchain solutions.</p>
</li>
<li><p><strong>Hyperledger Sawtooth</strong>: A highly modular and scalable platform for building, deploying, and running distributed ledgers. Sawtooth supports smart contracts in various languages through its "Seth" framework.</p>
</li>
<li><p><strong>Corda</strong>: A permissioned, distributed ledger platform designed for finance and other industries. Corda supports smart contracts in Java and Kotlin and focuses on privacy and interoperability.</p>
</li>
<li><p><strong>Quorum</strong>: A permissioned, Ethereum-based blockchain platform tailored for enterprise use cases, offering enhanced privacy and performance. It supports Ethereum's smart contract languages, Solidity and Vyper.</p>
</li>
<li><p><strong>Hardhat</strong>: A JavaScript development environment and task runner for Ethereum, Hardhat simplifies smart contract development and testing. It is particularly useful for creating and deploying Solidity-based projects.</p>
</li>
<li><p><strong>Cosmos</strong>: A scalable, interoperable blockchain ecosystem built on Tendermint and powered by Golang. Cosmos enables developers to build custom, high-performance blockchains with a focus on interoperability.</p>
</li>
</ul>
<p>When selecting a language and framework for blockchain development, consider your startup's specific needs, such as the desired network (permissioned vs permissionless), required transaction speed and privacy, and the language expertise of your development team. The right choice will enable you to leverage the transformative power of blockchain technology effectively.</p>
<h2 id="heading-migrating-between-languages-and-frameworks">Migrating Between Languages And Frameworks</h2>
<p>Although startups generally aim to select the most suitable programming languages and frameworks at the outset, there might be scenarios where migration becomes necessary. This section discusses such scenarios, strategies for a smooth migration process, and potential risks and challenges associated with migration.</p>
<p>It might be necessary for a startup to consider migrating from one programming language or framework to another in scenarios such as:</p>
<ul>
<li><p>Business requirements change, necessitating the adoption of a more appropriate language or framework.</p>
</li>
<li><p>A newer technology emerges, offering more efficient solutions, better performance, or enhanced scalability.</p>
</li>
<li><p>An existing language or framework loses community support or deprecates, making maintenance and updates difficult.</p>
</li>
</ul>
<p>When a startup encounters any of these scenarios, and they have come to a conclusion that migrating is necessary, here are some strategies that can be employed to effectively migrate from the current programming language or frameworks used to the new ones:</p>
<ul>
<li><p><strong>Plan</strong>: Conduct thorough research to identify the best target language or framework for your startup's needs. Create a detailed migration plan, including timeframes, milestones, and resource allocation.</p>
</li>
<li><p><strong>Divide and Conquer</strong>: Break down the migration into smaller, manageable tasks. Focus on core functionality first and prioritize tasks based on their criticality.</p>
</li>
<li><p><strong>Backup Data</strong>: Ensure data integrity throughout the migration process by creating backups, validating data structures, and thoroughly testing data migration procedures.</p>
</li>
<li><p><strong>Train the Team</strong>: Provide necessary training for your development team to familiarize them with the new language or framework. This will ensure a smooth transition and reduce downtime.</p>
</li>
<li><p><strong>Continuous Integration and Deployment</strong>: Adopt CI/CD practices to monitor and catch errors early, ensuring the migration process remains on track.</p>
</li>
</ul>
<p>Even while using the best strategies, there are some potential risks startups should look out for like:</p>
<ul>
<li><p><strong>Codebase break</strong>: Migrating to a new language or framework might result in some features becoming inoperable. Thorough testing can help identify and resolve such issues.</p>
</li>
<li><p><strong>Technical debt</strong>: Migration can potentially create technical debt if not planned and executed correctly. Avoid shortcuts, and allocate adequate resources to address migration-related tasks.</p>
</li>
<li><p><strong>Downtime</strong>: Migrating to a new language or framework might cause downtime during deployment, impacting your users and business operations. Plan the migration carefully to minimize downtime and disruptions.</p>
</li>
</ul>
<p>While migrating between languages and frameworks can be a complex undertaking, a well-planned and executed strategy can ensure a smooth transition and help your startup continue</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we have explored the complex process of choosing the right programming language and framework for your startup. We discussed the importance of understanding frontend, backend, mobile app, and blockchain development languages and frameworks, along with their respective use cases. We also covered the selection criteria, such as team strength, time to market, open-source resources, industry standards, and scalability.</p>
<p>As you consider your options, remember that the choice of programming language and framework should align with your startup's specific needs and goals. This decision has long-term implications for your project's success, so it's crucial to thoroughly analyze your options before making a commitment.</p>
<p>Lastly, the world of technology is constantly evolving. It's vital to stay up-to-date with industry trends and regularly evaluate your chosen technology stack. This will ensure that your startup remains competitive, flexible, and ready to adapt to new challenges and opportunities.</p>
<p>Now it's time to take action – begin by researching different languages and frameworks, and consult with your team to make the best choice for your startup. Remember, the success of your business depends on building a solid foundation with the right technology stack.</p>
]]></content:encoded></item><item><title><![CDATA[Infrastructure Automation: How To Streamline Your Deployment Process]]></title><description><![CDATA[Introduction
In today's fast-paced digital world, businesses, from startups to enterprise-level organizations, need to improve their efficiency and speed to market. A crucial area that significantly impacts a company's ability to achieve this goal is...]]></description><link>https://blog.wolzcodelife.com/infrastructure-automation-how-to-streamline-your-deployment-process</link><guid isPermaLink="true">https://blog.wolzcodelife.com/infrastructure-automation-how-to-streamline-your-deployment-process</guid><category><![CDATA[Devops]]></category><category><![CDATA[infrastructure]]></category><category><![CDATA[automation]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Sun, 29 Jun 2025 23:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1758745206647/685b1a92-0353-46fb-9d32-e375307d4ca0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction"><strong>Introduction</strong></h3>
<p>In today's fast-paced digital world, businesses, from startups to enterprise-level organizations, need to improve their efficiency and speed to market. A crucial area that significantly impacts a company's ability to achieve this goal is the management of its IT infrastructure. This is where infrastructure automation comes into play - the process of automating the deployment, configuration, and management of infrastructure components, such as servers, networks, and storage.</p>
<p>By leveraging automation tools, companies can achieve a streamlined deployment process that is faster, more reliable, and less prone to errors. For example, consider a software development team that needs to deploy a new application to a production environment. With infrastructure automation, they can quickly and easily spin up new servers, configure the necessary networking components, and deploy the application - all without the need for manual intervention.</p>
<p>The benefits of infrastructure automation are clear - increased efficiency, faster time to market, and improved reliability. In this article, we will delve deeper into the topic of infrastructure automation, exploring the various tools and techniques available, as well as providing practical guidance on how to implement automation within your organization. </p>
<p>In this article, we will explore the benefits of infrastructure automation and provide a practical guide on how to implement it in your organization. We will discuss the prerequisites for implementing infrastructure automation, tools and technologies for automation, and best practices for successful implementation. By the end of this article, you will have a better understanding of infrastructure automation and how it can help your business achieve greater efficiency and productivity.</p>
<h2 id="heading-prerequisite"><strong>Prerequisite</strong></h2>
<p>To effectively follow through with this article, the prerequisites below are recommended:</p>
<ul>
<li><p><strong>Basic knowledge of infrastructure and deployment processes</strong>: Before implementing infrastructure automation, it is important to have a basic understanding of how infrastructure works and the deployment process. This knowledge will help in identifying the areas of the deployment process that can be automated. It will also help in determining the best automation tools to use.</p>
</li>
<li><p><strong>Familiarity with configuration management tools</strong>: Configuration management tools are essential in implementing infrastructure automation. These tools are used to manage and automate the configuration of servers and other infrastructure components. Familiarity with these tools is necessary to effectively automate the deployment process. Some of the popular configuration management tools include Ansible, Chef, and Puppet.</p>
</li>
<li><p><strong>A clear understanding of the infrastructure components to be automated</strong>: A clear understanding of the infrastructure components to be automated is necessary to ensure that the automation process is successful. It is important to identify the components that can be automated and those that cannot. This will help in determining the scope of the automation process and ensure that the process is efficient and effective.</p>
</li>
</ul>
<h2 id="heading-what-is-infrastructure-automation"><strong>What is Infrastructure Automation?</strong></h2>
<p>Infrastructure automation refers to the use of software tools and processes to automate the management and deployment of IT infrastructure. This includes servers, databases, storage, networking, and other components that make up an organization's IT environment. The goal of infrastructure automation is to reduce the amount of time and effort required to manage and deploy infrastructure while improving reliability and consistency.</p>
<p>In modern software development, infrastructure automation is crucial for several reasons. As organizations move towards more agile and DevOps-focused methodologies, they need to be able to quickly and efficiently deploy infrastructure changes to keep up with the pace of development. Infrastructure automation can help facilitate this by automating tasks such as server configuration, network setup, and database provisioning.</p>
<h2 id="heading-tools-for-infrastructure-automation"><strong>Tools for Infrastructure Automation</strong></h2>
<p>There are numerous tools available for infrastructure automation, ranging from open source to commercial solutions, each with its own unique features and capabilities. These tools allow for the creation, deployment, and management of infrastructure as code, enabling organizations to streamline their deployment processes and ensure consistency across environments.</p>
<p><img src="https://io.dropinblog.com/uploaded/blogs/34251246/files/infrastructure-automation-how-to-streamline-your-deployment-process-j8aaw.png" alt /></p>
<p>Some of the most popular free modern tools for infrastructure automation include:</p>
<ul>
<li><p><a target="_blank" href="https://www.ansible.com/"><strong>Ansible</strong></a>: An open-source automation tool that simplifies complex IT tasks, such as configuration management, application deployment, and orchestration. Ansible uses a human-readable language called YAML to define automation scripts (playbooks) and relies on an agentless architecture, which eliminates the need for additional software on managed nodes.</p>
</li>
<li><p><a target="_blank" href="https://www.terraform.io/"><strong>Terraform</strong></a>: An Infrastructure as Code (IaC) tool that enables you to define and provision infrastructure using a declarative configuration language (HCL). Terraform supports multiple cloud providers such as AWS, Azure, and GCP, and allows you to manage resources in a consistent and reproducible manner, promoting collaboration and reducing manual errors.</p>
</li>
<li><p><a target="_blank" href="https://www.jenkins.io/"><strong>Jenkins</strong></a>: An open-source automation server that facilitates continuous integration and continuous delivery (CI/CD). With its extensive plugin ecosystem, Jenkins can be customized to support various DevOps practices and integrates with numerous tools and services to streamline the software delivery process.</p>
</li>
<li><p><a target="_blank" href="https://www.puppet.com/"><strong>Puppet</strong></a>: A configuration management tool that automates the provisioning, configuration, and management of servers. Puppet uses declarative language to define the desired state of your infrastructure and ensures consistency by enforcing the desired state across your environment.</p>
</li>
<li><p><a target="_blank" href="https://circleci.com/"><strong>CircleCI</strong></a>: A cloud-based CI/CD platform that supports many programming languages and frameworks. With its fast build times, scalable infrastructure, and flexible workflows, CircleCI helps automate the software delivery process, reducing manual errors and accelerating deployment.</p>
</li>
<li><p><a target="_blank" href="https://www.docker.com/products/docker-desktop/"><strong>Docker</strong></a>: A containerization platform that packages applications and their dependencies into a standardized unit called a container. Docker enables consistent and portable environments for running applications across different machines and operating systems, simplifying deployment and management.</p>
</li>
<li><p><a target="_blank" href="https://github.com/"><strong>GitHub</strong></a>: A web-based platform for version control and collaboration using Git. It provides a centralized repository for code, enabling teams to collaborate, track changes, and review code efficiently. GitHub also offers features such as issue tracking, project management, and integrations with other tools and services.</p>
</li>
<li><p><a target="_blank" href="https://www.chef.io/products/chef-infrastructure-management#implementing-and-using"><strong>Chef</strong></a>: A configuration management tool that allows for the automation of infrastructure deployment and management. Chef provides a flexible and powerful platform for managing infrastructure as code and can be used to manage both on-premises and cloud-based environments.</p>
</li>
<li><p><a target="_blank" href="https://kubernetes.io/"><strong>Kubernetes</strong></a>(K8s): A container orchestration platform that automates the deployment, scaling, and management of containerized applications. With features like automatic load balancing, horizontal scaling, and self-healing, Kubernetes is a powerful solution for managing complex, containerized applications. </p>
</li>
<li><p><a target="_blank" href="https://www.openstack.org/"><strong>OpenStack</strong></a>: An open-source cloud computing platform that provides Infrastructure as a Service (IaaS) for building and managing public and private clouds. OpenStack offers a modular architecture, making it highly customizable and extensible to fit various use cases.</p>
</li>
<li><p><a target="_blank" href="https://saltproject.io/"><strong>SaltStack</strong></a>: An automation and configuration management tool that uses a remote execution model and a declarative language (YAML) to manage infrastructure. SaltStack is known for its speed and scalability, enabling you to manage thousands of servers simultaneously.</p>
</li>
<li><p><a target="_blank" href="https://www.pulumi.com/"><strong>Pulumi</strong></a>: An Infrastructure as Code (IaC) platform that allows you to define, deploy, and manage cloud resources using familiar programming languages, such as Python, TypeScript, and Go. Pulumi enables seamless integration with existing development workflows, enhancing collaboration and code reusability.</p>
</li>
<li><p><a target="_blank" href="https://www.packer.io/"><strong>Packer</strong></a>: An open-source tool for creating identical machine images across multiple platforms from a single source configuration. Packer supports popular virtualization and cloud platforms such as Amazon EC2, Google Compute Engine, and Docker, allowing you to build images for different platforms and environments. By automating the creation of machine images, Packer helps ensure consistency and reduce deployment times.</p>
</li>
</ul>
<p>By understanding the unique features of each tool, decision-makers and influencers can make informed choices when selecting the right tool for their specific needs. Whether it's configuration management, containerization, or Infrastructure as Code, these tools provide the means to enhance speed, agility, code quality, and efficiency in modern software development practices.</p>
<h2 id="heading-using-docker-for-infrastructure-automation"><strong>Using Docker for Infrastructure Automation</strong></h2>
<p>Let's consider a practical example of a developer that needs to deploy a Node.js application to multiple servers in different environments. Traditionally, this process involves manually configuring each server, which is a time-consuming and error-prone task. However, with infrastructure automation, this process can be streamlined, and deployments can be made more efficient.</p>
<p>To implement infrastructure automation in this scenario, the first step is to select the right tool for the job. Depending on the specific needs of the organization, tools like Ansible, Jenkins, Docker, Kubernetes, and Puppet can be used to automate the deployment process.</p>
<p>Let's take the example of a Node.js application. In this scenario, we can use a tool like Docker for infrastructure automation. To create a plan for automation implementation, we need to identify the tasks that can be automated. These may include creating a new server instance, configuring the server, installing dependencies, deploying the application code, and starting the application server.</p>
<p>With Docker, we can easily manage our infrastructure by defining our infrastructure as code. Any changes to our infrastructure can be made in code and deployed automatically, reducing the risk of human error.</p>
<p>It uses a simple and easy-to-learn scripting language to automate tasks such as configuration management, application deployment, and infrastructure orchestration.</p>
<p>To begin with, we need to ensure that <a target="_blank" href="https://docs.docker.com/get-docker/">Docker is installed on our system</a>. Docker can be installed on various operating systems like Linux, macOS, and Windows. Once Docker is installed, we can proceed with the following steps:</p>
<ol>
<li><strong>Create your Node.js project, and install the necessary libraries:</strong> You can either use a boilerplate or manually create your project structure using the command:</li>
</ol>
<pre><code class="lang-plaintext">npm init
</code></pre>
<p>Follow the prompt in your terminal, till the project is set up with a “package.json” file. In this article, we would have a simple Node.js application with the following code in our “index.js” file:</p>
<pre><code class="lang-plaintext">const http = require('http');

const hostname = '0.0.0.0';
const port = 3000;

const server = http.createServer((req, res) =&gt; {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello, World!\n');
});

server.listen(port, hostname, () =&gt; {
  console.log(`Server running at http://${hostname}:${port}/`);
});
</code></pre>
<p>This code creates a simple HTTP server that listens on port 3000 and responds with "Hello, World!" to any incoming requests. Once you have built and run your Docker container, you can access this server by visiting http://localhost:3000 in your web browser or by using a tool like cURL to make a request to the server from the command line:</p>
<pre><code class="lang-plaintext">curl http://localhost:3000
</code></pre>
<p>You can run the following command to start the server:</p>
<pre><code class="lang-plaintext">node index.js
</code></pre>
<p>If everything is working correctly, you should see "Server running at http://0.0.0.0:3000/" printed in the terminal or “Hello, World!” in the response body. Here is a test using Postman:</p>
<p><strong>2. Create a Dockerfile in the working directory of your project</strong>: A Dockerfile is a script that contains instructions for building a Docker image. We will use a Dockerfile to define the environment for our Node.js application.<br />Create a file named “Dockerfile in the working directory of your Node.js application so that your project structure looks something like this:</p>
<p><img src="https://io.dropinblog.com/uploaded/blogs/34251246/files/infrastructure-automation-how-to-streamline-your-deployment-process-ukfjy.png" alt /></p>
<p>Here's an example of a simple Dockerfile that installs Node.js and copies our application files into the container: </p>
<pre><code class="lang-plaintext"># Use an official Node.js runtime as a parent image
FROM node:14

# Set the working directory in the container to /app
WORKDIR /app

# Copy the package.json and package-lock.json files to the container
COPY package*.json ./

# Install the dependencies
RUN npm install

# Copy the rest of the application files to the container
COPY . .

# Expose port 3000 to the host
EXPOSE 3000

# Start the application
CMD ["node", "index.js"]
</code></pre>
<p>The Dockerfile defines a base image, sets a working directory, installs our application dependencies, copies our application files into the container, exposes <code>port 3000</code>, and starts our application.</p>
<p><strong>3. Build a Docker image</strong>: Once we have defined our Dockerfile, we can use the Docker build command to build a Docker image. This command takes the name of the image and the path to the Dockerfile as arguments. Here's an example command:</p>
<pre><code class="lang-plaintext">docker build -t my-node-app .
</code></pre>
<p>This command will build a Docker image with the name my-node-app and you should find your Docker image in the Docker Console/Desktop just like mine below:</p>
<p><img src="https://io.dropinblog.com/uploaded/blogs/34251246/files/infrastructure-automation-how-to-streamline-your-deployment-process-jxlsr.png" alt /></p>
<p><strong>4. Run a Docker container</strong>: Once we have built a Docker image, we can use the Docker run command to run a Docker container. This command takes the name of the image as an argument. Here's an example command:</p>
<pre><code class="lang-plaintext">docker run -p 3000:3000 my-node-app
</code></pre>
<p>This command will run a Docker container with the name my-node-app and expose <code>port 3000</code>. You would see that the Node server starts and is running on port “3000” or whatever port you set it to just as below:</p>
<p><img src="https://io.dropinblog.com/uploaded/blogs/34251246/files/infrastructure-automation-how-to-streamline-your-deployment-process-wpnph.png" alt /></p>
<p><strong>5. Test the deployment</strong>: After the Docker container has been started, it's important to test the deployment to ensure that it was successful. This can be done by accessing the server and verifying that the Node.js express API is serving.</p>
<p>You can start the server address in the browser, terminal(using cURL), or Postman. In my browser, I got this result:</p>
<p><img src="https://io.dropinblog.com/uploaded/blogs/34251246/files/infrastructure-automation-how-to-streamline-your-deployment-process-6siqq.png" alt /></p>
<p><strong>6. Update the Dockerfile</strong>: As the deployment environment changes over time, it's important to update the Dockerfile to reflect these changes. We can modify the Dockerfile to install new dependencies, configure the environment, and perform other tasks.</p>
<h2 id="heading-best-practices-for-infrastructure-automation"><strong>Best Practices for Infrastructure Automation</strong></h2>
<p>Adopting best practices for infrastructure automation is critical for ensuring the efficient and effective delivery of applications. If best practices are not followed, the consequences can be significant. For example, if automation scripts are not properly tested and validated, there is a risk of unintended consequences, such as outages, data loss, and security breaches. </p>
<p>Let’s discuss four key areas of infrastructure automation and a list of dos and don'ts for each area:</p>
<h3 id="heading-version-control-and-configuration-management">Version Control and Configuration Management</h3>
<p>Version control and configuration management are critical aspects of infrastructure automation. They ensure that changes to your infrastructure are tracked, and configurations are consistently applied across your environment.</p>
<h4 id="heading-dos">Do(s):</h4>
<ul>
<li><p>Use a version control system like Git to track and manage changes to your infrastructure code.</p>
</li>
<li><p>Implement a configuration management tool like Ansible, Puppet, or Chef to manage infrastructure configurations.</p>
</li>
<li><p>Regularly review and update your configuration management policies to ensure they remain relevant and effective.</p>
</li>
</ul>
<h4 id="heading-donts">Don't(s):</h4>
<ul>
<li><p>Avoid using manual processes or ad-hoc scripts to manage infrastructure configurations.</p>
</li>
<li><p>Don't ignore the importance of documenting changes to your infrastructure code and configurations.</p>
</li>
<li><p>Avoid overcomplicating your configuration management policies, as this can make them difficult to understand and maintain.</p>
</li>
</ul>
<h3 id="heading-continuous-integration-and-continuous-deployment-cicd">Continuous Integration and Continuous Deployment (CI/CD)</h3>
<p>Implementing a CI/CD pipeline can significantly enhance your infrastructure automation efforts by automating the testing, integration, and deployment of infrastructure changes.</p>
<h4 id="heading-dos-1">Do(s):</h4>
<ul>
<li><p>Set up automated testing for your infrastructure code to catch issues before they reach production.</p>
</li>
<li><p>Implement a CI/CD pipeline using tools like Jenkins, GitLab CI, or CircleCI.</p>
</li>
<li><p>Monitor and optimize your CI/CD pipeline to identify bottlenecks and areas for improvement.</p>
</li>
</ul>
<h4 id="heading-donts-1">Don't(s):</h4>
<ul>
<li><p>Don't skip automated testing or rely solely on manual testing for your infrastructure code.</p>
</li>
<li><p>Avoid deploying infrastructure changes without proper testing and validation.</p>
</li>
<li><p>Don't ignore the need for continuous monitoring and optimization of your CI/CD pipeline.</p>
</li>
</ul>
<h3 id="heading-collaboration-and-cross-functional-teams">Collaboration and Cross-functional Teams</h3>
<p>Fostering collaboration and building cross-functional teams is essential for successful infrastructure automation initiatives.</p>
<h4 id="heading-dos-2">Do(s):</h4>
<ul>
<li><p>Encourage collaboration between development, operations, and other teams involved in infrastructure automation.</p>
</li>
<li><p>Use collaboration tools like Slack, Microsoft Teams, or Trello to streamline communication and information sharing.</p>
</li>
<li><p>Provide training and support for team members to develop the necessary skills for infrastructure automation.</p>
</li>
</ul>
<h4 id="heading-donts-2">Don't(s):</h4>
<ul>
<li><p>Don't operate in silos or allow teams to work independently without collaboration.</p>
</li>
<li><p>Avoid overloading team members with too many responsibilities, leading to burnout and reduced productivity.</p>
</li>
<li><p>Don't assume that team members possess all the necessary skills for infrastructure automation without offering proper training.</p>
</li>
</ul>
<h3 id="heading-monitoring-and-logging">Monitoring and Logging</h3>
<p>Effective monitoring and logging practices are crucial for maintaining the health and performance of your automated infrastructure.</p>
<h4 id="heading-dos-3">Do(s):</h4>
<ul>
<li><p>Implement comprehensive monitoring and logging for your infrastructure using tools like Prometheus, ELK Stack, or Datadog.</p>
</li>
<li><p>Set up meaningful alerts and notifications to proactively address potential issues.</p>
</li>
<li><p>Periodically review and analyze logs to identify patterns and trends that may indicate problems or opportunities for optimization.</p>
</li>
</ul>
<h4 id="heading-donts-3">Don't(s):</h4>
<ul>
<li><p>Don't rely solely on reactive monitoring or troubleshooting when issues arise.</p>
</li>
<li><p>Avoid setting up excessive alerts that can lead to alert fatigue and decreased responsiveness.</p>
</li>
<li><p>Don't neglect the importance of log analysis for continuous improvement and optimization of your infrastructure automation efforts.</p>
</li>
</ul>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Infrastructure automation is a critical aspect of modern IT operations and can have a significant impact on the efficiency, reliability, and security of your deployment process. Automation enables businesses to streamline their infrastructure management, reduce manual errors, and increase the speed of their deployments. By automating infrastructure, organizations can also improve their scalability and reduce their operational costs.</p>
<p>In conclusion, infrastructure automation should be implemented by all organizations. The benefits of automation are numerous and it's never too late to start automating your infrastructure; the process is much simpler than you might think. So, take the time to learn about the different automation tools and techniques available and start implementing them in your organization. The results will speak for themselves.</p>
]]></content:encoded></item><item><title><![CDATA[Exploring NoOps: Streamlining Operations in a Serverless Architecture]]></title><description><![CDATA[IT operations (ITOps) are continuously evolving and businesses are seeking solutions to streamline processes and adapt to industry standards.  ITOps have come a long way down to NoOps, yet there are still many complexities that can stifle innovation ...]]></description><link>https://blog.wolzcodelife.com/exploring-noops-streamlining-operations-in-a-serverless-architecture</link><guid isPermaLink="true">https://blog.wolzcodelife.com/exploring-noops-streamlining-operations-in-a-serverless-architecture</guid><category><![CDATA[serverless]]></category><category><![CDATA[architecture]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Wed, 30 Oct 2024 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1758749979836/c69dd283-5a8e-40ff-a06c-3ab0334d86d3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>IT operations (ITOps) are continuously evolving and businesses are seeking solutions to streamline processes and adapt to industry standards.  ITOps have come a long way down to NoOps, yet there are still many complexities that can stifle innovation and progress. </p>
<p>ITOps can be a maze packed with a series of puzzles. Legacy systems, sophisticated infrastructure designs, and a constant need for skilled professionals are just a few of the problems they face. These difficulties frequently limit their ability to quickly adjust to new technology and market demands, leading them to seek a better and more efficient solution.</p>
<p>This article will explore the fundamentals of NoOps and its application in a serverless architecture. After reading this article, you can make more informed decisions for your software development architecture.</p>
<p>So, without further ado, let's get started.</p>
<h2 id="heading-evolution-of-it-operations">Evolution of IT Operations</h2>
<p>The evolution of IT Operations has been a thrilling journey driven by the continuous pursuit of increased efficiency and adaptability in managing an organization's computing infrastructure.</p>
<p>ITOps has traditionally depended heavily on manual processes and dedicated professionals responsible for tasks such as:</p>
<ul>
<li><p><strong>Server Provisioning:</strong> Manually setting up, configuring, and deploying physical servers to meet the organization's computing needs. It was a time-consuming process that required careful planning.</p>
</li>
<li><p><strong>Configuration Management:</strong> Configuring servers and maintaining consistency across the infrastructure was a meticulous task. Any changes or updates required manual adjustments and often led to configuration drift.</p>
</li>
<li><p><strong>Software Deployment:</strong> Installing and updating software on servers was a manual operation, which posed challenges in terms of consistency, version control, and deployment speed.</p>
</li>
</ul>
<p>Over time, these approaches presented several challenges such as:</p>
<ul>
<li><p><strong>Complexity:</strong> As organizations grew, managing a diverse array of servers and configurations became complex, increasing the risk of errors and inefficiencies.</p>
</li>
<li><p><strong>Costs:</strong> Maintaining physical servers and data centers demanded substantial financial resources for procurement, maintenance, and infrastructure scaling, making it an expensive endeavor.</p>
</li>
<li><p><strong>Agility:</strong> Traditional ITOps models often struggled to keep up with the rapidly changing needs of the business and the market, leading to delays and missed opportunities.</p>
</li>
</ul>
<p>DevOps was introduced to address these issues. DevOps successfully addressed the challenges by providing enterprises with more streamlined, efficient, and responsive methods to manage their computing infrastructure, such as:</p>
<ul>
<li><p><strong>Automation:</strong> DevOps focuses on automating routine and repetitive operations, reducing manual effort and enhancing operational efficiency. Server provisioning, configuration, and software deployment are all automated, reducing errors and speeding up operations.</p>
</li>
<li><p><strong>Continuous Integration/Continuous Deployment (CI/CD):</strong> Pipelines for continuous integration and delivery (CI/CD) allow for faster testing, integration, and deployment of software changes into production environments. This strategy improves software release speed and reliability.</p>
</li>
<li><p><strong>Infrastructure as Code (IaC):</strong> Managing infrastructure with code allows resources to be provisioned and managed by version-controlled scripts. This approach improves infrastructure management by ensuring consistency, repeatability, and version tracking, making it more efficient and error-free.</p>
</li>
</ul>
<h2 id="heading-comparison-of-itops-devops-and-noops">Comparison of ITOps, DevOps, and NoOps</h2>
<p>To gain an in-depth understanding of the paradigm shifts in computing operations, it is crucial to compare and contrast the various techniques. Each of these techniques reflects a different stage in the history of infrastructure management, reflecting improvements in responsibility, automation, cost-effectiveness, and innovation capabilities. </p>
<p>The table below provides a detailed comparison between ITOps, DevOps, and NoOps, offering insight into how these techniques impact an organization's approach to IT infrastructure and operations.</p>
<table><tbody><tr><td><p>Aspect</p></td><td><p>ITOps</p></td><td><p>DevOps</p></td><td><p>NoOps</p></td></tr><tr><td><p>Operational Model</p></td><td><p>Manual infrastructure management</p></td><td><p>Collaboration between Dev and Ops</p></td><td><p>Outsourced infrastructure management</p></td></tr><tr><td><p>Responsibility</p></td><td><p>In-house teams handle operations</p></td><td><p>Shared responsibility</p></td><td><p>Shifted to cloud service provider or PaaS</p></td></tr><tr><td><p>Infrastructure Control</p></td><td><p>Full control over infrastructure</p></td><td><p>Control with automation and IaC</p></td><td><p>Limited control, mainly focused on application code</p></td></tr><tr><td><p>Automation</p></td><td><p>Limited automation of repetitive tasks</p></td><td><p>Extensive automation of tasks</p></td><td><p>Minimal infrastructure management, mainly application-focused</p></td></tr><tr><td><p>Deployment Speed</p></td><td><p>Slower due to manual processes</p></td><td><p>Faster due to CI/CD pipelines</p></td><td><p>Near-instant scaling and deployment</p></td></tr><tr><td><p>Costs</p></td><td><p>Significant infrastructure and personnel costs</p></td><td><p>Cost-effective automation</p></td><td><p>Cost-efficient with reduced infrastructure responsibilities</p></td></tr><tr><td><p>Flexibility</p></td><td><p>Limited scalability and adaptability</p></td><td><p>Improved agility and flexibility</p></td><td><p>High adaptability and rapid scalability</p></td></tr><tr><td><p>Resource Management</p></td><td><p>Manual provisioning and scaling</p></td><td><p>Infrastructure as Code (IaC)</p></td><td><p>Automatic provisioning and scaling</p></td></tr><tr><td><p>Human Intervention</p></td><td><p>High level of manual intervention</p></td><td><p>Reduced manual intervention</p></td><td><p>Minimal manual intervention in operations</p></td></tr><tr><td><p>Focusing on Innovation</p></td><td><p>Hindered by operational tasks</p></td><td><p>Frees up time for innovation</p></td><td><p>Enables a strong focus on innovation</p></td></tr></tbody></table>

<h2 id="heading-benefits-of-noops">Benefits of NoOps</h2>
<p>NoOps, the future of IT operations in a serverless world, provides an abundance of benefits that streamline operations and enhance productivity. Organizations can improve cost-effectiveness, scalability, and flexibility by cutting down the need for infrastructure management tasks and leveraging automation. </p>
<p>Here are some of the major advantages of implementing NoOps in serverless computing:</p>
<ol>
<li><p><strong>Efficiency and Cost-effectiveness:</strong> NoOps allows enterprises to devote more time and resources to providing value-added services rather than managing infrastructure. As a result, it improves operational efficiency while reducing expenses associated with traditional IT operations (ITOps).</p>
</li>
<li><p><strong>Elimination of Infrastructure Management Tasks:</strong> Organizations can use NoOps to shift their focus from managing servers and infrastructure to solving real problems. The underlying infrastructure can be handled by the cloud service provider, allowing developers to focus on developing creative solutions.</p>
</li>
<li><p><strong>Increased Scalability and Agility:</strong> NoOps leverages automation to streamline tasks such as resource provisioning, application scaling, and deployment management. This automation allows businesses to rapidly grow their applications in response to demand, ensuring optimal performance and responsiveness.</p>
</li>
</ol>
<p>By transitioning from traditional IT operations to NoOps in serverless computing, organizations can reap these benefits while embracing a more efficient and agile approach to software development and deployment.</p>
<h2 id="heading-getting-started-with-noops">Getting Started with NoOps</h2>
<p>To guarantee success, an organized plan has to be followed while transitioning from traditional IT operations to NoOps. To begin this journey, you have to assess your current infrastructure thoroughly. Here's how to get going:</p>
<h3 id="heading-assessing-current-infrastructure">Assessing Current Infrastructure</h3>
<p>Before venturing into NoOps, you must evaluate your current infrastructure. This evaluation involves a thorough examination of your present IT operations procedures and workflows to identify their suitability for a NoOps environment. Take special note of the following factors:</p>
<ul>
<li><p><strong>Dependency on Manual Tasks:</strong> Identify which processes, such as server provisioning and software updates, currently rely on manual intervention. Take note of these as suitable candidates for automation in a NoOps environment.</p>
</li>
<li><p><strong>Scalability Limitations:</strong> Check if your infrastructure can scale seamlessly to meet increased demands without requiring manual intervention. Scalability is a key component of NoOps and requires careful consideration.</p>
</li>
<li><p><strong>Resource Utilization:</strong> Examine the efficiency of your resource allocation. Find out whether resources are underutilized or overprovisioned. Strategic automation and optimization can help to eliminate any shortcomings.</p>
</li>
<li><p><strong>Monitoring and Observability:</strong> Evaluate the effectiveness of your current monitoring and observability capabilities. Robust monitoring is indispensable for timely issue detection and ensuring optimal performance within a serverless environment.</p>
</li>
</ul>
<h3 id="heading-identifying-areas-for-automation-and-optimization">Identifying Areas for Automation and Optimization</h3>
<p>Automation and optimization are essential in NoOps. After you've examined your infrastructure, concentrate on identifying specific locations that will benefit the most from the renovations. Think about the following:</p>
<ul>
<li><p><strong>Infrastructure Provisioning:</strong> By employing automation technologies like Terraform or AWS CloudFormation, you can speed up the provisioning of servers, containers, and other essential infrastructure components.</p>
</li>
<li><p><strong>Configuration Management:</strong> Automate the deployment and management of software configurations across your infrastructure using tools such as Ansible or Puppet.</p>
</li>
<li><p><strong>Deployment Pipelines:</strong> Implement continuous integration and continuous deployment (CI/CD) pipelines to automate the software release process. This can be facilitated through tools like Jenkins or GitLab CI/CD.</p>
</li>
<li><p><strong>Testing and Monitoring:</strong> Enhance reliability by automating the testing of your applications and infrastructure. Tools like Selenium or AWS CloudWatch are invaluable for early issue detection.</p>
</li>
</ul>
<h3 id="heading-choosing-the-right-tools-for-noops-implementation">Choosing the Right Tools for NoOps Implementation</h3>
<p>The choice of tools is pivotal to the success of your NoOps implementation. When selecting tools, consider the following factors:</p>
<ul>
<li><p><strong>Compatibility:</strong> Ensure the tools you select are compatible with your existing infrastructure and technology stack.</p>
</li>
<li><p><strong>Ease of Use:</strong> Opt for user-friendly tools with a low learning curve, enabling your team to swiftly adopt and implement them.</p>
</li>
<li><p><strong>Integration Capabilities:</strong> Assess how well the chosen tools integrate with other systems in your environment, particularly with regard to monitoring and deployment tools.</p>
</li>
<li><p><strong>Community Support:</strong> Consider the availability of active community support, thorough documentation, and ongoing development for the tools you choose.</p>
</li>
</ul>
<h3 id="heading-implementing-best-practices-for-successful-noops-transition">Implementing Best Practices for Successful NoOps Transition</h3>
<p>A smooth transition to NoOps hinges on adhering to best practices. These practices encompass:</p>
<ul>
<li><p><strong>Culture Shift:</strong> Cultivate a culture of automation and continuous improvement within your organization. Encourage collaboration between development and operations teams to drive innovation.</p>
</li>
<li><p><strong>Code Versioning:</strong> Enforce robust code versioning practices using platforms like Git or Bitbucket. This fosters efficient code management and simplifies collaboration among team members.</p>
</li>
<li><p><strong>Security and Compliance:</strong> Maintain a steadfast focus on security and compliance in a NoOps environment. Implement secure coding practices, stay vigilant in updating software dependencies, and proactively monitor for vulnerabilities.</p>
</li>
</ul>
<p>By meticulously assessing your infrastructure, identifying opportunities for automation and optimization, selecting the right tools, and implementing best practices, you can navigate the transition from traditional IT operations to NoOps with confidence. Embrace the advantages that NoOps offers in streamlining operations, and positioning your organization for the future of IT.</p>
<h2 id="heading-tools-for-noops-implementation">Tools for NoOps Implementation</h2>
<p>​​NoOps is an approach that aims to minimize or eliminate the need for traditional operations tasks in software development and deployment, emphasizing automation and self-service. While it doesn't create entirely "tool classes" on its own, NoOps relies on a combination of tools and practices to achieve its objectives.</p>
<p>These tools can generally be categorized into a few classes:</p>
<ol>
<li><p><strong>Automation and Deployment Tools:</strong></p>
<ul>
<li><p><strong>Continuous Integration/Continuous Deployment (CI/CD) Tools:</strong> These tools automate the building, testing, and deployment of software, ensuring a streamlined and efficient release process. Examples include Jenkins, Travis CI, and CircleCI.</p>
</li>
<li><p><strong>Infrastructure as Code (IaC) Tools:</strong> IaC tools like Terraform and Ansible enable the automated provisioning and management of infrastructure, treating it as code.</p>
</li>
<li><p><strong>Containerization and Orchestration Tools:</strong> Tools like Docker and Kubernetes automate the deployment and scaling of containerized applications.</p>
</li>
<li><p><strong>Serverless Frameworks:</strong> Serverless platforms like AWS Lambda and Azure Functions automate infrastructure management and scaling, allowing developers to focus on code.</p>
</li>
</ul>
</li>
<li><p><strong>Monitoring and Observability Tools:</strong></p>
<ul>
<li><p><strong>Monitoring Tools:</strong> Tools like Prometheus, Nagios, and Zabbix continuously track the performance and health of applications and infrastructure components.</p>
</li>
<li><p><strong>Log Management Tools:</strong> Platforms such as ELK Stack (Elasticsearch, Logstash, Kibana) and Splunk collect and analyze log data to provide insights into application behavior.</p>
</li>
<li><p><strong>AIOps Tools:</strong> These leverage artificial intelligence and machine learning to enhance monitoring and provide predictive analytics. Tools like Datadog and New Relic fall into this category.</p>
</li>
<li><p><strong>Tracing and Profiling Tools:</strong> Tools like Jaeger and Zipkin help trace requests and profile application performance for debugging and optimization.</p>
</li>
</ul>
</li>
<li><p><strong>Security and Compliance Tools:</strong></p>
<ul>
<li><p><strong>Security Scanning and Analysis Tools:</strong> Tools like OWASP ZAP and Nessus automate security testing, vulnerability scanning, and compliance checks.</p>
</li>
<li><p><strong>Policy as Code Tools:</strong> Policy as Code tools like Open Policy Agent (OPA) automate the enforcement of security and compliance policies.</p>
</li>
</ul>
</li>
<li><p><strong>Configuration Management Tools:</strong></p>
<ul>
<li><strong>Configuration Management Tools:</strong> Tools like Puppet, Chef, and SaltStack automate configuration management and ensure consistency across infrastructure.</li>
</ul>
</li>
<li><p><strong>Self-Service Tools:</strong></p>
<ul>
<li><strong>Self-Service Portals:</strong> These tools allow developers to self-service their infrastructure and application needs, reducing the dependency on traditional operations teams.</li>
</ul>
</li>
<li><p><strong>ChatOps Tools:</strong></p>
<ul>
<li><strong>ChatOps Platforms:</strong> Tools like Slack and Microsoft Teams enable automation through chat interfaces, facilitating collaboration and actions from within chat.</li>
</ul>
</li>
</ol>
<p>NoOps doesn't mean eliminating operations but rather automating and streamlining operations to the extent that developers can manage much of the process independently. It's essential to select and configure the right combination of tools to align with the NoOps approach and achieve its goals.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>NoOps is changing the way IT operations are done in a serverless world. By getting rid of the need for managing infrastructure and automating processes, organizations can make their operations more efficient.</p>
<p>In summary, here are the main benefits of using NoOps:</p>
<ol>
<li><p>Streamlined operations: NoOps makes IT operations simpler and faster, so teams can focus on providing value instead of dealing with infrastructure.</p>
</li>
<li><p>Improved scalability and flexibility: Automation allows organizations to easily expand their applications and adapt quickly to new business requirements.</p>
</li>
<li><p>Cost savings: With NoOps, organizations can save money on managing and maintaining infrastructure.</p>
</li>
</ol>
<p>You should consider implementing NoOps in your organization. By embracing this approach, you can make your operations better, increase productivity, and stay ahead in today's quickly changing digital landscape.</p>
<p>Take action now and start your NoOps journey. Embrace automation, follow best practices, and use the benefits of serverless computing to drive innovation and success in your organization.</p>
]]></content:encoded></item><item><title><![CDATA[Getting Started With Kubernetes: An Introduction To K8S]]></title><description><![CDATA[Managing containerized applications at scale can be a formidable challenge. As your infrastructure expands, ensuring availability, scalability, and fault tolerance grows increasingly intricate. Enter Kubernetes, the solution to these complexities.
Ku...]]></description><link>https://blog.wolzcodelife.com/getting-started-with-kubernetes-an-introduction-to-k8s</link><guid isPermaLink="true">https://blog.wolzcodelife.com/getting-started-with-kubernetes-an-introduction-to-k8s</guid><category><![CDATA[Kubernetes]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Wed, 02 Oct 2024 23:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1758747938656/1973b207-4add-4180-b83e-3573474a6516.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Managing containerized applications at scale can be a formidable challenge. As your infrastructure expands, ensuring availability, scalability, and fault tolerance grows increasingly intricate. Enter Kubernetes, the solution to these complexities.</p>
<p>Kubernetes simplifies container management through automated deployment, scaling, and monitoring across a node cluster. Its robust features and flexible architecture enable developers to focus on application development, rather than infrastructure concerns.</p>
<p>While alternatives like Docker Swarm and Apache Mesos exist, Kubernetes has risen as the container orchestration industry standard. Boasting an extensive ecosystem, active community support, and seamless integration with DevOps tools, Kubernetes stands out as the optimal choice for modern application deployment.</p>
<p>This article dives deep into Kubernetes: its introduction, architecture, and components, giving you a solid understanding of how it works under the hood. After reading this article, you'll have a good foundation to harness Kubernetes' capabilities, elevating your DevOps expertise.</p>
<h2 id="heading-introduction-to-kubernetes">Introduction to Kubernetes</h2>
<p>Kubernetes is a cluster orchestration system that allows you to manage and deploy containerized applications at scale. It provides a platform for automating the deployment, scaling, and management of containerized applications. With Kubernetes, you can easily scale the deployment of your applications, update containerized applications seamlessly, and debug any issues that may arise.</p>
<p>Kubernetes Architecture and Components:</p>
<p>The architecture of Kubernetes consists of several key components that work together to create a robust and reliable container infrastructure. These components include:</p>
<ol>
<li><p>Master Node:</p>
<ul>
<li><p>The master node is responsible for managing the cluster and making all the decisions about scheduling and deploying applications.</p>
</li>
<li><p>It includes various components such as the API server, controller manager, scheduler, etc.</p>
</li>
</ul>
</li>
<li><p>Slave Nodes (Worker Nodes):</p>
<ul>
<li><p>The slave nodes, also known as worker nodes, are responsible for running the actual application workloads.</p>
</li>
<li><p>Each worker node runs multiple containers using container runtime engines such as Docker or Container.</p>
</li>
</ul>
</li>
<li><p>Pods:</p>
<ul>
<li><p>Pods are the smallest and most basic unit in Kubernetes.</p>
</li>
<li><p>A pod represents a single instance of a running process or application in the cluster.</p>
</li>
<li><p>It encapsulates one or more containers that are tightly coupled and share resources.</p>
</li>
</ul>
</li>
<li><p>Services:</p>
<ul>
<li><p>Services provide a stable network endpoint for accessing a set of pods.</p>
</li>
<li><p>They enable load balancing across multiple pods and allow for easy communication between different parts of your application.</p>
</li>
</ul>
</li>
<li><p>Deployments:</p>
<ul>
<li><p>Deployments provide a declarative way to manage application updates and rollbacks.</p>
</li>
<li><p>They ensure that a specified number of pod replicas are running at all times, making it easy to scale your application up or down.</p>
</li>
</ul>
</li>
</ol>
<p>Understanding the roles and responsibilities of these components is crucial for effectively deploying and managing applications in Kubernetes.</p>
<h2 id="heading-installation-and-setup">Installation and Setup</h2>
<p>To begin your journey with Kubernetes, it is essential to understand the basics of installation and setup. Here, we will explore different installation options for Kubernetes on both local computers and cloud platforms.</p>
<p>When choosing an installation type, several factors should be considered, such as ease of maintenance, security, control, and available resources. Some popular installation options are:</p>
<ol>
<li><p><a target="_blank" href="https://minikube.sigs.k8s.io/docs/start/"><strong>Minikube</strong></a>: If you want to set up a single-node Kubernetes cluster on your local machine for development or testing purposes, Minikube is an excellent choice. It provides a lightweight Kubernetes implementation that runs inside a virtual machine (VM) on your computer.</p>
</li>
<li><p><a target="_blank" href="https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/"><strong>Kubeadm</strong></a>: Kubeadm simplifies the process of setting up a production-ready Kubernetes cluster. It allows you to initialize cluster control-plane nodes and join worker nodes to the cluster effortlessly. Kubeadm is often used in combination with other tools like kubectl and kubelet.</p>
</li>
<li><p><strong>Managed Kubernetes Services</strong>: Cloud providers such as Google Cloud Platform (GCP), Amazon Web Services (AWS), and Microsoft Azure offer managed Kubernetes services like <a target="_blank" href="https://cloud.google.com/kubernetes-engine">Google Kubernetes Engine (GKE)</a>, <a target="_blank" href="https://aws.amazon.com/eks/">Amazon Elastic Kubernetes Service (EKS)</a>, and <a target="_blank" href="https://azure.microsoft.com/en-us/products/kubernetes-service#:~:text=What%20is%20AKS%3F,like%20health%20monitoring%20and%20maintenance.">Azure Kubernetes Service (AKS)</a>. These services abstract away the complexities of managing the underlying infrastructure, making it easier to deploy and scale your applications.</p>
</li>
</ol>
<p>Each installation option has its advantages and considerations, depending on your specific requirements. The <a target="_blank" href="https://kubernetes.io/docs/home/">official Kubernetes documentation</a> provides detailed step-by-step guides for each installation method, helping you get started quickly.</p>
<p>Remember that once you have set up your Kubernetes cluster, you can deploy containerized applications, scale deployments, update applications seamlessly, and debug any issues that may arise during runtime.</p>
<h2 id="heading-deploying-applications-with-kubernetes">Deploying Applications with Kubernetes</h2>
<p>In this section, we will explore the process of deploying applications using Pods, Services, and Deployments in Kubernetes. Let's dive in!</p>
<h3 id="heading-step-by-step-guide-on-deploying-an-application">Step-by-step guide on deploying an application</h3>
<ol>
<li><p><strong>Create a Pod</strong>: A Pod is the smallest deployable unit in Kubernetes, representing a single instance of a running process. To create a Pod, you define a YAML file that specifies the container image, resource requirements, and other configurations. Here's an example:  </p>
 <table><tbody><tr><td><p>apiVersion: v1<br />kind: Pod<br />metadata:<br />  name: my-pod<br />spec:<br />  containers:<br />  - name: my-container<br />    image: nginx<br />    ports:<br />    - containerPort: 80</p></td></tr></tbody></table>
</li>
<li><p>Create a Service: A Service enables networking and load balancing for Pods. It provides a stable IP address and DNS name to access the deployed application. To create a Service, you define another YAML file. Here's an example:  </p>
 <table><tbody><tr><td><p>apiVersion: v1<br />kind: Service<br />metadata:<br />  name: my-service<br />spec:<br />  selector:<br />    app: my-app<br />  ports:<br />  - protocol: TCP<br />    port: 80<br />    targetPort: 80<br />  type: LoadBalancer</p></td></tr></tbody></table>
</li>
<li><p>Create a Deployment: A Deployment manages the lifecycle of your application by ensuring the desired number of Pods are running and handling updates and rollbacks. To create a Deployment, you define yet another YAML file. Here's an example:  </p>
 <table><tbody><tr><td><p>apiVersion: apps/v1<br />kind: Deployment<br />metadata:<br />  name: my-deployment<br />spec:<br />  replicas: 3<br />  selector:<br />    matchLabels:<br />      app: my-app<br />  template:<br />    metadata:<br />      labels:<br />        app: my-app<br />    spec:<br />      containers:<br />      - name: my-container<br />        image: nginx<br />        ports:<br />        - containerPort: 80</p></td></tr></tbody></table>


</li>
</ol>
<h3 id="heading-methods-to-explore-and-interact-with-deployed-applications">Methods to explore and interact with deployed applications</h3>
<p>After deploying your application, you can interact with it in several ways:</p>
<ul>
<li><p><strong>kubectl commands</strong>: Use the kubectl command-line tool to view information about your Pods, Services, and Deployments. For example, you can run <code>kubectl get pods</code> to see the status of your Pods.</p>
</li>
<li><p><strong>Dashboard</strong>: Kubernetes provides a web-based user interface called the Dashboard. It allows you to manage and monitor your cluster and deployed applications visually.</p>
</li>
</ul>
<h3 id="heading-how-to-expose-a-deployed-application-publicly">How to expose a deployed application publicly</h3>
<p>To expose your deployed application publicly, you can use the Service resource with a type of LoadBalancer. This will automatically provision an external load balancer and assign it an external IP address. Here's an example:</p>
<table><tbody><tr><td><p>apiVersion: v1<br />kind: Service<br />metadata:<br />  name: my-service<br />spec:<br />  selector:<br />    app: my-app<br />  ports:<br />  - protocol: TCP<br />    port: 80<br />    targetPort: 80<br />  type: LoadBalancer</p></td></tr></tbody></table>

<p>Once the external IP address is assigned, you can access your application using that IP address.</p>
<h3 id="heading-scaling-updating-and-debugging-applications-in-kubernetes">Scaling, Updating, and Debugging Applications in Kubernetes</h3>
<p>In the previous section, we discussed how to deploy applications using Pods, Services, and Deployments in Kubernetes. Now, let's explore how to scale, update, and debug containerized applications in Kubernetes.</p>
<h4 id="heading-scaling-deployments">Scaling Deployments</h4>
<p>One of the key benefits of using Kubernetes is its ability to scale deployments easily. To scale deployment in Kubernetes, you can use the kubectl scale command. Here's an example:</p>
<table><tbody><tr><td><p>kubectl scale deployment my-deployment --replicas=3</p></td></tr></tbody></table>

<p>This command scales the my-deployment deployment to have three replicas. Kubernetes will automatically distribute these replicas across available nodes in the cluster.</p>
<h4 id="heading-updating-containerized-applications">Updating Containerized Applications</h4>
<p>Updating containerized applications in Kubernetes can be done through rolling updates. With rolling updates, you can update your application without downtime by gradually replacing old instances with new ones. The process is managed by updating the deployment's image version.</p>
<p>To perform a rolling update, you can use the kubectl set image command. Here's an example:</p>
<table><tbody><tr><td><p>kubectl set image deployment/my-deployment my-container=my-image:v2</p></td></tr></tbody></table>

<p>This command updates the image version of the my-container container in the my-deployment deployment to <code>my-image:v2</code>. Kubernetes will automatically handle the rolling update process, ensuring a smooth transition between versions.</p>
<h4 id="heading-debugging-containerized-applications">Debugging Containerized Applications</h4>
<p>Debugging containerized applications in Kubernetes can be done through various approaches. One common method is to use logging and monitoring tools provided by Kubernetes. You can access logs for containers using the kubectl logs command. For example:</p>
<table><tbody><tr><td><p>kubectl logs pod/my-pod</p></td></tr></tbody></table>

<p>This command retrieves the logs for the my-pod pod. You can also use labels and selectors to retrieve logs for multiple pods simultaneously.</p>
<p>Additionally, Kubernetes provides debugging facilities like exec into a container or attaching a debugging container to a running pod. These options allow you to troubleshoot and diagnose issues within your containerized applications effectively.</p>
<h2 id="heading-kubernetes-features-and-comparison-with-docker-swarm">Kubernetes Features and Comparison with Docker Swarm</h2>
<p>Kubernetes is a powerful cluster orchestration system that enables efficient management of containerized applications. With its robust architecture and rich feature set, Kubernetes has become the de facto standard for container orchestration in the software development industry.</p>
<p>Key Features of Kubernetes:</p>
<ul>
<li><p><strong>Scalability</strong>: Kubernetes provides seamless scaling of deployments, allowing applications to handle increased workload without downtime or performance degradation. It automatically adjusts resources based on demand, ensuring optimal utilization and efficient resource allocation.</p>
</li>
<li><p><strong>High Availability</strong>: Kubernetes ensures high availability by automatically managing failures and distributing workloads across multiple nodes. It continuously monitors the health of containers and restarts them if necessary, reducing downtime and increasing overall reliability.</p>
</li>
<li><p><strong>Self-healing</strong>: Kubernetes automatically detects and replaces failed containers or nodes. It also provides replica sets and readiness probes to maintain the desired state of applications, making sure they are always up and running as intended.</p>
</li>
<li><p><strong>Rolling Updates</strong>: Kubernetes supports rolling updates, enabling seamless deployment of new versions of containerized applications without service interruption. It gradually replaces old instances with new ones, ensuring smooth transitions and minimizing user impact.</p>
</li>
</ul>
<h4 id="heading-comparison-with-docker-swarm">Comparison with Docker Swarm</h4>
<p>While Docker Swarm is another popular cluster orchestration system, there are some notable differences between Kubernetes and Docker Swarm:</p>
<ul>
<li><p><strong>Architecture</strong>: Kubernetes follows a more complex architecture with a master node responsible for managing the cluster and multiple slave nodes where containers run. On the other hand, Docker Swarm has a simpler architecture with manager nodes that control worker nodes.</p>
</li>
<li><p><strong>Scalability</strong>: Kubernetes provides more advanced features for scaling applications, such as auto-scaling based on metrics like CPU usage or custom metrics. Docker Swarm offers basic scaling capabilities but lacks some of the advanced features provided by Kubernetes.</p>
</li>
<li><p><strong>Community Support</strong>: Kubernetes has a larger community and ecosystem compared to Docker Swarm. This means that there are more resources, tools, and integrations available for Kubernetes users.</p>
</li>
</ul>
<p>Both Kubernetes and Docker Swarm have their strengths and are suitable for different use cases. The choice between them depends on factors such as the complexity of the application, scalability requirements, and the level of community support needed.</p>
<h2 id="heading-kubernetes-resources-for-beginners">Kubernetes Resources for Beginners</h2>
<p>When getting started with Kubernetes, it can be helpful to have access to resources that provide guidance and support. Whether you are new to Kubernetes or looking to expand your knowledge, there are plenty of tutorials, cheat sheets, and interview question resources available. Here are some recommendations for beginners learning Kubernetes:</p>
<ol>
<li><p><strong>Kubernetes Tutorials</strong>: Online tutorials are a great way to learn the basics of Kubernetes and understand its architecture and components. Some popular resources include:</p>
<ul>
<li><p><a target="_blank" href="https://kubernetes.io/docs/home/">Kubernetes Documentation</a>: The official documentation provides comprehensive guides and tutorials for all aspects of Kubernetes.</p>
</li>
<li><p><a target="_blank" href="http://kubernetesbyexample.com/">Kubernetes By Example</a>: This website offers practical examples and walkthroughs to help you grasp different concepts of Kubernetes.</p>
</li>
<li><p><a target="_blank" href="https://www.katacoda.com/courses/kubernetes">Katacoda</a>: Katacoda offers interactive scenarios where you can practice deploying applications on a live Kubernetes cluster.</p>
</li>
</ul>
</li>
<li><p><strong>Kubernetes Cheat Sheets</strong>: Cheat sheets can be handy references when you need quick information about a specific command or concept in Kubernetes. Some popular cheat sheets include:</p>
<ul>
<li><p><a target="_blank" href="https://kubernetes.io/docs/reference/kubectl/cheatsheet/">Kubectl Cheat Sheet</a>: This cheat sheet provides an overview of common kubectl commands used to interact with a Kubernetes cluster.</p>
</li>
<li><p><a target="_blank" href="https://kubernetes.io/docs/concepts/overview/components/">Kubernetes Components Cheat Sheet</a>: This cheat sheet explains the different components and services in the Kubernetes architecture.</p>
</li>
</ul>
</li>
<li><p><strong>Kubernetes Interview Questions</strong>: If you are preparing for a job interview or want to test your knowledge of Kubernetes, interview question resources can be valuable. Some websites that offer Kubernetes interview questions include:</p>
<ul>
<li><p><a target="_blank" href="https://www.interviewbit.com/kubernetes-interview-questions/">InterviewBit</a>: This website provides a collection of Kubernetes interview questions along with detailed answers.</p>
</li>
<li><p><a target="_blank" href="https://leetcode.com/tag/kubernetes/">LeetCode</a>: LeetCode offers coding problems related to Kubernetes that can help you practice your skills.</p>
</li>
</ul>
</li>
</ol>
<p>By exploring these resources, beginners can gain a solid understanding of Kubernetes and its components. These tutorials, cheat sheets, and interview question resources will serve as valuable references throughout your learning process, enabling you to scale deployments, update containerized applications, and debug them effectively.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we explored the world of Kubernetes and its fundamental concepts. We discussed the architecture and components of Kubernetes, including the roles and responsibilities of master and slave nodes in a Kubernetes cluster.</p>
<p>We then discussed the installation and setup process, considering different options for local computers and cloud platforms. We also covered how to deploy applications using Pods, Services, and Deployments in Kubernetes, as well as methods to scale, update, and debug applications. We compared Kubernetes with Docker Swarm as container orchestration systems, highlighting their key features. We also provided recommendations for helpful tutorials, cheat sheets, and interview question resources for beginners learning Kubernetes.</p>
<p>Now it's time for you to practice what you have learned and explore Kubernetes further. Dive into hands-on exercises, experiment with different deployment scenarios, and continue expanding your knowledge of this powerful container orchestration tool.</p>
<p>The best way to learn is by doing. So roll up your sleeves and start exploring Kubernetes today!</p>
]]></content:encoded></item><item><title><![CDATA[Build a dApp Using Waku (Decentralized Communication) and Vue.js]]></title><description><![CDATA[Hi, frens 👋!
TL;DR
Did you know that far beyond being a mere industry buzzword, decentralized communication represents a strategic response to the vulnerabilities inherent in centralized systems? It prioritizes privacy, security, and censorship resi...]]></description><link>https://blog.wolzcodelife.com/build-a-dapp-using-waku-decentralized-communication-and-vuejs</link><guid isPermaLink="true">https://blog.wolzcodelife.com/build-a-dapp-using-waku-decentralized-communication-and-vuejs</guid><category><![CDATA[Web3]]></category><category><![CDATA[dapps]]></category><category><![CDATA[Vue.js]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Mon, 29 Jan 2024 12:44:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1706532002629/d0f41ac0-14b3-45f8-9222-f525e74619fe.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi, frens 👋!</p>
<h3 id="heading-tldr">TL;DR</h3>
<p>Did you know that far beyond being a mere industry buzzword, decentralized communication represents a strategic response to the vulnerabilities inherent in centralized systems? It prioritizes privacy, security, and censorship resistance, making it an indispensable component in web developers' toolkits.</p>
<p>Traditional centralized communication systems have long struggled with censorship, single points of failure, and privacy concerns. With the rise of Web 3 and blockchain technology, decentralized communication solutions like Waku are emerging as a promising alternative. Waku offers a peer-to-peer (P2P) messaging system that is resilient to censorship, scalable, and secure, making it an ideal choice for dApp developers looking to build next-generation applications.</p>
<p>This article will guide you on how to build a decentralized application (dApp) using Waku, an uncompromising decentralized communication protocol, and Vue.js, a popular JavaScript framework for building user interfaces. Before diving into the hands-on development aspects of this article, it is recommended that you have a basic understanding of Vue.js, familiarity with Tailwind CSS for UI styling, and a grasp of web3.js for seamless wallet integration. </p>
<blockquote>
<p>If these technologies are new to you, no problem – this guide is meticulously created for all levels of expertise, providing step-by-step guidance at every level.</p>
<p>And don't forget to drop a "💖🦄🔥🙌🤯".</p>
</blockquote>
<h2 id="heading-understanding-waku">Understanding Waku</h2>
<p>Waku is a collection of decentralized peer-to-peer messaging protocols that enable secure and censorship-resistant communication over a decentralized network. Its features include end-to-end encryption, persistent/ephemeral messaging, and efficient peer discovery, providing a foundation for secure and reliable communication.</p>
<p>Waku operates within a peer-to-peer topology, creating a decentralized network that thwarts censorship and provides surveillance resistance. Its design supports scalability, with the ability to accommodate millions of users. It is designed to be the successor of Whisper, the messaging layer of the Ethereum blockchain P2P protocol suite, and outperforms it in scalability and resource efficiency.</p>
<p>Waku's architecture is underpinned by three distinct network interaction domains: gossip, discovery, and request/response. Although Waku is a cohesive whole in terms of capabilities, it encompasses three primary clients designed for different environments and several SDKs, including Rust, React Native, Kotlin, and Swift.</p>
<ol>
<li><p><strong>nwaku:</strong> The reference implementation in Nim.</p>
</li>
<li><p><strong>go-waku:</strong> Tailored for native integration with Golang applications.</p>
</li>
<li><p><strong>js-waku:</strong> A JavaScript implementation optimized for browser environments.</p>
</li>
</ol>
<p>Waku consists of multiple protocols, each serving a specific function within the network. They include, but are not limited to:</p>
<ul>
<li><p><strong>Waku Relay:</strong> The backbone of the Waku network, employing a pub/sub approach to peer-to-peer messaging. Emphasizes privacy, censorship resistance, and security, extending the libp2p GossipSub protocol.</p>
</li>
<li><p><strong>Waku Filter:</strong> A lightweight version of the relay protocol designed for resource-restricted devices. Allows light nodes to receive specific messages of interest from full nodes.</p>
</li>
<li><p><strong>Waku Store:</strong> Facilitates message retrieval for devices unable to participate in the Waku Relay network while offline.</p>
</li>
<li><p><strong>Waku Light Push:</strong> A request/response protocol enabling nodes with short connection windows or limited bandwidth to publish messages to the Waku network.</p>
</li>
</ul>
<p><a target="_blank" href="https://github.com/wolz-CODElife/waku-vue-poll/blob/master/docs/image.png"><img src="https://github.com/wolz-CODElife/waku-vue-poll/raw/master/docs/image.png" alt="Waku archtechture" /></a></p>
<p>Understanding Waku's architecture and protocols lays the groundwork for proceeding into practical implementations.</p>
<h2 id="heading-use-cases-of-waku">Use Cases of Waku</h2>
<p>Waku's versatile architecture and capabilities find relevance in a myriad of real-world scenarios where secure and decentralized communication is paramount. Whether it's facilitating private conversations between users, enabling data exchange between devices, or supporting communication among nodes within a network, Waku emerges as a robust solution.</p>
<h4 id="heading-privacy-focused-communication">Privacy-focused Communication</h4>
<p>Waku's emphasis on privacy makes it an ideal choice for scenarios where safeguarding user information is of utmost importance. In applications dealing with sensitive data or confidential conversations, Waku's end-to-end encryption and decentralized architecture provide a secure environment, mitigating the risks associated with centralized communication platforms.</p>
<h4 id="heading-censorship-resistant-messaging">Censorship-resistant Messaging</h4>
<p>Waku offers a beacon of hope for unrestricted communication in regions where internet censorship is prevalent. Its peer-to-peer topology prevents centralized authorities from controlling or monitoring messaging traffic, ensuring that users can communicate freely without fear of censorship. This makes Waku particularly valuable in promoting freedom of expression and supporting open communication channels.</p>
<h4 id="heading-use-in-dapps-for-decentralized-communication">Use in dApps for Decentralized Communication</h4>
<p>Decentralized Applications (dApps) form a burgeoning ecosystem where Waku can play a pivotal role. Waku's integration into dApps enhances communication functionalities, enabling real-time interactions among users while maintaining the decentralized ethos. This proves particularly valuable in scenarios such as collaborative platforms, social networks, or any application where user engagement and communication are central components.</p>
<p>By exploring the features and capabilities of Waku, it becomes evident that Waku's applicability extends beyond theoretical advantages, finding practical application in diverse areas.</p>
<h2 id="heading-building-a-dapp-with-waku-and-vuejs">Building a dApp with Waku and Vue.js</h2>
<p>Polling systems often face challenges related to centralization, privacy concerns, and susceptibility to manipulation. By integrating Waku and Vue.js, we can tackle these challenges, creating a decentralized voting poll application that leverages the power of peer-to-peer communication.</p>
<p>Here is the entire source code of my voting poll app on GitHub: <a target="_blank" href="https://github.com/wolz-CODElife/waku-vue-poll.git">https://github.com/wolz-CODElife/waku-vue-poll.git</a> and the <a target="_blank" href="https://waku-vue-poll.vercel.app/">live application</a> is hosted on Vercel.</p>
<p><a target="_blank" href="https://github.com/wolz-CODElife/waku-vue-poll/blob/master/docs/image-1.png"><img src="https://github.com/wolz-CODElife/waku-vue-poll/raw/master/docs/image-1.png" alt="Home component" /></a></p>
<p><a target="_blank" href="https://github.com/wolz-CODElife/waku-vue-poll/blob/master/docs/image-2.png"><img src="https://github.com/wolz-CODElife/waku-vue-poll/raw/master/docs/image-2.png" alt="Create poll component" /></a></p>
<p><a target="_blank" href="https://github.com/wolz-CODElife/waku-vue-poll/blob/master/docs/image-3.png"><img src="https://github.com/wolz-CODElife/waku-vue-poll/raw/master/docs/image-3.png" alt="Polls component" /></a></p>
<h3 id="heading-dev-tools-i-used">Dev Tools I Used?</h3>
<ul>
<li><p><strong>Vite</strong>: To bootstrap the Vue3 application with the Tailwind template.</p>
</li>
<li><p><strong>Vue 3</strong>: To build the user interface.</p>
</li>
<li><p><strong>TypeScript</strong>: For type safety and potential for catching errors during compiling.</p>
</li>
<li><p><strong>Tailwind CSS</strong>: For styling the user interface.</p>
</li>
<li><p><strong>Web3.js</strong>: For implementing wallet connect.</p>
</li>
<li><p><strong>Node Polyfill Webpack Plugin</strong>: For providing polyfills necessary for emitting Web3.js events in the browser. Since Vue3 uses webpack v5, where polyfill Node core modules were removed.</p>
</li>
<li><p><strong>Crypto Hash</strong>: For hashing user address, where wallet is not available.</p>
</li>
<li><p><strong>Protobufjs</strong>: For serializing message data sent through Waku.</p>
</li>
<li><p><code>@waku/sdk</code>: For accessing Waku node methods in JavaScript.</p>
</li>
</ul>
<h3 id="heading-setting-up-the-development-environment">Setting Up the Development Environment</h3>
<p>To set up your development environment, ensure you have Node v18+ then open a new terminal in your working directory and run the following command:</p>
<pre><code class="lang-bash">npm create vite@latest
</code></pre>
<p>Which will begin a dialog in the terminal, you can choose options that work for you, or use the same options as I used:</p>
<pre><code class="lang-bash">Need to install the following packages:
  create-vite@5.1.0
Ok to proceed? (y) y
✔ Project name: … waku-poll-app
✔ Select a framework: › Vue
✔ Select a variant: › TypeScript
</code></pre>
<p>This should create a new Vue application in your working directory, navigate to the app, install the default dependencies and start the app using the following command:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> waku-poll-app
npm install
npm run dev
</code></pre>
<p>Next, we want to create a file structure that allows us to componentize the various parts of the app. Your <code>src</code> path should have a file structure like this:</p>
<p><a target="_blank" href="https://github.com/wolz-CODElife/waku-vue-poll/blob/master/docs/image-4.png"><img src="https://github.com/wolz-CODElife/waku-vue-poll/raw/master/docs/image-4.png" alt="Project file structure" /></a></p>
<p>As we proceed we will update files with the necessary code, as for <code>assets/3dpoll.jpg</code> feel free to replace it with any image you see fit for your landing page.</p>
<h3 id="heading-setting-up-tailwind-in-vuejs">Setting up Tailwind in Vue.js</h3>
<p>To build our UI, we need to first install and configure Tailwind CSS in Vue 3. You can follow the official guide on <a target="_blank" href="https://v2.tailwindcss.com/docs/guides/vue-3-vite#setting-up-tailwind-css">Setting up Tailwind CSS</a>.</p>
<h3 id="heading-configuring-routes">Configuring Routes</h3>
<p>To create multiple pages/routes in the app, we have to install Vue Router by running the following command in the terminal:</p>
<pre><code class="lang-bash">npm install --save vue-router@next 
<span class="hljs-comment"># Install the latest version</span>
</code></pre>
<p>In this app, we just need two routes: “Home” and “Polls” which we have inside the <code>src/views</code> folder. These routes will contain the Layout of each page, and then we can define the routes in the <code>src/router/index.ts</code> file by using the following code:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { createRouter, createWebHistory, RouteRecordRaw } <span class="hljs-keyword">from</span> <span class="hljs-string">'vue-router'</span>
<span class="hljs-keyword">import</span> Home <span class="hljs-keyword">from</span> <span class="hljs-string">'@/views/Home.vue'</span>

<span class="hljs-keyword">const</span> routes: <span class="hljs-built_in">Array</span>&lt;RouteRecordRaw&gt; = [
  {
    path: <span class="hljs-string">'/'</span>,
    name: <span class="hljs-string">'Home'</span>,
    component: Home,
  },
  {
    path: <span class="hljs-string">'/polls'</span>,
    name: <span class="hljs-string">'Polls'</span>,

    component: <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'../views/Polls.vue'</span>),
  }
]

<span class="hljs-keyword">const</span> router = createRouter({
  history: createWebHistory(),
  routes,
})

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> router
</code></pre>
<p>In the code snippet above, a Vue.js router configuration is defined. We import the necessary functions and types from 'vue-router' and the Home component from <code>@/views/Home.vue</code>. </p>
<p>The routes array contains route definitions for the Home and Polls components. The router is created using createRouter and createWebHistory functions, and the routes we defined earlier.</p>
<p>The <code>component: () =&gt; import('../views/Polls.vue')</code> is used to dynamically import the 'Polls.vue' component. This is a feature provided by Vue.js to asynchronously load the component when it's needed, which can help improve initial page load performance by splitting the code into smaller chunks.</p>
<p>Finally, the router is exported so we can access it in “main.ts”.</p>
<p>Next, we register <code>router</code> to the Vue app by including it in the “main.ts” file like this:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// main.ts or main.js</span>
<span class="hljs-keyword">import</span> { createApp } <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App.vue'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./css/index.css'</span>

<span class="hljs-keyword">import</span> router <span class="hljs-keyword">from</span> <span class="hljs-string">'./router'</span>

createApp(App).use(router).mount(<span class="hljs-string">'#app'</span>)
</code></pre>
<p>Next, we will create a Layout for our application with the following inside “App.vue”:</p>
<pre><code class="lang-typescript">&lt;script lang=<span class="hljs-string">"ts"</span>&gt;
&lt;/script&gt;


&lt;template&gt;
  &lt;div <span class="hljs-keyword">class</span>=<span class="hljs-string">"flex flex-col h-screen justify-between"</span>&gt;
    &lt;router-view <span class="hljs-keyword">class</span>=<span class="hljs-string">"container max-w-8xl mx-auto mb-auto px-4"</span> /&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;style&gt;
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #<span class="hljs-number">2</span>c3e50;
}
&lt;/style&gt;
</code></pre>
<p>In the code above, we use <code>router-view</code> to dynamically load the components of the current route into the DOM.</p>
<h3 id="heading-installing-the-waku-and-its-dependencies">Installing the Waku and Its Dependencies</h3>
<p>To get started with Waku in our Vue 3 application, we need to install <code>@waku/sdk</code> which is a TypeScript implementation of the Waku protocol designed for web browser environments.</p>
<p>To install <code>@waku.sdk</code> run the following command in the terminal:</p>
<pre><code class="lang-bash">npm install @waku/sdk
</code></pre>
<p>It is also recommended to create a message structure for your app, typically Waku developers use <a target="_blank" href="https://protobuf.dev/">Protocol Buffers</a> for consistency, interoperability, compatibility and payload size. To install <code>protobufjs</code>, run the following command in the terminal:</p>
<pre><code class="lang-bash">npm install protobufjs
</code></pre>
<h3 id="heading-implementing-waku-logic">Implementing Waku Logic</h3>
<p>The application runs on two fundamental logic, which are the wallet connect and Waku communication integrations. We will create two composables “waku.ts” and “client.ts”  inside <code>src/composables</code>.</p>
<p>“waku.ts” contains all the methods our Vue app needs to interact with the Waku protocol and transmit messages(polls) across users on the app. Inside this file, you should have the following code:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { ref } <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span>;
<span class="hljs-keyword">import</span> protobuf, { Message } <span class="hljs-keyword">from</span> <span class="hljs-string">'protobufjs'</span>;
<span class="hljs-keyword">import</span> {
    createLightNode,
    waitForRemotePeer,
    createDecoder,
    createEncoder,
    Protocols,
    IFilterSubscription,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'@waku/sdk'</span>;

<span class="hljs-keyword">interface</span> PollOption {
    value: <span class="hljs-built_in">string</span>;
    votes: <span class="hljs-built_in">number</span>;
}

<span class="hljs-keyword">interface</span> PollMessage {
    question: <span class="hljs-built_in">string</span>;
    options: { [key: <span class="hljs-built_in">string</span>]: PollOption };
}

<span class="hljs-keyword">interface</span> Poll {
    msgid: <span class="hljs-built_in">string</span>;
    timestamp: <span class="hljs-built_in">string</span>;
    sender: <span class="hljs-built_in">string</span>;
    message: PollMessage;
    <span class="hljs-comment">// other properties...</span>
}


<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> status = ref&lt;<span class="hljs-built_in">string</span>&gt;(<span class="hljs-string">'connecting...'</span>);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> sender = ref(<span class="hljs-built_in">localStorage</span>.getItem(<span class="hljs-string">'senderWalletAddress'</span>) ?? <span class="hljs-string">''</span>);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> polls = ref&lt;Poll[]&gt;(<span class="hljs-built_in">JSON</span>.parse(<span class="hljs-built_in">localStorage</span>.getItem(<span class="hljs-string">'polls'</span>) ?? <span class="hljs-string">'[]'</span>));


<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> wakuNode = <span class="hljs-keyword">await</span> createLightNode({
    defaultBootstrap: <span class="hljs-literal">true</span>,
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> waitForRemotePeers = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-comment">// Wait for a successful peer connection</span>
    <span class="hljs-keyword">await</span> waitForRemotePeer(wakuNode, [
        Protocols.LightPush,
        Protocols.Filter,
    ]);
}

<span class="hljs-comment">// Choose a content topic</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> contentTopic = <span class="hljs-string">'/waku-vue-poll/1/polls/proto'</span>;

<span class="hljs-comment">// message encoder and decoder</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> encoder = createEncoder({ contentTopic, ephemeral: <span class="hljs-literal">true</span> });
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> decoder = createDecoder(contentTopic);

<span class="hljs-comment">// Message structure with Protobuf</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> PollQuestionWakuMessage = <span class="hljs-keyword">new</span> protobuf.Type(<span class="hljs-string">'PollQuestion'</span>)
    .add(<span class="hljs-keyword">new</span> protobuf.Field(<span class="hljs-string">'timestamp'</span>, <span class="hljs-number">1</span>, <span class="hljs-string">'string'</span>))
    .add(<span class="hljs-keyword">new</span> protobuf.Field(<span class="hljs-string">'msgid'</span>, <span class="hljs-number">2</span>, <span class="hljs-string">'string'</span>))
    .add(<span class="hljs-keyword">new</span> protobuf.Field(<span class="hljs-string">'sender'</span>, <span class="hljs-number">3</span>, <span class="hljs-string">'string'</span>))
    .add(<span class="hljs-keyword">new</span> protobuf.Field(<span class="hljs-string">'message'</span>, <span class="hljs-number">4</span>, <span class="hljs-string">'string'</span>));

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> serializeMessage = <span class="hljs-function">(<span class="hljs-params">protoMessage: Message</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> PollQuestionWakuMessage.encode(protoMessage).finish()
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useWaku</span>(<span class="hljs-params"></span>) </span>{

    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">start</span>(<span class="hljs-params"></span>) </span>{
        status.value = <span class="hljs-string">'connecting'</span>        
        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">await</span> wakuNode?.start().then(<span class="hljs-function">() =&gt;</span> {
                <span class="hljs-keyword">if</span> (wakuNode.isStarted()) <span class="hljs-keyword">return</span> waitForRemotePeers()
            }).then(<span class="hljs-function">() =&gt;</span> {
                <span class="hljs-keyword">return</span> wakuNode.connectionManager.getPeersByDiscovery()
            }).then(<span class="hljs-function">(<span class="hljs-params">data:<span class="hljs-built_in">any</span></span>) =&gt;</span> {
                <span class="hljs-keyword">if</span> (
                    wakuNode.libp2p.getConnections().length ||
                    data.CONNECTED.bootstrap.length ||
                    data.CONNECTED[<span class="hljs-string">'peer-exchange'</span>].length
                ) {
                    subscribe()
                    status.value = <span class="hljs-string">"connected"</span>
                }
            })
        }
        <span class="hljs-keyword">catch</span> (error) {
            <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error initializing Waku Light Node:'</span>, error);
            status.value = <span class="hljs-string">'not connected'</span>;
        }
    }

    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">stop</span>(<span class="hljs-params"></span>) </span>{
        unsubscribe();
        wakuNode.stop()
        status.value = <span class="hljs-string">'not conencted'</span>;
    }
    <span class="hljs-keyword">let</span> subscription = {} <span class="hljs-keyword">as</span> IFilterSubscription

    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">subscribe</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">if</span> (!wakuNode || status.value !== <span class="hljs-string">'connected'</span>) <span class="hljs-keyword">await</span> start();
        <span class="hljs-keyword">try</span> {
          subscription = <span class="hljs-keyword">await</span> wakuNode?.filter?.createSubscription();
          <span class="hljs-keyword">await</span> subscription.subscribe([decoder], <span class="hljs-function">(<span class="hljs-params">wakuMessage</span>) =&gt;</span> {
            <span class="hljs-keyword">const</span> messageObj = PollQuestionWakuMessage.decode(wakuMessage.payload).toJSON();
            <span class="hljs-keyword">const</span> result: Poll = {
                timestamp: messageObj.timestamp,
                msgid: messageObj.msgid,
                sender: messageObj.sender,
                message: <span class="hljs-built_in">JSON</span>.parse(messageObj.message ?? <span class="hljs-string">'{}'</span>)
            };
            handleSubscriptionResult(result);
          });
        } <span class="hljs-keyword">catch</span> (error) {
          <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error subscribing to Content Topic:'</span>, error);
        }
      }

      <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleSubscriptionResult</span>(<span class="hljs-params">result:Poll</span>) </span>{
        <span class="hljs-keyword">const</span> msgid = result.msgid;
        <span class="hljs-keyword">const</span> existingPollIndex = polls.value.findIndex(<span class="hljs-function"><span class="hljs-params">poll</span> =&gt;</span> poll.msgid === msgid);

        <span class="hljs-keyword">if</span> (existingPollIndex !== <span class="hljs-number">-1</span>) {
          <span class="hljs-comment">// Update the existing poll</span>
          polls.value.splice(existingPollIndex, <span class="hljs-number">1</span>, result);
        } <span class="hljs-keyword">else</span> {
          <span class="hljs-comment">// Add the new poll to the array</span>
          polls.value.unshift(result);
        }

        <span class="hljs-keyword">if</span> (polls.value.length &gt; <span class="hljs-number">0</span>) {
            <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'polls'</span>, <span class="hljs-built_in">JSON</span>.stringify(polls.value));
        }
      }

    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">unsubscribe</span>(<span class="hljs-params"></span>) </span>{
        subscription.unsubscribe([contentTopic])
    }

    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">publish</span>(<span class="hljs-params">sender: <span class="hljs-built_in">string</span>, message: <span class="hljs-built_in">string</span>, timestamp: <span class="hljs-built_in">string</span> = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toUTCString(), msgid: <span class="hljs-built_in">string</span> = <span class="hljs-built_in">Date</span>.now() + <span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * <span class="hljs-number">90000</span>).toString()</span>) </span>{    
        <span class="hljs-keyword">if</span> (!wakuNode || status.value !== <span class="hljs-string">'connected'</span>) <span class="hljs-keyword">await</span> start()

        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">const</span> protoData = PollQuestionWakuMessage.create({
                timestamp: timestamp,
                msgid: msgid,
                sender: sender,
                message: message
            })

            <span class="hljs-keyword">return</span> wakuNode.lightPush.send(encoder, { payload: serializeMessage(protoData) })
        }
        <span class="hljs-keyword">catch</span> (error) {
            <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error publishing to Content Topic:'</span>, error);
        }
    }

    <span class="hljs-keyword">return</span> {
        wakuNode,
        status,
        sender,
        polls,
        start,
        stop,
        subscribe,
        unsubscribe,
        publish,
    };
}
</code></pre>
<p>The above code enables interaction with the Waku network, enabling the creation and participation in polls within a Vue application.</p>
<p>Firstly, we import necessary functions and define data structure using TypeScript interfaces to set a standard for PollOption, PollMessage and Poll. These structures represent the questions and options available in a poll and the overall structure of a poll, respectively.</p>
<p>Reactive variables (status, sender, and polls) are defined to keep track of the connection status, the sender's information, and the list of polls. These variables will be necessary for updating the Vue application in response to changes in the Waku network.</p>
<blockquote>
<p>Notice that we didn’t make WakuNode or any variable interacting with the Waku network directly reactive. As this will trigger <a target="_blank" href="https://github.com/waku-org/js-waku/issues/1746">issue #1746</a> due to Waku nodes being too complex for Vue mechanisms to handle, so we have to keep the WakuNode instance outside Vue’s reactive scope.</p>
<p>BTW, this took me almost 3 months to figure out 😭</p>
</blockquote>
<p>The WakuNode connection is established using the createLightNode function, optimizing resource usage by creating a Waku light node. This node connects to the Waku network and waits for peers to join using the <a target="_blank" href="https://rfc.vac.dev/spec/19/">LightPush</a> and <a target="_blank" href="https://rfc.vac.dev/spec/12/">Filter</a> Protocols. We defined a specific <a target="_blank" href="https://docs.waku.org/learn/concepts/content-topics">Content Topic</a> for this app to categorize messages and should have this format, <code>/{application-name}/{version}/{content-topic-name}/{encoding}</code>, make sure to replace <code>WAKU_CONTENT_TOPIC</code> with your actual Content Topic. and Protobuf is utilized for encoding and decoding messages efficiently to suit the <code>PollQuestionWakuMessage</code> message structure.</p>
<p>After connecting to the Waku network, interaction follows. We created a function called useWaku() that encapsulates and returns all the variables and methods needed to interact with Waku across the entire application.</p>
<p>First, we have the <code>start()</code> function that initiates the WakuNode connection, waits for peers to connect and subscribes to the chosen content topic, before updating the user’s status to <code>status.value = "connected"</code>.</p>
<p>Next, we have <code>stop()</code> function that unsubscribes from the Content Topic and stops the WakuNode, before updating the user’s status to <code>status.value = 'not conencted'</code>.</p>
<p>Next, we have the <code>subscribe()</code> function that creates a subscription to the Content Topic using the Waku Filter, receives incoming poll messages, decodes them and updates the polls list. The handleSubscriptionResult function decodes incoming poll messages, checks for duplicates, and updates the list of polls accordingly.</p>
<p>Next, we have the <code>unsubscribe()</code> function that disconnects the app from the Content Topic.</p>
<p>Finally, the <code>publish()</code> function accepts the necessary parameters to create a new poll message and send the encoded poll message to the Waku network using the LightPush protocol.</p>
<h3 id="heading-implement-wallet-connect-logic">Implement Wallet Connect Logic</h3>
<p>The <code>sender</code> variable in the “waku.ts” composable stores the wallet address of the connected wallet. For us to implement wallet connect, we need to first install “Web3.js” by running the following command in the terminal:</p>
<pre><code class="lang-bash">npm install web3
</code></pre>
<p>Since Vue 3 uses webpack v5, we need to install Node Polyfill Webpack Plugin to provide the polyfills necessary for emitting Web3.js events in the browser. Run the following command in the terminal to install the Node Polyfill Webpack Plugin:</p>
<pre><code class="lang-bash">npm i node-polyfill-webpack-plugin
</code></pre>
<p>Then include it in the “vite.config.ts” so that your “vite.config.ts” looks like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'vite'</span>;
<span class="hljs-keyword">import</span> vue <span class="hljs-keyword">from</span> <span class="hljs-string">'@vitejs/plugin-vue'</span>;
<span class="hljs-keyword">import</span> path <span class="hljs-keyword">from</span> <span class="hljs-string">'path'</span>;

<span class="hljs-comment">// https://vitejs.dev/config/</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      <span class="hljs-string">'@/'</span>: <span class="hljs-string">`<span class="hljs-subst">${path.resolve(__dirname, <span class="hljs-string">'src'</span>)}</span>/`</span>,
    },
  },
  optimizeDeps: {
    include: [<span class="hljs-string">'node-polyfill-webpack-plugin'</span>],
  },
  esbuild: {
    supported: {
      <span class="hljs-string">'top-level-await'</span>: <span class="hljs-literal">true</span>
    }
  }
});
</code></pre>
<p>You will notice we are also supporting <code>top-level-await</code>, this is because we are instantiating WakuNode at a top-level and the Vite build doesn’t support this.</p>
<p>Inside the “client.ts” we will have the following code:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> Web3 <span class="hljs-keyword">from</span> <span class="hljs-string">'web3'</span>;
<span class="hljs-keyword">import</span> { useWaku } <span class="hljs-keyword">from</span> <span class="hljs-string">'./waku'</span>;
<span class="hljs-keyword">import</span> { sha256 } <span class="hljs-keyword">from</span> <span class="hljs-string">'crypto-hash'</span>;

<span class="hljs-keyword">declare</span> <span class="hljs-built_in">global</span> {
    <span class="hljs-keyword">interface</span> Window {
        ethereum: <span class="hljs-built_in">any</span>;
        web3: <span class="hljs-built_in">any</span>
    }
}

<span class="hljs-keyword">const</span> waku = useWaku()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> generateUniqueID = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> userAgentHash = sha256(navigator.userAgent + <span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * <span class="hljs-number">90000</span>));
  <span class="hljs-keyword">return</span> userAgentHash;
};

<span class="hljs-comment">// Validate Ethereum Address</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> validateEthereumAddress = <span class="hljs-function">(<span class="hljs-params">address:<span class="hljs-built_in">any</span></span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-regexp">/^(0x)?[0-9a-fA-F]{40}$/</span>.test(address);
}

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">useWalletConnect</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// Improved connectWallet Function</span>
    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">connectWallet</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">window</span>.ethereum) {
            <span class="hljs-keyword">try</span> {
                <span class="hljs-keyword">const</span> accounts = <span class="hljs-keyword">await</span> <span class="hljs-built_in">window</span>.ethereum.request({ method: <span class="hljs-string">'eth_requestAccounts'</span> });
                <span class="hljs-built_in">window</span>.web3 = <span class="hljs-keyword">new</span> Web3(<span class="hljs-built_in">window</span>.ethereum);

                <span class="hljs-keyword">if</span> (accounts.length &gt; <span class="hljs-number">0</span> &amp;&amp; validateEthereumAddress(accounts[<span class="hljs-number">0</span>])) {
                    <span class="hljs-keyword">const</span> walletAddress = accounts[<span class="hljs-number">0</span>];
                    waku.sender.value = walletAddress;
                    <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'senderWalletAddress'</span>, walletAddress);
                } <span class="hljs-keyword">else</span> {
                    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Invalid Ethereum address detected. Generating fallback ID.'</span>);
                    generateUniqueID().then(<span class="hljs-function">(<span class="hljs-params">hashID</span>) =&gt;</span> {
                        <span class="hljs-keyword">const</span> newHash = <span class="hljs-string">'abcdef012345'</span>[<span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * <span class="hljs-number">12</span>)] + <span class="hljs-string">"x"</span> + hashID.slice(<span class="hljs-number">-20</span>);
                        waku.sender.value = newHash;
                        <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'senderWalletAddress'</span>, newHash);
                    });
                }

                <span class="hljs-keyword">await</span> waku.start();
            } <span class="hljs-keyword">catch</span> (error) {
                <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error connecting wallet:'</span>, error);
            }
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'No Ethereum wallet detected.'</span>);
        }
    }


    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">disconnectWallet</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">localStorage</span>.removeItem(<span class="hljs-string">'senderWalletAddress'</span>);
        <span class="hljs-built_in">localStorage</span>.removeItem(<span class="hljs-string">'polls'</span>);
        <span class="hljs-comment">// stop waku's light node</span>
        <span class="hljs-keyword">await</span> waku.wakuNode.stop();
        waku.stop()
        waku.sender.value = <span class="hljs-string">""</span>
        waku.status.value = <span class="hljs-string">"connecting..."</span>
        waku.polls.value = []
    }
    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">signMessage</span>(<span class="hljs-params">msgid: <span class="hljs-built_in">string</span>, stringifiedMessage:<span class="hljs-built_in">string</span></span>) </span>{
        <span class="hljs-keyword">const</span> messageToSign = <span class="hljs-string">`Message ID: <span class="hljs-subst">${msgid}</span>, Content: <span class="hljs-subst">${stringifiedMessage}</span>`</span>;
        <span class="hljs-keyword">let</span> signature;
        <span class="hljs-keyword">try</span> {
            signature = <span class="hljs-keyword">await</span> <span class="hljs-built_in">window</span>.ethereum.request({
                method: <span class="hljs-string">'personal_sign'</span>,
                params: [messageToSign, waku.sender.value],
            });
            <span class="hljs-keyword">return</span> signature
        } <span class="hljs-keyword">catch</span> (signError) {
            <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error signing the message:'</span>, signError);
            <span class="hljs-keyword">return</span>;
        }
    }

    <span class="hljs-keyword">return</span> {
        connectWallet,
        disconnectWallet,
        signMessage
    };
}
</code></pre>
<p>The above code enables users to connect their crypto wallet to the app as a means of identification. In this scenario, we used the wallet address as the sender of the poll.</p>
<p>However, some users may not have wallets and we don’t want to limit the application to only users that have crypto wallets. To tackle this, we created the <code>generateUniqueID()</code> function to form a random hash from the <code>navigator.userAgent</code> address of the user’s browser. Then we store the sender’s address in localStorage as “'senderWalletAddress'”.</p>
<p>We also created a <code>disconnectWallet()</code> function to remove the wallet address from localStorage and stop the WakuNode running.</p>
<p>To claim ownership of the polls, users have to sign each poll message using their wallet, for this the <code>signMessage</code> function is executed.</p>
<p>The <code>useWalletConnect</code> composable encapsulates and returns the <code>connectWallet</code>, <code>disconnectWallet</code> and <code>signMessage</code> functions so that they are accessible across the application.</p>
<h3 id="heading-building-the-ui-components">Building the UI Components</h3>
<p>Now that we have our logic, we can build the UI to utilize the data and methods in our composables.</p>
<p>We have 3 major components in this app, the <code>NavBar</code>, <code>Home</code> and <code>Polls</code>. Feel free to create your user interface or use mine:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/wolz-CODElife/waku-vue-poll/blob/master/src/components/NavBar.vue">NavBar</a>: <code>src/components/NavBar.vue</code></p>
</li>
<li><p><a target="_blank" href="https://github.com/wolz-CODElife/waku-vue-poll/blob/master/src/views/Home.vue">Home</a>: <code>src/views/Home.vue</code></p>
</li>
<li><p><a target="_blank" href="https://github.com/wolz-CODElife/waku-vue-poll/blob/master/src/views/Polls.vue">Polls</a>: <code>src/views/.vue</code></p>
</li>
</ul>
<h3 id="heading-creating-polls">Creating Polls</h3>
<p>If you go through my NavBar component code, you will find that we have a <code>ref</code> called poll:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> poll = ref&lt;Poll&gt;({
  question: <span class="hljs-string">""</span>,
  options: {
    a: { value: <span class="hljs-string">""</span>, votes: <span class="hljs-number">0</span>},
    b: { value: <span class="hljs-string">""</span>, votes: <span class="hljs-number">0</span>},
    c: { value: <span class="hljs-string">""</span>, votes: <span class="hljs-number">0</span>},
    d: { value: <span class="hljs-string">""</span>, votes: <span class="hljs-number">0</span>},
    e: { value: <span class="hljs-string">""</span>, votes: <span class="hljs-number">0</span>}
  }
})
</code></pre>
<p>This <code>ref</code> is updated by the modal form, and on submit, we trigger the <code>sendMessage</code> function:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> sendMessage = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> stringifiedMessage = <span class="hljs-built_in">JSON</span>.stringify(poll.value)
  <span class="hljs-keyword">const</span> msgid = <span class="hljs-built_in">Date</span>.now() + <span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * <span class="hljs-number">90000</span>).toString();
  <span class="hljs-keyword">const</span> timestamp = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toUTCString()

  <span class="hljs-comment">// sign message</span>
  signMessage(msgid, stringifiedMessage).then(<span class="hljs-function">(<span class="hljs-params">signature</span>) =&gt;</span> {
    <span class="hljs-comment">// send a message</span>
    waku.publish(signature, stringifiedMessage, timestamp, msgid)

    <span class="hljs-comment">// reset question state</span>
    poll.value = {
      question: <span class="hljs-string">""</span>,
      options: {
        a: { value: <span class="hljs-string">""</span>, votes: <span class="hljs-number">0</span>},
        b: { value: <span class="hljs-string">""</span>, votes: <span class="hljs-number">0</span>},
        c: { value: <span class="hljs-string">""</span>, votes: <span class="hljs-number">0</span>},
        d: { value: <span class="hljs-string">""</span>, votes: <span class="hljs-number">0</span>},
        e: { value: <span class="hljs-string">""</span>, votes: <span class="hljs-number">0</span>}
      }
    }
    }
    onToggle()
    <span class="hljs-comment">// redirect user to where the new poll is populated</span>
    <span class="hljs-keyword">if</span> (router.currentRoute.value.path !== <span class="hljs-string">"/polls"</span>) {
      router.push(<span class="hljs-string">"/polls"</span>)
    }
  }).catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Error sending message"</span>, error);
  })
}
</code></pre>
<p>In the above code, we stringify the poll data which includes the question, and options so that we can publish the poll as a message to Waku. Then we create a <code>msgid</code> and <code>timestamp</code> for the message, before using the user's wallet to sign the message. Once the message is signed, we call the <code>waku.publish(waku.sender.value, stringifiedMessage)</code> function to register the update for other users subscribing to the Content Topic.</p>
<h3 id="heading-real-time-voting-and-result-polling">Real-Time Voting and Result Polling</h3>
<p>In the “Poll.vue” component, we have a <code>handleVote()</code> function:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> handleVote = <span class="hljs-keyword">async</span> (msgid: <span class="hljs-built_in">string</span>, selectedOption: <span class="hljs-built_in">string</span> | <span class="hljs-built_in">number</span>) =&gt; {
  loading.value = <span class="hljs-literal">true</span>
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Find the selected poll in the polls array</span>
    <span class="hljs-keyword">let</span> selectedPollIndex = waku.polls.value.findIndex(<span class="hljs-function">(<span class="hljs-params">poll</span>) =&gt;</span> poll.msgid === msgid);

    <span class="hljs-keyword">if</span> (selectedPollIndex !== <span class="hljs-number">-1</span>) {
      <span class="hljs-comment">// Update the vote count before publishing</span>
      waku.polls.value[selectedPollIndex].message.options[selectedOption].votes += <span class="hljs-number">1</span>;

      <span class="hljs-comment">// Create a reactive copy to trigger reactivity</span>
      <span class="hljs-keyword">const</span> reactiveCopy = reactive({ ...waku.polls.value[selectedPollIndex] });

      <span class="hljs-comment">// Publish the updated poll</span>

      <span class="hljs-keyword">const</span> stringifiedMessage = <span class="hljs-built_in">JSON</span>.stringify(reactiveCopy.message);

      <span class="hljs-keyword">await</span> waku.publish(reactiveCopy.sender , stringifiedMessage, reactiveCopy.timestamp, msgid);

      <span class="hljs-comment">// Store the msgid in local storage</span>
      votedPolls.value.push(msgid);
      <span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'votedPolls'</span>, <span class="hljs-built_in">JSON</span>.stringify(votedPolls.value));
    }
    loading.value = <span class="hljs-literal">false</span>
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error in handleVote:'</span>, error);
  }
};
</code></pre>
<p>This function is triggered when the radio input of any option is clicked. This function collected the <code>msgid</code> and the <code>selectedOption</code> as parameters. Then call the <code>subscribe()</code> function to fetch the latest version of the polls, before updating the vote counts of an option in the poll that has the <code>msgid</code>.</p>
<p>We created a reactive copy of the poll so that the vote count update will be reflected even if the state changes. Then we publish the reactive copy, which will send the updated poll results to all the users that are subscribed to the Content Topic of this app.</p>
<p>To track the polls a user has voted for, we store a “votePolls” array in the localStorage.</p>
<p>Feel free to play around with the functionality and optimize the performance to meet your application requirements.</p>
<h2 id="heading-summary-of-the-article">Summary of the Article</h2>
<p>In this comprehensive guide, we embarked on a journey to integrate Waku, a decentralized communication protocol, into a Vue.js application, creating a real-time voting poll dApp. Let's recap the key takeaways from the guide:</p>
<ul>
<li><p><strong>Understanding Waku</strong></p>
<ul>
<li><p>Explored Waku as a family of protocols facilitating private, censorship-resistant communications over a decentralized network.</p>
</li>
<li><p>Examined Waku's features, architecture, and its focus on privacy, decentralization, and adaptability to various platforms.</p>
</li>
<li><p>Discussed the different components of Waku, such as Waku Relay, Waku Filter, Waku Store, and Waku Light Push.</p>
</li>
</ul>
</li>
<li><p><strong>Use Cases of Waku</strong></p>
<ul>
<li>Discussed real-world scenarios where Waku proves invaluable, emphasizing its role in privacy-focused communication, censorship-resistant messaging, and decentralized communication within dApps.</li>
</ul>
</li>
<li><p><strong>Building a dApp with Waku and Vue.js</strong></p>
<ul>
<li><p>Set up a Vue.js application using Vite and Tailwind CSS.</p>
</li>
<li><p>Established a connection to the Waku network, implemented wallet authentication using Web3.js, and integrated the <code>@waku/sdk</code> for decentralized communication.</p>
</li>
<li><p>Demonstrated the step-by-step process of building a real-time voting poll, connecting to the Waku network.</p>
</li>
</ul>
</li>
</ul>
<p>As you conclude this guide, consider taking the following actions to further explore and experiment with Waku:</p>
<ol>
<li><p><strong>Waku Documentation:</strong>: Visit the <a target="_blank" href="https://docs.waku.org/">Waku documentation</a> to delve deeper into the functionalities, protocols, and use cases of Waku.</p>
</li>
<li><p><strong>Experiment with Additional Functionalities:</strong>: Extend the capabilities of your dApp by experimenting with additional functionalities provided by Waku. Explore features like ephemeral messaging, decentralized storage, and more to enhance your decentralized applications.</p>
</li>
<li><p><strong>Join the Waku Community:</strong>: Engage with the <a target="_blank" href="https://waku.org/community/">Waku community</a> on forums, social media, or developer channels. Connect with like-minded developers, share your experiences, and stay updated on the latest developments within the Waku ecosystem.</p>
</li>
<li><p><strong>Contribute to Waku:</strong>: Consider <a target="_blank" href="https://waku.org/about/team">contributing</a> to the Waku project on platforms like GitHub. Whether it's reporting issues, submitting pull requests, or suggesting improvements, your contributions can play a vital role in the growth of this decentralized communication protocol.</p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[GitHub Universe 2023 Recap]]></title><description><![CDATA[It's that time of the year again - GitHub Universe season! The annual global event took place IRL(in real life) at the Yerba Buena Center for the Arts in San Francisco from November 8th to November 9th, 2023. For those who couldn't make it in person,...]]></description><link>https://blog.wolzcodelife.com/github-universe-2023-recap</link><guid isPermaLink="true">https://blog.wolzcodelife.com/github-universe-2023-recap</guid><category><![CDATA[GitHub]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Fri, 10 Nov 2023 23:31:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1699656931449/46e9cdea-0b52-4711-9cd5-fc2a43f8a459.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It's that time of the year again - GitHub Universe season! The annual global event took place IRL(in real life) at the Yerba Buena Center for the Arts in San Francisco from November 8th to November 9th, 2023. For those who couldn't make it in person, the event was also streamed virtually.</p>
<p>For those who are unfamiliar with GitHub Universe, it's a yearly gathering of industry experts, developers, and professionals for two days of networking, conversation, and learning about the latest innovations. This year's theme was AI, security, and DevEx, covered in <a target="_blank" href="https://reg.githubuniverse.com/flow/github/universe23/sessioncatalog/page/sessioncatalog">over 80 sessions with 1,000 speakers</a>.</p>
<p><img src="https://lh7-us.googleusercontent.com/6br0G1DkqoQ4XjFHloSghDqoE3st9J_-8YIjpQhPHB7kIVV0mKM_QXgZreYnJbUJJiEaxb0SiXjoJ8GMaSPO2ERoMqLWxq3QcEg4paX7V0lhSg6KfGn4HtzF7eHeAculxXIfi1-yifEbpT5DBvJmGQk" alt /></p>
<h2 id="heading-opening-keynote">Opening Keynote</h2>
<p>On Day 1, <a target="_blank" href="https://github.com/ashtom">GitHub’s CEO, Thomas Dohmke</a>, kicked off the event with an exciting presentation, revealing GitHub's latest advancements and initiatives.</p>
<p><img src="https://lh7-us.googleusercontent.com/c9i1QAInmHu7cfWn-D2XWyxPYAA_vsvgbYt6edPjcaawKSlSwGsfxZ-Pyh31Z9r9LhMhi9c1dZ0Rz6eJjP4aAh4lDfVOM4bQsqeYfHeNbcu9Ir-RVNUVfbOC6SQ2CAsQLonFWW6WuvETJDoYUISU228" alt /></p>
<p>GitHub's journey with generative AI began in 2020 with the Coding Oracle Paper, exploring the potential of OpenAI's GPT-3 model. This led to the development of <a target="_blank" href="https://github.com/features/copilot">Copilot</a>, an AI-powered developer tool that has gained widespread adoption, enabling coding to be 55% more productive. Thomas showcased Copilot's evolution beyond code generation, integrating it into various aspects of the developer workflow, from coding to security scanning and pull requests.</p>
<p><img src="https://lh7-us.googleusercontent.com/PvE2opSVGyLXJMAnJmjz6RpU1s4OrZaRj5ylNaJdFMrMk9EDVVubPj4j9WnQthQaZ-uYAEvGLjKlg0rnInFXFknC2llW9CcaH6MQ9bF3L5O1L7YRDteu7CGDwHB6dsEGIEJFVzMjZre2RpiNglXf4v8" alt /></p>
<p>During the keynote, Thomas demonstrated Copilot's integration into <a target="_blank" href="http://GitHub.com">GitHub.com</a>, which allows users to generate detailed pull request descriptions directly from the editor. Copilot Chat was also integrated into <a target="_blank" href="http://GitHub.com">GitHub.com</a> and various IDEs such as Visual Studio, Visual Studio Code, and JetBrains to provide AI assistance across code editors.</p>
<p>GitHub Copilot's expansion includes Copilot X, Copilot Workspaces, Copilot Enterprise, Copilot Partner Program, Advanced Security, Copilot Chat on mobile, AI-powered regular expression assistants, and integration with external services like LaunchDarkly and Postman. Copilot now provides customization features, allowing organizations to tailor it to their needs.</p>
<p>The keynote also highlighted Accenture's collaboration with GitHub in creating low-latency, interactive user experiences for stateless microservices and integrating Copilot into its automation platforms.</p>
<p>Microsoft CEO Satya Nadella expressed his enthusiasm for GitHub Copilot, emphasizing its transformative impact on his coding experience. He highlighted Copilot's role in reducing drudgery, bringing joy back to coding, and the potential of natural language as a universal programming language.</p>
<p>The keynote concluded with a surprise announcement of a new feature that allows users to edit Copilot's plans, steering it in the right direction for optimal code synthesis, reminiscent of Steve Jobs's famous "One more thing" moments.</p>
<p><img src="https://lh7-us.googleusercontent.com/vOX4ndpFeLELQi1rd6yDzY9E-7rUrQsgo5iQ2RqkRgBj1o4RqH3IQumiHkWsC9c5L4jAGd8PKXxOCSV9HdVK-m9ejMqFCvlCLhBairQwKlxgi1rLqjMcQYNL-GxbdDvn1FetF98AXNrabDoozdCCTFQ" alt /></p>
<p>So starting from February 2024,  GitHub Copilot Enterprise will be generally available for $39 per user per month.</p>
<p>Copilot Enterprise allows developers to onboard quickly, search codebase and documentation, get suggestions based on private code, and review pull requests.</p>
<h2 id="heading-keynote-day-2-the-productivity-platform-for-all-developers">Keynote Day 2: The productivity platform for all developers</h2>
<p>GitHub's Chief Product Officer, Inbal Shani, delivered an interesting keynote speech on the second day of the event, emphasizing GitHub's mission to build the best developer tools and empower users in software development.</p>
<p><img src="https://lh7-us.googleusercontent.com/X3OPAtr09iMBfyoPLDjz1r03tyU-yFAtK41Y9-7zC88h3q0t1id3Iq0k1ErBHq1i-VRG7vXrqhr6fUBEieBC6HV7fVAVDkz1MTv5iavv8hDLZh5nauWdqtkHipglQUqXqUlO6iZMoogcOLJDJYHC800" alt /></p>
<p>Inbal discussed the increasing importance of AI across the software development lifecycle, and how GitHub is focused on meeting developer needs at every step. She highlighted the benefits of an AI-powered developer experience and GitHub's plans to provide an efficient workflow that not only serves as a business asset but also makes developers happy and addresses the world's toughest problems.</p>
<p>She also explained how GitHub's collaboration features, such as pull requests and discussions, simplify project management and enable scaling for distributed teams.</p>
<p>The keynote session also focused on GitHub's advanced security features, such as code scanning and dependency scanning, which have contributed to fixing 32 million security issues in 2023. This highlighted the importance of secure software development.</p>
<p>Automation was another key focus, with GitHub Actions helping developers automate workflows, reduce cognitive load, and improve efficiency. GitHub has introduced the new <a target="_blank" href="https://github.blog/2023-10-02-introducing-the-new-apple-silicon-powered-m1-macos-larger-runner-for-github-actions/#:~:text=Apple%20silicon%20powered%20M1%20macOS%20larger%20runners&amp;text=The%20M1%20macOS%20runner%20comes,and%2014%20GB%20of%20storage.">M1 Mac OS larger runners</a>, which enable faster build times and improved scalability.</p>
<p>In the keynote, Inbal reiterated the importance of GitHub's commitment to collaboration and security, with features and tools for project planning and tracking. Advanced security features such as code scanning, secret scanning, and supply chain security contribute to fixing security vulnerabilities 7x faster than the industry average. Dependency scanning is made available cost-free to the open-source community to enhance the safety of applications using open-source.</p>
<p>She also highlighted GitHub's compliance controls for organizations, repositories, and users, which enable administrators to manage their GitHub footprint effectively. Granular access permissions and roles are leveraged to provide better control over access and permissions for repositories. These are made possible with the Enterprise identity integration and features for <a target="_blank" href="https://docs.github.com/en/enterprise-server@3.6/admin/overview/about-github-enterprise-server">GitHub Enterprise Server</a>.</p>
<p>Finally, Inbal shared GitHub's initiatives for open-source support, including <a target="_blank" href="https://github.com/sponsors">GitHub Sponsors</a>, <a target="_blank" href="https://education.github.com/pack">GitHub Student Developer Pack</a>, and making Copilot free for teachers, students, and maintainers. This demonstrated GitHub's commitment to supporting the developer community and education.</p>
<h2 id="heading-github-awards-2023">GitHub Awards 2023</h2>
<p>At the event, exceptional projects and individuals in the GitHub Open Source community were recognized and celebrated for their contributions and achievements that have positively impacted the developer community.</p>
<p><img src="https://lh7-us.googleusercontent.com/TWaqewjE6GzpWAyPuo_cadSKcbBQf_Ypq8fqF3mo-1aHknVboSKRHuuOWyCap59G1g5gotaPOBVd2diVmy_iZ6bMov2nvaE0PvsW7FHsqxJpn35Vz_ai9XFhtIOSZ6K831NpH7sQiThsHVdpIhiZIbk" alt /></p>
<p>The awards were presented across several categories, including <a target="_blank" href="https://github.blog/2023-11-09-celebrating-the-github-awards-2023-recipients/#open-source-awards">Open Source</a>, <a target="_blank" href="https://github.blog/2023-11-09-celebrating-the-github-awards-2023-recipients/#education-awards">Education</a>, <a target="_blank" href="https://github.blog/2023-11-09-celebrating-the-github-awards-2023-recipients/#customer-awards">Customer</a>, and <a target="_blank" href="https://github.blog/2023-11-09-celebrating-the-github-awards-2023-recipients/#github-stars-awards">GitHub Stars</a>.</p>
<h2 id="heading-github-certification-testing">GitHub Certification Testing</h2>
<p>During the event, attendees were able to take the exclusive beta GitHub certification exams in person. Those who passed received an Official GitHub Certification in Foundations, Actions, Advanced Security, and Administration.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1699657618339/f402f6e7-4022-4a32-bd04-0071eb1a10f6.png" alt class="image--center mx-auto" /></p>
<p>This certificate is industry-endorsed and demonstrates proficiency with GitHub technologies. It is also complementary to Microsoft's existing role-based certifications, which validate knowledge of foundational DevOps and cloud development concepts.</p>
<p>The certification program is expected to be generally available in early 2024.</p>
<h2 id="heading-takeaways-from-github-universe-2023">Takeaways from GitHub Universe 2023</h2>
<p>The GitHub Universe 2023 event was not just a showcase of cutting-edge technologies; it was an invitation to the global developer community to actively engage in the future of software development. The event called developers to action, urging them to explore the newly unveiled GitHub Copilot features, customize them to organizational needs, and contribute to the ever-expanding ecosystem. As we move beyond the event's confines, it's important to stay connected. GitHub encourages event attendees and enthusiasts alike to join community forums, participate in open-source projects, and leverage the recently introduced Copilot API. Embrace the collaborative spirit that GitHub Universe fosters by following GitHub's social media channels, tuning into webinars, and participating in ongoing discussions. The journey doesn't end here; it evolves with each line of code, and GitHub ensures you're part of the narrative.</p>
<p>You can watch the online live stream at your convenience on the <a target="_blank" href="https://reg.githubuniverse.com/flow/github/universe23/sessioncatalog/page/sessioncatalog?search.deliveryformat=1692799009854004CQlx">Official GitHub Universe website</a>.</p>
<p>Mark your calendars for GitHub Universe 2024, which will take place in San Francisco, CA on October 29-30, 2024. <a target="_blank" href="https://reg.rainfocus.com/flow/github/universe23/presale/login">Presale tickets</a> are currently 60% off until November 17, 2023, so don't miss out!</p>
]]></content:encoded></item><item><title><![CDATA[What Is an Airdrop? A Guide for Community Managers]]></title><description><![CDATA[Building and managing a strong community is essential in the web3 era. As a community manager, your role is to create a space that attracts, engages, and motivates like-minded individuals. A strong community not only fosters collaboration, feedback, ...]]></description><link>https://blog.wolzcodelife.com/what-is-an-airdrop-a-guide-for-community-managers</link><guid isPermaLink="true">https://blog.wolzcodelife.com/what-is-an-airdrop-a-guide-for-community-managers</guid><category><![CDATA[crypto]]></category><category><![CDATA[community]]></category><category><![CDATA[marketing]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Blockchain]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Thu, 02 Nov 2023 23:26:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1698966137161/f0daf5bd-4ed5-481b-a60c-4ed842c76f23.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Building and managing a strong community is essential in the web3 era. As a community manager, your role is to create a space that attracts, engages, and motivates like-minded individuals. A strong community not only fosters collaboration, feedback, and support but also plays a pivotal role in the success of decentralized projects.</p>
<p>Understanding what motivates community members is key to your community's growth and impact. People in the blockchain and crypto space often join projects intending to find a lucrative source of income or investment while others genuinely believe in the mission and goals of the project. For instance, a developer seeking to build a secure dApp may gravitate toward the Ethereum community, given Ethereum's reputation as a secure blockchain network.</p>
<p>Your ultimate joy as a community manager lies in having members who genuinely believe in and contribute to the project's success. Decentralized communities also wield considerable influence over a project's direction. Hence, it's crucial to find effective ways to manage member behavior and expectations. This is where incentivization comes into play.</p>
<p>Incentivization is a proven strategy to encourage community members to actively contribute to a project's success. Incentives can take various forms, including bounties, referral programs, creative competitions, content creation, and airdrops. In this article, we'll focus on airdrops and how they can be leveraged as a rewarding mechanism within your community.</p>
<h2 id="heading-what-is-an-airdrop"><strong>What Is an Airdrop?</strong></h2>
<p>An airdrop is a marketing and promotional strategy involving the distribution of small amounts of a project's assets to individuals' wallet addresses at no cost. Participants receive airdrops as a reward for completing specific tasks, such as advertisements or referrals. This strategy is particularly popular among blockchain startups, aiming to raise awareness and stimulate the circulation of a new token, often associated with an <a target="_blank" href="https://www.investopedia.com/terms/i/initial-coin-offering-ico.asp#:~:text=Initial%20coin%20offerings%20(ICOs)%20are,have%20yielded%20returns%20for%20investors.">initial coin offering (ICO)</a>.</p>
<blockquote>
<p>😃 <strong>Fun Fact: The term "crypto airdrop" was inspired by physical airdrops that used aircraft to deliver resources, such as weapons, food, or medicine.</strong></p>
</blockquote>
<h3 id="heading-types-of-airdrops">Types of Airdrops?</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698966659737/45671b38-1b55-4369-b225-b723b41eab3e.png" alt class="image--center mx-auto" /></p>
<p>Airdrops are versatile and can be tailored to suit the specific goals and objectives of a project. Understanding the different types of airdrops can help you as a community manager to make informed decisions when planning your incentive programs. Here are the three main types of airdrops:</p>
<ol>
<li><p><strong>Standard Airdrop</strong></p>
<ul>
<li><p><em>Simplicity in Distribution:</em> Standard airdrops are perhaps the simplest form, making them accessible to a wide range of participants.</p>
</li>
<li><p><em>Minimal Requirements:</em> Participants typically only need to provide a valid wallet address, and in some cases, no additional information is required.</p>
</li>
<li><p><em>Token Limits:</em> These airdrops often have a predefined supply of tokens, and there may be a cap on the number of tokens each individual can receive.</p>
</li>
<li><p><em>Time Sensitivity:</em> Some standard airdrops are time-sensitive, creating a sense of urgency to participate.</p>
</li>
<li><p><em>Potential Challenges:</em> However, one challenge with standard airdrops is that individuals could create multiple wallets to maximize their rewards.</p>
</li>
</ul>
</li>
<li><p><strong>Bounty Airdrop</strong></p>
<ul>
<li><p><em>Task-Oriented Rewards:</em> Bounty airdrops, on the other hand, require participants to actively engage in specific tasks or actions to qualify for free tokens.</p>
</li>
<li><p><em>Task Examples:</em> These tasks may include promoting the project on social media, sharing posts, writing reviews, inviting friends, or participating in other project-related activities.</p>
</li>
<li><p><em>Point-Based Rewards:</em> Participants earn points for completing these tasks, and the number of points often determines the size of their bounty airdrop.</p>
</li>
<li><p><em>Qualification Thresholds:</em> Some bounty airdrops may have minimum point requirements for participants to be eligible for their airdrop.</p>
</li>
<li><p><em>Recruitment Incentives:</em> There could also be referral bonuses or finder's fees for those who bring in new participants.</p>
</li>
</ul>
</li>
<li><p><strong>Holder Airdrop</strong></p>
<ul>
<li><p><em>Rewarding Loyalty:</em> Holder airdrops automatically distribute tokens to users based on the amount of a particular cryptocurrency they hold in their wallets.</p>
</li>
<li><p><em>Public Ledger Transparency:</em> The blockchain's transparent ledger ensures that token distribution is fair and verifiable.</p>
</li>
<li><p><em>Downsides and Requirements:</em> However, this approach may not suit all participants, as some token holders may not desire additional airdrops.</p>
</li>
<li><p><em>Minimum Holdings:</em> In some cases, holder airdrops may require participants to hold a certain quantity of tokens to qualify, while others may provide pro-rated awards based on holdings.</p>
</li>
</ul>
</li>
</ol>
<p>Each type of airdrop has its unique advantages and challenges, all you need to do is, understand your project's goals and target audience and select the most suitable.</p>
<h2 id="heading-how-do-airdrops-work"><strong>How Do Airdrops Work?</strong></h2>
<p>Airdrops operate according to the goals and plans set by the project. Here's a typical process for how airdrops work:</p>
<ol>
<li><p><strong>Campaign Design:</strong> The company designs a campaign to announce airdrop details and eligibility requirements on its website, social media channels, or forums.</p>
</li>
<li><p><strong>Collecting Participant Details:</strong> The company gathers information from interested participants, including proof of meeting eligibility requirements (such as a link to a post or receipt of a specific amount of token purchase), wallet addresses, and optionally email addresses for newsletters and promotions.</p>
</li>
<li><p><strong>Eligibility Verification:</strong> The company validates participants' eligibility, often using smart contracts to capture instances that prove a participant met the criteria. For example, a snapshot might be taken to identify wallet addresses holding a minimum amount of tokens at a specific time and date.</p>
</li>
<li><p><strong>Token Distribution:</strong> The company dispatches tokens to participants' wallet addresses, either immediately after meeting the criteria or at a predetermined date, often during a project's launch.</p>
</li>
<li><p><strong>Usage and Benefits:</strong> Once participants receive their airdrops, they are free to use them as they see fit or follow the project's terms and conditions. Airdrops can take various forms, such as NFT access tokens for private events, in-game assets, or convertible assets.</p>
</li>
</ol>
<h2 id="heading-criticism-around-airdrops"><strong>Criticism Around Airdrops</strong></h2>
<p>Despite the growing popularity and success rate achieved by blockchain projects, there are still potential risks attributed to airdrops. Here are some criticisms that pose a challenge to airdrops:</p>
<ul>
<li><p><strong>KYC Forms:</strong> Some airdrops require users to complete KYC (Know Your Customer) forms, which may conflict with the principles of privacy and anonymity in web3.</p>
</li>
<li><p><strong>Dusting Attacks:</strong> Malicious actors may use airdrops to send small amounts of tokens (dust) to trace recipients' transactions, attempting to de-anonymize them.</p>
</li>
<li><p><strong>Illiquid Altcoins:</strong> In some cases, illiquid altcoin projects may use airdrops as a means to inflate token value temporarily and then "pump and dump" them, leaving investors with worthless tokens.</p>
</li>
</ul>
<p>Web3 users must conduct due diligence and verify the legitimacy of projects before sharing personal details or wallet addresses for airdrops.</p>
<h2 id="heading-whats-next"><strong>What's Next?</strong></h2>
<p>Now that you have a comprehensive understanding of airdrops and how they operate, you may be eager to explore this incentive mechanism. However, exercise caution to avoid falling victim to fraudulent projects.</p>
<p>Airdrops are just one element of the diverse tokenomics models available to web3 startups. If you are a community manager for a web3 project, consider crafting a strategic plan that aligns with your budget and the project's needs. And, if necessary, explore <a target="_blank" href="https://ninjapromo.io/web3-marketing-a-comprehensive-guide#10_Best_Web3_Marketing_Strategies_for_2023">other marketing and promotional strategies</a> to enhance your community's engagement and growth.</p>
]]></content:encoded></item><item><title><![CDATA[Top VSCode AI Extension Tools for Senior Devs]]></title><description><![CDATA[In software development, engineers make use of an endless list of tools to bring their ideas and innovations to life. There are tools like browsers, Command Line Interfaces(CLI), databases and more. Then there is the Integrated Development Environmen...]]></description><link>https://blog.wolzcodelife.com/top-vscode-ai-extension-tools-for-senior-devs</link><guid isPermaLink="true">https://blog.wolzcodelife.com/top-vscode-ai-extension-tools-for-senior-devs</guid><category><![CDATA[AI]]></category><category><![CDATA[vscode extensions]]></category><category><![CDATA[IDEs]]></category><category><![CDATA[Visual Studio Code]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Wed, 25 Oct 2023 23:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1698367794457/7df76082-4353-4627-b0dc-1da4f7a90758.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In software development, engineers make use of an endless list of tools to bring their ideas and innovations to life. There are tools like browsers, Command Line Interfaces(CLI), databases and more. Then there is the Integrated Development Environment(IDE) that helps developers build other software code and tools.</p>
<p>Code can be written in any text editor, but IDEs provide an environment specifically for software development processes like writing the code, testing, building and deploying. Some IDEs have inbuilt browsers, CLIs, databases, version control etc. while some allow you to install extensions of these tools into your IDE.</p>
<p>Among the popular IDEs are <a target="_blank" href="https://www.jetbrains.com/idea/">IntelliJ IDEA</a> for Java programming, <a target="_blank" href="https://www.jetbrains.com/ruby/">RubyMine</a> which primarily supports Ruby, <a target="_blank" href="https://www.jetbrains.com/pycharm/">PyCharm</a> for Python programming, <a target="_blank" href="https://www.jetbrains.com/phpstorm/">PhpStrom</a> for PHP programming, <a target="_blank" href="https://www.eclipse.org/ide/">Eclipse</a> which supports multiple languages, <a target="_blank" href="https://developer.android.com/studio">Android Studio</a> for Andriod app development and supports Kotlin and Java, <a target="_blank" href="https://developer.apple.com/xcode/">Xcode</a> for IOS app development and supports Object-C, C++ and Swift, <a target="_blank" href="https://aws.amazon.com/cloud9/">AWS Cloud9 IDE</a> which is cloud-based and support multiple languages, <a target="_blank" href="https://www.arduino.cc/">Arduino</a> which is mostly used for hardware programming, <a target="_blank" href="https://netbeans.apache.org/">NetBeans</a> which is one of the best IDE that support multiple languages and finally the IDE we will focus on in the article, although the list continues, <a target="_blank" href="https://visualstudio.microsoft.com/">Visual Studio Code(VSCode)</a> which is Microsoft-powered IDE and supports the multiple languages.</p>
<p>Each IDE caters to distinct developer preferences, and understanding their capabilities is crucial for selecting the right environment.</p>
<h2 id="heading-emphasizing-the-need-for-extensions">Emphasizing the Need for Extensions</h2>
<p>Senior developers recognize that while IDEs are robust on their own, they must enhance their capabilities through extensions. This is not just a preference; it's a necessity in today's dynamic coding landscape. AI extensions, in particular, are vital for more efficient and optimized development processes.</p>
<p>This doesn’t mean junior developers should not explore these tools, but you do not want to fully depend on them, as you need to learn some basic processes and understand how these things work before handing them over to AI to do them for you.</p>
<p>Traditionally, for a developer to implement version control in a new environment he/she might need to install a couple of software, set up configuration/authentication/authorization, and then run a series of commands in an external CLI tool. IDEs like VSCode have made these processes seamless by providing extensions that can automate some of these processes with just a single click or shortcut combination.</p>
<p>For instance, in VSCode, there is a <a target="_blank" href="https://code.visualstudio.com/docs/sourcecontrol/github">GitHub extension</a> that allows developers to quickly search, edit and commit to any remote repository they have access to directly from the VSCode environment.</p>
<blockquote>
<p>Life is not hard, you don't just have the right amount of information to make your life easier than it is. 😝</p>
</blockquote>
<h2 id="heading-top-vscode-ai-extensions">Top VSCode AI Extensions</h2>
<p>Now, let's explore the AI extensions that can truly supercharge your coding experience in VSCode. These are the top AI extensions designed to make your development process smoother, more efficient, and more enjoyable:</p>
<h3 id="heading-github-copilot">GitHub Copilot:</h3>
<p>Look at <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=GitHub.copilot">Copilot</a> as an assistant developer, developed by GitHub and OpenAI that helps you generate code from simple prompts that describe what you want to implement.</p>
<p>Here is an example of GitHub Copilot in use:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698632738186/40d15a99-1fed-4350-ab29-f740ee00e8ad.gif" alt="Example of GitHub Copilot Usage" class="image--center mx-auto" /></p>
<h3 id="heading-blackbox">Blackbox:</h3>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=Blackboxapp.blackbox">Blackbox</a> is an AI coding assistant that helps you provide code completion on the go, documentation and debugging suggestions. It also offers features like code chat, auto-completion, AI commit, code and comments suggestions and difference tracking.</p>
<p>Here is an example of Blackbox in use:</p>
<p><img src="https://i.postimg.cc/G229swYv/blackbox.gif" alt="Example of Blackbox Usage" /></p>
<h3 id="heading-tabnine">Tabnine:</h3>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=TabNine.tabnine-vscode">Tabnine</a>, another remarkable coding assistant, offers code chat, unit tests, documentation, legacy code explanation and code completion suggestions based on your code’s structure.</p>
<p>Here is an example of Tabnine in use:</p>
<p><img src="https://i.postimg.cc/wjyCMW73/tabnine.gif" alt="Example of Tabnine Usage" /></p>
<h3 id="heading-intellicode">Intellicode:</h3>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=VisualStudioExptTeam.vscodeintellicode">Intellicode</a> by Microsoft provides easy access to API usage example codes. With just a single click, you can access examples of 100k+ APIs and let you simulate how other developers will use APIs/functions given.</p>
<p>Here is an example of Intellicode in use:</p>
<p><img src="https://aka.ms/IntelliCodeUsageExamplesv2" alt="Example of Intellicode Usage" /></p>
<h3 id="heading-gitlens-ai">GitLens AI:</h3>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens">GitLens</a> provides rich code authorship visualization via Git blame annotations and CodeLens, allowing you to seamlessly navigate and explore Git repositories and gain valuable insights on repositories using powerful comparison commands.</p>
<p>Here is an example of GitLens AI in use:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698632980976/2a8b2890-1601-4ab4-9c74-f22cf9a7f74f.gif" alt="Example of GitLens AI Usage" class="image--center mx-auto" /></p>
<h3 id="heading-bito">Bito:</h3>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=Bito.Bito">Bito</a>, powered by ChatGPT and OpenAI, allows you to interact with a chatbot that supports GPT-4 and GPT Turbo 3.5 models in your VSCode. The chatbot provides complex code explanation, text creation, code editing, documentation and more.</p>
<p>Here is an example of Bito in use:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698632966761/860dba4c-a5b6-4e73-bdde-a5b62730098c.gif" alt="Example of Bito Usage" class="image--center mx-auto" /></p>
<h3 id="heading-mintlify-doc-writer">Mintlify Doc Writer:</h3>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=mintlify.document">Mintlify Doc Writer</a> is your savior when it comes to code documentation. It supports multiple documentation formats and programming languages and helps you create documentation once you highlight a code.</p>
<p>Here is an example of Mintlify Doc Writer in use:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698632947667/25db2aee-3162-4d52-bdc3-a6a5eb47f2c2.gif" alt="Example of Mintlify Doc Writer Usage" class="image--center mx-auto" /></p>
<h3 id="heading-denigma">Denigma:</h3>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=denigmaapp.denigma">Denigma</a> reads and explains code blocks in natural language. Simply highlight a section of code, right-click, and select to explain with Denigma. This tool comes in handy for technical writers.</p>
<p>Here is an example of Denigma in use:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1698632932588/8b568e1f-e16c-48f1-9f69-648ab38e28c3.gif" alt="Example of Degnima Usage" class="image--center mx-auto" /></p>
<h3 id="heading-codiumai">CodiumAI:</h3>
<p><a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=Codium.codium">CodiumAI</a> powered by GPT-3.5&amp;4 &amp; TestGPT-1, analyzes code and generates tests to catch bugs before you ship. It detects functions and blocks that need testing and creates test cases for each of them.</p>
<p>Here is an example of CodiumAI in use:</p>
<p><img src="https://i.postimg.cc/kgKTLL2N/codiumai.gif" alt="Example of CodiumAI Usage" class="image--center mx-auto" /></p>
<h2 id="heading-whats-next">What’s Next?</h2>
<p>I shouldn’t tell you what’s next, but I will do you the favour.</p>
<p>As we conclude our exploration of these remarkable VSCode AI extensions, it's your turn to take action. Experiment with these tools, elevate your development game and embrace the power they bring to your coding experience.</p>
]]></content:encoded></item><item><title><![CDATA[Build a Custom TikTok Autoplay React Hook With Intersection Observer]]></title><description><![CDATA[Have you ever wondered how social media applications like TikTok, Instagram, or Twitter detect a particular video post that is in the viewport, autoplay it, and then stop it immediately after it goes out of view?
In this article, I will explain how I...]]></description><link>https://blog.wolzcodelife.com/build-a-custom-tiktok-autoplay-react-hook-with-intersection-observer</link><guid isPermaLink="true">https://blog.wolzcodelife.com/build-a-custom-tiktok-autoplay-react-hook-with-intersection-observer</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Interaction Observer API]]></category><category><![CDATA[Tiktok]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Mon, 23 Oct 2023 11:00:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697109560616/a4262d8c-9cea-421d-8c00-a24cf0a24006.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Have you ever wondered how social media applications like TikTok, Instagram, or Twitter detect a particular video post that is in the viewport, autoplay it, and then stop it immediately after it goes out of view?</p>
<p>In this article, I will explain how Intersection Observer can be used to implement this autoplay and pause feature by creating a React custom Hook for use in a TikTok clone.</p>
<p>As a developer, you might want to implement an autoplay feature in a video player application, <a target="_blank" href="https://blog.logrocket.com/lazy-loading-using-the-intersection-observer-api/">lazy load an image</a>, or detect when an advertisement is in the viewport of a user’s browser. With Intersection Observer you can do all these.</p>
<h2 id="heading-what-is-intersection-observer"><strong>What is Intersection Observer?</strong></h2>
<p>Intersection Observer is a JavaScript browser API that asynchronously monitors the position of DOM elements with respect to the client’s viewport or a root element.</p>
<h3 id="heading-how-intersection-observer-works"><strong>How Intersection Observer works</strong></h3>
<p>Basically, the Intersection Observer API triggers a callback function in specific situations.</p>
<p>These situations include when the position of the selected element comes into the client’s viewport, when a selected element intersects a parent or root element, or when the observer is initially declared.</p>
<h3 id="heading-specifications-and-browser-compatibility"><strong>Specifications and browser compatibility</strong></h3>
<p>At the time of writing this article, the specifications are still a working draft<em>.</em> However, updates can be found <a target="_blank" href="https://w3c.github.io/IntersectionObserver/">here</a>.</p>
<p>As for the browser compatibility, here is the current report:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_27F54750736534E986D2E60F6C3491B4AFF8491308890171E1134DE46933F221_1632991834237_broswer_compatibility.png" alt /></p>
<h3 id="heading-applications-for-intersection-observer"><strong>Applications for Intersection Observer</strong></h3>
<p>Intersection Observer can be used for a wide variety of various applications outside of the scope of this article.</p>
<p>They include optional rendering of DOM elements, <a target="_blank" href="https://blog.logrocket.com/lazy-loading-using-the-intersection-observer-api/">l</a>azy <a target="_blank" href="https://blog.logrocket.com/lazy-loading-using-the-intersection-observer-api/">l</a>oading, loading content on-demand with <a target="_blank" href="https://blog.logrocket.com/react-hooks-infinite-scroll-advanced-tutorial/">infinite scrolling</a>, rendering advertisements and animations, and creating carousels.</p>
<p>The example I am using in this article (creating a custom autoplay Hook for a TikTok clone) can help you become familiar with the Intersection Observer API in order to start exploring the other options it can offer your apps.</p>
<h2 id="heading-using-intersection-observer"><strong>Using Intersection Observer</strong></h2>
<p>Firstly, we want to find out if our browser supports the Intersection Observer API.</p>
<p>We can write a condition to check, like so:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> (<span class="hljs-string">'IntersectionObserver'</span> <span class="hljs-keyword">in</span> <span class="hljs-built_in">window</span>) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"IntersectionObserver is supported!"</span>);
} <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"IntersectionObserver is not supported!"</span>);
}
</code></pre>
<p>The <code>ItersectionObserver</code> object is usually structured like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> options= {
    <span class="hljs-attr">root</span>: <span class="hljs-literal">null</span>,
    <span class="hljs-attr">rootMargin</span>: <span class="hljs-string">'0px'</span>,
    <span class="hljs-attr">threshold</span>: <span class="hljs-number">0.5</span>
};

<span class="hljs-keyword">const</span> callback = (entries){ <span class="hljs-comment">// entries = array of targeted elements</span>
    entries.forEach(<span class="hljs-function"><span class="hljs-params">entry</span>=&gt;</span>{
        <span class="hljs-comment">// what happens each entry</span>
    })
}

<span class="hljs-keyword">let</span> observerObj = <span class="hljs-keyword">new</span> IntersectionObserver(callback, options);
observerObj.observe();
</code></pre>
<p>Here, the <code>IntersectionObserver</code> object accepts two arguments. The <code>callback</code> function, which is triggered after Intersection Observer is executed, and an optional <code>options</code> object. This is an object with certain properties that determine when, and how, the Intersection Observer works.</p>
<h3 id="heading-the-callback-function"><strong>The</strong> <code>callback</code> function</h3>
<p>When the <code>callback</code> the function is executed, a list of targeted elements is checked by the Intersection Observer. These elements all have specific properties.</p>
<p>Examples of those properties are:</p>
<ul>
<li><p><code>boundingClientRect</code>:</p>
</li>
<li><p><code>intersectionRatio</code>:</p>
</li>
<li><p><code>intersectionRect</code></p>
</li>
<li><p><code>isIntersecting</code></p>
</li>
<li><p><code>rootBounds</code></p>
</li>
<li><p><code>target</code></p>
</li>
<li><p><code>time</code></p>
</li>
</ul>
<p>These properties are used to check the current element’s behavior relative to their root element.</p>
<p>In this article, we will be using <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry/isIntersecting"><code>isIntersecting</code></a> to check if the current entry is intersecting with the root. This will be the indicator that our video is in the viewport, and therefore ready to begin playing.</p>
<h3 id="heading-the-options-object"><strong>The</strong> <code>options</code> object</h3>
<p>The <code>options</code> object contains the following properties:</p>
<p>The <code>root</code> is the browser’s viewport by default, or if set as <code>null</code>. If an element is specified as the root, it has to be a parent to the targeted element. The root is what the targeted element needs to intersect with before the <code>callback</code> function is triggered</p>
<p>The <code>rootMargin</code> sets the margin around the root element before detecting the intersection. By default, it is 0 (which triggers the action exactly when the <code>root</code> property enters the viewport), but it can be valued in the same manner as a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/margin">CSS margin</a> in case you’d like the <code>callback</code> function to occur at a different moment.</p>
<p>The <code>threshold</code> represents what percentage of the targeted element should intersect <code>root</code> before the <code>callback</code> function is <a target="_blank" href="http://executed.It">executed.</a> It can be either a number or an array of numbers; the accepted values range from 0 to 1.</p>
<p>If it is 0, it means the first pixel of the target element needs to intersect with the <code>root</code> element before the <code>callback</code> function is executed. if it is 0.5, 50 per cent of the target element needs to intersect with the <code>root</code>, and so on.</p>
<h2 id="heading-targeting-an-element-to-be-observed"><strong>Targeting an element to be observed</strong></h2>
<p>To target an element with JavaScript, we have to use the <code>querySelector</code> function, which will search the DOM for a given <code>id</code> or <code>class</code>.</p>
<p>In React, we can use the <code>useRef</code> Hook to target an element. Then, we pass <code>targetElement</code> as a parameter in the observe function, like so:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/*
In JavaScript we can use querySelector to select a DOM element like this...
*/</span>
<span class="hljs-keyword">let</span> targetElement = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#item'</span>)
observerObj.observe(targetElement)

<span class="hljs-comment">//In React we can use the useRef hook like this...</span>
<span class="hljs-keyword">let</span> targetRef = useRef(<span class="hljs-literal">null</span>); <span class="hljs-comment">//Set a component to be ref of targetRef</span>
<span class="hljs-keyword">let</span> targetElement = targetRef.current
observerObj.observe(targetElement)
</code></pre>
<p>In the TikTok clone, we will be using the <code>useRef</code> Hook to target each video component in order to track when it comes into the viewport.</p>
<h1 id="heading-creating-an-intersection-observer-custom-hook-in-react"><strong>Creating an Intersection Observer custom Hook in React</strong></h1>
<p>To create a reusable Intersection Observer Hook, we will create a new function called <code>useElementOnScreen</code> and implement Intersection Observer using <code>options</code> and <code>targetRef</code> we passed in as props:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useEffect, useMemo, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
<span class="hljs-keyword">const</span> useElementOnScreen = <span class="hljs-function">(<span class="hljs-params">options, targetRef</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> [isVisibile, setIsVisible] = useState()
    <span class="hljs-keyword">const</span> callbackFunction = <span class="hljs-function"><span class="hljs-params">entries</span> =&gt;</span> {
        <span class="hljs-keyword">const</span> [entry] = entries <span class="hljs-comment">//const entry = entries[0]</span>
        setIsVisible(entry.isIntersecting)
    }
    <span class="hljs-keyword">const</span> optionsMemo = useMemo(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">return</span> options
    }, [options])
    useEffect(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">const</span> observer = <span class="hljs-keyword">new</span> IntersectionObserver(callbackFunction, optionsMemo)
        <span class="hljs-keyword">const</span> currentTarget = targetRef.current
        <span class="hljs-keyword">if</span> (currentTarget) observer.observe(currentTarget)

        <span class="hljs-keyword">return</span> <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">if</span>(currentTarget) observer.unobserve(currentTarget)
        }
    }, [targetRef, optionsMemo])
    <span class="hljs-keyword">return</span> isVisibile
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> useElementOnScreen
</code></pre>
<p>Having understood what the <code>options</code> and <code>targetRef</code> are, we need to pass them as props to the <code>useElementOnScreen</code> Hook, as we will need them as parameters for a new Intersection Observer function.</p>
<p>Then, we set a default state for the element’s <code>visibility</code> as <code>null</code>.</p>
<p>Inside the <code>callback</code> function, we are setting the <code>isVisible</code> state to the value returned if the targeted Element <code>isIntersecting</code> (we are always expecting <code>true</code> or <code>false</code>).</p>
<p>After observing the target element, we return the <code>isVisible</code> state. The returned value of <code>isVisible</code> is what we will use to decide when a video should play or stop.</p>
<p>If the <code>isVisible</code> state of a video component is <code>true</code> we play the video, else if it is <code>false</code> we stop the video.</p>
<h2 id="heading-using-the-intersection-observer-custom-hook-in-a-tiktok-clone"><strong>Using the Intersection Observer custom Hook in a TikTok clone</strong></h2>
<h3 id="heading-setting-up-the-application"><strong>Setting up the application</strong></h3>
<p>For the sake of brevity, I have created a starter project that contains the entire source code of the TikTok clone where we will implement the Intersection Observer hook we just created above. It is available on my <a target="_blank" href="https://github.com/wolz-CODElife/Tiktok-clone">GitHub repository</a>.</p>
<p>To start the application running, open your terminal to a new work folder and run the following commands:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/wolz-CODElife/Tiktok-clone.git

<span class="hljs-built_in">cd</span> Tiktok-clone

npm install
</code></pre>
<p>In the folder downloaded, the following files and directories should be present:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_27F54750736534E986D2E60F6C3491B4AFF8491308890171E1134DE46933F221_1633234797556_files.png" alt /></p>
<p>The files and folders we are working with are inside the <a target="_blank" href="http://src.As"><code>src</code>.As</a> shown above, I have already included the Intersection Observer hook that we created in the previous section of this article in the <code>hooks</code> directory. All that is remaining to do is to import the <code>useElementOnScreen</code> hooks in the TikTok application.</p>
<h3 id="heading-setting-up-autoplay"><strong>Setting up autoplay</strong></h3>
<p>Now, let’s update the <code>Video.js</code> component to play and stop a video depending on its visibility status.</p>
<p>Inside the <code>Video.js</code> file, put the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useEffect, useRef, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./Video.css"</span>;
<span class="hljs-keyword">import</span> VideoFooter <span class="hljs-keyword">from</span> <span class="hljs-string">"./VideoFooter"</span>;
<span class="hljs-keyword">import</span> VideoSidebar <span class="hljs-keyword">from</span> <span class="hljs-string">"./VideoSidebar"</span>;
<span class="hljs-keyword">import</span> useElementOnScreen <span class="hljs-keyword">from</span> <span class="hljs-string">'./hooks/useElementOnScreen'</span>
<span class="hljs-keyword">import</span> VideoPlayButton <span class="hljs-keyword">from</span> <span class="hljs-string">"./VideoPlayButton"</span>;
<span class="hljs-keyword">const</span> Video = <span class="hljs-function">(<span class="hljs-params">{ url, channel, description, song, likes, messages, shares }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [playing, setPlaying] = useState(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> videoRef = useRef(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> options = {
      <span class="hljs-attr">root</span>: <span class="hljs-literal">null</span>,
      <span class="hljs-attr">rootMargin</span>: <span class="hljs-string">'0px'</span>,
      <span class="hljs-attr">threshold</span>: <span class="hljs-number">0.3</span>
  }
  <span class="hljs-keyword">const</span> isVisibile = useElementOnScreen(options, videoRef)
  <span class="hljs-keyword">const</span> onVideoClick = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (playing) {
      videoRef.current.pause();
      setPlaying(!playing);
    } <span class="hljs-keyword">else</span> {
      videoRef.current.play();
      setPlaying(!playing);
    }
  };
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (isVisibile) {
      <span class="hljs-keyword">if</span> (!playing) {        
        videoRef.current.play();
        setPlaying(<span class="hljs-literal">true</span>)
      }
    }
    <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">if</span> (playing) {        
        videoRef.current.pause();
        setPlaying(<span class="hljs-literal">false</span>)
      }
    }
  }, [isVisibile])


  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"video"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">video</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"video_player"</span> <span class="hljs-attr">loop</span> <span class="hljs-attr">preload</span>=<span class="hljs-string">"true"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{videoRef}</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onVideoClick}</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{url}</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">video</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">VideoFooter</span> <span class="hljs-attr">channel</span>=<span class="hljs-string">{channel}</span> <span class="hljs-attr">description</span>=<span class="hljs-string">{description}</span> <span class="hljs-attr">song</span>=<span class="hljs-string">{song}</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">VideoSidebar</span> <span class="hljs-attr">likes</span>=<span class="hljs-string">{likes}</span> <span class="hljs-attr">messages</span>=<span class="hljs-string">{messages}</span> <span class="hljs-attr">shares</span>=<span class="hljs-string">{shares}</span> /&gt;</span>
      {!playing &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">VideoPlayButton</span> <span class="hljs-attr">onVideoClick</span>=<span class="hljs-string">{onVideoClick}</span> /&gt;</span>}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Video;
</code></pre>
<p>Here, we imported the custom Hook (<code>useElementOnScreen</code>), then used the value returned (which could be <code>true</code> or <code>false</code>) as the <code>isVisible</code> value.</p>
<p>Note that we set the following options for the Intersection Observer: <code>root</code> is <code>null</code>, which means we are using the window as a parent element. <code>rootMargin</code> is <code>0px</code>, and <code>threshold</code> is <code>0.3</code> which means once 30 per cent of the target element is in the viewport, the callback function is triggered.</p>
<p>Next, we use <code>UseEffect</code> to change the <code>playing</code> state of the video if the <code>isVisible</code> value changes, like so:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> (isVisibile) {
      <span class="hljs-keyword">if</span> (!playing) {        
        videoRef.current.play();
        setPlaying(<span class="hljs-literal">true</span>)
      }
    }
    <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">if</span> (playing) {        
        videoRef.current.pause();
        setPlaying(<span class="hljs-literal">false</span>)
      }
    }
</code></pre>
<p>This code means that, if the video is visible, the <code>playing</code> state is set to <code>true</code>. If it is not yet playing, and if the video is not visible, the <code>playing</code> state is set to <code>false</code>.</p>
<p>With this done, we can run the application with the following:</p>
<pre><code class="lang-bash">npm start
</code></pre>
<p>If everything goes well, we should have something like this:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_27F54750736534E986D2E60F6C3491B4AFF8491308890171E1134DE46933F221_1633236840410_GIF-2021-10-03-05-51-59.gif" alt /></p>
<p>If you wish to change the videos or even use a live database, edit the <code>video</code> state in <code>App.js</code>.</p>
<p>Currently, we have the following array of objects:</p>
<pre><code class="lang-json">[
    {
      url: 'https:<span class="hljs-comment">//res.cloudinary.com/codelife/video/upload/v1633232723/tiktok-clone/tiktok2_qxafx3.mp4',</span>
      channel: 'DanceCrew',
      description: 'Video by Lara Jameson from Pexels',
      song: 'Bounce - Ruger',
      likes: <span class="hljs-number">250</span>,
      messages: <span class="hljs-number">120</span>,
      shares: <span class="hljs-number">40</span>
    },
    {
      url: 'https:<span class="hljs-comment">//res.cloudinary.com/codelife/video/upload/v1633232725/tiktok-clone/tiktok1_np37xq.mp4',</span>
      channel: 'Happyfeet',
      description: '#happyfeetlegwork videos on TikTok',
      song: 'Kolo sound - Nathan',
      likes: <span class="hljs-number">250</span>,
      messages: <span class="hljs-number">120</span>,
      shares: <span class="hljs-number">40</span>
    },
    {
      url: 'https:<span class="hljs-comment">//res.cloudinary.com/codelife/video/upload/v1633232726/tiktok-clone/tiktok3_scmwvk.mp4',</span>
      channel: 'thiskpee',
      description: 'The real big thug boys💛🦋 The real big thug boys💛🦋 ',
      song: 'original sound - KALEI KING 🦋',
      likes: <span class="hljs-number">250</span>,
      messages: <span class="hljs-number">120</span>,
      shares: <span class="hljs-number">40</span>
    },
  ]
</code></pre>
<h1 id="heading-conclusion"><strong>Conclusion</strong></h1>
<p>Having created the application successfully, we should have learned how Intersection Observer works and how you can use it to implement an autoplay feature similar to that in TikTok or Instagram.</p>
<p>With this knowledge, you can try implementing lazy loading images, carousels or even an infinitely scrolling blog feeds page!</p>
<p>You can check the live demo of my TikTok clone <a target="_blank" href="https://wctiktok-4102d.web.app/">here</a>.I advise viewing it on a desktop browser for the best experience.</p>
<p>If you have any questions or remarks, please feel free to let me know in the comments.</p>
]]></content:encoded></item><item><title><![CDATA[Why You Should Use a Proxy Server With Create React App]]></title><description><![CDATA[There are many cases in which developers need to consume APIs from the backend while using Create React App (CRA) to build an application. Because most client apps are hosted on different servers than the backend application, there are complications ...]]></description><link>https://blog.wolzcodelife.com/why-you-should-use-a-proxy-server-with-create-react-app</link><guid isPermaLink="true">https://blog.wolzcodelife.com/why-you-should-use-a-proxy-server-with-create-react-app</guid><category><![CDATA[React]]></category><category><![CDATA[server]]></category><category><![CDATA[proxy]]></category><category><![CDATA[Proxy Server]]></category><category><![CDATA[create-react-app]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Fri, 20 Oct 2023 11:00:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697108972702/66bde796-cc6c-4149-b8b1-7a374292825d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There are many cases in which developers need to consume APIs from the backend while using Create React App (CRA) to build an application. Because most client apps are hosted on different servers than the backend application, there are complications that arise as a result of requests being sent across both servers. CRA supports proxying to mitigate or entirely eliminate these issues.</p>
<p>In this article, we will discuss what a proxy server is, why you should use a proxy server in development, and use cases for proxying requests in a React application. Then, we will implement a real-life example of setting up a proxy server in React.</p>
<h2 id="heading-what-is-a-proxy-server"><strong>What is a proxy server?</strong></h2>
<p>A proxy server is a system or application that acts as a conduit between a client application and the server when it requests resources.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_E153F985CCA0871B8F795BB0D02D161E6FDFF67FED461875497602FA6590BD2A_1645710516230_image.png" alt /></p>
<p>The diagram above illustrates how proxy servers work.When you make a request to a server, it is routed through the proxy, which receives the response from the server and transmits the information back to the client.</p>
<h2 id="heading-why-you-should-use-a-proxy-server-in-development"><strong>Why you should use a proxy server in development</strong></h2>
<p>You might be asking why it’s necessary to route some requests through a proxy before sending them to the server. The following scenarios need the use of a proxy server:</p>
<p>Need to protect your client from cross-site attacks? Proxy servers add an extra degree of protection by allowing server responses to be validated before being delivered to the client.They can be used as web filters and firewalls.</p>
<p>To avoid crashes, bandwidth must be conserved and server traffic must be regulated. Proxy servers can cache requests and server responses so that not all queries are transmitted to the server at the same time. This is typically done when dealing with static information and huge files.</p>
<p>Proxy servers are useful when client data must be protected or a request must be made anonymously.Proxy servers do not provide information to the server, such as the client’s location or IP address. Because the requests are not sent on a known network, this helps clients keep their data private by preventing hackers from intercepting important information.</p>
<p>Additionally, proxy servers can specify which requests are allowed and which are not. And finally, proxy servers can be used to log requests and the clients that make them within organizations that require it.</p>
<h2 id="heading-use-cases-for-proxying-requests-in-a-react-application"><strong>Use cases for proxying requests in a React application</strong></h2>
<p>After understanding why proxy servers are required, it is critical to understand real-life scenarios in which proxy servers can be implemented. Some examples of proxying requests in React applications are listed below.</p>
<p>First is requesting HTTPS APIs in development (<a target="_blank" href="https://localhost"><code>https://localhost</code></a>). Browsers have cross-origin limitations that block HTTPS API requests from HTTP sites running on <a target="_blank" href="http://localhost">localhost</a>. Proxy servers can assist in redirecting requests to APIs without having to go via the browser’s default request options, which helps to evade several cross-origin limitations.</p>
<p>The second step is fetching data from cross-origin APIs that don’t support CORs in web browsers. Certain APIs, regardless of the Hypertext Transfer Protocol, don’t support CORs for security concerns, and browsers impose same-origin policies to protect users from cross-site scripting (XSS). Proxy servers can be used to make API calls and then transmit the results to the web browser.</p>
<p>Finally, there is obtaining media resources from the server. A proxy server can be used to cache media files from the server, eliminating the need to send requests for such files to the server every time they are needed.</p>
<h2 id="heading-how-to-set-up-a-proxy-server-in-react"><strong>How to set up a proxy server in React</strong></h2>
<p>There are two common approaches to setting up proxy servers in React applications developed using CRA. We have the default CRA proxy option as well as the npm package <a target="_blank" href="https://www.npmjs.com/package/http-proxy-middleware">http-proxy-middleware</a>.</p>
<blockquote>
<p><em>Please note that these methods are only effective in the development. I recommend following these guides to implement proxies in production:</em></p>
<ul>
<li><p><a target="_blank" href="https://blog.logrocket.com/how-a-proxy-server-works-in-node-js/"><em>How to implement proxy server in Express</em></a></p>
</li>
<li><p><a target="_blank" href="https://blog.logrocket.com/how-to-run-a-node-js-server-with-nginx/"><em>How to use Nginx as a reverse proxy server</em></a></p>
</li>
</ul>
</blockquote>
<p>First, we will set up the application with CRA so we can set up the proxy servers.</p>
<h3 id="heading-create-react-app-setup"><strong>Create React App setup</strong></h3>
<p>Make sure you have Node installed on your computer to use CRA. Then, in a new directory, start a terminal and run the following command:</p>
<pre><code class="lang-bash">
npx create-react-app proxyclient &amp;&amp; <span class="hljs-built_in">cd</span> proxyclient
</code></pre>
<p>The command above will create a new directory called <code>proxyclient</code> and set the terminal directory to <code>/proxyclient</code>.The following folders and files should be present in the folder:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_E153F985CCA0871B8F795BB0D02D161E6FDFF67FED461875497602FA6590BD2A_1645752681620_image.png" alt /></p>
<p>The <code>package.json</code> file should also have a similar structure:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"proxyclient"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"0.1.0"</span>,
  <span class="hljs-attr">"private"</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">"dependencies"</span>: {
    <span class="hljs-attr">"@testing-library/jest-dom"</span>: <span class="hljs-string">"^5.16.2"</span>,
    <span class="hljs-attr">"@testing-library/react"</span>: <span class="hljs-string">"^12.1.3"</span>,
    <span class="hljs-attr">"@testing-library/user-event"</span>: <span class="hljs-string">"^13.5.0"</span>,
    <span class="hljs-attr">"react"</span>: <span class="hljs-string">"^17.0.2"</span>,
    <span class="hljs-attr">"react-dom"</span>: <span class="hljs-string">"^17.0.2"</span>,
    <span class="hljs-attr">"react-scripts"</span>: <span class="hljs-string">"5.0.0"</span>,
    <span class="hljs-attr">"web-vitals"</span>: <span class="hljs-string">"^2.1.4"</span>
  },
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"react-scripts start"</span>,
    <span class="hljs-attr">"build"</span>: <span class="hljs-string">"react-scripts build"</span>,
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"react-scripts test"</span>,
    <span class="hljs-attr">"eject"</span>: <span class="hljs-string">"react-scripts eject"</span>
  },
  <span class="hljs-attr">"eslintConfig"</span>: {
    <span class="hljs-attr">"extends"</span>: [
      <span class="hljs-string">"react-app"</span>,
      <span class="hljs-string">"react-app/jest"</span>
    ]
  },
  <span class="hljs-attr">"browserslist"</span>: {
    <span class="hljs-attr">"production"</span>: [
      <span class="hljs-string">"&gt;0.2%"</span>,
      <span class="hljs-string">"not dead"</span>,
      <span class="hljs-string">"not op_mini all"</span>
    ],
    <span class="hljs-attr">"development"</span>: [
      <span class="hljs-string">"last 1 chrome version"</span>,
      <span class="hljs-string">"last 1 firefox version"</span>,
      <span class="hljs-string">"last 1 safari version"</span>
    ]
  }
}
</code></pre>
<p>Edit the <code>App.js</code> file in the <code>src</code> folder to include the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  useEffect(<span class="hljs-function">() =&gt;</span> {
    fetch(<span class="hljs-string">'https://google.com/search?q=javascript'</span>)
      .then(<span class="hljs-function"><span class="hljs-params">resp</span> =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(resp);
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'======success======='</span>);
      })
      .catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'======failure======='</span>);
        <span class="hljs-built_in">console</span>.log(err);
      });
  }, [])
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>App<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  )
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App
</code></pre>
<p>Above, the <code>fetch</code> function is used to make a request to the cross-origin URL <a target="_blank" href="https://google.com/search?q=javascript"><code>https://google.com/search?q=javascript</code></a>.</p>
<p>The application server should then be started so that we can view the response. Run the following command in the project directory’s terminal to start the application server:</p>
<pre><code class="lang-bash">
npm start
</code></pre>
<p>By default, the above command will start listening on port 3000 on <a target="_blank" href="http://localhost"><code>localhost</code></a> or <code>127.0.0.1</code>.If you open a browser and type “<a target="_blank" href="http://localhost:3000">localhost:3000</a>,” you should see something like this in the console:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_E153F985CCA0871B8F795BB0D02D161E6FDFF67FED461875497602FA6590BD2A_1645753164561_image.png" alt /></p>
<h3 id="heading-using-a-cra-default-proxy"><strong>Using a CRA default proxy</strong></h3>
<p>To avoid this problem, we’ll define our CRA’s default proxy by including a <code>proxy</code> field in the <code>package.json</code> file like this:</p>
<pre><code class="lang-json">{
  ...,
  <span class="hljs-attr">"proxy"</span>: <span class="hljs-string">"https://www.google.com"</span>,
  ...
}
</code></pre>
<p>Then, in the <code>App.js</code> file, change the fetch request like so:</p>
<pre><code class="lang-javascript">fetch(<span class="hljs-string">'/search?q=proxy'</span>)
</code></pre>
<p>Above, we removed the origin and structured the request URL as if it were a same-origin request. The request should be successful, as shown in the browser console. It should output something like this:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_E153F985CCA0871B8F795BB0D02D161E6FDFF67FED461875497602FA6590BD2A_1645753533717_image.png" alt /></p>
<p>Take notice of the URL in the response; it was transmitted to the browser as a same-origin, which resulted in <a target="_blank" href="http://localhost:3000/search?q=proxy"><code>http://localhost:3000/search?q=proxy</code></a>, and the CORs error was gone.<br />The browser receives the request and transmits it to the proxy server, which then redirects the request to the actual API server specified in the <code>package.json</code> file.</p>
<p>We may also make requests to several servers by specifying the routes that should be used to target a specific domain. To accomplish this, we’ll structure our <code>proxy</code> field in the <code>package.json</code> file like so:</p>
<pre><code class="lang-json">{
  ...,
  <span class="hljs-attr">"proxy"</span>: {
    <span class="hljs-attr">"/search"</span> : {
      <span class="hljs-attr">"target"</span> : <span class="hljs-string">"https://www.google.com"</span>,
      <span class="hljs-attr">"changeOrigin"</span> : <span class="hljs-literal">true</span>
    },
    <span class="hljs-attr">"/jobs"</span> : {
      <span class="hljs-attr">"target"</span> : <span class="hljs-string">"https://stackoverflow.com"</span>,
      <span class="hljs-attr">"changeOrigin"</span> : <span class="hljs-literal">true</span>
    }
  }
  ...
}
</code></pre>
<p>Above, we defined two <code>paths</code>: <code>/search</code> and <code>/jobs</code>, which targets two separate domains.</p>
<p>When we execute a fetch request on <code>/jobs</code>, the browser sends the request as <a target="_blank" href="http://localhost:3000/jobs"><code>http://localhost:3000/jobs</code></a>, but the proxy server forwards it as <a target="_blank" href="https://stackoverflow.com/jobs"><code>https://stackoverflow.com/jobs</code></a>.</p>
<h2 id="heading-using-a-manually-created-proxy-in-create-react-app"><strong>Using a manually created proxy in Create React App</strong></h2>
<p>If you don’t want to use the default CRA proxy, you may use the <code>http-proxy-middleware</code> npm package. Just note that this feature is available in <code>react-scripts@2.0.0</code> or higher.</p>
<p>This package must be installed as a project dependency before it can be used. To do so, open a terminal and execute the following command in the project directory:</p>
<pre><code class="lang-bash">npm i http-proxy-middleware --save
</code></pre>
<p>Ensure you don’t have proxy defined in the <code>package.json</code> file, then create a new file named <code>setupProxy.js</code> in the <code>src</code> directory. Add the following code snippet to the <code>setupProxy.js</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { createProxyMiddleware } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http-proxy-middleware'</span>);
<span class="hljs-keyword">const</span> proxy = {
    <span class="hljs-attr">target</span>: <span class="hljs-string">'https://www.google.com'</span>,
    <span class="hljs-attr">changeOrigin</span>: <span class="hljs-literal">true</span>
}
<span class="hljs-built_in">module</span>.exports = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">app</span>) </span>{
  app.use(
    <span class="hljs-string">'/search'</span>,
    createProxyMiddleware(proxy)
  );
};
</code></pre>
<p>The code snippet above exports a function to the application so that the proxy middleware is registered to the application as soon as the development server starts up, without the need to import it into any file. Once the application is launched, it will start automatically.</p>
<p>We used <code>createProxyMiddleware</code> from <code>http-proxy-middleware</code> that we installed previously to register a proxy target for <code>/search</code>.</p>
<p>In cases when there are several proxy targets, we simply call the <code>app.use</code> function as follows:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { createProxyMiddleware } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http-proxy-middleware'</span>);
<span class="hljs-keyword">const</span> proxy = {
    <span class="hljs-attr">target</span>: <span class="hljs-string">'https://www.google.com'</span>,
    <span class="hljs-attr">changeOrigin</span>: <span class="hljs-literal">true</span>
}
<span class="hljs-keyword">const</span> proxy2 = {
    <span class="hljs-attr">target</span>: <span class="hljs-string">'https://www.stackoverflow.com'</span>,
    <span class="hljs-attr">changeOrigin</span>: <span class="hljs-literal">true</span>,
}
<span class="hljs-built_in">module</span>.exports = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">app</span>) </span>{
  app.use(
    <span class="hljs-string">'/search'</span>,
    createProxyMiddleware(proxy)
  );


  app.use(
    <span class="hljs-string">'/jobs'</span>,
    createProxyMiddleware(proxy2)
  );
};
</code></pre>
<p>Above, we called the <code>app.use</code> method after creating another object named <code>proxy2</code> that included the proxy parameters of the other target domain in order to construct a proxy middleware.</p>
<h1 id="heading-conclusion"><strong>Conclusion</strong></h1>
<p>You may expect better security, confidential requests, regulated requests, and other benefits when you use proxy servers in your client <a target="_blank" href="http://applications.Now">applications.</a> Now that you know why and how to use a dev proxy server with CRA, I encourage you to put it to use in your next project.</p>
]]></content:encoded></item><item><title><![CDATA[8 Best Ways to Define Component Spacing in a Design System]]></title><description><![CDATA[Design systems are made up of UI components such as checkboxes, buttons, textfields and so on, and incorporate many design scaffolding ideologies. However, one important aspect of these systems that receives little attention is spacing.
Every design ...]]></description><link>https://blog.wolzcodelife.com/8-best-ways-to-define-component-spacing-in-a-design-system</link><guid isPermaLink="true">https://blog.wolzcodelife.com/8-best-ways-to-define-component-spacing-in-a-design-system</guid><category><![CDATA[components]]></category><category><![CDATA[Design Systems]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Thu, 19 Oct 2023 11:00:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697108170775/8ebe6e3c-c8fa-4fbb-a3ff-c1e686070a3a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Design systems are made up of UI components such as checkboxes, buttons, textfields and so on, and incorporate many design scaffolding ideologies. However, one important aspect of these systems that receives little attention is spacing.</p>
<p>Every design system’s essential characteristic is space, which determines whether or not other components can be accommodated and where they are placed. The concept of spacing and the standardization of <a target="_blank" href="https://blog.logrocket.com/getting-started-floating-ui/">UI component</a> spacing are grouped under a design ideology called the spacial system.</p>
<p>In this article, we will look at how the spatial system affects design systems, how to standardize spacing using spatial system principles, and some best practices for spacing components in design systems.</p>
<p>The only thing you will need to understand this tutorial is working knowledge of HTML and CSS.</p>
<h2 id="heading-how-a-spatial-system-plays-a-role-in-a-design-system"><strong>How a spatial system plays a role in a design system</strong></h2>
<p>A spatial system is a collection of design guidelines that coordinate the spacing, sizing, and measurement of UI components in <a target="_blank" href="https://www.interaction-design.org/literature/article/the-power-of-white-space">white space</a>. Prioritizing the spatial system ensures uniformity and consistency, and enhances the user experience.</p>
<p>The following are four examples of spatial systems that can be used and suggested:</p>
<h3 id="heading-4-point-grid-system"><strong>4-point grid system</strong></h3>
<p>The 4-point grid system is a rigid grid layout based on incrementing space values by multiples of four.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_14230E1026DAE47A844B6E65A64E4868CE2D77711EEB36E14798D906E2F764C1_1646967090586_image.png" alt /></p>
<h3 id="heading-8-point-grid-system"><strong>8-point grid system</strong></h3>
<p>This spatial system, like the 4-point grid system, is based on increments of space values by multiples of eight.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_14230E1026DAE47A844B6E65A64E4868CE2D77711EEB36E14798D906E2F764C1_1646966670306_image.png" alt /></p>
<h3 id="heading-simple-grid-system"><strong>Simple grid system</strong></h3>
<p>This spatial system is built on a 12 column rule offered by the standard CSS style guide. Every row with a 100vw of media has these 12 columns.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_14230E1026DAE47A844B6E65A64E4868CE2D77711EEB36E14798D906E2F764C1_1646967643861_image.png" alt /></p>
<h3 id="heading-flexbox-grid-system"><strong>Flexbox grid system</strong></h3>
<p>The <a target="_blank" href="https://blog.logrocket.com/how-to-build-a-basic-flexbox-layout-a-tutorial-with-examples/">flexbox grid system</a> is derived from the basic CSS flex display property.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_14230E1026DAE47A844B6E65A64E4868CE2D77711EEB36E14798D906E2F764C1_1649457482743_image.png" alt /></p>
<h2 id="heading-what-to-consider-when-implementing-a-spatial-system"><strong>What to consider when implementing a spatial system</strong></h2>
<p>Spatial systems may be applied to UI attributes such as margins, paddings, z-indexes, and borders, among many others.</p>
<p>You should always specify a base unit before adding spatial systems to a design. This will help you to evaluate which spatial system you will use in your design. You’ll notice certain differences in the pattern of size increments in different designs. Some designs employ 4pt, 5pt, 6pt, 8-point, and 10pt increment schemes, as well as irregular increments. There’s nothing wrong with picking a different system to use, as long as it’s defined and there’s a good rationale for it.</p>
<p>There are several variables to assess when selecting a spatial system to decide whether it is appropriate for the use case. The following are some of these variables:</p>
<h3 id="heading-user-needs"><strong>User needs</strong></h3>
<p>Consider how users will interact with your design when considering spatial systems. Do they require larger typography to access information, or do they require less space to access a feature? Before deciding which spatial system is appropriate, user testing and surveys should be conducted for how users will interact with a design.</p>
<h3 id="heading-adaptability"><strong>Adaptability</strong></h3>
<p>This is a feature of a design that allows it to be displayed in any format, including landscape or portrait in small and large devices. When constructing a design with this attribute, the spatial system’s flexibility and size alternatives are critical.</p>
<h3 id="heading-responsiveness"><strong>Responsiveness</strong></h3>
<p>A responsive design is flexible and adaptable to changing circumstances. Choosing a spatial system for this sort of design will also necessitate a great deal of size flexibility and control.</p>
<h3 id="heading-strictness"><strong>Strictness</strong></h3>
<p>This design is difficult to adapt to changes and is difficult to fit into a variety of layouts or media sizes. As a result, it’s critical to choose a spatial system that will maintain the design acceptable on every layout it’s displayed on.</p>
<p>These variables are also influenced by the units used to measure the design dimension’s points. As stated previously, there are designs that allow for flexibility or rigidity in both the units and the designs.</p>
<p>The three most common design units are em, rem, and pixels. Pixels are rigid and precise, but ems and rems are variable and based on the parent element’s font size.</p>
<h2 id="heading-comparing-em-rem-and-pixel-units"><strong>Comparing em, rem, and pixel units</strong></h2>
<p>Em is the em value multiplied by the parent element’s font size’s pixel <a target="_blank" href="http://value.As">value.</a> As a result, if an element’s parent has a font size of 32px, the element’s 10em will look like</p>
<p><img src="https://s0.wp.com/latex.php?latex=32px%2A10%3D320px&amp;bg=ffffff&amp;fg=000&amp;s=0&amp;c=20201002" alt="32px*10=320px" /></p>
<p>Rem is the pixel value of the root element’s font size of an HTML page multiplied by the rem <a target="_blank" href="http://value.As">value.</a> As a result, if an element’s root font size is 64px, the element’s 5rem will be</p>
<p><img src="https://s0.wp.com/latex.php?latex=64px+%2A+5%3D320px&amp;bg=ffffff&amp;fg=000&amp;s=0&amp;c=20201002" alt="64px * 5=320px" /></p>
<p>The pixel value of the element size is the actual pixel value. If the element’s size is 1px, so is the pixel value.</p>
<p>Let us look at some instances of how to apply a spatial system design now that we have a better understanding of the elements that decide which spatial system to employ, and the units of spatial systems in design.</p>
<h2 id="heading-applying-a-spacial-system-in-web-design"><strong>Applying a spacial system in web design</strong></h2>
<p>Because it is a fairly popular and suggested system to adopt, I have picked the 8-point grid system to show how spatial systems might be used in design in this article. We’ll talk about how to apply this approach to the following spatial properties.</p>
<p>First, let’s discuss the margin. The margin is an empty space between UI components that is offset from the component’s border. Here’s an example of how to use margins in an 8-point grid system.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_14230E1026DAE47A844B6E65A64E4868CE2D77711EEB36E14798D906E2F764C1_1647040422843_image.png" alt /></p>
<p>The padding is the empty space between a UI component’s border and its content; it is inset to the component’s border and outset to the component’s content. Here’s an example of how to use paddings in an 8-point grid system.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_14230E1026DAE47A844B6E65A64E4868CE2D77711EEB36E14798D906E2F764C1_1647041024342_image.png" alt /></p>
<p>The border is a visibly spaced line around the boundaries of a component. Here’s an example of how to use borders in an 8-point grid system.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_14230E1026DAE47A844B6E65A64E4868CE2D77711EEB36E14798D906E2F764C1_1647043834803_image.png" alt /></p>
<p>The line height is the gap that contains the content of a line of text. The size of the text that may be handled in one line is determined by the line height. Here’s an example of how to use line height in an 8-point grid system.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_14230E1026DAE47A844B6E65A64E4868CE2D77711EEB36E14798D906E2F764C1_1647043814367_image.png" alt /></p>
<p>Shadows are a visual effect that uses space slightly out or inside an element to project the light’s perspective on it. Depending on the shadow style, shadows have either a margin or padding overlay (inset or outset). Here’s an example of how to use shadow in an 8-point grid system.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_14230E1026DAE47A844B6E65A64E4868CE2D77711EEB36E14798D906E2F764C1_1647039997786_image.png" alt /></p>
<h2 id="heading-8-best-ways-to-define-component-spacing-in-a-design-system"><strong>8 best ways to define component spacing in a design system</strong></h2>
<p>When designing, using the best or most suggested spatial system is insufficient. There are a number of other practices that can help to improve a design’s outcome. Let’s take a look at some of the best practices for spacing components in design systems.</p>
<p>The first step is to create a wireframe for your white space design. Before commencing the real design, it’s critical to map out the information hierarchy and how to handle white space. This will limit the number of extraneous edits or modifications.</p>
<p>Second, try adopting the <a target="_blank" href="https://www.usertesting.com/blog/gestalt-principles#:~:text=The%20principle%20of%20proximity%20states,that%20are%20spaced%20farther%20apart.&amp;text=Proximity%20is%20so%20powerful%20that,differentiate%20a%20group%20of%20objects.">Gestalt principle</a> of proximity. Using the Gestalt principle helps us learn how to quickly communicate information to our audience through the utilization of space. This will aid in maximizing existing resources for information transmission, even if they are insufficient.</p>
<p>Third, set memorable base numbers and expectations. Most people are familiar with a base 10 number system, so this makes predicting the next value in a sequence easy.</p>
<p>Fourth, try scaling with fixed increments. When working with components of varying sizes, remembering the next level of measurement might be challenging. It will be easy to figure out which value comes next in succession if the measurement has a set pattern of increments.</p>
<p>Fifth, name dimensions for easy reuse. Sizes and measurements named for easy memorization and reusability by others, as embraced by design systems like Bootstrap and Material UI, are helpful.</p>
<p>A collection of dimensions, for example, may be called as follows:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">margin</span>: 8<span class="hljs-selector-tag">px</span>; // <span class="hljs-selector-tag">m-sm</span>
<span class="hljs-selector-tag">margin</span>: 16<span class="hljs-selector-tag">px</span>; // <span class="hljs-selector-tag">m-md</span>
<span class="hljs-selector-tag">margin</span>: 32<span class="hljs-selector-tag">px</span>; // <span class="hljs-selector-tag">m-lg</span>
<span class="hljs-selector-tag">margin</span>: 64<span class="hljs-selector-tag">px</span>; // <span class="hljs-selector-tag">m-xlg</span>
</code></pre>
<p>People will be able to read meaningful names to the measurements instead of remembering figures, or having to do a calculation every time the dimensions are needed, if standard size naming is used, such as sm (small), md (medium), and lg (large).</p>
<p>Sixth, use the grid as a component and not as space. Grid is a component that utilizes space, yet it is frequently misunderstood as a space itself. Even when utilizing grids, it’s still vital to manage space (margin, padding, gutter, and so on).</p>
<p>Seventh, handle overwriting the default line height. When dealing with textual content, many individuals overlook the amount of space that the text takes up. There will be inconsistent line height, especially in circumstances where the font size fluctuates, which will affect the design by creating disordered whitespace or even clusters.</p>
<p>Finally, organize content and <a target="_blank" href="https://www.justinmind.com/blog/visual-hierarchy/">visual hierarchy</a>. Prioritizing the arrangement of information is critical when using space. Communication may not be effective if content is not organized logically according to its importance.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>After reading this article, readers should have a better understanding of the importance of spacing in design systems and how to use spatial systems. There are a number of other design system aspects that were not covered in depth in this <a target="_blank" href="http://article.To">article.</a> To discover more about design systems, visit <a target="_blank" href="https://www.designsystems.com/">https://www.designsystems.com/</a>.</p>
<p>If you have any more questions or comments, please leave them in the comments section below.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Progressive Enhancement]]></title><description><![CDATA[In web development, there are several approaches to content distribution, but most developers simply employ static or dynamic content delivery without considering user accessibility. Putting accessibility first in web design is a must, because if an ...]]></description><link>https://blog.wolzcodelife.com/understanding-progressive-enhancement</link><guid isPermaLink="true">https://blog.wolzcodelife.com/understanding-progressive-enhancement</guid><category><![CDATA[ProgressiveDelivery]]></category><category><![CDATA[Progressive Enhancement]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Wed, 18 Oct 2023 11:00:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697107564618/942a8a5a-a413-4beb-a45f-d82eb916a717.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In web development, there are several approaches to content distribution, but most developers simply employ static or dynamic content delivery without considering user accessibility. Putting accessibility first in web design is a must, because if an application’s content is inaccessible, many people will be unable to interact with the application, regardless of whether it is static or dynamic.</p>
<p>Many developers create PWAs (progressive web applications) to create accessible, native-like experiences for their users, but they do not understand what they are or why they are called “progressive.”The phrase “progressive enhancement,” which we will discuss later in this article, is inspired the “progressive” in PWA. As a developer, it’s important to know why progressive enhancement is a necessary piece of knowledge to have in your tool belt.</p>
<p>In this article, we’ll go over the basic principles of progressive enhancement, as well as the relevance and criticisms of using it in web development.</p>
<h2 id="heading-what-is-progressive-enhancement"><strong>What is progressive enhancement?</strong></h2>
<p>Progressive enhancement is a web design methodology that ensures that the content of the web app reaches all users first, regardless of their digital advantage, before those with more advanced browser features and internet connection receive augmented content.</p>
<p>In “graceful degradation,” web content is designed for the best experience and delivered to users with the latest browser versions first, then degraded to work well with older browser versions. Progressive enhancement does the opposite.</p>
<p>The rule of “separation of presentation and content, separation of content and style, or separation of semantics and presentation” is also known as progressive enhancement in markup circles.</p>
<h2 id="heading-core-principles-of-progressive-enhancement"><strong>Core principles of progressive enhancement</strong></h2>
<p>There are a number of guidelines that will help you stick to the progressive enhancement approach to web design. They are as follows:</p>
<p>First, all web browsers should be able to access basic content.There are a variety of web browsers available, each with its own set of features and <a target="_blank" href="http://capabilities.It">capabilities.It</a> may be hard to design a website that works with all of the different browsers available. However, there are <a target="_blank" href="https://en.wikipedia.org/wiki/Web_standards">global web standards</a> that are accepted by all browsers.</p>
<p>Prior to implementing new features to explore specific browsers, websites should follow web standards to ensure that they are accessible to everyone.</p>
<p>Second, basic functions and standard events should be available in all web browsers. Before implementing custom events to handle advanced functionalities, it is vital to use all of the normal DOM events to manage user experience while constructing websites.</p>
<p>Third, all content should be contained in minimal, semantic markup. In web design, it is critical to focus on content delivery rather than aesthetics. The content of the website should be correctly structured, as allowed by standard semantic HTML. For example, instead of pictures of text, suitable typography HTML semantics can be used to show text. This enhances the website’s content accessibility for people who may not be able to view images.</p>
<p>Fourth, externally connected JavaScript should provide enhanced functionality. The usage of third-party JavaScript libraries to provide expanded functionality should come after the site has proven that it can provide basic functionality to users who do not have access to such third-party libraries.Even though certain web browsers do not enable JavaScript, users should still be able to access and interact with some information.</p>
<p>Fifth, CSS that is externally connected should provide improved layout. Users should be able to see the website without any CSS styling and it would still be presentable.The purpose of CSS styling is to improve the layout of a website and offer some additional designs that HTML cannot supply.The usage of CSS should not be misused to the detriment of the website’s accessibility. For experimental or nonstandard style attributes, CSS additionally supports <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/Vendor_Prefix">vendor prefixes</a>.</p>
<p>Lastly, end-user web browser preferences should be respected. Users should be able to use whichever browser they wish, and should not be compelled to use a certain browser in order to access website content.</p>
<h2 id="heading-practical-examples-of-progressive-enhancement"><strong>Practical examples of progressive enhancement</strong></h2>
<p>Have you ever come across a website feature that is available when your computer is connected to the internet, but unavailable when your computer is disconnected from the internet? This is a regular occurrence in progressive web applications (PWAs), which are a perfect demonstration of progressive enhancement.</p>
<p>There are other examples, such as alternative content if JavaScript is not enabled in the client’s browser. In frameworks like Angular, Vue, or React, an error handler is required to show alternative content from the application if JavaScript is not enabled in the client’s browser. This is because the application will not operate properly if JavaScript is disabled, thus, rather than putting the user through the pain of accessing an application that isn’t entirely functioning, the developer provides alternate content.</p>
<p>It’s common practice in React to add a <code>noscript</code> tag with a message indicating that JavaScript is necessary for the app to execute. This tag may be found in the <code>body</code> tag of the <code>index.html</code> file in the <code>public</code> folder in apps produced with <code>create-react-app</code>. It appears as follows:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">noscript</span>&gt;</span>You need to enable JavaScript to run this app.<span class="hljs-tag">&lt;/<span class="hljs-name">noscript</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"root"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
</code></pre>
<p>Web fonts are another example of progressive enhancement. When custom fonts are used to style a website, they may not be supported by all browsers, or may take a long time to load. If the custom font fails to load, the developer provides a fallback font.</p>
<p>Here’s an example of importing an alternate font, but using the default font:</p>
<pre><code class="lang-css">
<span class="hljs-keyword">@import</span> url(<span class="hljs-attribute">https:</span>//fonts.googleapis.com/css?family=Open+Sans);

<span class="hljs-selector-tag">body</span>{
   <span class="hljs-attribute">font-family</span>: <span class="hljs-string">'Open Sans'</span>, sans-serif;
}
</code></pre>
<p>Above, we imported <code>Open Sans</code> and set the body <code>font-family</code> to <code>Open Sans, sans-serif</code>. <code>sans-serif</code>, which was added to the font list, is a generic typeface that is supported by nearly all browsers. If the imported font (<code>Open Sans</code>) fails to load, the <code>font-family</code> will be changed to <code>san-serif</code>.</p>
<p>Our final example of progressive enhancement concerns HTML5. When using the HTML5 video element, you may define the text that will be displayed if the browser does not support videos or the file type. It’s often done by inserting text between the opening and closing tags, as shown below:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">video</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"320"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"240"</span> <span class="hljs-attr">controls</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">source</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"movie.mp4"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"video/mp4"</span>&gt;</span>
  Your browser does not support the video tag.
<span class="hljs-tag">&lt;/<span class="hljs-name">video</span>&gt;</span>
</code></pre>
<p>If your browser does not support the video element, the words “Your browser does not support the video tag” will appear in the video’s section.</p>
<h2 id="heading-why-you-should-apply-progressive-enhancement-to-your-web-app"><strong>Why you should apply progressive enhancement to your web app</strong></h2>
<p>When it comes to online content delivery, there are a variety of challenges that might arise that can be caused by either the user or the developer. Progressive enhancement is a solution that was created to mitigate the consequences of these issues, or at the very least provide the end-user with some, if not all, information.</p>
<p>Other reasons to consider practicing progressive enhancement include:</p>
<ul>
<li><p>Improved SEO: using HTML semantics correctly on a website will boost the SEO of that site, because the information will be more accessible to screen readers, web spiders, and search engines</p>
</li>
<li><p>Improved compatibility and accessibility: the website’s content should be able to load on a variety of devices, so if a user’s device or browser does not support the language used to develop the website, there will be fewer errors</p>
</li>
<li><p>Simple scalability: the website should reach its widest audience while still delivering adequate information.Programmers should be sure they can raise their workload while still delivering information to users</p>
</li>
<li><p>Improved speed and user experience: using suitable semantics enhances the rate at which the contents are loaded, and when a website loads its contents quickly, the user experience is enhanced</p>
</li>
</ul>
<h2 id="heading-how-to-implement-progressive-enhancement"><strong>How to implement progressive enhancement</strong></h2>
<p>The fundamentals of progressive enhancement in web design are to supply the user with the appropriate content they need if the upper layer of the web design is unavailable.</p>
<p>For example, say we have a site designed with JavaScript as the third layer, CSS as the second layer, and HTML as the first layer. The site design should work fine even if the JavaScript isn’t there, implying that JavaScript is only a supplement to what is already working properly.</p>
<p>Let’s have a look at how this works with a sample dropdown button.</p>
<h3 id="heading-first-layer-html"><strong>First layer: HTML</strong></h3>
<p>This layer is a semantic markup that allows text-based, archaic browsers, screen readers, and user agents to correctly browse and access the website’s content.</p>
<p>For the dropdown button, here’s an example of semantic markup:</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">"X-UA-Compatible"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"IE=edge"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Dropdown<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"dropbtn"</span>&gt;</span>Navigation Menu<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"ul"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/home"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/about"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>About<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/contact"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>Contact<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/signin"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>Signin<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>The dropdown menu is organized in an unordered list, and the button is currently not functional. As a result, the menu list will remain static, with no ability to collapse or expand it.</p>
<p>When you run the above code in your browser, you should see the following:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_328FC621C36F4FE2DAE2507357541272A8F2DDAEC1E8AD4B2CCF09C2F4A63E3B_1650896891332_image.png" alt /></p>
<h3 id="heading-second-layer-css"><strong>Second layer: CSS</strong></h3>
<p>This is the initial layer of additional functionality. CSS may or may not bring functionality to a webpage; it is mostly used to organize and enhance the layout in order to give the website a more visually appealing appearance.</p>
<p>An example of a CSS enhancement is as follows:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
    <span class="hljs-selector-tag">button</span> {
        <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">20px</span>;
        <span class="hljs-attribute">border</span>: none;
        <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span> <span class="hljs-number">20px</span>;
        <span class="hljs-attribute">cursor</span>: pointer;
        <span class="hljs-attribute">background</span>: <span class="hljs-number">#ccc</span>;
        <span class="hljs-attribute">transition</span>: all ease <span class="hljs-number">0.2s</span>;
    }
    <span class="hljs-selector-tag">button</span><span class="hljs-selector-pseudo">:hover</span> {
        <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">2px</span> <span class="hljs-number">2px</span> <span class="hljs-number">4px</span> <span class="hljs-built_in">rgb</span>(<span class="hljs-number">90</span>, <span class="hljs-number">90</span>, <span class="hljs-number">90</span>);
        <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">invert</span>(<span class="hljs-number">1</span>);
    }
    <span class="hljs-selector-tag">ul</span> {
        <span class="hljs-attribute">list-style</span>: none;
        <span class="hljs-attribute">padding</span>: <span class="hljs-number">0px</span>;
        <span class="hljs-attribute">width</span>: <span class="hljs-number">250px</span>;
    }
    <span class="hljs-selector-class">.active</span> {
        <span class="hljs-attribute">height</span>: <span class="hljs-number">0px</span>;
        <span class="hljs-attribute">overflow-y</span>: auto;
    }
    <span class="hljs-selector-tag">li</span> {
        <span class="hljs-attribute">height</span>: <span class="hljs-number">25px</span>;
        <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
        <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#ccc</span>;
    }
    <span class="hljs-selector-tag">li</span><span class="hljs-selector-pseudo">:hover</span> {
        <span class="hljs-attribute">filter</span>: <span class="hljs-built_in">invert</span>(<span class="hljs-number">1</span>);
    }
    <span class="hljs-selector-tag">li</span> <span class="hljs-selector-tag">a</span> {
        <span class="hljs-attribute">height</span>: <span class="hljs-number">100%</span>;
        <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
        <span class="hljs-attribute">color</span>: black;
        <span class="hljs-attribute">text-decoration</span>: none;
    }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>The dropdown should appear like this after adding the CSS styles between the <code>head</code> and <code>body</code> tags of the webpage:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_328FC621C36F4FE2DAE2507357541272A8F2DDAEC1E8AD4B2CCF09C2F4A63E3B_1650898331745_image.png" alt /></p>
<h3 id="heading-third-layer-javascript"><strong>Third layer: JavaScript</strong></h3>
<p>This layer is the functionality layer; we may choose to manipulate the DOM in any way we want to generate new user experiences, but it’s not required.</p>
<p>Without this layer of JavaScript, our dropdown is still accessible. Let’s have a look at what it’ll look like once we’ve added additional functionality scripts.</p>
<p>Here’s an example of JavaScript functionality that our dropdown may have:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    <span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string">'load'</span>, <span class="hljs-function">() =&gt;</span> {
        dropDownMenu = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#ul'</span>)
        btn = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#dropbtn'</span>)

        dropDownMenu.classList.add(<span class="hljs-string">'closed'</span>)
        btn.addEventListener(<span class="hljs-string">'click'</span>, <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
            e.preventDefault()
            dropDownMenu.classList.toggle(<span class="hljs-string">'closed'</span>)
        })
    })
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>In the code above, we listen to the <code>window.onload</code> event, then use <code>querySelector</code> to select the <code>dropDownMenu</code> and <code>btn</code>. We then add the default class <code>closed</code> to the <code>dropDownMenu</code> to collapse it. The <code>closed</code> class is then toggled whenever the <code>btn</code> is clicked.</p>
<p>Having added this script just before the <code>body</code> closing tag of the webpage, the dropdown should look like this when the page load in the browser:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_328FC621C36F4FE2DAE2507357541272A8F2DDAEC1E8AD4B2CCF09C2F4A63E3B_1650909818102_image.png" alt /></p>
<p>The menu list is collapsed; however, if you click the <strong>Navigation Men</strong>u button, the menu list should expand as follows:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_328FC621C36F4FE2DAE2507357541272A8F2DDAEC1E8AD4B2CCF09C2F4A63E3B_1650909889422_image.png" alt /></p>
<p>We were still able to offer access to the menu list before adding each successive layer of enhancement, even though this is a very user-friendly experience.</p>
<h2 id="heading-criticism-of-progressive-enhancement"><strong>Criticism of progressive enhancement</strong></h2>
<p>As appealing as the concept may appear, there are still many opposing viewpoints on progressive enhancement.</p>
<p>Some individuals believe it is a waste of time, while others believe that users should upgrade their browsers to match the website’s standards. Progressive enhancement is also thought to be for users who disable JavaScript in their browser on purpose, which is incorrect. Regardless of whether JavaScript is disabled intentionally or not, the user should be able to view the website’s content.</p>
<p>Others believe that progressive enhancement is only available in outdated browsers. But users may use whichever browser they like, regardless of how old or new it is. It is the developers’ responsibility to ensure that the website is compatible with any browser that attempts to access the website’s contents.</p>
<h2 id="heading-closing-thoughts"><strong>Closing thoughts</strong></h2>
<p>Progressive enhancement is more concerned with a website’s long-term viability. It will be easier to expand and transition to better frameworks and technologies in the future if you use this methodology.</p>
<p>I hope that readers will understand the concept of progressive enhancement and start putting it into practice. To put your knowledge of progressive enhancement to the test, create a progressive web application (PWA) and evaluate if it fits the progressive enhancement standards discussed in this article.</p>
]]></content:encoded></item><item><title><![CDATA[How to Write an ERC-4626 Token Contract for Yield-Bearing Vaults]]></title><description><![CDATA[In April 2022, Yearn Finance, a popular DEFI protocol, announced its support for the newly introduced Ethereum Request for Comment (ERC)-4626 token standard, stating that “Yearn V3 + ERC-4626 = inevitable.”
https://twitter.com/yearnfi/status/15114442...]]></description><link>https://blog.wolzcodelife.com/how-to-write-an-erc-4626-token-contract-for-yield-bearing-vaults</link><guid isPermaLink="true">https://blog.wolzcodelife.com/how-to-write-an-erc-4626-token-contract-for-yield-bearing-vaults</guid><category><![CDATA[Solidity]]></category><category><![CDATA[erc4626]]></category><category><![CDATA[token]]></category><category><![CDATA[Smart Contracts]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Tue, 17 Oct 2023 11:00:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697106818463/7ff8b219-9a9e-4cd8-af3e-3852e36a122c.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In April 2022, Yearn Finance, a popular DEFI protocol, announced its support for the newly introduced Ethereum Request for Comment (ERC)-4626 token standard, stating that “Yearn V3 + ERC-4626 = inevitable.”</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/yearnfi/status/1511444226566983683">https://twitter.com/yearnfi/status/1511444226566983683</a></div>
<p> </p>
<p>For Ethereum-based applications, ERCs (Ethereum Request for Comments) are standards that include name registries, package formats, libraries, and token requirements. To enable other developers to predict how a set of functions are implemented even without access to the source code of apps that adhere to these standards, this set of standards describes how those functions will be implemented or interacted with in applications and smart contracts.</p>
<p>Given the size of the Ethereum community and the diversity of developer skill levels and implementation methods, ERCs are essential to the Ethereum ecosystem. These guidelines serve as a framework to guarantee that applications and smart contracts are constructed in a consistent manner so that other people can contribute to them.</p>
<p>Before ERC-4626, about 25 ERC standards have been successfully deployed, including ERC-20 (fungible tokens), ERC-721 (non-fungible tokens, or NFTs) and ERC-1155 (the single smart contract multi-token).</p>
<p>There has not been a simpler way to implement yield vaults than ERC-4626. By providing a single API that allows minting tokens from multiple chains on a shared interface, ERC-4626 made varying protocols interoperable.</p>
<p>This article will explain what ERC-4626 is, how yield-bearing vaults work, and how to create a yield-bearing vault ERC-4626 token smart contract.</p>
<h2 id="heading-what-are-yield-bearing-vaults"><strong>What are yield-bearing vaults?</strong></h2>
<p>Smart contracts are created to ensure that agreements between various blockchain transactions are fulfilled.A yield-bearing vault is a smart contract that allows users to deposit different ERC-20 tokens to a pool of tokens in exchange for vTokens (vault tokens).</p>
<p>Users redeem vTokens for initial capital, plus any profits made. The deposited tokens are commutated (pooled) with other comparable crypto assets and distributed over many protocols with the ability to yield profit in the shortest amount of time.</p>
<p>A yield-bearing vault ranks different protocols according to which are the most profitable, and then distributes a fraction of the token pool to the best yielding protocols while keeping a reserve of tokens for users who want to withdraw their funds. The vesting procedure repeats after the harvesting profits are made. Then, the vault converts them back to the initially deposited tokens.</p>
<p>The following diagram depicts how yield-bearing vaults work:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_9EBCD5FB4641D5700D2747B1B888183DC373CD06D059A9071A72C131038B0A2F_1652643594453_image.png" alt /></p>
<p>The diagram above may be broken down into a process as follows:</p>
<p>To begin, vault participants must deposit tokens. The vault groups similar ERC tokens into a pool. Participants in the vault are allocated vault tokens, which reflect their claim to the tokens in the pool.</p>
<p>To optimize yield, the vault utilizes a preprogrammed strategy. This strategy looks for the opportunity with the highest yield, and reallocates a percentage of the tokens to optimize pool profits while keeping some in reserve.</p>
<p>When users withdraw their tokens, they are first taken from the vault reserve and then from the yield pool. A withdrawal charge is calculated as the sum of gas fees, strategy fees, and treasury fees when participants withdraw.</p>
<h3 id="heading-use-cases-for-yield-bearing-vaults"><strong>Use cases for yield-bearing vaults</strong></h3>
<p>You might be wondering how to use yield-bearing vaults now that you know how they work. The following are some examples of yield-bearing vault applications:</p>
<ul>
<li><p>Funding: DAOs and governments employ yield-bearing vaults to raise funding without crowdsourcing</p>
</li>
<li><p>Crypto lending: companies like Yearn Finance provide protocols that allow users to maximize their profits by lending and selling crypto assets</p>
</li>
<li><p>DCA (Dollar Cost Averaging) vaults: DCA vaults employ yield-bearing strategies to optimize profits</p>
</li>
</ul>
<h2 id="heading-what-is-erc-4626"><strong>What is ERC-4626?</strong></h2>
<p>The “tokenized vault standard,” also known as ERC-4626, is a standard protocol for tokenized vaults that represents shares of yield-bearing tokens and builds on the ERC-20 token standard.</p>
<p>In other words, ERC-4626 is an extension of ERC-20 that adds new functionality to allow users to profit from their stakes. Previously, using ERC-20 standards, users could only withdraw less than or equal to the amount of tokens they deposited in their account. ERC-4626 allows users to withdraw more than their initial payment over time, based on the amount of profits the vault has generated.</p>
<p>As an extension of ERC-20, ERC-4626 implements the following:</p>
<ul>
<li><p>Deposits and withdrawals</p>
</li>
<li><p>Vault balances</p>
</li>
<li><p>Interfaces</p>
</li>
<li><p>Events</p>
</li>
</ul>
<h2 id="heading-history-of-erc-4626"><strong>History of ERC-4626</strong></h2>
<p>On December 22, 2021, Joey Santoro, the creator of Fei Finance, and five other writers proposed ERC-4626 as an <a target="_blank" href="https://eips.ethereum.org/EIPS/eip-4626#:~:text=Reference%20Implementations-,Abstract,withdrawing%20tokens%20and%20reading%20balances.">Ethereum Improvement Proposal</a> (EIP) to address the absence of standardization for yield-bearing tokens, which is a problem in decentralized finance.</p>
<p>If you’ve ever wondered how the number “4626” came to be, T11s, a coauthor of the ERC-4626, revealed in a tweet that Joey had suggested the numbers to him during a workout and that the name sounded better than the original proposal of “4700.”</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/transmissions11/status/1511575415357247491">https://twitter.com/transmissions11/status/1511575415357247491</a></div>
<h2 id="heading-how-to-write-an-erc-4626-vault-contract"><strong>How to write an ERC-4626 vault contract</strong></h2>
<p>After establishing your license identifier and version, the first step in building our vault is to create your ERC20 and ERC4626 interface, also known as IERC20 and IERC4626. Keep in mind that your contract must use every function in your interface; Solidity’s interface has a defined function that is implemented together with the logic. They are inherited, and the original contract makes use of their functions.</p>
<p>Below is an IERC20 interface:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> 0.8.7;</span>

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">IERC20</span></span>{

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transferFrom</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> A, <span class="hljs-keyword">address</span> B, <span class="hljs-keyword">uint</span> C</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span>(<span class="hljs-params"><span class="hljs-keyword">bool</span></span>)</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">approve</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>)</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">decimals</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>)</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">totalSupply</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>)</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">balanceOf</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> account</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>)</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transfer</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> D, <span class="hljs-keyword">uint</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>;
}
</code></pre>
<p>Below is an IERC4626 interface:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> 0.8.7;</span>

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">IERC4626</span> </span>{ 
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">totalAssets</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>)</span>; 
}
</code></pre>
<p>After creating your interface, import them into your contract with the ERC20 token standard.</p>
<p>The next step is to write your contract. Give your contract a name, and import the necessary files and libraries.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> 0.8.7;</span>

<span class="hljs-comment">// Import the necessary files and lib</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"./Interfaces/IERC4626.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./Interfaces/IERC20.sol"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol"</span>;

<span class="hljs-comment">// create your contract and inherit the your imports</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">TokenizedVault</span> <span class="hljs-keyword">is</span> <span class="hljs-title">IERC4626</span>, <span class="hljs-title">ERC20</span> </span>{

}
</code></pre>
<p>Then, create events. Here, there will be two events: a deposit event for users to deposit tokens, and a withdrawal event for users to request withdrawals:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// create an event that will the withdraw and deposit function</span>
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">Deposit</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> caller, <span class="hljs-keyword">uint256</span> amt</span>)</span>;
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">Withdraw</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> caller, <span class="hljs-keyword">address</span> receiver, <span class="hljs-keyword">uint256</span> amt, <span class="hljs-keyword">uint256</span> shares</span>)</span>;
</code></pre>
<p>The ERC-20 token you imported will be an immutable asset to be used as a constructor. To do this, you will create an immutable variable called <code>asset</code> that references your ERC20.</p>
<p>After that, make a mapping to demonstrate the user’s status as a shareholder following the deposits:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// create your variables and immutables</span>
    ERC20 <span class="hljs-keyword">public</span> <span class="hljs-keyword">immutable</span> asset;

<span class="hljs-comment">// a mapping that checks if a user has deposited</span>
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">uint256</span>) shareHolder;
</code></pre>
<p>Next, create a constructor that assigns the asset variable to the underlying token whose address associates with the address, name, and symbols of your ERC20 token:</p>
<pre><code class="lang-solidity"><span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params">ERC20 _underlying, <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> _name, <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> _symbol </span>)
     <span class="hljs-title">ERC20</span>(<span class="hljs-params">_name, _symbol, <span class="hljs-number">18</span></span>) </span>{
        asset <span class="hljs-operator">=</span> _underlying;
    }
</code></pre>
<p>Now, write the function for your vault after configuring the contract’s assets and events. A user should be able to deposit tokens for the contract to function as a vault; the user receives proof of deposit after deposit, referred to as “shares”. The user will use this to claim ownership of her shares during withdrawal:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// a deposit function that receives assets from users</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deposit</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> assets</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span></span>{
        <span class="hljs-comment">// checks that the deposit is higher than 0</span>
        <span class="hljs-built_in">require</span> (assets <span class="hljs-operator">&gt;</span> <span class="hljs-number">0</span>, <span class="hljs-string">"Deposit less than Zero"</span>);

        asset.transferFrom(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>), assets);
<span class="hljs-comment">// checks the value of assets the holder has</span>
        shareHolder[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> assets;
<span class="hljs-comment">// mints the reciept(shares)</span>
        _mint(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, assets);

        <span class="hljs-keyword">emit</span> Deposit(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, assets);

    }
</code></pre>
<p>Before the function transfers or accepts the token into the vault, perform a check to ensure the user is depositing an actual token (and not zero tokens). The user becomes a shareholder, and each shareholder owns shares equal to the amount they deposited in vault tokens; so, if they deposited 50 ETH, they now own shares equal to 50 iETH.</p>
<p>The following function gives the total amount of assets deposited in this vault:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// returns total number of assets</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">totalAssets</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
        <span class="hljs-keyword">return</span> asset.balanceOf(<span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>));
    }
</code></pre>
<p>Implementing a <code>redeem</code> function will come next. This <code>internal</code> function will check whether a user has shares, and if the number of shares is more than zero. If the user is a shareholder, he may redeem any number of shares from the holdings assigned to him.</p>
<p>Before executing the burn functions that convert the shares into the same asset tokens that were initially deposited, we assign a fixed ten percent interest on the number of shares the user owns.</p>
<p>Note that the contract owner may adjust the interest rate on shares as desired.</p>
<p>Finally, it emits the withdrawal event to grant the user access to the assets:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// users to return shares and get thier token back before they can withdraw, and requiers that the user has a deposit</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">redeem</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> shares, <span class="hljs-keyword">address</span> receiver </span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span> assets</span>) </span>{
        <span class="hljs-built_in">require</span>(shareHolder[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">&gt;</span> <span class="hljs-number">0</span>, <span class="hljs-string">"Not a share holder"</span>);
        shareHolder[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">-</span><span class="hljs-operator">=</span> shares;

        <span class="hljs-keyword">uint256</span> per <span class="hljs-operator">=</span> (<span class="hljs-number">10</span> <span class="hljs-operator">*</span> shares) <span class="hljs-operator">/</span> <span class="hljs-number">100</span>;

        _burn(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, shares);

        assets <span class="hljs-operator">=</span> shares <span class="hljs-operator">+</span> per;

        <span class="hljs-keyword">emit</span> Withdraw(receiver, assets, per);
        <span class="hljs-keyword">return</span> assets;
    }
</code></pre>
<p>The <code>withdraw</code> feature is last. A vault that permits deposits but not withdrawals is considered malicious.</p>
<p>To withdraw, the <code>redeem</code> function is invoked by the <code>withdraw</code> function, which converts shares into asset tokens and calculates interest on the asset. Then, the user can withdraw her assets and interest using the following:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// allow msg.sender to withdraw his deposit plus interest</span>

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">withdraw</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> shares, <span class="hljs-keyword">address</span> receiver</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-keyword">uint256</span> payout <span class="hljs-operator">=</span> redeem(shares, receiver);
        asset.<span class="hljs-built_in">transfer</span>(receiver, payout);
    }

}
</code></pre>
<p>The whole contract code can be found in this <a target="_blank" href="https://gist.github.com/wolz-CODElife/0acdee6ac30b85521377be81a0af19ac">GitHub gist</a>.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>After reading this article, you should hopefully have a better understanding of what an ERC, ERC-4626 tokens, and yield-bearing vaults are, and how to write a yield-bearing vaults smart contract for ERC-4626 tokens.</p>
<p>You can also read the <a target="_blank" href="https://ethereum.org/en/developers/docs/standards/tokens/erc-4626/">documentation</a> I wrote on the Ethereum official website for ERC-4626. Feel free to leave a comment in the comment section below! 🥂</p>
]]></content:encoded></item><item><title><![CDATA[A Developer’s Guide to Solidity Design Patterns]]></title><description><![CDATA[Due to the continued increasing popularity of blockchain and DApps (decentralized applications), open source DApps are seeing growth in contributions from a wide variety of developers.The heart of most DApps and blockchain applications are smart cont...]]></description><link>https://blog.wolzcodelife.com/a-developers-guide-to-solidity-design-patterns</link><guid isPermaLink="true">https://blog.wolzcodelife.com/a-developers-guide-to-solidity-design-patterns</guid><category><![CDATA[Solidity]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[developers]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Mon, 16 Oct 2023 11:00:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697106502782/9f1fad3a-eaa9-4c95-9407-39af5db9c70f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Due to the continued increasing popularity of blockchain and <a target="_blank" href="https://blog.logrocket.com/how-build-dapp-host-ipfs-fleek/">DApps</a> (decentralized applications), open source DApps are seeing growth in contributions from a wide variety of developers.The heart of most DApps and blockchain applications are smart contracts developed using Solidity.</p>
<p>Contribution to open source projects raises concerns within the <a target="_blank" href="https://blog.logrocket.com/daml-vs-solidity-choose-smart-contract-language/">Solidity</a> community because these projects have real-world consequences for people’s money, and when developers from different backgrounds collaborate on a project, it is almost certain that there will be errors and code conflicts in the applications. This is why practicing proper standards for DApps is so critical.</p>
<p>To maintain excellent standards, eliminate risks, mitigate conflicts, and construct scalable and secure smart contracts, it is necessary to study and use the correct implementation of design patterns and styles in Solidity.</p>
<p>This article will discuss the Solidity design pattern; you must be familiar with Solidity to follow along.</p>
<h2 id="heading-what-is-a-solidity-design-pattern"><strong>What is a Solidity design pattern?</strong></h2>
<p>As a developer, you can learn to use Solidity from various resources online, but these materials are not the same, because there are many different ways and styles of implementing things in Solidity.</p>
<p>Design patterns are reusable, conventional solutions used to solve reoccurring design flaws.Making a transfer from one address to another is a practical example of frequent concern in Solidity that can be regulated with design patterns.</p>
<p>When transferring Ether in Solidity, we use the <code>Send</code>, <code>Transfer</code>, or <code>Call</code> methods. These three methods have the same singular goal: to send Ether out of a smart contract. Let’s have a look at how to use the <code>Transfer</code> and <code>Call</code> methods for this purpose. The following code samples demonstrate different implementations.</p>
<p>First is the <code>Transfer</code> method. When using this approach, all receiving smart contracts must define a fallback function, or the transfer transaction will fail. There is a gas limit of 2300 gas available, which is enough to complete the transfer transaction and aids in the prevention of reentry assaults:</p>
<pre><code class="lang-solidity"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Transfer</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> <span class="hljs-keyword">payable</span> _to</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{     
  _to.<span class="hljs-built_in">transfer</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>); 
}
</code></pre>
<p>The code snippet above defines the <code>Transfer</code> function, which accepts a receiving address as <code>_to</code> and uses the <code>_to.transfer</code> method to initiate the transfer of Ether specified as <code>msg.value</code>.</p>
<p>Next is the <code>Call</code> method. Other functions in the contract can be triggered using this method, and optionally set a gas fee to use when the function executes:</p>
<pre><code class="lang-solidity">
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Call</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> <span class="hljs-keyword">payable</span> _to</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
    (<span class="hljs-keyword">bool</span> sent) <span class="hljs-operator">=</span> _to.<span class="hljs-built_in">call</span>.<span class="hljs-built_in">gas</span>(<span class="hljs-number">1000</span>){<span class="hljs-built_in">value</span>: <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>}(<span class="hljs-string">""</span>);
    <span class="hljs-built_in">require</span>(<span class="hljs-string">"Sent, Ether not sent"</span>);
}
</code></pre>
<p>The code snippet above defines the <code>Call</code> function, which accepts a receiving address as <code>_to</code>, sets the transaction status as boolean, and the result returned is provided in the data variable. If <a target="_blank" href="http://msg.data"><code>msg.data</code></a> is empty, the <code>receive</code> function executes immediately after the <code>Call</code> method. The fallback runs where there is no implementation of the receive function.</p>
<p>The most preferred way to transfer Ether between smart contracts is by using the <code>Call</code> method.</p>
<p>In the examples above, we used two different techniques to transfer Ether. You can specify how much gas you want to expend using <code>Call</code>, whereas <code>Transfer</code> has a fixed amount of gas by default.</p>
<p>These techniques are patterns practiced in Solidity to implement the recurring occurrence of <code>Transfer</code>.</p>
<p>To keep things in context, the following sections are some of the design patterns that Solidity has regulated.</p>
<h2 id="heading-behavioral-patterns"><strong>Behavioral patterns</strong></h2>
<h3 id="heading-guard-check"><strong>Guard check</strong></h3>
<p>Smart contracts’ primary function is to ensure the requirements of transactions pass. If any condition fails, the contract reverts to its previous state. Solidity achieves this by employing the EVM’s error handling mechanism to throw exceptions and restore the contract to a working state before the exception.</p>
<p>The smart contract below shows how to implement the guard check pattern using all three techniques:</p>
<pre><code class="lang-solidity"><span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Contribution</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">contribute</span> (<span class="hljs-params"><span class="hljs-keyword">address</span> _from</span>) <span class="hljs-title"><span class="hljs-keyword">payable</span></span> <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
    <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span> <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>);
    <span class="hljs-built_in">require</span>(_from <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>));
    unit prevBalance <span class="hljs-operator">=</span> <span class="hljs-built_in">this</span>.<span class="hljs-built_in">balance</span>;
    unit amount;

    <span class="hljs-keyword">if</span>(_from.<span class="hljs-built_in">balance</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>) {
      amount <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>;
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (_from.<span class="hljs-built_in">balance</span> <span class="hljs-operator">&lt;</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>.<span class="hljs-built_in">balance</span>) {
      amount <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span> <span class="hljs-operator">/</span> <span class="hljs-number">2</span>;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">revert</span>(<span class="hljs-string">"Insufficent Balance!!!"</span>);
    }

    _from.<span class="hljs-built_in">transfer</span>(amount);
    <span class="hljs-built_in">assert</span>(<span class="hljs-built_in">this</span>.<span class="hljs-built_in">balance</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span> prevBalance <span class="hljs-operator">-</span> amount);
  }
}
</code></pre>
<p>In the code snippet above, Solidity handles error exceptions using the following:</p>
<p><code>require()</code> declares the conditions under which a function executes. It accepts a single condition as an argument and throws an exception if the condition evaluates to false, terminating the function’s execution without burning any gas.</p>
<p><code>assert()</code> evaluates the conditions for a function, then throws an exception, reverts the contract to the previous state, and consumes the gas supply if the requirements fail after execution.</p>
<p><code>revert()</code> throws an exception, returns any gas supplied, and reverts the function call to the contract’s original state if the requirement for the function fails. The <code>revert()</code> method does not evaluate or require any conditions.</p>
<h3 id="heading-state-machine"><strong>State machine</strong></h3>
<p>The state machine pattern simulates the behavior of a system based on its previous and current inputs. Developers use this approach to break down big problems into simple stages and transitions, which are then used to represent and control an application’s execution flow.</p>
<p>The state machine pattern can also be implemented in smart contracts, as shown in the code snippet below:</p>
<pre><code class="lang-solidity"><span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Safe</span> </span>{
    Stages <span class="hljs-keyword">public</span> stage <span class="hljs-operator">=</span> Stages.AcceptingDeposits;
    <span class="hljs-keyword">uint</span> <span class="hljs-keyword">public</span> creationTime <span class="hljs-operator">=</span> <span class="hljs-built_in">now</span>;
    <span class="hljs-keyword">mapping</span> (<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">uint</span>) balances;

    <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">atStage</span>(<span class="hljs-params">Stages _stage</span>) </span>{
      <span class="hljs-built_in">require</span>(stage <span class="hljs-operator">=</span><span class="hljs-operator">=</span> _stage);
      <span class="hljs-keyword">_</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">timedTransitions</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-keyword">if</span> (stage <span class="hljs-operator">=</span><span class="hljs-operator">=</span> Stages.AcceptingDeposits <span class="hljs-operator">&amp;</span><span class="hljs-operator">&amp;</span> <span class="hljs-built_in">now</span> <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span>
      creationTime <span class="hljs-operator">+</span> <span class="hljs-number">1</span> <span class="hljs-literal">days</span>)
      nextStage();
      <span class="hljs-keyword">if</span> (stage <span class="hljs-operator">=</span><span class="hljs-operator">=</span> Stages.FreezingDeposits <span class="hljs-operator">&amp;</span><span class="hljs-operator">&amp;</span> <span class="hljs-built_in">now</span> <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span>
      creationTime <span class="hljs-operator">+</span> <span class="hljs-number">4</span> <span class="hljs-literal">days</span>)
      nextStage();
      <span class="hljs-keyword">_</span>;
    }
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">nextStage</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> </span>{
      stage <span class="hljs-operator">=</span> Stages(<span class="hljs-keyword">uint</span>(stage) <span class="hljs-operator">+</span> <span class="hljs-number">1</span>);
    }
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deposit</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> <span class="hljs-title">timedTransitions</span> <span class="hljs-title">atStage</span>(<span class="hljs-params">Stages.AcceptingDeposits</span>) </span>{
      balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>;
    }
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">withdraw</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">timedTransitions</span> <span class="hljs-title">atStage</span>(<span class="hljs-params">Stages.ReleasingDeposits</span>) </span>{
      <span class="hljs-keyword">uint</span> amount <span class="hljs-operator">=</span> balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>];
      balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
      <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>.<span class="hljs-built_in">transfer</span>(amount);
    }
}
</code></pre>
<p>In the code snippet above, the <code>Safe</code> contract uses modifiers to update the state of the contract between various stages. The stages determine when deposits and withdrawals can be made. If the current state of the contract is not <code>AcceptingDeposit</code>, users can not deposit to the contract, and if the current state is not <code>ReleasingDeposit</code>, users can not withdraw from the contract.</p>
<h3 id="heading-oracle"><strong>Oracle</strong></h3>
<p>Ethereum contracts have their own ecosystem where they communicate. The system can only import external data via a transaction (by passing data to a method), which is a drawback because many contract use cases involve knowledge from sources other than the blockchain (e.g., the stock market).</p>
<p>One solution to this problem is to use the oracle pattern with a connection to the outside world. When an oracle service and a smart contract communicate asynchronously, the oracle service serves as an API. A transaction begins by invoking a smart contract function, which comprises an instruction to send a request to an oracle.</p>
<p>Based on the parameters of such a request, the oracle will fetch a result and return it by executing a callback function in the primary contract. Oracle-based contracts are incompatible with the blockchain concept of a decentralized network, because they rely on the honesty of a single organization or group.</p>
<p>Oracle services <a target="_blank" href="https://docs.oracle.com/en/database/oracle/oracle-database/21/whats-new.html">21</a> and <a target="_blank" href="https://docs.oracle.com/en/cloud/saas/b2b-service/22a/index.html">22</a> address this flaw by providing a validity check with the data supplied. Note that an oracle must pay for the callback invocation. Therefore, an oracle charge is paid alongside the Ether required for the callback invocation.</p>
<p>The code snippet below shows the transaction between an oracle contract and its consumer contract:</p>
<pre><code class="lang-solidity"><span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">API</span> </span>{
    <span class="hljs-keyword">address</span> trustedAccount <span class="hljs-operator">=</span> <span class="hljs-number">0x000</span>...; <span class="hljs-comment">//Account address</span>
    <span class="hljs-keyword">struct</span> <span class="hljs-title">Request</span> {
        <span class="hljs-keyword">bytes</span> data;
        <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"><span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">callback</span></span>;
    }
    Request[] requests;
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">NewRequest</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span></span>)</span>;

    <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">onlyowner</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> account</span>) </span>{
        <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span> account);
        <span class="hljs-keyword">_</span>;
    }
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">query</span>(<span class="hljs-params"><span class="hljs-keyword">bytes</span> data, <span class="hljs-keyword">function</span>(<span class="hljs-params"><span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span></span>) <span class="hljs-keyword">external</span> callback</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        requests.<span class="hljs-built_in">push</span>(Request(data, callback));
        NewRequest(requests.<span class="hljs-built_in">length</span> <span class="hljs-operator">-</span> <span class="hljs-number">1</span>);
    }
    <span class="hljs-comment">// invoked by outside world</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">reply</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span> requestID, <span class="hljs-keyword">bytes</span> response</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span>
    <span class="hljs-title">onlyowner</span>(<span class="hljs-params">trustedAccount</span>) </span>{
    requests[requestID].callback(response);
    }
}
</code></pre>
<p>In the code snippet above, the <code>API</code> smart contract sends a query request to a <code>knownSource</code> using the <code>query</code> function, which executes the <code>external callback</code> function and uses the <code>reply</code> function to collect response data from the external source.</p>
<h3 id="heading-randomness"><strong>Randomness</strong></h3>
<p>Despite how tricky it is to generate random and unique values in Solidity, it is in high demand. The block timestamps are a source of randomness in Ethereum, but they are risky because the miner can tamper with them. To prevent this issue, solutions like block-hash PRNG and Oracle RNG were created.</p>
<p>The following code snippet shows a basic implementation of this pattern using the most recent block hash:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// This method is predicatable. Use with care!</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">random</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint</span></span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">uint</span>(<span class="hljs-built_in">blockhash</span>(<span class="hljs-built_in">block</span>.<span class="hljs-built_in">number</span> <span class="hljs-operator">-</span> <span class="hljs-number">1</span>));
}
</code></pre>
<p>The <code>randomNum()</code> function above generates a random and unique integer by hashing the block number (<code>block.number</code>, which is a variable on the blockchain).</p>
<h2 id="heading-security-patterns"><strong>Security patterns</strong></h2>
<h3 id="heading-access-restriction"><strong>Access restriction</strong></h3>
<p>Because there are no built-in means to manage execution privileges in Solidity, one common trend is to limit function execution. Execution of functions should only be on certain conditions like timing, the caller or transaction information, and other criteria.</p>
<p>Here’s an example of conditioning a function:</p>
<pre><code class="lang-solidity"><span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">RestrictPayment</span> </span>{
    <span class="hljs-keyword">uint</span> <span class="hljs-keyword">public</span> date_time <span class="hljs-operator">=</span> <span class="hljs-built_in">now</span>;

    <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">only</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> account</span>) </span>{
        <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span> account);
        <span class="hljs-keyword">_</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">f</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">payable</span></span> <span class="hljs-title">onlyowner</span>(<span class="hljs-params">date_time + <span class="hljs-number">1</span> <span class="hljs-literal">minutes</span></span>)</span>{
      <span class="hljs-comment">//code comes here</span>
    }
}
</code></pre>
<p>The Restrict contract above prevents any <code>account</code> different from the <code>msg.sender</code> from executing the <code>payable</code> function. If the requirements for the <code>payable</code> function are not met, <code>require</code> is used to throw an exception before the function is executed.</p>
<h3 id="heading-check-effects-interactions"><strong>Check effects interactions</strong></h3>
<p>The check effects interaction pattern decreases the risk of malicious contracts attempting to take over control flow following an external call. The contract is likely transferring control flow to an external entity during the Ether transfer procedure. If the external contract is malicious, it has the potential to disrupt the control flow and cause the sender to rebound to an undesirable state.</p>
<p>To use this pattern, we must be aware of which parts of our function are vulnerable so that we can respond once we find the possible source of vulnerability.</p>
<p>The following is an example of how to use this pattern:</p>
<pre><code class="lang-solidity"><span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">CheckedTransactions</span> </span>{
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">uint</span>) balances;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deposit</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
        balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">withdraw</span>(<span class="hljs-params"><span class="hljs-keyword">uint</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-built_in">require</span>(balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span> amount);
        balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">-</span><span class="hljs-operator">=</span> amount;
        <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>.<span class="hljs-built_in">transfer</span>(amount);
    }
}
</code></pre>
<p>In the code snippet above, the <code>require()</code> method is used throw an exception if the condition <code>balances[msg.sender] &gt;= amount</code> fails. This means, a user can not withdraw an <code>amount</code> greater the balance of the <code>msg.sender</code>.</p>
<h3 id="heading-secure-ether-transfer"><strong>Secure Ether transfer</strong></h3>
<p>Although cryptocurrency transfers are not Solidity’s primary function, they happen frequently. As we discussed earlier, <code>Transfer</code>, <code>Call</code>, and <code>Send</code> are the three fundamental techniques for transferring Ether in Solidity. It is impossible to decide which method to use unless one is aware of their differences.</p>
<p>In addition to the two methods(<code>Transfer</code> and <code>Call</code>) discussed earlier in this article, transmitting Ether in Solidity can be done using the <code>Send</code> method.</p>
<p><code>Send</code> is similar to <code>Transfer</code> in that it costs the same amount of gas as the default (2300). Unlike <code>Transfer</code>, however, it returns a boolean result indicating whether the <code>Send</code> was successful or not. Most Solidity projects no longer use the <code>Send</code> method.</p>
<p>Below is an implementation of the <code>Send</code> method:</p>
<pre><code class="lang-solidity"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">send</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> <span class="hljs-keyword">payable</span> _to</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span></span>{
    <span class="hljs-keyword">bool</span> sent <span class="hljs-operator">=</span> _to.<span class="hljs-built_in">send</span>(<span class="hljs-number">123</span>);
    <span class="hljs-built_in">require</span>(sent, <span class="hljs-string">"send failed"</span>);
}
</code></pre>
<p>The <code>send</code> function above, uses the <code>require()</code> function to throw an exception if the <code>Boolean</code> value of sent returned from <code>_to.send(123)</code> is <code>false</code>.</p>
<h3 id="heading-pull-over-push"><strong>Pull-over-push</strong></h3>
<p>This design pattern shifts the risk of Ether transfer from the contract to the users. During the Ether transfer, several things can go wrong, causing the transaction to fail. In the pull-over-push pattern, three parties are involved: the entity initiating the transfer (the contract’s author), the smart contract, and the receiver.</p>
<p>This pattern includes mapping, which aids in the tracking of users’ outstanding balances. Instead of delivering Ether from the contract to a recipient, the user invokes a function to withdraw their allotted Ether. Any inaccuracy in one of the transfers has no impact on the other transactions.</p>
<p>The following is an example of pull-over-pull:</p>
<pre><code class="lang-solidity"><span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">ProfitsWithdrawal</span> </span>{
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">uint</span>) profits;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">allowPull</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> owner, <span class="hljs-keyword">uint</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">private</span></span> </span>{
        profits[owner] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount;
    }
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">withdrawProfits</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-keyword">uint</span> amount <span class="hljs-operator">=</span> profits[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>];
        <span class="hljs-built_in">require</span>(amount <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>);
        <span class="hljs-built_in">require</span>(<span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>).<span class="hljs-built_in">balance</span> <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span> amount);
        profits[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
        <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>.<span class="hljs-built_in">transfer</span>(amount);
    }
}
</code></pre>
<p>In the <code>ProfitsWithdrawal</code> contract above, allows users to withdraw the profits mapped to their <code>address</code> if the balance of the user is greater than or equal to profits alloted to the user.</p>
<h3 id="heading-emergency-stop"><strong>Emergency stop</strong></h3>
<p>Audited smart contracts may contain bugs that aren’t detected until they’re involved in a cyber incident. Errors discovered after the contract launch will be tough to fix. With the help of this design, we can halt a contract by blocking calls to critical functions, preventing attackers until the rectification of the smart contract.</p>
<p>Only authorized users should be allowed to use the stopping functionality to prevent users from abusing it. A state variable is set from <code>false</code> to <code>true</code> to determine the termination of the contract. After terminating the contract, you can use the access restriction pattern to ensure that there is no execution of any critical function.</p>
<p>A function modification that throws an exception if the state variable indicates the initiation of an emergency stop can is used to accomplish this, as show below:</p>
<pre><code class="lang-solidity"><span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">EmergencyStop</span> </span>{
    <span class="hljs-keyword">bool</span> Running <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
    <span class="hljs-keyword">address</span> trustedAccount <span class="hljs-operator">=</span> <span class="hljs-number">0x000</span>...; <span class="hljs-comment">//Account address</span>
    <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">stillRunning</span> </span>{
        <span class="hljs-built_in">require</span>(Running);
        <span class="hljs-keyword">_</span>;
    }
    <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">NotRunning</span> </span>{
        <span class="hljs-built_in">require</span>(¡Running<span class="hljs-operator">!</span>);
        <span class="hljs-keyword">_</span>;
    }
    <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">onlyAuthorized</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> account</span>) </span>{
        <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span> account);
        <span class="hljs-keyword">_</span>;
    }
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">stopContract</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">onlyAuthorized</span>(<span class="hljs-params">trustedAccount</span>) </span>{
        Running <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;
    }
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resumeContract</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">onlyAuthorized</span>(<span class="hljs-params">trustedAccount</span>) </span>{
        Running <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
    }
}
</code></pre>
<p>The <code>EmergencyStop</code> contract above makes use of modifiers to check conditions, and throw exceptions if any of these conditions is met. The contract uses the <code>stopContract()</code> and <code>resumeContract()</code> functions to handle emergency situations.</p>
<p>The contract can be resumed by resetting the state variable to <code>false</code>. This method should be secured against unauthorized calls the same way the emergency stop function is.</p>
<h2 id="heading-upgradeability-patterns"><strong>Upgradeability patterns</strong></h2>
<h3 id="heading-proxy-delegate"><strong>Proxy delegate</strong></h3>
<p>This pattern allows upgrading smart contracts without breaking any of their components. A particular message called <code>Delegatecall</code> is employed when using this method. It forwards the function call to the delegate without exposing the function signature.</p>
<p>The fallback function of the proxy contract uses it to initiate the forwarding mechanism for each function call. The only thing <code>Delegatecall</code> returns is a boolean value that indicates whether or not the execution was successful. We’re more interested in the return value of the function call. Keep in mind that, when upgrading a contract, the storage sequence must not change; only additions are permitted.</p>
<p>Here’s an example of implementing this pattern:</p>
<pre><code class="lang-solidity"><span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">UpgradeProxy</span> </span>{
    <span class="hljs-keyword">address</span> delegate;
    <span class="hljs-keyword">address</span> owner <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">upgradeDelegate</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> newDelegateAddress</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span> owner);
        delegate <span class="hljs-operator">=</span> newDelegateAddress;
    }
    <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
        <span class="hljs-keyword">assembly</span> {
            <span class="hljs-keyword">let</span> _target <span class="hljs-operator">:=</span> <span class="hljs-built_in">sload</span>(<span class="hljs-number">0</span>)
            <span class="hljs-built_in">calldatacopy</span>(<span class="hljs-number">0x01</span>, <span class="hljs-number">0x01</span>, <span class="hljs-built_in">calldatasize</span>)
            <span class="hljs-keyword">let</span> result <span class="hljs-operator">:=</span> <span class="hljs-built_in">delegatecall</span>(<span class="hljs-built_in">gas</span>, _target, <span class="hljs-number">0x01</span>, <span class="hljs-built_in">calldatasize</span>, <span class="hljs-number">0x01</span>, <span class="hljs-number">0</span>)
            <span class="hljs-built_in">returndatacopy</span>(<span class="hljs-number">0x01</span>, <span class="hljs-number">0x01</span>, <span class="hljs-built_in">returndatasize</span>)
            <span class="hljs-keyword">switch</span> result <span class="hljs-keyword">case</span> <span class="hljs-number">0</span> {<span class="hljs-keyword">revert</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>)} <span class="hljs-keyword">default</span> {<span class="hljs-keyword">return</span> (<span class="hljs-number">0</span>, <span class="hljs-built_in">returndatasize</span>)}
        }
    }
}
</code></pre>
<p>In the code snippet above, <code>UpgradeProxy</code> handles a mechanism that allows the <code>delegate</code> contract to be upgraded once the <code>owner</code> executes the contract by calling the fallback function that transfers a copy of the the <code>delegate</code> contract data to the new version.</p>
<h3 id="heading-memory-array-building"><strong>Memory array building</strong></h3>
<p>This method quickly and efficiently aggregates and retrieves data from contract storage. Interacting with a contract’s memory is one of the most expensive actions in the EVM. Ensuring the removal of redundancies and storage of only the required data can help minimize cost.</p>
<p>We can aggregate and read data from contract storage without incurring further expenses using the view function modification. Instead of storing an array in storage, it is recreated in memory each time a search is required.</p>
<p>A data structure that is easily iterable, such as an array, is used to make data retrieval easier. When handling data having several attributes, we aggregate it using a custom data type such as struct.</p>
<p>Mapping is also required to keep track of the expected number of data inputs for each aggregate instance.</p>
<p>The code below illustrates this pattern:</p>
<pre><code class="lang-solidity"><span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Store</span> </span>{
    <span class="hljs-keyword">struct</span> <span class="hljs-title">Item</span> {
        <span class="hljs-keyword">string</span> name;
        <span class="hljs-keyword">uint32</span> price;
        <span class="hljs-keyword">address</span> owner;
    }
    Item[] <span class="hljs-keyword">public</span> items;
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">uint</span>) <span class="hljs-keyword">public</span> itemsOwned;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getItems</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _owner</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint</span>[] <span class="hljs-keyword">memory</span></span>) </span>{
        <span class="hljs-keyword">uint</span>\[] <span class="hljs-keyword">memory</span> result <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">uint</span>[\](itemsOwned[_owner]);
        <span class="hljs-keyword">uint</span> counter <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">uint</span> i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&lt;</span> items.<span class="hljs-built_in">length</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
            <span class="hljs-keyword">if</span> (items[i].owner <span class="hljs-operator">=</span><span class="hljs-operator">=</span> _owner) {
                result[counter] <span class="hljs-operator">=</span> i;
                counter<span class="hljs-operator">+</span><span class="hljs-operator">+</span>;
            }
        }
        <span class="hljs-keyword">return</span> result;
    }
}
</code></pre>
<p>In the <code>Store</code> contract above, we use <code>struct</code> to design a data structure of items in a list, then we mapped the items to their owners’ <code>address</code>. To get the items owned by an address, we use the <code>getItems</code> function to aggrgate a memory called <code>result</code>.</p>
<h3 id="heading-eternal-storage"><strong>Eternal storage</strong></h3>
<p>This pattern maintains the memory of an upgraded smart contract. Because the old contract and the new contract are deployed separately on the blockchain, the accumulated storage remains at its old location, where user information, account balances, and references to other valuable information are stored.</p>
<p>Eternal storage should be as independent as possible to prevent modifications to the data storage by implementing multiple data storage mappings, one for each data type. Converting the abstracted value to a map of sha3 hash serves as a key-value store.</p>
<p>Because the proposed solution is more sophisticated than conventional value storage, wrappers can reduce complexity and make code legible. In an upgradeable contract that uses eternal storage, wrappers make dealing with unfamiliar syntax and keys with hashes easier.</p>
<p>The code snippets below shows how to use wrappers to implement eternal storage:</p>
<pre><code class="lang-solidity"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getBalance</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> account</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span>(<span class="hljs-params"><span class="hljs-keyword">uint</span></span>) </span>{
    <span class="hljs-keyword">return</span> eternalStorageAdr.getUint(<span class="hljs-built_in">keccak256</span>(<span class="hljs-string">"balances"</span>, account));
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setBalance</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> account, <span class="hljs-keyword">uint</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> </span>{
    eternalStorageAdr.setUint(<span class="hljs-built_in">keccak256</span>(<span class="hljs-string">"balances"</span>, account), amount);
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addBalance</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> account, <span class="hljs-keyword">uint</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> </span>{
    setBalance(account, getBalance(account) <span class="hljs-operator">+</span> amount);
}
</code></pre>
<p>In the code snippet above, we got the balance of an <code>account</code> from eternal storage using the <code>keccak256</code> hash function in <code>enternalStorageAdr.getUint()</code>, and likewise for setting the balance of the account.</p>
<h2 id="heading-memory-vs-storage"><strong>Memory vs. storage</strong></h2>
<p><code>Storage</code>, <code>memory</code>, or <code>calldata</code> are the methods used when declaring the location of a dynamic data type in the form of a variable, but we’ll concentrate on <code>memory</code> and <code>storage</code> for now. The term <code>storage</code> refers to a state variable shared across all instances of smart contract, whereas <code>memory</code> refers to a temporary storage location for data in each smart contract execution instance. Let’s look at an example of code below to see how this works:</p>
<p>Example using <code>storage</code>:</p>
<pre><code class="lang-solidity"><span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">BudgetPlan</span> </span>{
        <span class="hljs-keyword">struct</span> <span class="hljs-title">Expense</span> {
                <span class="hljs-keyword">uint</span> price;
                <span class="hljs-keyword">string</span> item;
        } 
        <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> Expense) <span class="hljs-keyword">public</span> Expenses;
        <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">purchase</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
                Expense <span class="hljs-keyword">storage</span> cart <span class="hljs-operator">=</span> Expenses[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>]
                cart.string <span class="hljs-operator">=</span> <span class="hljs-string">"Strawberry"</span> 
                cart.price <span class="hljs-operator">=</span> <span class="hljs-number">12</span>
        }
}
</code></pre>
<p>In the <code>BudgetPlan</code> contract above, we designed a data structure for an account’s expenses where each expense (<code>Expense</code>) is a struct containing <code>price</code> and <code>item</code>. We then declared the <code>purchase</code> function to add a new <code>Expense</code> to <code>storage</code>.</p>
<p>Example using <code>memory</code>:</p>
<pre><code class="lang-solidity"><span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">BudgetPlan</span> </span>{
        <span class="hljs-keyword">struct</span> <span class="hljs-title">Expense</span> {
                <span class="hljs-keyword">uint</span> price;
                <span class="hljs-keyword">string</span> item;
        } 
        <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> Expense) <span class="hljs-keyword">public</span> Expenses;
        <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">purchase</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
                Expense <span class="hljs-keyword">memory</span> cart <span class="hljs-operator">=</span> Expenses[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>]
                cart.string <span class="hljs-operator">=</span> <span class="hljs-string">"Strawberry"</span> 
                cart.price <span class="hljs-operator">=</span> <span class="hljs-number">12</span>
        }
}
</code></pre>
<p>Almost like the example using <code>storage</code>, everything is the same, but in the code snippet we add a new <code>Expense</code> to memory when the <code>purchase</code> function is executed.</p>
<h2 id="heading-closing-thoughts"><strong>Closing thoughts</strong></h2>
<p>Developers should stick to design patterns because there are different methods to achieve specific objectives or implement certain concepts.</p>
<p>You will notice a substantial change in your applications if your practice these Solidity design patterns. Your application will be easier to contribute to, cleaner, and more secure.</p>
<p>I recommend you use at least one of these patterns in your next Solidity project to test your understanding of this topic.</p>
<p>Feel free to ask any questions related to this topic or leave a comment in the comment section below.</p>
]]></content:encoded></item><item><title><![CDATA[Migrating to React Router v6: A Complete Guide]]></title><description><![CDATA[Editor’s note*: This React Router migration guide was last updated on 25 October 2022 to include information about* useNavigate vs. useHistory, changes to NavLink, and more information about React Router v6. 

When we maintain React apps, we’ll need ...]]></description><link>https://blog.wolzcodelife.com/migrating-to-react-router-v6-a-complete-guide</link><guid isPermaLink="true">https://blog.wolzcodelife.com/migrating-to-react-router-v6-a-complete-guide</guid><category><![CDATA[React]]></category><category><![CDATA[react router]]></category><category><![CDATA[React Router 6]]></category><category><![CDATA[migration]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Fri, 13 Oct 2023 11:00:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1697105561776/f633536e-4416-4f74-b685-4bc46ef49ba1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong><em>Editor’s note*</em></strong>: This React Router migration guide was last updated on 25 October 2022 to include information about* <code>useNavigate</code> vs. <code>useHistory</code>, changes to <code>NavLink</code>, and more information about React Router v6. </p>
</blockquote>
<p>When we maintain React apps, we’ll need to upgrade dependency libraries by changing our existing codebases over time. For example, upgrading the React Rounder v5 dependency to v6 requires step-by-step changes in your existing codebase. It may be challenging to transition from React Router v5 to v6 because several changes have altered how things were done in React Router v5. In addition, several new features have been introduced, so it is recommended to upgrade to v6 even if the transition is slightly annoying.</p>
<p>To upgrade from React Router v5 to v6, you’ll either need to create a new project or upgrade an existing one using npm. React Router v6 also extensively uses <a target="_blank" href="https://blog.logrocket.com/react-hooks-cheat-sheet-unlock-solutions-to-common-problems-af4caf699e70/">React Hooks</a>, requiring React v16.8 or above. In this article, we’ll look at issues with React Router v5, what changed, how to upgrade to v6, and what benefits this upgrade <a target="_blank" href="http://offers.To">offers.To</a> follow along, you should be familiar with <a target="_blank" href="https://blog.logrocket.com/react-router-v6/">React Router</a>.</p>
<h2 id="heading-issues-with-react-router-v5"><strong>Issues with React Router v5</strong></h2>
<p>React Router v5 came close to perfection, but there were still some flaws. The v5 library has some issues with the routing algorithm and routing configuration defaults (JSX component prop defaults). Also, the v5 came with some inconsistent, somewhat complex APIs that affect the developer’s productivity. Moreover, v5’s bundle size weighs more compared to what it offers as a React library. Here is a detailed explanation of the major issues that every developer faces in React Router v5:</p>
<h3 id="heading-path-matching-issues"><strong>Path-matching issues</strong></h3>
<p><code>Routes</code> queries route paths with the most similar naming instead of with exact naming. For instance, a route name <code>/dashboard</code> would still be called if the browser route is <code>/dashboard/test</code>, or <code>/dashboard/testagain</code>, etc., which is not expected by app developers. Developers have to explicitly specify the prop <code>exact</code> to strictly query route names.</p>
<p>Also, defining routes with the same path but optional parameters requires special arrangements. For instance, the parameter is required when defining the route <code>/games</code> and another route with the same name. Thus, developers need to arrange the definition, so the route with the parameter comes first. Otherwise, the routes won’t work as expected because of the issues in v5’s routing algorithm.</p>
<p>Look at the following example that demonstrates the ranking problem in the v5’s routing algorithm:</p>
<p>The correct way: Here, <code>/games</code> will render the <code>Games</code> component but not <code>SelectedGame</code>, because it does not have a parameter <code>id</code>. While <code>/games/:id</code> will render only the <code>SelectedGame</code> component:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">Router</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/games/:id"</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{SelectedGame}</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/games"</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Games}</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Router</span>&gt;</span>
</code></pre>
<p>The incorrect way: Here, either <code>/games</code> or <code>/games/:id</code> will render the <code>Games</code> component:</p>
<pre><code class="lang-xml">
<span class="hljs-tag">&lt;<span class="hljs-name">Router</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/games"</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Games}</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/games/:id"</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{SelectedGame}</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Router</span>&gt;</span>
</code></pre>
<p>The above code snippets illustrate the right and wrong way to order routes that are related by paths or parameters according to React Router v5. The first example is the most suitable order, while the second allows only the route <code>/games</code> to render for any situation with a parameter.</p>
<p>According to v5’s perspective, the second approach is incorrect, and developers need to use the <code>exact</code> prop or re-order (as in the first code snippet) to fix it. However, the v5 route ranking algorithm could be intelligent enough to identify the most suitable route without explicit ordering or <code>exact</code> usage.</p>
<p>For developing nested routes, developers had to write more code with the <code>useRouteMatch</code> Hook, <code>Route</code>, and <code>Switch</code> components. For nested routes, developers had to find the entire route because there is no relative route handling in v5:</p>
<pre><code class="lang-xml">// ----
<span class="hljs-tag">&lt;<span class="hljs-name">Switch</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/dashboard"</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Dashboard}</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Switch</span>&gt;</span>;
// ----

function Dashboard() {
  const { path } = useRouteMatch();
  return (
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Dashboard<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Switch</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">path</span>}/<span class="hljs-attr">charts</span>`} <span class="hljs-attr">component</span>=<span class="hljs-string">{Charts}</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Switch</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  );
}
</code></pre>
<h3 id="heading-issues-in-api-consistency-and-simplicity"><strong>Issues in API consistency and simplicity</strong></h3>
<p>When a specific library offers inconsistent and somewhat complex APIs, application codebases become less maintainable and more error-prone. So, software library developers always try to offer consistent and simple APIs for app developers to manage their codebases better. However, library developers can’t offer the most optimal API design for app developers with their first release. API improvements typically come with the open-source developer community’s feedback, bug reports, and feature requests.</p>
<p>React Router v5 has some inconsistent APIs and unfamiliar naming. Also, app developers had to write more <a target="_blank" href="https://en.wikipedia.org/wiki/Boilerplate_code">boilerplate code</a> than they expected to configure and integrate React Router v5 into their apps. For example, for programmatic navigation, v5 offers the <code>useHistory</code> Hook, but almost all React Router newcomers expect <code>useNavigate</code>.</p>
<p>Also, the <code>Route</code> component offers two different props to link components: <code>component</code> and <code>render</code>, but it’s possible to offer one <code>element</code> prop as the <a target="_blank" href="https://blog.logrocket.com/react-suspense-data-fetching/#what-is-react-suspense">Suspense API</a> does. Moreover, for defining your routes with <a target="_blank" href="https://blog.logrocket.com/tag/vanilla-javascript/">JavaScript objects</a> in v5, you have to use the separate <a target="_blank" href="https://www.npmjs.com/package/react-router-config"><code>react-router-config</code></a> package.</p>
<h3 id="heading-excessive-bundle-and-code-size"><strong>Excessive bundle and code size</strong></h3>
<p>As we already know, when we use heavy dependencies, our applications also become heavy. Similarly, if we use a library that requires writing verbose API calls, our application bundles also contain excessive code, which leads to heavy bundle sizes.</p>
<p>React Router v5 latest stable release (<a target="_blank" href="https://bundlephobia.com/package/react-router-dom@5.3.4">v5.3.4</a>) ‘s bundle size is about four times larger than <a target="_blank" href="https://bundlephobia.com/package/react@18.2.0">React</a>!Having considered the issues with React Router v5, we will now discuss how to migrate and what has changed that makes React Router v6 different.</p>
<h2 id="heading-migrating-to-react-router-v6"><strong>Migrating to React Router v6</strong></h2>
<p>The following sections will teach you how to upgrade to React Router v6 in projects where React Router is already installed and from scratch.</p>
<h3 id="heading-upgrading-react-router-in-a-project-where-it-is-already-installed"><strong>Upgrading React Router in a project where it is already installed</strong></h3>
<p>To upgrade the React Router version, open a terminal and navigate to the project directory where you wish to upgrade it.</p>
<p>To see a list of the project’s dependencies, use the following command:</p>
<pre><code class="lang-bash">npm ls
<span class="hljs-comment"># --- or ---</span>
yarn list
</code></pre>
<p>You should see a list like this:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_54146A2F584E7952F77DC32D411741D277C15DC44BE60F3EBF781B7EBBD7AABC_1638888973788_image.png" alt /></p>
<p>Although the list generated may not be exactly the one above, you should see an entry with its installed version if you have React Router installed.</p>
<p>Next, run the following command to initiate an upgrade:</p>
<pre><code class="lang-bash">npm install react-router-dom@latest
<span class="hljs-comment"># --- or ---</span>
yarn install react-router-dom@latest
</code></pre>
<p>If you execute this command without being connected to the internet, it will fail because some files must be downloaded during the installation. If everything is in order, you should see something similar; in our case, the version is v6.0.2:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_54146A2F584E7952F77DC32D411741D277C15DC44BE60F3EBF781B7EBBD7AABC_1638994774561_image.png" alt /></p>
<p>If everything goes well, we should notice that React Router has been updated when we run the <code>npm ls</code> or <code>yarn list</code> command again:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_54146A2F584E7952F77DC32D411741D277C15DC44BE60F3EBF781B7EBBD7AABC_1638994912612_image.png" alt /></p>
<h3 id="heading-installing-react-router-from-scratch"><strong>Installing React Router from scratch</strong></h3>
<p>First, open a terminal in a project directory where React Router isn’t installed.</p>
<p>To install a specific version of React Router, run the following:</p>
<pre><code class="lang-bash">npm install react-router-dom@[VERSION_TO_BE_INSTALLED]
</code></pre>
<p>Replace <code>[VERSION_TO_BE_INSTALLED]</code> with the version you want to install, for example, <code>6.0.2</code>.</p>
<p>Or, run the following code to install the newest version:</p>
<pre><code class="lang-xml">npm install react-router-dom
# --- or ---
yarn install react-router-dom
</code></pre>
<p>This installation also demands the use of the internet. If the installation went well, you should see something similar to this:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_54146A2F584E7952F77DC32D411741D277C15DC44BE60F3EBF781B7EBBD7AABC_1638996731135_image.png" alt /></p>
<h2 id="heading-whats-changed-in-react-router-v6"><strong>What’s changed in React Router v6?</strong></h2>
<p>It’s important to understand what changed so we can see why upgrading to React Router v6 is helpful. Note that in certain circumstances, developers will downgrade a program to increase functionality or avoid issues.</p>
<p>We will go through the changes in React Router v5 that one should consider when choosing which version to implement in a project.</p>
<h3 id="heading-setting-up-routes"><strong>Setting up routes</strong></h3>
<p>We had three different techniques for generating routes in React Router v5, which caused confusion. The first technique is to pass the <code>component</code> and <code>path</code> as props of the <code>Route</code> component:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/games"</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Games}</span> /&gt;</span>
</code></pre>
<p>This works well, however, we cannot pass props to the rendered component. The second is to pass in the component as a child of the <code>Route</code> component:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/games"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Games</span> <span class="hljs-attr">count</span>=<span class="hljs-string">”10”</span> <span class="hljs-attr">category</span>=<span class="hljs-string">”Action”</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Route</span>&gt;</span>
</code></pre>
<p>We may pass custom props to the component we want to render using this approach. The third and final technique is to use the <code>render</code> prop where a function returns the component to be rendered:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/games"</span> <span class="hljs-attr">render</span>=<span class="hljs-string">{(props)</span> =&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">Games</span> {…<span class="hljs-attr">props</span>} /&gt;</span>} /&gt;
</code></pre>
<p>This also works and lets us give props to the component we’re rendering. However, it is ambiguous and prone to inaccuracy.</p>
<p>In React Router v6, routes have been simplified to the point that we no longer need to utilize <code>Switch</code> to query them. Instead, we utilize a “required” component called <code>Routes</code>, which only searches for routes by name. The <code>*</code> character can be used to query using a wildcard.</p>
<p>We then supply the component to be rendered to the <code>Route</code> component as <code>element</code> props. We can also supply custom props to the components in each route we wish to render.</p>
<p>The code snippets below demonstrate how to define routes in v6:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/games"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Games</span> /&gt;</span>} /&gt;
  <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/movies"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Movies</span> <span class="hljs-attr">genre</span>=<span class="hljs-string">"Action"</span> <span class="hljs-attr">age</span>=<span class="hljs-string">"13"</span> /&gt;</span>} /&gt;
<span class="hljs-tag">&lt;/<span class="hljs-name">Routes</span>&gt;</span>
</code></pre>
<p>You can also use <code>useRoutes</code> to query the routes in the app. To do this, we must alter the <code>index.js</code> content, where we change the <code>App</code> wrapper from <code>React.StrictMode</code> to <code>BrowserRouter</code> as below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;
<span class="hljs-keyword">import</span> { BrowserRouter } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>

ReactDOM.render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BrowserRouter</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">BrowserRouter</span>&gt;</span></span>,
  <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)
);
</code></pre>
<p>Then, in the <code>App.js</code> file, we define the routes by performing the following:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Outlet, useRoutes } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>;
<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> routes = useRoutes([
    {
      <span class="hljs-attr">path</span>: <span class="hljs-string">'/'</span>,
      <span class="hljs-attr">element</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Hello Index<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    },
    {
      <span class="hljs-attr">path</span>: <span class="hljs-string">'games'</span>,
      <span class="hljs-attr">element</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Games</span> /&gt;</span></span>,
      children: [
      {
        <span class="hljs-attr">path</span>: <span class="hljs-string">''</span>,
        <span class="hljs-attr">element</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Games Index<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
      },
      {
        <span class="hljs-attr">path</span>: <span class="hljs-string">':id'</span>,
        <span class="hljs-attr">element</span>: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Game Details<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
      }]
    }
  ]);
  <span class="hljs-keyword">return</span> routes;
}

<span class="hljs-keyword">const</span> Games = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"Games"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>This is the Games page<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Outlet</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Here, we imported <code>Outlet</code> and <code>useRoutes</code>. The <code>useRoutes</code> allows us to define the routes as an array of objects in which we can specify a <code>path</code>, the <code>element</code> to be rendered when the path is browsed, and sub-paths. <code>Outlet</code> helps us render the child route that matches the current path.</p>
<h2 id="heading-usenavigate-vs-usehistory"><code>useNavigate</code> vs. <code>useHistory</code></h2>
<p>In React Router v5, we use <code>useHistory()</code> for handling navigation programmatically. There have been concerns with this technique, such as naming confusion and having two methods for navigation, <code>history.push</code> and <code>history.replace</code>.</p>
<p>To implement navigation in v5, we usually do the following:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useHistory } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-route-dom'</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> history = useHistory();
  <span class="hljs-keyword">const</span> handleClick = <span class="hljs-function">() =&gt;</span> {
    history.push(<span class="hljs-string">'/home'</span>);
  }
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClick}</span>&gt;</span>Go Home<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  ) 
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>We use the history if we need to replace the current history <code>frame.replace('/home')</code> method call.</p>
<p>In v6, we use <code>useNavigate</code> instead of <code>useHistory</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> navigate = useNavigate();
  <span class="hljs-keyword">const</span> handleClick = <span class="hljs-function">() =&gt;</span> {
    navigate(<span class="hljs-string">"/home"</span>);
  }
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleClick}</span>&gt;</span>Go Home<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App
</code></pre>
<p>Instead of <code>history.replace</code>, we can call the navigate method with an options object as follows:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> handleClick = <span class="hljs-function">() =&gt;</span> {
  navigate(<span class="hljs-string">'/home'</span>, { <span class="hljs-attr">replace</span>: <span class="hljs-literal">true</span> });
}
</code></pre>
<p>So, what happened to the <code>go</code>, <code>goBack</code>, and <code>goForward</code> methods in the legacy history API in v5? In v6, we can call the same navigate function with numbers. For example, look at the following code snippet that demonstrates <code>go back</code>, <code>forward</code>, and <code>2nd history</code> frame navigation:</p>
<pre><code class="lang-javascript">navigate(<span class="hljs-number">-1</span>)   <span class="hljs-comment">// v5's history.go(-1) or history.goBack()</span>
navigate(<span class="hljs-number">1</span>)    <span class="hljs-comment">// v5's history.go(1) or history.goForward()</span>
navigate(<span class="hljs-number">2</span>)    <span class="hljs-comment">// v5's history.go(2)</span>
</code></pre>
<p>Also, v6 replaces <code>Redirect</code> with a declarative version of <code>useNavigate</code>, <code>Navigate</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Navigate } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Navigate</span> <span class="hljs-attr">to</span>=<span class="hljs-string">'/home'</span> <span class="hljs-attr">replace</span> <span class="hljs-attr">state</span>=<span class="hljs-string">{state}</span> /&gt;</span></span>;
}
</code></pre>
<p>Moreover, the navigate API is now suspense-ready. You can inspect a sample suspense-based router implementation from <a target="_blank" href="https://github.com/remix-run/react-router/blob/4d915e3305df5b01f51abdeb1c01bf442453522e/examples/data-router/src/routes.tsx#L289">this source file on GitHub</a>.</p>
<h2 id="heading-understanding-changes-in-navlink"><strong>Understanding changes in</strong> <code>NavLink</code></h2>
<p>The v6 versions also changed the <code>NavLink</code> component interface that helps you create breadcrumbs, tabs, and navigation menus with dynamic styles. This is a frequently used component in most React Router-based apps, so you may have to allocate more time for <code>NavLink</code> related rewrites.</p>
<h3 id="heading-specifying-exact-route-paths-in-navlink"><strong>Specifying exact route paths in</strong> <code>NavLink</code></h3>
<p>In v5, we use the prop when enforcing an exact path or route. To implement this, we do the following:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">NavLink</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/dashboard"</span> <span class="hljs-attr">exact</span>&gt;</span>Go Home<span class="hljs-tag">&lt;/<span class="hljs-name">NavLink</span>&gt;</span>
</code></pre>
<p>In v6, we use the <code>end</code> prop to ensure exact routes:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">NavLink</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/dashboard"</span> <span class="hljs-attr">end</span>&gt;</span>Go Home<span class="hljs-tag">&lt;/<span class="hljs-name">NavLink</span>&gt;</span>
</code></pre>
<p>The React Router team renamed this prop to align the library with the React ecosystem’s practices.</p>
<h3 id="heading-styling-an-active-navlink"><strong>Styling an active</strong> <code>NavLink</code></h3>
<p>In React Router v5, we use the <code>activeClassName</code> or <code>activeStyle</code> props to style a <code>NavLink</code> that is currently active.</p>
<p>For instance:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">NavLink</span> 
  <span class="hljs-attr">to</span>=<span class="hljs-string">"/home"</span> 
  <span class="hljs-attr">style</span>=<span class="hljs-string">{{color:</span> '<span class="hljs-attr">black</span>'}} 
  <span class="hljs-attr">activeStyle</span>=<span class="hljs-string">{{color:</span> '<span class="hljs-attr">blue</span>'}} 
  <span class="hljs-attr">className</span>=<span class="hljs-string">"nav_link"</span> 
  <span class="hljs-attr">activeClassName</span>=<span class="hljs-string">"active"</span> &gt;</span>
  Go Home
<span class="hljs-tag">&lt;/<span class="hljs-name">NavLink</span>&gt;</span>
</code></pre>
<p>In v6, we have to use a function with the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#object_destructuring">destructured</a> argument <code>{isActive}</code> to condition the <code>style</code> or <code>className</code> to be used for an active <code>NavLink</code>.</p>
<p>For instance:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">NavLink</span> 
  <span class="hljs-attr">to</span>=<span class="hljs-string">"/home"</span> 
  <span class="hljs-attr">style</span>=<span class="hljs-string">{({isActive})</span> =&gt;</span> ({color: isActive ? 'blue' : 'black'})} 
  className={({isActive}) =&gt; `ln-${isActive ? ' active' : ''}`} &gt;
  Go Home
<span class="hljs-tag">&lt;/<span class="hljs-name">NavLink</span>&gt;</span>
</code></pre>
<p>These changes also fix the consistency and simplicity issues in the v5 legacy API. However, if your React app uses the above-deprecated props extensively, you can make your migration process faster and smoother by creating a temporary wrapper for v6’s <code>NavLink</code> as follows:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { NavLink <span class="hljs-keyword">as</span> BaseNavLink } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>;

<span class="hljs-keyword">const</span> NavLink = React.forwardRef(
  <span class="hljs-function">(<span class="hljs-params">{ activeClassName, activeStyle, ...props }, ref</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BaseNavLink</span>
        <span class="hljs-attr">ref</span>=<span class="hljs-string">{ref}</span>
        {<span class="hljs-attr">...props</span>}
        <span class="hljs-attr">className</span>=<span class="hljs-string">{({</span> <span class="hljs-attr">isActive</span> }) =&gt;</span>
          [
            props.className,
            isActive ? activeClassName : null,
          ]
            .filter(Boolean)
            .join(" ")
        }
        style={({ isActive }) =&gt; ({
          ...props.style,
          ...(isActive ? activeStyle : null),
        })}
      /&gt;</span>
    );
  }
);
</code></pre>
<p>The above code converts the v6 <code>NavLink</code> to a v5-like <code>NavLink</code> and lets you deploy the app with v6 by keeping working v5-styled <code>NavLinks</code> that you can re-write without a rush.</p>
<h3 id="heading-use-usematch-instead-of-useroutematch"><strong>Use</strong> <code>useMatch</code> instead of <code>useRouteMatch</code></h3>
<p>In v5, <code>useRouteMatch</code> was used to create relative sub-route paths that matched a particular route. We can use this Hook with or without the pattern argument as follows:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Receive the matched path and url of the current &lt;Route/&gt;</span>
<span class="hljs-keyword">const</span> { path, url } = useRouteMatch();

<span class="hljs-comment">// Receive the matched route details based on the pattern argument</span>
<span class="hljs-keyword">const</span> match = useRouteMatch(<span class="hljs-string">'/users/:id'</span>);
</code></pre>
<p>In v6, we use <code>useMatch</code> for this. Using the <code>useMatch</code> Hook requires a pattern argument and does not accept patterns as an array. So, the following code snippet is valid for v6:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> match = useRouteMatch(<span class="hljs-string">'/users/:id'</span>);
</code></pre>
<p>However, v6 throws an <code>error</code> if you don’t pass the pattern argument to the Hook. The above <code>match</code> constant will receive <a target="_blank" href="https://github.com/remix-run/react-router/blob/main/docs/utils/match-path.md">details about the route match</a>.</p>
<h3 id="heading-relative-routes-support-for-nesting"><strong>Relative routes support for nesting</strong></h3>
<p>In v5, creating JSX-based nested routes generated more boilerplate code segments since we had to construct full URLs explicitly. Consider the following example code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ----</span>
&lt;Switch&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/dashboard"</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Dashboard}</span> /&gt;</span></span>
&lt;/Switch&gt;;
<span class="hljs-comment">// ----</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Dashboard</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { path } = useRouteMatch();
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Dashboard<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Switch</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">path</span>}`} <span class="hljs-attr">component</span>=<span class="hljs-string">{Summary}</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">path</span>}/<span class="hljs-attr">stats</span>`} <span class="hljs-attr">component</span>=<span class="hljs-string">{Stats}</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">path</span>}/<span class="hljs-attr">charts</span>`} <span class="hljs-attr">component</span>=<span class="hljs-string">{Charts}</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Switch</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Here we need to manually construct the full path for each’s <code>path</code> prop using the <code>useRouteMatch</code> Hook. So, when you develop complex apps, you can see this boilerplate code everywhere.</p>
<p>React Router v6 made JSX-based nested routes definitions so minimal. Look at the following v6 re-write of the above v5 sample code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// ---</span>
&lt;Routes&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/dashboard"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Dashboard</span>/&gt;</span>}&gt;
    <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">""</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Summary</span>/&gt;</span>}/&gt;
    <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"stats"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Stats</span>/&gt;</span>}/&gt;
    <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"charts"</span> <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>&lt;<span class="hljs-attr">Charts</span>/&gt;</span>}/&gt;
  <span class="hljs-tag">&lt;/<span class="hljs-name">Route</span>&gt;</span></span>
&lt;/Routes&gt;
<span class="hljs-comment">// ---</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Dashboard</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Dashboard<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Outlet</span>/&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Here v6 lets developers use the <code>Route</code> component in a nested way to define nested routes. Note the <code>Outlet</code> component that renders nested components: <code>Summary</code>, <code>Stats</code>, and <code>Charts</code>. Here we don’t need to prepend <code>/dashboard/</code> to all nested routes, unlike v5, since v6 supports relational path definitions.</p>
<h2 id="heading-what-was-removed-from-react-router-v6"><strong>What was removed from React Router v6?</strong></h2>
<p>In React Router v6, some features are no longer supported because they are ambiguous or faulty. So far, two features were found to have been removed:</p>
<h3 id="heading-prompt-useprompt-and-useblocker"><code>Prompt</code>, <code>usePrompt</code>, and <code>useBlocker</code></h3>
<ul>
<li><p><code>usePrompt</code> (JSX <code>Prompt</code>): Was used to confirm whether a user wants to exit a page when the page is in a state that does not require the user to leave</p>
</li>
<li><p><code>useBlocker</code>: Similar to <code>usePrompt</code>, and was used to prevent users from leaving a particular page</p>
</li>
</ul>
<p>These two features are similar and have the same issue. In a situation where a user tries to navigate outside a page and navigation is restricted by either <code>usePrompt</code> or <code>useBlocker</code>, the URL path changes even though the navigation is prevented.</p>
<p>Although there were issues raised about <code>useBlocker</code> and <code>usePrompt</code>, the creators are still considering adding them back to v6 after they release a stable version. <a target="_blank" href="https://github.com/remix-run/react-router/issues/8139#issuecomment-954427837">Check here for more details</a>. Meanwhile, the developer community created libraries like <a target="_blank" href="https://www.npmjs.com/package/react-router-prompt"><code>react-router-prompt</code></a> for app developers who need these removed features in React Router v6.</p>
<h3 id="heading-nested-routers-support"><strong>Nested routers support</strong></h3>
<p>Using one <code>BrowserRouter</code> component is enough for developing advanced React app navigations. Some app developers who used React Router v5 practiced using nested routers in their apps to isolate complex components. For example, most developers used v5’s <code>MemoryRouter</code> inside the <code>BrowserRouter</code> instance to insolate modals and tab groups. Unfortunately, v6 dropped supporting nested routers and motivated app developers to use only one preferred router implementation.</p>
<p>Most app developers who built nested routers now request the deprecated feature back in v6 to upgrade their v5 React Router dependency to v6. Some developers worry about this breaking change in v6 and even <a target="_blank" href="https://github.com/shapeshift/web/pull/968#issuecomment-1033431536">consider migrating</a> to another React routing module.</p>
<p>According to <a target="_blank" href="https://github.com/remix-run/react-router/issues/7375">this discussion</a>, it seems that maintainers are not focusing on nested router support during the current development timeline. But, the developer community may support maintainers to at this deprecated feature soon! Or, maintainers will offer a production-friendly workaround for this issue.</p>
<p>The developer community found the following workaround (rather a hack) to enable nested routers in v6, but it’s not production-friendly due to unexpected behaviors:</p>
<pre><code class="lang-javascript">&lt;UNSAFE_LocationContext.Provider value={ <span class="hljs-literal">null</span> }&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">MemoryRouter</span>&gt;</span>
    { /* some routes not related to the outer router */ }
  <span class="hljs-tag">&lt;/<span class="hljs-name">MemoryRouter</span>&gt;</span></span>
&lt;/UNSAFE_LocationContext.Provider&gt;
</code></pre>
<p>Subscribe to issue <a target="_blank" href="https://github.com/remix-run/react-router/issues/7375">#7375</a> on GitHub and get updates related to the v6 nested routers.</p>
<h2 id="heading-why-doesnt-react-router-v6-work-in-your-app"><strong>Why doesn’t React Router v6 work in your app?</strong></h2>
<p>You might notice unexpected behaviors, error messages, and warning messages once you complete the migration process. You may have to solve a bug due to a breaking change in v6. We can’t ship apps to production with routing issues. So, detecting routing issues with a string test plan is better.</p>
<p>Your React Router integration won’t work correctly after upgrading to v6 because of the following issues.</p>
<h3 id="heading-the-historypush-method-wont-work-properly"><strong>The</strong> <code>history.push</code> method won’t work properly</h3>
<p>You’ve probably updated the <code>history</code> package to the latest without updating React Router to v6. The v5 <code>history</code> package is compatible with React Router v6, not React Router v5. To solve this, first, update React Router, then it will automatically download a compatible <code>history</code> version. If you still need to run React Router v5, use <code>history</code> v4 (i.e., v4.10.1). See <a target="_blank" href="https://github.com/remix-run/history/issues/804">this issue</a>.</p>
<h3 id="heading-export-x-was-not-found-in-react-router-dom"><strong>Export</strong> <code>x</code> was not found in <code>react-router-dom</code></h3>
<p>You are importing a Hook or component that was removed or renamed in v6. For example, <code>useRouteMatch</code> won’t work in v6. To solve this, make sure that you don’t import deprecated v5 Hooks or components.</p>
<h3 id="heading-nested-routes-wont-render-components"><strong>Nested routes won’t render components</strong></h3>
<p>Make sure to add <code>&lt;Outlet/&gt;</code> in the parent component that embeds nested route components. Check the previous <code>Dashboard</code> component as a reference implementation.</p>
<h3 id="heading-x-is-not-a-component"><code>x</code> is not a <code>&lt;Route&gt;</code> component</h3>
<p>In v6, <code>Routes</code> can contain only <code>Route</code> or <code>React.Fragment</code> children, so make sure to move other HTML elements and components to suitable places from the <code>Routes</code> component.</p>
<h3 id="heading-metarelativepathstartswith-is-not-a-function"><code>meta.relativePath.startsWith</code> is not a function</h3>
<p>You are using an object in the <code>path</code> prop of <code>Route</code>. In v6, you can’t use Regex objects or arrays as a path. Make sure that you use only strings for paths.</p>
<p>Here we discussed some frequently occurring issues. But, you might get a unique error message you can’t find on the internet. Inspect your codebase thoroughly for deprecated API usage in such scenarios, then open a new discussion thread in <a target="_blank" href="https://github.com/remix-run/react-router/discussions">React Router.</a></p>
<h2 id="heading-benefits-of-react-router-v6-over-v5"><strong>Benefits of React Router v6 over v5</strong></h2>
<p>It’s pointless to migrate if one version doesn’t offer any advantages over the other. In this section, we’ll talk about the benefits of upgrading from React Router v5 to v6.</p>
<p>One of the most important considerations for developers is the application’s portability. The size of React Router v6 has been reduced significantly compared to previous versions. The difference between v5 and v6 is around 60 percent.</p>
<p>Here is a comparison from <a target="_blank" href="https://bundlephobia.com/">Bundlephobia</a>:</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_54146A2F584E7952F77DC32D411741D277C15DC44BE60F3EBF781B7EBBD7AABC_1639015877696_image.png" alt /></p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_54146A2F584E7952F77DC32D411741D277C15DC44BE60F3EBF781B7EBBD7AABC_1639015714297_image.png" alt /></p>
<p>Compiling and deploying apps will be easier and faster due to the size reduction. In addition, the bulk of the modifications in React Router v6 that we covered are more beneficial and have fewer issues.</p>
<p>As previously mentioned, React Router v6 allows routes to accept components as elements when constructing routes, and pass custom props to components. We may also nest routes and use relative links as well. This helps us prevent or reduce the definition of new routes inside various component files and makes it easy to pass global data to components and props.</p>
<p>When redirecting instead of using <code>useHistory</code>, the new approach using <code>useNavigate</code> has been designed to offer better navigation API. It allows us to set the new route easily via <code>navigate()</code> instead of using multiple methods: <code>history.push()</code>, <code>history.replace()</code>, and <code>history.goBack()</code>. Also, the new v6 API is so minimal and developer friendly. It lets you reduce boilerplate code and complex route definitions to make your app codebase clean.</p>
<p>Finally, the navigation link <code>NavLink</code> allows us to condition active links, which makes our code neater and simpler, instead of passing two different props for an active and inactive state. By doing this, we can easily use a <a target="_blank" href="https://blog.logrocket.com/a-comprehensive-guide-to-javascript-expressions/">ternary operator</a> to condition which style will be affected when a link is active or not.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>After reading this article, I hope you are able to upgrade your React Router version and restructure your codebases to work seamlessly with React Router v6. Updating your code based on the above points helps you to migrate any React Router-based app. But, if your app’s routing is so complex and extensively uses deprecated v5 features, you can consider using the <a target="_blank" href="https://github.com/remix-run/react-router/discussions/8753">official incremental migration guide</a> from maintainers.</p>
<p>Not only should React Router v5 be upgraded to v6, but Reach Router should be switched to v6 as well.</p>
<p>Regularly upgrade React Router v6 and review the <a target="_blank" href="https://reactrouter.com/en/main">documentation</a> for any changes to stay up-to-date with new releases.</p>
]]></content:encoded></item><item><title><![CDATA[How to Mint NFTs Using Tatum NFT Express in JavaScript]]></title><description><![CDATA[To implement NFT minting, blockchain developers typically use tools like Cadence and Moralis. Thanks to these libraries and modules, by utilizing pre-written smart contracts, these tools allow programmers to interact with the blockchain with fewer li...]]></description><link>https://blog.wolzcodelife.com/how-to-mint-nfts-using-tatum-nft-express-in-javascript</link><guid isPermaLink="true">https://blog.wolzcodelife.com/how-to-mint-nfts-using-tatum-nft-express-in-javascript</guid><category><![CDATA[NFT]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[Blockchain]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Mon, 12 Dec 2022 13:17:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1670850950339/5qlWy59m6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>To implement NFT minting, blockchain developers typically use tools like Cadence and Moralis. Thanks to these libraries and modules, by utilizing pre-written smart contracts, these tools allow programmers to interact with the blockchain with fewer lines of code than would otherwise be necessary.</p>
<p><a target="_blank" href="https://tatum.io/">Tatum</a> offers a relatively simple way to interact with the blockchain without requiring developers to create new smart contracts and have any knowledge of Solidity or Truffle. Although it requires subscribing to different paid plans from which gas fees will be covered, there is a free plan for small-scale applications.</p>
<p>In this article, I'll discuss Tatum and demonstrate how to mint NFTs in javascript using Tatum NFT Express. You'll need a basic understanding of blockchain and JavaScript to follow along. You may not need to become proficient in any blockchain programming language like Solidity to create smart contracts.</p>
<p>With this, let's jump right in 🚀.</p>
<h2 id="heading-what-is-tatum">What is Tatum?</h2>
<p>Tatum offers a unifying framework for thousands of digital assets and more than 40 different blockchain protocols(🤯). It is a versatile platform that aids programmers in minimizing the complexity of most blockchain development processes.</p>
<p>To assist in the reduction of complexity and the faster and simpler scaling of blockchain applications, Tatum offers features like:</p>
<ul>
<li><p>NFT Express: This feature enables users instantly mint NFTs on various blockchains with just one API call.</p>
</li>
<li><p>Virtual Account: With this feature, you can access multi-currency wallets, make fee-free transactions, and receive alerts via webhook notifications.</p>
</li>
<li><p>Notification Station: This feature is the simplest and most effective way to be notified about blockchain events.</p>
</li>
</ul>
<h2 id="heading-minting-nfts-with-tatum-nft-express-in-javascript">Minting NFTs with Tatum NFT Express in JavaScript</h2>
<p>Tatum is designed to make minting NFTs easier than any other platform that assists developers with this functionality. Since the monthly credit allocation of your paid plan covers gas costs, you can successfully mint any NFT with just one API request and as many as you wish.</p>
<p>You must register on the <a target="_blank" href="https://dashboard.tatum.io/sign-up">Tatum dashboard</a> to mint your first NFT using Tatum. As demonstrated below, you can register using either social authentication or an email address and password:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oklxqaggqo5eculkad1x.png" alt="Tatum signup preview" /></p>
<p>After signing up, you will be redirected to your dashboard, where you can choose between using the Mainnet or Testnet and have access to two free API keys.</p>
<blockquote>
<p>📌 <strong>NOTE</strong>: When deploying your application to real users, you should use the Mainnet rather than the Testnet.</p>
</blockquote>
<p>API keys should be kept secret or limited to authorized people, such as the program's developers. If they fall into the wrong hands, they could compromise the security of the application and its users.</p>
<p>In the top-right corner of the dashboard, there is a button labelled <strong>"Create API key"</strong>. By subscribing to a new billing plan, you can create new API keys with extra functionalities, as displayed below:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t54cfy01cxp1twmnd9y3.png" alt="Tatum billing plans" /></p>
<p>You can integrate Tatum into your application once you have an API key. You need to configure Tatum first in your IDE or development environment.</p>
<p>Firstly, install the Tatum NFT Express JavaScript SDK by running the command given below in a terminal of your project directory:</p>
<pre><code class="lang-bash">npm install @tatumio/tatum
</code></pre>
<p>After installing the SDK, we must configure the required environment variables; for the sake of this tutorial, we only need to set the <code>TATUM_API_KEY</code> environment variable. Run the following command in the terminal of your application directory to do this:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> TATUM_API_KEY=<span class="hljs-string">"YOUR_TATUM_API_KEY"</span>
</code></pre>
<p>You should now be able to retrieve the value of your API key from your terminal by executing the following in your application:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(process.env.TATUM_API_KEY);
</code></pre>
<p>If everything is well done, we want to use Tatum's <code>mintNFTWithUri()</code> method to implement the functionality for minting NFT. For now, we need to import <code>Tatum</code> into a file called "index.js". Next, call the method with the necessary parameter as shown below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Tatum = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@tatumio/tatum'</span>);
Tatum.mintNFTWithUri(<span class="hljs-literal">false</span>, {
    <span class="hljs-attr">chain</span>: Tatum.Currency.CHAIN_SYMBOL,
    <span class="hljs-attr">to</span>: <span class="hljs-string">'ADDRESS_OF_RECEIVER'</span>,
    <span class="hljs-attr">url</span>: <span class="hljs-string">'URL_OF_NFT_METADATA'</span>
}).then(<span class="hljs-function"><span class="hljs-params">transactionHash</span> =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(transactionHash);
});
</code></pre>
<p>You will notice no private key or signature ID in the code snippet above. That is because NFT Express uses a default private key, token ID, and built-in smart contracts offered by Tatum to make blockchain requests.</p>
<p>We then logged the 'transactionHash' as the output of the <code>mintNFTWithUri()</code> method, which took the following arguments:</p>
<ul>
<li><p><code>chain</code>: This is the blockchain protocol you want to use to mint NFTs. Tatum permits minting for chains including ETH, MATIC, BSC, CELO, ONE, and KLAY on both the Mainnet and Testnet.</p>
</li>
<li><p><code>to</code>: The NFT is sent to this blockchain address after it has been minted.</p>
</li>
<li><p><code>url</code>: this is the metadata of the NFT.</p>
</li>
</ul>
<p>This is my actual code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Tatum = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@tatumio/tatum'</span>);
Tatum.mintNFTWithUri(<span class="hljs-literal">false</span>, {
    <span class="hljs-attr">chain</span>: Tatum.Currency.ETH,
    <span class="hljs-attr">to</span>: <span class="hljs-string">'0xC34bCC0Be78C84EB94e9544982C5027861ec0D6b'</span>,
    <span class="hljs-attr">url</span>: <span class="hljs-string">'https://i.postimg.cc/Wp0GZFK4/image.png'</span>
}).then(<span class="hljs-function"><span class="hljs-params">transactionHash</span> =&gt;</span> {
        <span class="hljs-built_in">console</span>.log(transactionHash);
});
</code></pre>
<p>I want the NFT to be sent to this address: <code>0xC34bCC0Be78C84EB94e9544982C5027861ec0D6b</code>. Open the terminal in the program's root directory and enter the following command to execute the application and mint the NFT:</p>
<pre><code class="lang-bash">node index.js
</code></pre>
<p>You should get something similar to this:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tywa02px24rwy67mv2g5.png" alt="Terminal result" /></p>
<p>I looked up the transaction hash on <a target="_blank" href="https://ropsten.etherscan.io/tx/0x5b0b4cdbeb17041e370b51d78719d8b6db7a83480bf4c213b46cd22984063b6c">EtherScan</a> to see if the mint had been successful, and this is what I found👀:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zlvo9z0eq8f2jum9td0p.png" alt="EtherScan showing successful transaction" /></p>
<p>🥳 TADA! We successfully minted an NFT seamlessly.</p>
<h2 id="heading-final-thoughts">Final Thoughts🤔</h2>
<p>You will work with the blockchain seamlessly now that you are aware of Tatum, especially if you are a front-end developer. Tatum contains practically everything you may need while working with blockchains. You can also learn more about:</p>
<ul>
<li><p><a target="_blank" href="https://tatum.io/framework">Tatum frameworks</a>.</p>
</li>
<li><p><a target="_blank" href="https://docs.tatum.io">Tatum developer documentation</a>.</p>
</li>
<li><p><a target="_blank" href="https://docs.tatum.io/introduction/supported-blockchains">Tatum supported blockchains</a>.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Automating Dependency Management Using Renovate]]></title><description><![CDATA[Software development is a process that entails various stages that birth a successful product. From ideation, to design, then development, testing, and production. During this magical process, developers integrate third-party libraries known as Softw...]]></description><link>https://blog.wolzcodelife.com/automating-dependency-management-using-renovate</link><guid isPermaLink="true">https://blog.wolzcodelife.com/automating-dependency-management-using-renovate</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[npm]]></category><category><![CDATA[Devops]]></category><category><![CDATA[GitHub]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Mon, 12 Dec 2022 13:13:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1670851209432/INnB1fvvW.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Software development is a process that entails various stages that birth a successful product. From ideation, to design, then development, testing, and production. During this magical process, developers integrate third-party libraries known as Software development kits (SDKs) to help the application meet its intended goal. Since these third-party libraries are created and updated frequently by other developers, consumers must be alert for upgrades and adapt to them.</p>
<p>Maintaining updates may be demanding for developers because they have to reinstall several packages and libraries and even replace ones that become deprecated. Different solutions have been developed by some businesses to address this issue.</p>
<p>In this article, we will discuss how developers can use Renovate to manage dependencies. To follow through with this article, you will need a basic knowledge of libraries, modules, and version control.</p>
<h1 id="heading-what-are-dependencies">What are Dependencies?</h1>
<p>Dependencies are a collection of tools, typically modular fragments of code that other applications rely on to carry out specific tasks. Dependencies are mostly supported in object-oriented programming (OOP), where classes extend functionalities to other applications.</p>
<p>Dependencies in JavaScript are referred to as libraries or packages, and they are distributed to consumers using package managers like NPM and Yarn. These package managers provide CLI(Command Line Interface) for managing dependencies in your development environment. For instance, NPM installs packages using the following command:</p>
<pre><code class="lang-bash">npm install PACKAGE_NAME
</code></pre>
<p>While Yarn uses <code>install</code> to install all the dependencies in a Yarn project.</p>
<pre><code class="lang-bash">yarn install
</code></pre>
<p>And uses <code>add</code> to install a single dependency in a Yarn project.</p>
<pre><code class="lang-bash">yarn add PACKAGE_NAME
</code></pre>
<p>After a package has been installed using the CLI, the package name and version are added to the list of dependencies in the "package.json" file in the application folder.</p>
<p>The "dependencies" object in the "package.json" file contains the list of dependencies, where the package names are the keys, and the versions of each package are the values. Here is an example of a list of dependencies:</p>
<pre><code class="lang-javascript"> <span class="hljs-string">"dependencies"</span>: {
     <span class="hljs-string">"@testing-library/jest-dom"</span>: <span class="hljs-string">"^5.16.4"</span>,
     <span class="hljs-string">"@testing-library/react"</span>: <span class="hljs-string">"^13.3.0"</span>,
     <span class="hljs-string">"@testing-library/user-event"</span>: <span class="hljs-string">"^13.5.0"</span>,
     <span class="hljs-string">"react"</span>: <span class="hljs-string">"^18.2.0"</span>,
     <span class="hljs-string">"react-dom"</span>: <span class="hljs-string">"^18.2.0"</span>,
     <span class="hljs-string">"react-scripts"</span>: <span class="hljs-string">"5.0.1"</span>,
     <span class="hljs-string">"web-vitals"</span>: <span class="hljs-string">"^2.1.4"</span>
 }
</code></pre>
<h1 id="heading-what-is-renovate">What is Renovate?</h1>
<p>Renovate is an open-source software approved by GitHub and other version control solutions to detect changes to dependencies and automatically create PRs(Pull Requests) to resolve these changes. Renovate can be used on various platforms, like GitHub, GitLab, Azure DevOps, Bitbucket Cloud, Bitbucket Server and Gitea.</p>
<p>Customers including Prisma, Mozilla, Yarn, Netlify, Envoy, Telus, Red Hat, Uber, Cypress, eBay, Algolia, Hashcorp, Atlassian, Microsoft, Sourcegraph, and Buildkite also use Renovate.</p>
<p>Let's now look at how Renovate can be set up in your workflow to automate dependencies management.</p>
<h1 id="heading-configuring-renovate-in-your-workflow">Configuring Renovate in Your Workflow</h1>
<p>Renovate can be installed on the version control system of your choosing. In this article, for example, we will use GitHub.</p>
<p>On the GitHub Marketplace, search for the <a target="_blank" href="https://github.com/apps/renovate">Renovate app</a> and click install. Select the organization or account where you wish to install Renovate. Next, choose whether to install Renovate across all of your repositories or just one particular one. We will only select one repository in this article.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9m5qhitus3tvil0k1mp1.png" alt="Image description" /></p>
<p>Proceed to install Renovate and complete the necessary authentication.</p>
<p>You can sign in using GitHub or GitLab, then you will be redirected to the Renovate Dashboard. Complete the following forms, then submit your registration. If everything goes correctly, you'll be able to access the Renovate Dashboard.</p>
<p>Navigate to the project where Renovate was installed. You should see a screen like this:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/awkpqspk9lie1tp0gdm8.png" alt="Image description" /></p>
<p>Renovate hasn't found any dependency modifications yet, hence the result is "null."</p>
<p>When you visit the GitHub repository for the project where Renovate was installed, you will see a new PR titled "Configure Renovate."</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s4ppa9a9x992kizlr3ug.png" alt="Image description" /></p>
<p>From this PR, you may learn everything you need to know about Renovate in your workflow. The PR also contains a list of detected packages, a list of what to expect(dependencies that need update) and a commit that adds the “renovate.json” file to your project.</p>
<p>Settings for customising Renovate in your project are defined in the "renovate.json" file. However, merge the PR to add the file in the repo.</p>
<p>After merging the onboarding PR, you may determine how frequently Renovate creates PRs of updates by changing the value of the variable "prhourlylimit".</p>
<pre><code class="lang-javascript">{
  <span class="hljs-string">"$schema"</span>: <span class="hljs-string">"https://docs.renovatebot.com/renovate-schema.json"</span>,
  <span class="hljs-string">"extends"</span>: [
    <span class="hljs-string">"config:base"</span>
  ],
  <span class="hljs-string">"prhourlylimit"</span>: <span class="hljs-number">3</span>,
}
</code></pre>
<p>Having set all the necessary configurations, commit the changes. Renovate will create PRs for the dependencies that need updates after a few minutes.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wcot3fbvqd7r26u16bat.png" alt="Image description" /></p>
<p>The update PRs target a single dependency and sets the version in the “package.json” file to the latest version available for that dependency. In this case, the previous version of “@testing-library/jest-dom” was version “^5.16.2”, Renovate updated the version to “5.16.5”. Ensure to check the change logs of the dependencies to learn of any breaking changes, before merging the PR.</p>
<p>Congratulations!🥳 You have successfully configured Renovate in your workflow.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Dependency management can be painstaking sometimes, as developers might need to refactor their implementation due to breaking changes in the dependencies. But the major issue is knowing when these updates are available. Thanks to Renovate, your application wouldn’t have to break before you notice a change in dependencies.</p>
<p>Check out the <a target="_blank" href="https://docs.renovatebot.com">official documentation</a> to learn more about how to use Renovate to manage dependencies automatically.</p>
]]></content:encoded></item><item><title><![CDATA[Improving Developer Experience With Dev Portals]]></title><description><![CDATA[It is essential to take developers into consideration when designing products, just as user experience influences business decisions. Even if you have the best product in the world, if your developers are having trouble using it or onboarding, it's t...]]></description><link>https://blog.wolzcodelife.com/improving-developer-experience-with-dev-portals</link><guid isPermaLink="true">https://blog.wolzcodelife.com/improving-developer-experience-with-dev-portals</guid><category><![CDATA[DevRel]]></category><category><![CDATA[Devops]]></category><category><![CDATA[APIs]]></category><category><![CDATA[Startups]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Mon, 12 Dec 2022 13:10:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1670851251263/pDnWeheN5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It is essential to take developers into consideration when designing products, just as user experience influences business decisions. Even if you have the best product in the world, if your developers are having trouble using it or onboarding, it's time to revisit your product designs.</p>
<p>Many people are talking about how important developer experience is to the success of most enterprises. And with time, a lot more businesses will become aware of the impacts and realize their significance.</p>
<p>In this article, we will have a closer look at developer experience and how it differs from user experience, the importance of a successful developer experience, what are dev portals, how to develop a working dev portal and the importance of dev portals.</p>
<p>Let’s jump right in!🚀</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/931usngbaz795qyrn1ee.png" alt="Image description" /></p>
<h1 id="heading-what-is-developer-experience">What is Developer Experience?</h1>
<p>The term "developer experience," often referred to as "DevEx" or "DX," is a new user persona/perception that many companies have embraced to evaluate how developers engage with the tools and systems that support their products.</p>
<p>A great developer experience should enhance the workflows, environments, and procedures that developers use on a daily basis. Although user experience and developer experience are closely related, they are not the same. They should be taken into account while creating a product, but individually.</p>
<p>For instance, let's say that while developing an API, user experience requires taking into consideration factors like request speed to ensure that consumers do not have to wait long for the API to respond. The developer experience, on the other hand, will require taking into consideration factors like speed but also more technical ones like error handling, modularity, documentation, and so on.</p>
<p>Below is an illustration showing the relationship between developer experience and user experience:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bf86b884idm1xc20jj2q.png" alt="Image description" /></p>
<h2 id="heading-difference-between-devex-and-ux">Difference Between DevEx and UX</h2>
<p>The simplest approach to understanding developer experience is to see it through the perspective of the common idea of user experience, but not to assume them as interchangeable.</p>
<p>Yes! The concepts of developer experience and user experience are distinct due to significant differences.</p>
<p>The approach used to create each experience differs significantly. User experience is more concerned with end consumers using the product, as opposed to developer experience, which focuses more on enabling developers to use the product to build solutions for other end users.</p>
<p>User experience strives to provide equal support to all users, regardless of technical capabilities, unlike developer experience, which aims to provide varying levels of support based on various users' technical capabilities.</p>
<p>PayPal is an excellent real-world example; the user experience makes it simple for customers to make purchases with a few clicks, and the developer experience clarifies which API endpoints or methods to use and how to use API keys to make requests.</p>
<p>Now that you can distinguish between user experience and developer experience, you might want to answer the question of why developer experience is important.</p>
<h1 id="heading-importance-of-developer-experience">Importance of Developer Experience</h1>
<p>The growth of a company is greatly influenced by the experience of its developers. If you are unfamiliar with the term "ramp-up", it generally refers to the capacity to expand a team fast by bringing on a new developer when a project requires scaling. This term introduces us to the ramp-up problem, which arises when a team tries to scale a project by adding new developers. The organization has a ramp-up problem if it takes a long time for new developers to become comfortable with the new environment before they can contribute usefully.</p>
<p>Companies need to improve their developer experience when ramp-up problems are noticed. To onboard new engineers more quickly, they might need to pay closer attention to internal tooling, documentation, and developer support.</p>
<p>Additionally, when developers feel comfortable and secure in their working environment, their work will be of a high quality, which results in timely releases, improved end-user experience, and a boost in the company's revenue.</p>
<p>Finally, developer experience provides stability(reliability, consistency), clarity(intuitive visuals, clear displays), ease of use(quick access, shortcuts, speed), and function for your software development ecosystem(expected behavior, feature-rich).</p>
<h1 id="heading-what-are-developer-portals">What are Developer Portals?</h1>
<p>Developer portals are single sources of truth or centralized repositories where resources and tools are maintained for developers who use the software of a specific company. Developer portals can be internal or external, and they can regulate who has access to which external or internal resources.</p>
<p>Developers frequently encounter challenges when integrating SDKs, consuming APIs, or contributing to legacy codebases. The developer portal, which we can refer to as the central repository for all relevant documentation and support, can be used to address these challenges.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/igzq8rlu0aogc57akobm.png" alt="Image description" /></p>
<p>An ideal developer portal can create an ecosystem around the developer experience of a product, as depicted in the image above.</p>
<p>Most developer portals' primary objective is to provide a sufficient knowledge base free of SME assistance by offering functional and technical documentation.</p>
<h1 id="heading-how-to-create-a-developer-portal">How to Create a Developer Portal</h1>
<p>The idea of developer portals sounds excellent right?🤩</p>
<p>Since developer portals are designed to hold extensive information about a company, setting one up might take a long time, followed by regular maintenance.</p>
<p><a target="_blank" href="https://www.getport.io">Port</a> is a developer-focused platform that provides organizations with a single source of truth for all operational and infrastructure resources. Blueprints, Entities, and Relations are the three main building blocks of Port, which can be used to establish a complete software catalog, unified standards, or governance over processes in your organization.</p>
<p>To start creating your portal, you might want to check the pricing and plans Port offers. You can use a free unlimited plan, and there are paid plans with additional features. To subscribe to any plan of your choice you need to <a target="_blank" href="https://auth.getport.io/u/signup?state=hKFo2SBOSWF3Ylp2ZGRDdk5YYVNINVRlWVNrcFlXVzE4TF82M6Fur3VuaXZlcnNhbC1sb2dpbqN0aWTZIDh0UjR2cGsxSEV2UEhhUVZFWWFpcGpvdTZVNXFDbjBoo2NpZNkgOTZJZXFMMzZRMFVJQnhJZlYxb3FPa0RXVTZVc2xmRGo">sign up</a> on Port first by navigating to the screen below:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hyecgqlfwlbmdqawf152.png" alt="Image description" /></p>
<p>You can sign up with Google or manually fill in the necessary credentials; you will be required to sign up with a work email. Verify your email and setup your organization, and you should see a screen like the image below:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7e0091wxoy6jyl8c02fg.png" alt="Image description" /></p>
<p>If you reach this point, your authentication is successful, and you can now begin building your self-service developer portal.</p>
<p>Next, we want to design a new blueprint for services. When you click the "Add Blueprint" button in the top-right corner of the blueprint page, a JSON template listing the microservices we can connect to will come up. A service blueprint will appear on the blueprint page after you click "Save".</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fldr07k4xmnyizr2xda7.png" alt="Image description" /></p>
<p>To examine all of the services included in this blueprint, expand the services pane and customize the ones you need. When the pane is expanded, a pop-up appears that looks like this:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t05a7akue08spajeig6n.png" alt="Image description" /></p>
<p>As in the image above, you can adjust each service's properties in the pop-up window. Make sure to click save after editing.</p>
<p>To define an environment blueprint, simply follow the steps above but set the identifier to "environment" instead of "microservice". If you require more details, please see the <a target="_blank" href="https://docs.getport.io/#environment-blueprint">related documentation</a>.</p>
<p>We want to create entities after creating service or environment blueprints. An entity is a module of software (microservice) that follows a specific blueprint. To create a new Entity, select "Service" from the list of options under "Software Catalog" in the left sidebar. You should then see a screen similar to this one:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ndg75b9kvr81capwmz37.png" alt="Image description" /></p>
<p>At the top-right corner, click “+ Service” to create a new Entity under this blueprint. You should see a form like below, or use the JSON template to create the new Entity.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/84zev8owt3klq4uype78.png" alt="Image description" /></p>
<p>Click “Create” after filling in the appropriate information, and the new Entity will be added to the list of Entities under the parent blueprint.</p>
<p>We are nearly done. The final building block is Relations, which comes after defining our data model using Blueprints and storing data objects using Entities.</p>
<p>A Relation is a connection between two blueprints and their entities. Relations are only required when multiple Blueprints depend on one another. You can have your entities without creating Relations in a case where the blueprints are independent.</p>
<p>In our case, there is only one service and one blueprint, but if you have more than one and need to synchronize your blueprints, you can use the <a target="_blank" href="https://docs.getport.io/#create-a-relation">official documentation</a> as a guide to set up a Relation.</p>
<p>Having successfully created your blueprint, entities and relations for your software infrastructure, feel free to explore the Port environment, you can also define <a target="_blank" href="https://docs.getport.io/platform-overview/self-service-actions/">self-service actions</a> and check out the Port <a target="_blank" href="https://docs.getport.io/complete-use-cases/">complete use case</a> to fully set up your software catalog.</p>
<p>Congrats!🥳 You have successfully created your developer portal using Port. Developer portals can be created using other tools like <a target="_blank" href="https://backstage.io">Backstage</a>, <a target="_blank" href="https://docs.apigee.com/api-platform/publish/drupal/creating-developer-portal">Apigee</a>, <a target="_blank" href="https://pronovix.com/developer-portals">Pronovix</a>, or <a target="_blank" href="https://www.3scale.net">3Scale</a>.</p>
<h1 id="heading-importance-of-developer-portals">Importance of Developer Portals</h1>
<p>A functional developer portal shares almost the same significance as a good developer experience. We can highlight some other importance of developer portals like:</p>
<ul>
<li><p><strong>Easy onboarding</strong>: Developer portals contain tools for easy navigation, search, code samples, or tutorials on how to get started using a specific asset.</p>
</li>
<li><p><strong>Awareness</strong>: Developer portals make it easy for developers to comprehend specific workflows and encourage service exploration.</p>
</li>
<li><p><strong>Increased productivity</strong>: Instead of spending time looking for information, developer portals enable developers to concentrate on executing their work.</p>
</li>
<li><p><strong>Easy collaboration</strong>: Developer portals promote a culture of documentation that ensures all the information a developer needs to access a particular resource is properly documented.</p>
</li>
</ul>
<h1 id="heading-next-steps">Next Steps</h1>
<p>Improving developer experience can have a significant beneficial impact on a company's success. The quality of developers will increase internally and externally, resulting in a ramp-up for the company.</p>
<p>Visit the <a target="_blank" href="https://www.getport.io/blog">Port blog</a> for relevant articles if you still have questions regarding developer experience or how developer portals improve developers' experience.</p>
]]></content:encoded></item><item><title><![CDATA[10 SEO Tips for Ecommerce Websites]]></title><description><![CDATA[Ecommerce websites are a brilliant way to promote and sell your products to potential customers all around the world. However, with so many websites out there, it can be challenging to get noticed and attract traffic to your site. That's where search...]]></description><link>https://blog.wolzcodelife.com/10-seo-tips-for-ecommerce-websites</link><guid isPermaLink="true">https://blog.wolzcodelife.com/10-seo-tips-for-ecommerce-websites</guid><category><![CDATA[ecommerce]]></category><category><![CDATA[SEO]]></category><category><![CDATA[webdev]]></category><category><![CDATA[sales]]></category><dc:creator><![CDATA[Joel Adewole]]></dc:creator><pubDate>Mon, 12 Dec 2022 13:01:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1670851160197/vm9d9xHZv.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Ecommerce websites are a brilliant way to promote and sell your products to potential customers all around the world. However, with so many websites out there, it can be challenging to get noticed and attract traffic to your site. That's where search engine optimization (SEO) comes in. You can increase your website's visibility and ranking on search engines, bringing in more visitors and sales as a result of using effective SEO strategies</p>
<p>Even if you are familiar with SEO, you may not be getting the best results. </p>
<p>Whether you have an ecommerce website or any other site, you might need to optimize it for search engine ranking. </p>
<p>In this article, we will discuss how to optimize your ecommerce website for higher search engine rankings. This will help increase traffic and sales for your business. You will also learn about link building, content marketing, and keyword research. You can then create an effective SEO strategy for your ecommerce website using the tips provided in this article.</p>
<p>Let’s dive in!</p>
<h2 id="heading-what-does-seo-mean">What does SEO mean?</h2>
<p>Search engine optimization (SEO) involves creating relevant content based on the keywords that people use in search queries to help search engines algorithms understand the content of a website. It also involves adding links and other elements to make the site easy to access and navigate. SEO can help a website rank higher at the top of the search engine results pages (SERPs), increasing its visibility to people searching for specific information.</p>
<p>Additionally, SEO entails improving the website to make it user-friendly and better crawling and indexing by search engines. SEO in ecommerce is specifically intended to boost a product's visibility in search engine results pages to increase sales and conversion rates.</p>
<p>Below is an image of a Google search engine result page showing the result of a search with “Laptop for sale amazon” as the search query.</p>
<p><img src="https://i.imgur.com/PxHdyv6.png" alt="Image of a Google search engine result page showing the result of a search with “Laptop for sale amazon” as the search query." /></p>
<h2 id="heading-why-is-seo-important-in-ecommerce">Why is SEO important in ecommerce?</h2>
<p>SEO is important in ecommerce and shouldn't be taken for granted. You can effectively target customers who are looking for goods or services available in your online store.</p>
<p>SEO raises your search engine ranking, which increases organic traffic to your website, creating chances of generating more inquiries and sales rise as a result. Since it provides potential clients with relevant, accurate, and current information, SEO also aids in establishing credibility and trust with them. In the end, SEO aids in boosting revenue and sales for your ecommerce store.</p>
<h2 id="heading-best-seo-practices-for-ecommerce-websites">Best SEO practices for ecommerce websites.</h2>
<p>Here are some tips for effectively implementing SEO on your website now that you know why it's important for ecommerce websites.</p>
<ol>
<li><p>Use relevant keywords properly across your website to improve search engine optimization. You may boost your website's rating by researching keywords and adding relevant keywords to content, title tags, and meta descriptions. </p>
<p> The intentions of your keywords are important. The purpose a user has in mind when searching for a specific keyword is known as keyword intent. There are four different types of keyword intent:</p>
<ul>
<li>Directional Intent: users use these keywords to search for a specific website or place. For example, "How far is", "where is", and "Direction".</li>
<li>Educational Intent: users use these keywords to find information on a specific subject. Examples include "What is" and "How to".</li>
<li>Transactional Intent: users use these keywords to look for products or services to make a purchase. Examples are "How much" and "Payment".</li>
<li>Lateral Intent: users use these keywords to look for products or topics related to one another. Say, "An alternative for".
It is also recommended to use keyword research tools like <a target="_blank" href="https://ads.google.com/intl/en_ng/home/tools/keyword-planner/">Google Keyword Planner</a>, <a target="_blank" href="https://www.semrush.com">SEMrush</a>, <a target="_blank" href="https://ahrefs.com">Ahrefs</a>, <a target="_blank" href="https://moz.com">Moz</a>, <a target="_blank" href="https://www.google.com/search?client=safari&amp;rls=en&amp;q=Wordtracker&amp;ie=UTF-8&amp;oe=UTF-8">Wordtracker</a>, <a target="_blank" href="https://app.neilpatel.com/en/ubersuggest/">Ubersuggest</a>, <a target="_blank" href="https://answerthepublic.com">AnswerThePublic</a>, <a target="_blank" href="https://keywordseverywhere.com">Keywords Everywhere</a> and <a target="_blank" href="https://kwfinder.com">KWFinder</a></li>
</ul>
</li>
<li><p>Improve your product pages: since product pages have the most impact on conversions, they are undoubtedly the most crucial ones on an ecommerce website. You can improve the content of your product pages by using relevant keywords in product titles, meta descriptions and product descriptions. You should also use a product-tagging system to ensure that products are precisely classified and effectively optimized for relevant keywords.</p>
</li>
<li><p>Use image alt text: since search engines cannot read images, providing alt text to your product images enables them to know what the image is about. It becomes easier for search engines to crawl your website and raises its position in search results. </p>
</li>
<li><p>Web performance optimization: a slow website might result in a high bounce rate and a low search engine rating. Ensure that you use content delivery networks(CDN), image compression, and code minification to increase the speed at which your website loads.</p>
</li>
<li><p>Utilize structured data: using structured data will help your ecommerce website perform better in search engine results. Structured data allows you to provide details about products and services, such as customer reviews, ratings, and discounts. Structured data can also assist search engines in better understanding the context of your website and index your content.</p>
</li>
<li><p>Create unique content: for ecommerce SEO, developing unique content about your products and services is essential. You can increase the organic traffic to your website by creating educational and helpful content. Additionally, you can boost traffic and conversions by including links to product pages within your content.</p>
</li>
<li><p>Optimize your URLs: users may find it simpler to understand what is on each product or category page if URLs are simplified. URLs should be brief and descriptive, contain relevant keywords, and use hyphens to separate words. As a result, the URL will be easier to read, and indexing the page will be simpler for search engine crawlers.</p>
</li>
<li><p>Monitor your site performance: to ensure the success of your SEO efforts and achieve your desired results, it is essential to regularly monitor the performance of your website. This will help you identify any areas that may need improvement. This can help you make necessary adjustments and improvements to your website in order to increase its visibility and improve its performance in search engine results pages. </p>
<p> You may track your page load times, server response times, and other metrics by using tools like Google Analytics, webpagetest.org, and Pingdom to keep an eye on the performance of your website.</p>
<p> To evaluate the effectiveness of your page and pinpoint areas for development, you can also employ browser development tools. You may also set up alerts or notifications to be informed if the performance of your website drops below a predetermined level. Monitoring your site's performance on a regular basis will help you find and fix any performance problems and make sure that your site is operating effectively.</p>
</li>
<li><p>Monitor your backlinks: by keeping track of your backlinks, you can find any broken links or spam links that can affect your search engine rankings. You can watch and monitor backlinks using tools like Ahrefs or Moz and then utilize the information to improve your ecommerce SEO strategy. This can assist you in determining which websites add value and which might harm the reputation of your website. </p>
<p> A backlink tracking tool allows you to track and evaluate the backlinks to your ecommerce website. It provides data on the quantity, quality, relevancy, and the domains of the backlinks. This information can help you improve your website's search engine rankings. </p>
<p> To monitor your backlinks, you can follow these steps:</p>
<ul>
<li>Join a backlink tracking service and add your website to the service.</li>
<li>Create a list of your backlinks with the tool. A list of the websites and pages that are linked to your website will normally be provided by the program. </li>
<li>Examine the list of backlinks and judge the value and significance of each. Avoid links from spammy or low-quality websites and seek out backlinks from pertinent websites. </li>
<li>Follow any alterations or additions to the backlinks throughout time. Usually, the program will send messages or alerts whenever new backlinks are added or old backlinks are deleted.</li>
<li>Increase the number of high-quality backlinks to your website by optimizing your link-building strategies using the data from the backlink monitoring tool. By doing this, you can raise your website's search engine rankings and increase traffic.</li>
</ul>
</li>
<li><p>Utilize internal linking: internal linking is a fantastic technique to enhance user experience on your website and facilitate easy content crawling for search engines. Be careful to connect from each page to the appropriate product pages and categories.</p>
<p>An ecommerce website can use internal linking in the following ways: </p>
<ul>
<li>Links to comparable or related products should be added to product pages so that customers can simply find related things and browse your whole catalog. </li>
<li>Link to category pages from the main navigation: To make it easier for users to reach the various product categories on your website, provide links to your category pages in the main menu. </li>
<li>Link to product pages from category pages: On each category page, include links to specific product pages so visitors may quickly access this information and add things to their cart.</li>
<li>Link to popular or featured products: To draw attention to your best-selling or most popular things, include links to popular or featured products on your homepage and other prominent pages. </li>
</ul>
<p>Utilizing internal linking can make it easier for consumers to explore your website and find new products, which will increase the likelihood that they will make a purchase.    </p>
<p>With these tips, you should see a significant change in your ecommerce search engine ranking, and also a noticeable improvement in sales and engagements.</p>
</li>
</ol>
<h2 id="heading-building-seo-enabled-ecommerce-websites-with-medusa">Building SEO-enabled ecommerce websites with Medusa</h2>
<p><a target="_blank" href="https://medusajs.com">Medusa</a> is a powerful open-source platform for building ecommerce websites that allows you to quickly and easily create highly optimized online stores. The platform is designed to assist business owners and entrepreneurs in setting up profitable online shops that are search engine optimized.</p>
<p>With Medusa, it's simple to manage customer orders, keep track of inventory, and develop aesthetically pleasing user-friendly websites. Advanced capabilities like real-time analytics and automated inventory management are also available on the platform.</p>
<p>To further help you build a unique website experience, Medusa gives you access to a variety of configurable themes and plugins. Medusa is a great choice for organizations that want to quickly create an ecommerce website with SEO capabilities. This is because Medusa has a user-friendly design that is easy to use.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, SEO plays a crucial role in the success of any ecommerce website. You can make sure that your website is optimized for search engines by using the advice provided in this article. This will help you rank higher, attract more visitors, and eventually boost sales. Your ecommerce website will also stand out from the crowd and realizes its full potential with a little effort and commitment.</p>
<p>You can reach out to the Medusa team via <a target="_blank" href="https://discord.gg/F87eGuwkTp">Discord</a> if you have any inquiries about Medusa or if you run into any problems using it. You can get personalized assistance and get your questions answered in real-time by contacting the Medusa team on Discord.</p>
]]></content:encoded></item></channel></rss>