<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Augusta Ehihebolo</title>
    <description>The latest articles on Forem by Augusta Ehihebolo (@augustae).</description>
    <link>https://forem.com/augustae</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F740572%2F8c40752b-5242-47b3-9911-f0df2e55263c.jpg</url>
      <title>Forem: Augusta Ehihebolo</title>
      <link>https://forem.com/augustae</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/augustae"/>
    <language>en</language>
    <item>
      <title>Easy and Clean Way to Use Fastest-Validator in Your Express.js App</title>
      <dc:creator>Augusta Ehihebolo</dc:creator>
      <pubDate>Fri, 23 Dec 2022 06:18:31 +0000</pubDate>
      <link>https://forem.com/augustae/easy-and-clean-way-to-use-fastest-validator-in-your-expressjs-app-3npp</link>
      <guid>https://forem.com/augustae/easy-and-clean-way-to-use-fastest-validator-in-your-expressjs-app-3npp</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Data validation is a way of checking the integrity, structure and accuracy of data before sending to the database. It is a way of ensuring that your data have been cleaned before entering the database to assure data quality, that is, that they are both accurate and valuable. You do not want to go to bed thinking of the possible wrong data users might have sent to the database. Therefore, data validation must be placed as a topmost priority while creating your API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fastest-Validator&lt;/strong&gt; is one of the different types of validation libraries used for data validation. All thanks to everyone behind the numerous validation libraries that have made data validation a lot easier lately. &lt;/p&gt;

&lt;p&gt;In this tutorial, we shall understand what the fastest-validator is, its advantages over other types of validation libraries, and learn the simple and clean way to validate data using the fastest-validator. We shall achieve this by building a product management API using Express.js, MongoDB database and the fastest-validator library to validate every input.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This tutorial is a hands-on-tutorial, code along with me to get the most out of it and ensure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; installed&lt;/li&gt;
&lt;li&gt;Knowledge of &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express.js&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;knowledge of &lt;a href="https://www.mongodb.com" rel="noopener noreferrer"&gt;MongoDB&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Your favorite code editor opened&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.postman.com/" rel="noopener noreferrer"&gt;Postman&lt;/a&gt; or &lt;a href="https://insomnia.rest" rel="noopener noreferrer"&gt;Insomnia&lt;/a&gt; installed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is Fastest-Validator&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Fastest-validator is a validation library for Node.js, browser, and Deno used to validator input data to ensure clean and quality data in our database. It is very easy to use. Some of its key features are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It's super fast.&lt;/li&gt;
&lt;li&gt;It has custom validators &amp;amp; aliases.&lt;/li&gt;
&lt;li&gt;nested objects &amp;amp; array handling.&lt;/li&gt;
&lt;li&gt;strict object validation.&lt;/li&gt;
&lt;li&gt;customizable error messages.&lt;/li&gt;
&lt;li&gt;It has no dependencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Advantages of Fastest-Validator Over Other Validation Libraries&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Compared to other popular validation libraries, the fastest-validator is super fast.&lt;br&gt;
It has a customizable error message and a programmable error object&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Project Set-up&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Without further ado, let’s start our project by creating the project directory and installing the necessary dependencies. &lt;/p&gt;

&lt;p&gt;First, create your project directory:&lt;/p&gt;

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

&lt;/div&gt;

&lt;p&gt;Open the folder in your code editor and initialize npm by running &lt;code&gt;npm init -y&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Install Dependencies&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we have set-up our project by initializing npm, let’s install the necessary dependencies to get us started.&lt;/p&gt;

&lt;p&gt;Go to your terminal, run:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install express dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Take a deep breath, in a few seconds, the installation will be done.&lt;/p&gt;

&lt;p&gt;After installing express and dotenv, create a &lt;strong&gt;src&lt;/strong&gt; folder, and inside the folder, create &lt;strong&gt;models&lt;/strong&gt;, &lt;strong&gt;validations&lt;/strong&gt;, &lt;strong&gt;controllers&lt;/strong&gt;, &lt;strong&gt;routes&lt;/strong&gt; folders, and &lt;strong&gt;app.js&lt;/strong&gt; file; create a &lt;strong&gt;.env&lt;/strong&gt; file in the root directory. Then, create a product file inside each of the folders in the &lt;strong&gt;src&lt;/strong&gt; folder.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your project directory should look like this:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fastest_Val_Express&lt;/strong&gt;&lt;br&gt;
│&lt;br&gt;
└─&lt;strong&gt;src&lt;/strong&gt;&lt;br&gt;
│ └───controllers&lt;br&gt;
│ │            └───product.controller.js&lt;br&gt;
│ │&lt;br&gt;
│ └───models&lt;br&gt;
│ │            └───product.model.js&lt;br&gt;
│ │&lt;br&gt;
│ └───routes&lt;br&gt;
│ │            └───product.route.js&lt;br&gt;
│ │&lt;br&gt;
│ └───validations&lt;br&gt;
│ │            └───product.vaidation.js&lt;br&gt;
│ │&lt;br&gt;
│ └───&lt;strong&gt;app.js&lt;/strong&gt;&lt;br&gt;
│ │ &lt;br&gt;
└─&lt;strong&gt;.env&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Create Server&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Moving on, we need to create the server&lt;/p&gt;

&lt;p&gt;Go to your &lt;strong&gt;app.js&lt;/strong&gt; file, then require express and create the server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;src/app.js&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const app = express();

const port = 5000;

app.listen(port, console.log(`server is listening on port: ${port}...`));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can start the server by running the command &lt;code&gt;node src/app.js&lt;/code&gt;, but to avoid restarting our project every time we make any change, let's install nodemon to help monitor our project for any change and automatically restart the server.&lt;/p&gt;

&lt;p&gt;In your terminal, run:  &lt;code&gt;npm install --save-dev nodemon&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Take another deep breath while nodemon is installing, it only takes a few seconds. Once you have installed nodemon, head to your package.json file, and add &lt;code&gt;"dev": "nodemon src/app"&lt;/code&gt; to the scripts object, then run &lt;code&gt;npm run dev&lt;/code&gt;  to re-start the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Connect Database&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Once the server is up and running, you need to set up and connect the database. Since we will be using MongoDB database, install mongoose with the command:  &lt;code&gt;npm i mongoose&lt;/code&gt;, then set up and connect the database. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;N.B:&lt;/strong&gt; as a best practice, put your database-sensitive information in your .&lt;strong&gt;env&lt;/strong&gt; file, require the file in your app.js file so you can have access to the environment variables.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;src/app.js&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const mongoose = require('mongoose');
const { config } = require('dotenv');
config();

const app = express();

app.use(express.json());

//connect database
mongoose.set("strictQuery", false);
mongoose
  .connect(`mongodb+srv://${process.env.DB_username}:${process.env.DB_password}@cluster0.kngtf.mongodb.net/${process.env.DB_name}?retryWrites=true&amp;amp;w=majority`)
  .then(console.log('database connected...'))
  .catch((err) =&amp;gt; console.log(err));

const port = 5000;

app.listen(port, console.log(`server is listening on port: ${port}...`));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Example of dotenv file&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;.env.example&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB_username = 
DB_password = 
DB_name = 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Having cleared that up, let’s create our product schema; we want the product name, the category it belongs to and the price. &lt;/p&gt;

&lt;p&gt;Go to your &lt;strong&gt;product.model.js&lt;/strong&gt; file in your models' folder, and create your product schema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;product.model.js&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongoose = require('mongoose');
const ProductSchema = new mongoose.Schema({
  productName: {
    type: String,
    trim: true,
  },
  category: {
    type: String,
    trim: true,
  },
  amount: {
    type: Number,
  },
},
{ timestamps: true },
);
module.exports = mongoose.model('Product', ProductSchema);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With that out of the way, we need to validate every data going to our database using the &lt;strong&gt;fastest-validator&lt;/strong&gt; library.&lt;/p&gt;

&lt;p&gt;Install the fastest-validator library with the command: &lt;code&gt;npm install fastest-validator&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt;Go to your &lt;strong&gt;product.validation.js&lt;/strong&gt; file in your validation folder, and require the fastest-validator library, then instantiate Validator.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;src/vaidation/product.validation.js&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Validator = require("fastest-validator");
const validate = new Validator(); 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Using the Fastest-Validator library is quite easy; the simple, clean and fastest way to use it is to compile the schema first to a compiled "checker" function. After that, to validate your object, just call this "checker" function. The error reporting is pretty detailed and straightforward.&lt;/p&gt;

&lt;p&gt;Now, head over to your &lt;strong&gt;product.validation.js file,&lt;/strong&gt; write your schema, and compile it to a compiled "checker" function, then export the module so you can call the checker function in your controller.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;src/vaidation/product.validation.js&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Validator = require("fastest-validator");
const validate = new Validator(); 

const productVaidationSchema = {
    productName: {
        type: "string", 
        min: 3, 
        max: 255,
        label: "Product name error"
    },
    category: { 
        type: "string", 
        min: 3, 
        max: 255,
        label: "Product category",
        optional: true
    },
    amount: {
        type: "number",
        positive: true, 
        integer: true,
        label: "Amount"
    }
};
const check = validate.compile(productVaidationSchema);

module.exports = check
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you have successfully accomplished the steps so far, you should take a chilled glass of wine and relax, knowing that every data going to your database is accurate and valuable. Cheers to that!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Project Logic&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now, we need to write our logics.&lt;/p&gt;

&lt;p&gt;Go to your &lt;strong&gt;product.controller.js file&lt;/strong&gt; in your controller folder, and require both the &lt;strong&gt;product.validation.js&lt;/strong&gt; and &lt;strong&gt;product.model.js&lt;/strong&gt; files.&lt;/p&gt;

&lt;p&gt;For the createProduct and updateProduct functions, we need to check if the input data we are sending to the database meet the validation conditions we specified in our &lt;strong&gt;product.validation.js&lt;/strong&gt; file, if "noError" is not true, then all validation conditions are not met, and so, it returns the error message else we proceed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;src/controllers/product.controller.js&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Product = require('../models/product.model');
const check = require('../validations/product.validation');
const  ObjectId = require('mongoose').Types.ObjectId;

module.exports = {
  //create product function
  createProduct: async (req, res) =&amp;gt; {
    //check if validation conditions are met
    const noError = check(req.body);
    if (noError != true) {
      return res.status(400).json({ status: 400, error: noError});
    };
    //check if product already exists
    const productExist = await Product.findOne({ productName: req.body.productName});
    if (productExist) {
      return res.json({msg: "Product already exist"})
    };
   //create the product
    const product = await Product.create(req.body);
    res.status(201).json({ msg: 'successfully added a product', product });
  },

  //get all products function
  getAllProducts: async (req, res) =&amp;gt; {
    const products = await Product.find({});
    res.status(200).json({ products, number: products.length });
  },

  //get product by Id function
  getProductById: async (req, res) =&amp;gt; {
      const productId = req.params.id;
      const product = await Product.findById(productId);
      //check if product Id is valid
      if (!product || ObjectId.isValid(productId) == false) {
      return res.status(404).json({
             message: `No product with id: ${productId}` 
     });
  }
    res.status(200).json({ message: product });
  },

  //update product by Id function
  updateProductById: async (req, res) =&amp;gt; {
    const productId = req.params.id;
    const product = await Product.findByIdAndUpdate(productId, req.body);
    //check if Id is valid
    if (!productId || ObjectId.isValid(productId) == false) {
    return res.status(404).json({ 
           message: `No product with id: ${productId}` 
   });
} 
    //check if validation conditions are met
    const error = check(req.body);
    if (noError != true) {
      return res.status(400).json({ status: 400, error: noError});
    };
    res.status(200).json({ message: `Product successfuly updated` });
  },

  //Delete product by Id
  deleteProductById: async (req, res) =&amp;gt; {
    const productId = req.params.id;
    const product = await Product.findByIdAndDelete(productId);
    //check if Id is a valid
    if (!product || ObjectId.isValid(productId) == false) {
   return res.status(404).json({
          message: `No product with id: ${productId}` });
  }
    res.status(200).json({message: `Product successfuly deleted`});
  },
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now that we have completed our logic, let’s work on our routes. &lt;/p&gt;

&lt;p&gt;Go to your &lt;strong&gt;product.routes.js&lt;/strong&gt; file in your route folder, require Router from express, and all the functions from your controller, then create the routes for the respective functions and export your route.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;src/routes/product.route.js&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const route = require('express').Router();
const {
  getAllProducts,
  createProduct,
  getProductById,
  updateProductById,
  deleteProductById,
} = require('../controllers/product.controller');

route.post('/product', createProduct);
route.get('/products', getAllProducts);
route.get('/product/:id', getProductById);
route.patch('/product/:id', updateProductById);
route.delete('/product/:id', deleteProductById);

module.exports = route;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, take another deep breath because we're almost done, all that is left is to call our route in the app.js file so that our app can access all the routes. &lt;/p&gt;

&lt;p&gt;Go to your app.js file, require the routes folder and expose the routes to be used by the app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;src/app.js&lt;/strong&gt;&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');&lt;br&gt;
const mongoose = require('mongoose');&lt;br&gt;
const route = require('./routes/product.route');&lt;br&gt;
const { config } = require('dotenv');

&lt;p&gt;config();&lt;/p&gt;

&lt;p&gt;const app = express();&lt;/p&gt;

&lt;p&gt;//connect database&lt;br&gt;
mongoose.set("strictQuery", false);&lt;br&gt;
mongoose&lt;br&gt;
  .connect(&lt;code&gt;mongodb+srv://${process.env.DB_username}:${process.env.DB_password}@cluster0.kngtf.mongodb.net/${process.env.DB_name}?retryWrites=true&amp;amp;amp;w=majority&lt;/code&gt;)&lt;br&gt;
  .then(console.log('database connected...'))&lt;br&gt;
  .catch((err) =&amp;gt; console.log(err));&lt;/p&gt;

&lt;p&gt;const port = 5000;&lt;/p&gt;

&lt;p&gt;app.use('/api/v1', route);&lt;/p&gt;

&lt;p&gt;app.listen(port, console.log(&lt;code&gt;server is listening on port: ${port}...&lt;/code&gt;));&lt;br&gt;
&lt;/p&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  &lt;strong&gt;Testing our API&lt;/strong&gt;&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;Here is the moment of truth, let's test our API routes to see if they work appropriately.&lt;br&gt;
Head over to your postman or insomnia, and test all the routes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create Product:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671139792538_post.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671139792538_post.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671139750808_post3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671139750808_post3.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671139722931_post2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671139722931_post2.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671139815143_post4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671139815143_post4.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fastest-validator gives you a detailed error report; for the &lt;strong&gt;Create Product&lt;/strong&gt; route, we were only able to successfully create a product when all validation conditions were met.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update Product by id:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671139966926_update1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671139966926_update1.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671139992168_update2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671139992168_update2.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671139941210_update.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671139941210_update.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Like the &lt;strong&gt;Create Product&lt;/strong&gt;, when we try to update a particular product by its Id, it is only successful once it fulfils all validation conditions. Notice that it was also successful without the &lt;strong&gt;category&lt;/strong&gt; because category in our validation is not required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Get products:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671140047683_get.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671140047683_get.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Get Product by Id:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671140093543_getid.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671140093543_getid.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Delete product by Id:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671140134807_delete.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropboxusercontent.com%2Fs_E09D6782AAF10B6FA40BC349DC880388575D7449466248BC76CF60F1450CB71A_1671140134807_delete.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This returns a message "Product successfully deleted" to let you know that the delete process was successful.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The first two things to consider in choosing a validation library are the flexibility of the validation rules and speed. Understanding the pros and cons of a validation library before using it is key to getting the best out of it.&lt;br&gt;
In this tutorial, we learnt what data validation and fastest-validator are; we further briefly looked at some of the advantages of fastest-validator over other types of validation libraries. We demonstrated the clean and easy way to use the fastest-validator library in our Express.js API/application by building a product management API using the express.js framework, MongoDB database, and the fastest-validator library. At the end of the tutorial, the API routes were tested and the results were as expected as seen in the tutorial.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Get the complete code&lt;/strong&gt; &lt;a href="https://github.com/Augusta-E/Fastest_Val_Express" rel="noopener noreferrer"&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;connect with me:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/augusta-e/" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt;&lt;br&gt;
&lt;a href="https://twitter.com/EhiheboloA" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>node</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>Master String Manipulation in Solidity</title>
      <dc:creator>Augusta Ehihebolo</dc:creator>
      <pubDate>Sun, 15 May 2022 20:17:33 +0000</pubDate>
      <link>https://forem.com/augustae/master-string-manipulation-in-solidity-31em</link>
      <guid>https://forem.com/augustae/master-string-manipulation-in-solidity-31em</guid>
      <description>&lt;h1&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;String manipulation in Solidity is not as straightforward as it is in most other programming languages, like JavaScript, Python, Java, etc.; with the entire notion/belief that a good background in JavaScript gives you an edge in Solidity, it sucks and becomes frustrating when you can't just use the (+) sign to concatenate strings in Solidity, like ("a"+"b") or do other simple string manipulations the way we are used to in most other programming languages. &lt;/p&gt;

&lt;h2&gt;
  
  
  What is string in programming?
&lt;/h2&gt;

&lt;p&gt;String is a piece of text or an array/sequence/collection of alphanumeric characters enclosed within a single or double quote mark, such as 'Welcome!' or "number 3". It is one of the essential concepts in computer programming.&lt;/p&gt;

&lt;p&gt;String is a data type used in most computer languages to store data values of ordered sequences of characters. It can be saved in a variable, entered by the user (input), or displayed on the screen (output). &lt;/p&gt;

&lt;p&gt;Manipulation of string to deliver information or change its contents is usually possible and relatively simple. The following are some of the things we can do with string:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check length of a string&lt;/li&gt;
&lt;li&gt;Check character position in a string&lt;/li&gt;
&lt;li&gt;Concatenate(join strings to form another word) strings&lt;/li&gt;
&lt;li&gt;Compare if two strings are the same&lt;/li&gt;
&lt;li&gt;Change letters in a string from uppercase to lowercase and verse versa&lt;/li&gt;
&lt;li&gt;Reverse a string&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  String in solidity
&lt;/h2&gt;

&lt;p&gt;String in Solidity has some similarities with bytes; both are dynamic array types, which means they can hold data of any size. Each element of a bytes variable is a single byte, whereas each element of a string variable is a string character. it does not support functions to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get string length&lt;/li&gt;
&lt;li&gt;Concatenate strings &lt;/li&gt;
&lt;li&gt;Convert from upper case to lower case &lt;/li&gt;
&lt;li&gt;Join two strings &lt;/li&gt;
&lt;li&gt;Reverse string&lt;/li&gt;
&lt;li&gt;Compare two strings &lt;/li&gt;
&lt;li&gt;To achieve any of the above mentioned, you have to do some sorts of manual manipulations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Solidity, string is an array of UTF-8 characters that can be converted to bytes easily, and this is the primary way of manipulating string. It's vital to note that UTF-8 characters don't always match bytes perfectly. Although the conversion will be accurate in either direction, there is no direct relationship between each byte index and the associated string index. It's also worth remembering that string literals are limited to readable ASCII characters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project setup
&lt;/h2&gt;

&lt;p&gt;Go to &lt;a href="https://remix.ethereum.org/"&gt;Remix IDE&lt;/a&gt;, in your workspace create a new file called &lt;strong&gt;stringMan.sol.&lt;/strong&gt;&lt;br&gt;
Go to your workspace compiler, set the compiler to the latest local version or any version greater than or equal to 0.8.0, and enable the auto compiler so that your work compiles automatically on the go, this will allow you to spot an error easily, that's one great thing I really love about Remix IDE.&lt;br&gt;
Now, open the &lt;strong&gt;stringMan.sol&lt;/strong&gt; file and set the &lt;code&gt;SPDX-Licence-Identifier: UNLICENSED&lt;/code&gt; and &lt;code&gt;Pragma solidity ^0.8.0.0;&lt;/code&gt;. Awesome! Our environment is all set. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YA9daqDB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682263043511_set.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YA9daqDB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682263043511_set.png" alt="" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Find the length of a string
&lt;/h2&gt;

&lt;p&gt;Now that we have successfully set up our project environment, let’s start getting our hands dirty!&lt;br&gt;
In your &lt;strong&gt;stringMan.sol&lt;/strong&gt; file, create a contract called &lt;strong&gt;StringManipulation,&lt;/strong&gt; inside the StringManipulation contract, create a &lt;strong&gt;string&lt;/strong&gt; called &lt;strong&gt;str1,&lt;/strong&gt; then set &lt;strong&gt;str1&lt;/strong&gt; to the string literal "Congratulations".&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: UNLICENSED;
pragma solidity ^0.8.0.0;

contract StringManipulation{
    string public str1 = "Congratulations";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Moving on, let’s create a function that gets the value of our string variable  &lt;strong&gt;str1,&lt;/strong&gt;  a function that gets the length of the string, and a function that sets the value of &lt;strong&gt;str1&lt;/strong&gt; to a new string.&lt;/p&gt;

&lt;p&gt;First, declare a function called &lt;strong&gt;getStr&lt;/strong&gt; that returns the string &lt;strong&gt;str1,&lt;/strong&gt; then declare another function called &lt;strong&gt;getStrLength&lt;/strong&gt; that returns the length of the string, and declare another function called &lt;strong&gt;setStr&lt;/strong&gt; that sets the string “&lt;strong&gt;str1&lt;/strong&gt;” to a new string of your choice.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: UNLICENSED;
pragma solidity ^0.8.0.0;

contract StringManipulation {
    //create string
    string public str1 = "Congratulations";

   //get string function
    function getStr() public view returns(string memory) {
        return str1;
    }

    //get string length function
    function getStrLength() public view returns(uint) {
        bytes memory strB = bytes(str1);
        return strB.length;
    }

    //set string function
    function setStr(string memory str) public {
        str1 = str;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the above code, the first function i.e the &lt;strong&gt;get string function&lt;/strong&gt; will return the value of the string variable “&lt;strong&gt;str1&lt;/strong&gt;” which is &lt;strong&gt;congratulations&lt;/strong&gt;, for the second function i.e the &lt;strong&gt;get string length function&lt;/strong&gt;, since we cannot get the length of a string directly, we converted the string &lt;strong&gt;str1&lt;/strong&gt; to byte and return the length, and for the last function which is the &lt;strong&gt;set string function&lt;/strong&gt;, we set the string variable &lt;strong&gt;str1&lt;/strong&gt; to a new string variable &lt;strong&gt;str&lt;/strong&gt; which allows us to set the string &lt;strong&gt;str1&lt;/strong&gt; to any string of our choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concatenate strings
&lt;/h2&gt;

&lt;p&gt;Now that we know how to find our way around getting the length of a string, let’s move on to string concatenation. &lt;br&gt;
In your StringManipulation contract, create another function called &lt;strong&gt;concateString,&lt;/strong&gt; let it take 2 arguments &lt;strong&gt;str1&lt;/strong&gt; and &lt;strong&gt;str2&lt;/strong&gt;, and return the concatenated string.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: UNLICENSED;
pragma solidity ^0.8.0.0;

contract StringManipulation{
    string public str1 = "Congratulations";

//get string function
    function getStr() public view returns(string memory) {
        return str1;
    }

    //set string function
    function setStr(string memory str) public {
        str1 = str;
    }

    //get string length function
    function getStrLength() public view returns(uint) {
        bytes memory strB = bytes(str1);
        return strB.length;
    }


    //concatenate strings function
    function concatString(
        string memory _str1, 
        string memory _str2
        ) public pure returns(string memory) {
    return string (abi.encodePacked(_str1,_str2));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In solidity, you cannot concatenate strings simply by using the plus sign like in JavaScript and some other languages, e.g. (str1 + str2), instead, you call the abi.encodedPacked() function and passed in the strings to be concatenated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compare strings
&lt;/h2&gt;

&lt;p&gt;With string concatenation successfully out of the way, you should drink a glass of juice and take a deep breath. having done that, let’s keep on moving…&lt;br&gt;
Head over to your &lt;strong&gt;StringManipulation&lt;/strong&gt; contract again, create another function called &lt;strong&gt;compareStr&lt;/strong&gt;, let it take two(2) string arguments &lt;strong&gt;str1&lt;/strong&gt; and &lt;strong&gt;str2&lt;/strong&gt; and return a boolean.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: UNLICENSED;
pragma solidity ^0.8.0.0;

contract StringManipulation{
    string public str1 = "Congratulations";

   //get string function
    function getStr() public view returns(string memory) {
        return str1;
    }

    //set string function
    function setStr(string memory str) public {
        str1 = str;
    }

    //get string length function
    function getStrLength() public view returns(uint) {
        bytes memory strB = bytes(str1);
        return strB.length;
    }

    //concatenate strings function
    function concatString(
        string memory _str1, 
        string memory _str2
        ) public pure returns(string memory) {
    return string (abi.encodePacked(_str1,_str2));
    }

    //compare strings function
    function compare(
        string memory _str1, 
        string memory _str2
        ) external pure returns(bool){
            return keccak256(abi.encodePacked(_str1)
            ) == keccak256(abi.encodePacked(_str2));
            }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Just as in concatenation, to compare 2 strings in solidity, we called the keccak256 function and passed in the abi.encoded function which takes the argument, and then compares.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reverse string
&lt;/h2&gt;

&lt;p&gt;I am sure you are feeling like a boss already, you should be because it’s not easy getting here. Without any delay, let’s see how we can reverse a string.&lt;br&gt;
Still, inside your &lt;strong&gt;StringManipulation&lt;/strong&gt; smart contract, create a function called &lt;strong&gt;reverseStr&lt;/strong&gt; that takes a string argument &lt;strong&gt;_str&lt;/strong&gt; and returns a string(reversed of the string that was passed in)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: UNLICENSED;
pragma solidity ^0.8.0.0;

contract StringManipulation{
    string public str1 = "Congratulations";

   //get string function
    function getStr() public view returns(string memory) {
        return str1;
    }

    //set string function
    function setStr(string memory str) public {
        str1 = str;
    }

    //get string length function
    function getStrLength() public view returns(uint) {
        bytes memory strB = bytes(str1);
        return strB.length;
    }

    //concatenate strings function
    function concatString(
        string memory _str1, 
        string memory _str2
        ) public pure returns(string memory) {
    return string (abi.encodePacked(_str1,_str2));
    }

    //compare strings function
    function compareStr(
        string memory _str1, 
        string memory _str2
        ) external pure returns(bool){
            return keccak256(abi.encodePacked(_str1)
            ) == keccak256(abi.encodePacked(_str2));
            }

       //reverse string function
    function reverseStr(string memory _str) external pure returns(string memory){
        bytes memory baseByte = bytes(_str);
        string memory tempValue = new string(baseByte.length);
        bytes memory reverse = bytes(tempValue); 
        for(uint i = 0; i &amp;lt; baseByte.length; i++) {
             reverse[baseByte.length - i - 1] = baseByte[i];
             }
             return string(reverse);
             }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here, we converted the string to byte, get the instance of the string length, and simply looped through from the back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Convert string to lower case
&lt;/h2&gt;

&lt;p&gt;Moving further, let’s see how we can convert a string from uppercase to lowercase. In your &lt;strong&gt;StringManipulation&lt;/strong&gt; contract, create a function called &lt;strong&gt;toLowerCase&lt;/strong&gt; that takes a string argument &lt;strong&gt;_str&lt;/strong&gt; and returns a string(the lowercase of the passed in string)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: UNLICENSED;
pragma solidity ^0.8.0.0;

contract StringManipulation{
    string public str1 = "Congratulations";

   //get string function
    function getStr() public view returns(string memory) {
        return str1;
    }

    //set string function
    function setStr(string memory str) public {
        str1 = str;
    }

    //get string length function
    function getStrLength() public view returns(uint) {
        bytes memory strB = bytes(str1);
        return strB.length;
    }

    //concatenate strings function
    function concatString(
        string memory _str1, 
        string memory _str2
        ) public pure returns(string memory) {
    return string (abi.encodePacked(_str1,_str2));
    }

    //compare strings function
    function compareStr(
        string memory _str1, 
        string memory _str2
        ) external pure returns(bool){
            return keccak256(abi.encodePacked(_str1)
            ) == keccak256(abi.encodePacked(_str2));
            }

       //reverse string function
    function reverseStr(string memory _str) external pure returns(string memory){
        bytes memory baseByte = bytes(_str);
        string memory tempValue = new string(baseByte.length);
        bytes memory reverse = bytes(tempValue); 
        for(uint i = 0; i &amp;lt; baseByte.length; i++) {
             reverse[baseByte.length - i - 1] = baseByte[i];
             }
             return string(reverse);
             } 

    //convert string to lowercase
    function toLowerCase(string memory _str) public pure returns (string memory) {
        bytes memory bString = bytes(_str);
        bytes memory bLowerCase = new bytes(bString.length);
        for (uint j = 0; j &amp;lt; bString.length; j++) {
            // Uppercase character...
            if ((uint8(bString[j]) &amp;gt;= 65) &amp;amp;&amp;amp; (uint8(bString[j]) &amp;lt;= 90)) {
                // So we add 32 to make it lowercase
                bLowerCase[j] = bytes1(uint8(bString[j]) + 32);
            } else {
                bLowerCase[j] = bString[j];
            }
        }
        return string(bLowerCase);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For the &lt;strong&gt;toLowerCase&lt;/strong&gt; function, we first converted the string to byte, then get the instance of the length; since the ASCII values of &lt;code&gt;A - Z&lt;/code&gt; are from &lt;code&gt;65 - 90&lt;/code&gt;, and that of &lt;code&gt;a - z&lt;/code&gt;, from &lt;code&gt;97 - 112&lt;/code&gt;, we looped through to check if each character is within the range of &lt;code&gt;65 - 90(A - Z)&lt;/code&gt;, add 32 if found to be true, to convert it to a lower case else return it that way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test functions
&lt;/h2&gt;

&lt;p&gt;If everything went well, your smart contract should be successfully compiled by now since it’s in auto compile. If you didn’t enable auto compile, now is the time to compile your smart contract, hit the compile button to compile it, and head over to deploy once compiled. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tuTVfC9U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682262730781_deploy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tuTVfC9U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682262730781_deploy.png" alt="" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that you have successfully deployed your smart contract, let’s test all the functions to ensure they are working as they should:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Get string, set string and get string length functions:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4uIA6gLX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682258946390_get3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4uIA6gLX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682258946390_get3.png" alt="" width="707" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XOAZAcdj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682258973193_get1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XOAZAcdj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682258973193_get1.png" alt="Get string and get string length" width="419" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Kx54chii--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682258993512_get2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Kx54chii--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682258993512_get2.png" alt="Set string, get string and get string length" width="419" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Concatenate strings function:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5w-5aQ_p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682258835003_concate2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5w-5aQ_p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682258835003_concate2.png" alt="" width="800" height="149"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VsgnJEIc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682258855402_concat1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VsgnJEIc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682258855402_concat1.png" alt="" width="429" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compare strings function:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XP1Idjy1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682258646400_compare3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XP1Idjy1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682258646400_compare3.png" alt="" width="800" height="167"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CXncfvSZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682258690724_compare1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CXncfvSZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682258690724_compare1.png" alt="It returns true if the words are the same" width="440" height="207"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wZS4GNRY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682258721245_compare2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wZS4GNRY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682258721245_compare2.png" alt="it returns false if the two(2) words are different" width="428" height="208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reverse string function:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LAmmniJS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682257761123_reverse2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LAmmniJS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682257761123_reverse2.png" alt="" width="800" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R7cqPxru--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682257875698_reverse1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R7cqPxru--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682257875698_reverse1.png" alt="" width="437" height="170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;toLowerCase function:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8Mc9v6-8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682259344032_lowercase2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8Mc9v6-8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682259344032_lowercase2.png" alt="" width="800" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HaoSoGal--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682259373539_lowercase1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HaoSoGal--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://paper-attachments.dropboxusercontent.com/s_E5157F8A5E63F9FAA7ED8C99D44B5138C3B736F508C947E5B288014315DA4CD3_1682259373539_lowercase1.png" alt="" width="434" height="178"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion:
&lt;/h2&gt;

&lt;p&gt;It is not very efficient to manipulate strings in solidity, hence it is not recommended. Using strings in solidity is quite expensive since it consumes too much gas thereby costing too much gas fee; if you can, avoid string manipulation and attempt to replace it with byte instead. &lt;/p&gt;

&lt;p&gt;Also, Stings in Solidity accepts the backslash character ( \ ) as an escape character and the backslash plus n characters (\ + n)  (\n) as a new line character, just like JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.soliditylang.org/en/latest/types.html?highlight=string#string-literals-and-types"&gt;Solidity 0. 8. 13 Documentation&lt;/a&gt;&lt;br&gt;
&lt;a href="https://gist.github.com/ottodevs/c43d0a8b4b891ac2da675f825b1d1dbf"&gt;Etheruem/Solidity toLower() equivalent&lt;/a&gt;&lt;br&gt;
&lt;a href="https://youtu.be/gNlwpr3vGYM"&gt;String manipulation in Solidity&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Get the complete code&lt;/strong&gt; &lt;a href="https://github.com/Augusta-E/string-manipulation-sol/blob/e371cc524b0e9f9c206ed0ef31f56c1a2388d1f6/stringMan.sol"&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's connect:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/augusta-e/"&gt;Linkedin&lt;/a&gt;&lt;br&gt;
&lt;a href="https://twitter.com/EhiheboloA"&gt;Twitter&lt;/a&gt; &lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>solidity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Comparing Web 3.0 features with Web 2.0 and Web 1.0</title>
      <dc:creator>Augusta Ehihebolo</dc:creator>
      <pubDate>Tue, 04 Jan 2022 18:59:18 +0000</pubDate>
      <link>https://forem.com/augustae/comparing-web-30-features-with-web-20-and-web-10-3fk0</link>
      <guid>https://forem.com/augustae/comparing-web-30-features-with-web-20-and-web-10-3fk0</guid>
      <description>&lt;p&gt;It's incredible how technology has extensively transformed our society lately, particularly in the evolution of the Web from 1.0 to 3.0; Truly, there is no such thing as versions of the Web, just a way to help us keep track of what has been, and what currently is. The &lt;strong&gt;World Wide Web&lt;/strong&gt; referred to as the "&lt;strong&gt;Web&lt;/strong&gt;" for short, is the fundamental tool used to view and explore information through the internet by millions of people. It started with the basic browsers like Netscape, Mosaic, etc that only interpreted text, then appeared the HTML, making the pages more friendly and easily accessible. Taking a wild trip down memory lane with me to keep up with the fast-paced advancement of Web features is something worthwhile, so let’s go!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_53EA0B3E97644BE83B2E45F3BFC241944AC0FB57860AA45EBC49711830C7BD97_1641044076082_file.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpaper-attachments.dropbox.com%2Fs_53EA0B3E97644BE83B2E45F3BFC241944AC0FB57860AA45EBC49711830C7BD97_1641044076082_file.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Web 1.0&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Web 1.0 is a term used to represent the first stage of the evolution of the World Wide Web, it is the first iteration of the Web, it started from 1990 to 2004. The era of Web 1.0 was the time when the Web was being powered by HTML and CSS; the pages were static and were built using a &lt;a href="https://en.wikipedia.org/wiki/Common_Gateway_Interface" rel="noopener noreferrer"&gt;common gateway interface&lt;/a&gt; (CGI) or &lt;a href="https://en.wikipedia.org/wiki/Server_Side_Includes" rel="noopener noreferrer"&gt;server-side includes&lt;/a&gt;, and contents were served from the server file system. To be able to access the Web, you have to be a programmer or someone who knows about technology. According to Berners-Lee, Web 1.0 is a "Read-only" Web, in order words, we could only search and read information. It only had a few content creators and a large number of users that consume the contents, it brought the people from offline to online to be able to search and purchase products and services. Unfortunately, Web 1.0 couldn't strive because of its inaccessibility problem, users could not interact and contribute to the content that was created.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Web 2.0&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The term Web 2.0 has been frequently used since early-2000 to mid-2000. Web 2.0 was the massive adoption age and second iteration of the Web, where innovations moved from being static to dynamic, it can also be referred to as participative or social Web because it made it possible for people to interact and collaborate in social media, it is the “Read-Write” Web. The birth of new technologies that solved the inaccessibility problem of Web 1.0 by giving room to the vast majority of people to be able to publish information with just a click of a button led us to Web 2.0. &lt;br&gt;
Early Web 2.0 companies like Amazon, Facebook, YouTube,  Twitter, etc started coming up with easy ways to publish content and make them accessible. Web 2.0 made it possible for us to store our information in the cloud and access it from anywhere. &lt;br&gt;
Web 2.0 is centralized, it uses client/server architecture. Just like the famous quote "if you're not paying for it, you are the product", Web 2.0 gave us value in exchange for our privacy, ownership of our data; the big tech companies decide what to do with our data, we have the power to write contents but we do not have the power to own our contents; they use our data for ads and generate a huge sum of money with it, while we spend money directly or indirectly to access the Web through the internet, only to be welcomed with an unsolicited ad, it sucks right! well, how about a situation where you can reap the reward of your value? exciting right! continue the trip with me, let's take a deep look into Web 3.0.&lt;/p&gt;

&lt;h2&gt;
  
  
  Web 3.0
&lt;/h2&gt;

&lt;p&gt;Web 3.0 is a Decentralized technology powered by blockchain technology. Blockchain technology makes it possible to store data securely, bringing about a more reliable method of data integrity and checks.&lt;br&gt;
The problems of Web 2.0: centralization of control, ownership of data, privacy issue led us to Web 3.0. One of the Web 3.0 evolutions is transforming the Web into a database. The 2 pillars of Web 3.0 are Artificial Intelligence (AI) which helps the computer to interpret information like humans, and semantic Web; following the explanation of Berners-Lee, Web 3.0 would be "Read-Write-Execute" Web.&lt;br&gt;
According to Sandeep Nailwal, the co-founder of polygon technology, "through Web 3.0, users create the value, control the network and reap the reward". Web 3.0 returns control to users, gives users ownership of data, and allows interaction. Big tech companies like Apple, Google, Facebook, and their likes will have no control over users data because Web 3.0 is &lt;a href="https://en.wikipedia.org/wiki/Semantic_Web" rel="noopener noreferrer"&gt;semantic Web&lt;/a&gt; with no middle man to control the data, it has no centralized database that stores the state of the application, unlike the Web 2.0, the backend logics have no centralized Web server, the apps run on nodes. Web 3.0 allows individual users to monetize the computer and reap the reward of their value. File sharing in Web 3.0 is done through peer-to-peer. &lt;/p&gt;

&lt;h3&gt;
  
  
  WEB 3.0 FEATURES COMPARED WITH WEB 2.0 AND WEB 1.0
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Web 3.0&lt;/th&gt;
&lt;th&gt;Web 2.0&lt;/th&gt;
&lt;th&gt;Web 1.0&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Read-Write-Execute&lt;/td&gt;
&lt;td&gt;Read-Write&lt;/td&gt;
&lt;td&gt;Read-only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Smart Applications that leverage on Artificial Intelligence&lt;/td&gt;
&lt;td&gt;Web applications&lt;/td&gt;
&lt;td&gt;Webforms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Behavioral advertising method&lt;/td&gt;
&lt;td&gt;Interactive advertising method&lt;/td&gt;
&lt;td&gt;Banner advertising method&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Content is owned by the network&lt;/td&gt;
&lt;td&gt;Content is owned and shared by the entity through a network&lt;/td&gt;
&lt;td&gt;Content is consolidated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High security of data and privacy&lt;/td&gt;
&lt;td&gt;Low security of data and privacy&lt;/td&gt;
&lt;td&gt;No security and privacy concern&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The semantic Web (for machine)&lt;/td&gt;
&lt;td&gt;The community Web (For people:  app/site connectivity them)&lt;/td&gt;
&lt;td&gt;The Hypertext/GCI Web (the basics)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Live-streams / Waves&lt;/td&gt;
&lt;td&gt;Blogs / Wikis&lt;/td&gt;
&lt;td&gt;Home Pages&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I believe that we stop living once we stop thinking. As we continue to live, the advancement of the Web and its features are inevitable. Tim Berners-Lee, ‘the Web creator’ once said in one of his interviews in 1999 “people keep asking me what I think of it now that it’s done. Hence my protest: The Web is not done!”. In the same way, I believe a lot of people are currently muttering on what is next after Web 3.0; well, trust me the Web is still not done, we have Web 4.0 (the &lt;strong&gt;“Symbiotic Web”&lt;/strong&gt;) just around the corner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;References:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://ir.inflibnet.ac.in/bitstream/1944/1285/1/54.pdf" rel="noopener noreferrer"&gt;Comparative Study of Web 1.0, Web 2.0 and Web 3.0&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.geeksforgeeks.org/web-1-0-web-2-0-and-web-3-0-with-their-difference/" rel="noopener noreferrer"&gt;Web 1.0, Web 2.0 and Web 3.0 with their difference&lt;/a&gt;&lt;br&gt;
&lt;a href="https://youtu.be/y7FD-LqD4YY?t=620s" rel="noopener noreferrer"&gt;Web 1.0 vs. Web 2.0 vs Web 3: Exploitative Fad or Promising Future?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connect with me on&lt;/strong&gt; &lt;a href="https://www.linkedin.com/in/augusta-e" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt; &lt;/p&gt;

</description>
      <category>web3</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
