Search by Category
Close

Filter by Category

Artificial Intelligence
React
Ruby on Rails
Next.js
Python
Javascript
HTML & Frontend
CSS
CSS Tricks
Caching
Database & Designs
Authentication & Security
Web Hosting
Technology
user profile avatar

tech girl

Published on • 🕑5 min


10 Unique HTML Elements You Might Not Know

HTML offers a vast array of elements that can enhance the way you present content on the web. While most developers are familiar with standard tags like <div><p>, and <a>, there are some lesser-known elements that can be quite useful. Here are five unique HTML elements you might not know about:

1. <q></q> Tag

The <q> tag defines a short quotation. It’s perfect for including inline quotes within your text. This element is intended for short quotations that don't require paragraph breaks; for long quotations use the <blockquote> element.

It's particularly useful in articles, blogs, or essays where referencing someone else's words within the body of your text enhances clarity and credibility. It is also most often in conjuction with <cite></cite> tags.

Here’s an example:

<q>Hi 👋, my name is Jane.</q>

Result⤵️

Hi 👋, my name is Jane.

2. <s></s> Tag

The <s> HTML element renders text with a strikethrough, or a line through it. Use the <s> element to represent things that are no longer relevant or accurate. The <s> tag should not be used to define deleted text in a document, use the <del> tag for that.

This tag is particularly effective in e-commerce, educational materials, or content revisions where you need to show what has been updated or corrected.

Here’s an example:

<p>Old Price <s>100</s></p>
<p>New price 50</p>

Result⤵️

Old Price: $100

New price: $50

3. <mark></mark> Tag

The <mark> HTML element represents text which is marked or highlighted for reference or notation purposes due to the marked passage's relevance in the enclosing context.

Use the <mark> tag when you want to draw attention to specific text within a paragraph or section, such as key points, warnings, or items that require further action. It's useful in tutorials, important notices, or highlighting search results.

Don't use <mark> for syntax highlighting purposes; instead, use the <span> element with appropriate CSS applied to it.

Here’s an example:

<p>Hi, you should <mark>Follow me</mark> for more amazing content. Thanks!</p>

Result⤵️

Hi, you should Follow me for more amazing content. Thanks!

4. <sup></sup> Tag

The <sup> HTML element specifies inline text which is to be displayed as superscript for solely typographical reasons. Superscripts are usually rendered with a raised baseline using smaller text.

The <sup> element should only be used for typographical reasons—that is, to change the position of the text to comply with typographical conventions or standards, rather than solely for presentation or appearance purposes.

Here’s an example:

<p>
  One of the most common equations in all of physics is <var>E</var>=<var>m</var
  ><var>c</var><sup>2</sup>.
</p>

Result⤵️

One of the most common equations in all of physics is E=mc2.

5. <details></details> Tag

The <details> HTML element creates a disclosure widget where information is visible only when the widget is toggled into an "open" state. A summary or label must be provided using the <summary> element.

Use the <details> tag to hide content that is not immediately necessary but can be revealed if the user wants more information. It’s ideal for FAQs, additional reading, toggling descriptions, or any content where you want to manage space effectively.

Fully standards-compliant implementations automatically apply the CSS display: list-item to the <summary> element. You can use this to customize its appearance further.

Here’s an example:

<details open>
  <summary>Details</summary>
  Something small enough to escape casual notice.
</details>

Result⤵️

Details Something small enough to escape casual notice.

6. <menu></menu> Tag

The <menu> HTML element is described in the HTML specification as a semantic alternative to <ul>, but treated by browsers (and exposed through the accessibility tree) as no different than <ul>. It represents an unordered list of items (which are represented by <li> elements).

You can use this tag to create a toolbar and make your group commands that a user might execute.

Here’s an example:

<div class="news">
  <a href="#">NASA’s Webb Delivers Deepest Infrared Image of Universe Yet</a>
  <menu>
    <li><button id="save">Save for later</button></li>
    <li><button id="share">Share this news</button></li>
  </menu>
</div>

Result⤵️

NASA’s Webb Delivers Deepest Infrared Image of Universe Yet
  • 7. <aside></aside> Tag

    The <aside> HTML element represents a portion of a document whose content is only indirectly related to the document's main content. Asides are frequently presented as sidebars or call-out boxes.

    You can use this element for any content not directly related to the main content of the page. It works well for displaying advertisements, related posts, promotional content, blockquotes, nav elements, and so on.

    Here’s an example:

    <article>
      <p>
        The Disney movie <cite>The Little Mermaid</cite> was first released to
        theatres in 1989.
      </p>
      <aside>
        <p>The movie earned $87 million during its initial release.</p>
      </aside>
      <p>More info about the movie…</p>
    </article>

    Result⤵️

    The Disney movie The Little Mermaid was first released to theatres in 1989.

    More info about the movie…

    8. <search></search> Tag

    The <search> HTML element is a container representing the parts of the document or application with form controls or other content related to performing a search or filtering operation.

    The <search> element semantically identifies the purpose of the element's contents as having search or filtering capabilities. The search or filtering functionality can be for the website or application, the current web page or document, or the entire Internet or subsection thereof.

    The tag helps provide a better user experience on mobile devices with search-optimized keyboards.

    Here’s an example:

    <search>
        <form action="./search/">
          <label for="movie">Find a Movie</label>
          <input type="search" id="movie" name="q" />
          <button type="submit">Search</button>
        </form>
      </search>

    Result⤵️

    9. <datalist></datalist> Tag

    You might be familiar with the select element that lets you provide users with a bunch of options to select from. A similar element is the datalist element.

    The only difference between them is the datalist element provides suggestions instead of a finite set of options. Users can also type in their own input if none of the suggestions match their requirements, whereas when using the select element, users must pick from the list of options in the dropdown.

    You can use <datalist> with the input element so the user can type anything they want. Then if it matches the values in the datalist, the user can select that value.

    In order to link the input element with the datalist, you'll need to use a list attribute on the input element. The value of the list attribute must be the id of the datalist. 

    ⚠ Data List has limited support availability and does not work in most widely used browsers. See Full Compatibility

    Here’s an example:

    <label for="ice-cream-choice">Choose a flavor:</label>
    <input list="ice-cream-flavors" id="ice-cream-choice" name="ice-cream-choice" />
    <datalist id="ice-cream-flavors">
      <option value="Chocolate"></option>
      <option value="Coconut"></option>
      <option value="Mint"></option>
      <option value="Strawberry"></option>
      <option value="Vanilla"></option>
    </datalist>

    Result⤵️

    10. <optgroup></optgroup> Tag

    The <optgroup> tag is used to group related options within a <select> dropdown list. This makes the list easier to navigate, especially when there are many options, by categorizing them under different headings.

    When to Use:

    • To organize options in a long dropdown menu.
    • To enhance the user experience by logically grouping related options.

    Here’s an example:

     <div>
            <label for="cars">Choose a car:</label>
            <select id="cars" name="cars">
              <optgroup label="German Cars">
                <option value="bmw">BMW</option>
                <option value="audi">Audi</option>
                <option value="mercedes">Mercedes-Benz</option>
              </optgroup>
              <optgroup label="Japanese Cars">
                <option value="toyota">Toyota</option>
                <option value="honda">Honda</option>
                <option value="nissan">Nissan</option>
              </optgroup>
            </select>
          </div>

    Result⤵️

    These unique HTML elements can be extremely helpful in specific scenarios, enhancing the semantic richness and functionality of your web content. Next time you’re building a webpage, consider incorporating these tags to improve the user experience and accessibility of your site.

    44Blog views

    854

    share this blog
    user profile avatar

    tech girl

    Published on • 🕑2 min


    Why My Opinion on NextJS is Changing

    I have been the greatest fan of NextJS, but I believe there is more hype to the framework. My opinion about NextJS is changing and I am considering switching to Remix or Just the old plain React. Here is why I think NextJS is overhyped.


    NextJS, which is a react framework that enables developers create full-stack React-based web applications with server-side rendering and static website generation, is currently in version 14. Ironically, React is currently in version 18 despite being released in 2013 while NextJS was released in 2016. Undoubtedly the framework is way over its head.

    One of the major concerns is that NextJS packages and ships Experimental React Features, and marks them as stable, ultimately using developers as guinea pigs for new features. Shipping experimental react features such as useServer significantly introduces a lot of bugs into NextJS code, requiring the work of a bounty hunter!

    Make Money By Hacking?? Bug Bounty Guide (Resources) | by Om Arora |  InfoSec Write-ups

    Call me a noob but I have not experienced any improvement in performance after switching to NextJS. As a matter of fact, my application has gotten too slow compared to applications created using React. However, other developers have reported perfomance improvements after switching to NextJS. I presume I have not been able to fully leverage NextJS server-side rendering and data fetching.

    Another significant issue is that Vercel  has made it exceedingly difficult to host NextJS code in other hosting service providers such as Netlify. But part of the problem is that the line between Next.js and Vercel is very thin so if you're not deploying on Vercel, you're actually using a different framework from what's documented in the Next.js docs and it's not always clear what those differences are because Vercel isn't incentivized to invest time in that.
    We can argue about whether Vercel is right or wrong about their current approach. But the fact remains that if Vercel’s pricing or other things become a problem for you, getting off of Vercel will also be a problem. It comes back down to the incentives, although the company still remains unprofitable

    Let me know what you guys think about NextJS. PS this website is built using NEXTJS!

    214Blog views

    1.9K

    share this blog
    user profile avatar

    Tech Wizard

    Published on • 🕑3 min


    How to Secure Your Website with Google Recaptcha

    If you have contact, registration or other forms on your website it's important to try and ensure that they are only used by humans. Robots (or 'bots') search out websites with unprotected forms - to either spam the site owner, or worse, potentially send spam to contacts registered with the site.

    Google reCAPTCHA can help to stop this - either via a challenge that a human needs to complete (reCAPTCHA v2) or by monitoring the use of the site to establish human usage by score (reCAPTCHA v3). v3 reCAPTCHA is potentially less invasive as a result of its score based system - most valid human users will never see a challenge.

    For this tutorial, i am going to focus on reCAPTCHA v3, which works in the background. To get started, head over to google cloud and create a reCAPTCHA key for your site and make sure to choose V3.

     

    Google gives you a site key that should be included in your website and client secret that you can use to verify users. Create a .env file and add the keys.

    //.env
    NEXT_PUBLIC_GOOGLE_RECAPTCHA_SITE_KEY="YOUR_SITE_KEY"
    GOOGLE_RECAPTCHA_CLIENT_SECRET="YOUR_CLIENT_SECRET"

    Note that i named the site key using NEXT_PUBLIC since browsers require access to this key. However, I do not know if this is the best practice. To get started with recaptcha if you are using react or nextjs, you need to install react-google-recaptcha-v3. 

    npm i react-google-recaptcha-v3

    For this project, i wanted to secure my login, registration and password reset pages to ensure they do not allow bot traffic. Therefore, i added the GoogleReCaptchaProvider in the layout of my auth pages.

    //create a google context provider in .providers/google
    "use client";
    import { GoogleReCaptchaProvider } from "react-google-recaptcha-v3";
    export function GoogleContextProviders({ children }) {
      return (
          <GoogleReCaptchaProvider
            reCaptchaKey={process.env.NEXT_PUBLIC_GOOGLE_RECAPTCHA_SITE_KEY}>
            {children}
          </GoogleReCaptchaProvider>
      );
    }
    //add the provider to the auth layout
    import "../globals.css";
    import { GoogleContextProviders } from "@/providers/google";
    export default function RootLayout({ children }) {
      return (
        <html lang="en">
          <body>
            <main>
              <GoogleContextProviders>{children}</GoogleContextProviders>
            </main>
          </body>
        </html>
      );
    }
    

    After adding the context provider in our routes, we need to initialize google recaptcha in forms that we want to protect. We do this by setting a token state that is submitted when the form is filled, and then verifying the score. Here is a sample login page:

    "use client";
    import { useState } from "react";
    import toast from "react-hot-toast";
    import { useGoogleLogin } from "@react-oauth/google";
    import { validateRecaptcha } from "@/lib/actions";
    export default function LoginPage() {
      const [token, setToken] = useState(false);
      const [formData, setformData] = useState({
                email: "",
                password: "",
      });
      async function handleSubmit(e) {
        e.preventDefault();
        if (!token) {
          toast.error("Kindly complete the recaptcha challenge");
          return;
        }
        const isValid = await validateRecaptcha(token);
        if (isValid) {
          handleLogin(formData);
        } else {
          toast.error("Recaptcha Validation Failed");
        }
     }
      return (
        <form  onSubmit={handleSubmit}>
              </div>
                  {/* Add your inputs here */}
              </div>
                <GoogleReCaptcha onVerify={(token) => {  setToken(token) }}  />
                <button type="submit" title="login">
                 Login
                </button>  
        </form>
      );
    }
    

    Next we need to create a helper function that will be called to validate the recaptcha challenge. Since v3 works in the background, users are not required to prove they are a robot unless required.

    //lib.actions
    export async function validateRecaptcha(captcha: string) {
      const secretKey = process.env.GOOGLE_RECAPTCHA_CLIENT_SECRET;
      if (!secretKey) {
        throw new Error("Missing Google reCAPTCHA client secret");
      }
      if (!captcha) {
        throw new Error("Missing reCAPTCHA response token");
      }
      const url = `https://www.google.com/recaptcha/api/siteverify?secret=${secretKey}&response=${captcha}`;
      const response = await fetch(url, {
        method: "POST",
        headers: {
          "Content-Type": "application/x-www-form-urlencoded",
        },
      });
      if (!response.ok) {
        throw new Error(
          `Failed to validate reCAPTCHA response: ${response.statusText}`
        );
      }
      const data = await response.json();
      if (!data.success && data.score < 0.5) {
        throw new Error("Failed reCAPTCHA validation", data.score);
      }
      return true;
    }
    

    The validatecaptcha checks the captcha each time the form is submitted and throws an error if the token is absent. In the function we are checking if the user score is above five, meaning they might be a legit user. However, you might choose to be more strict and maybe use a score of 7, which is the average score a normal user would get. 

    The final login page looks like this, with the recaptcha protection:

    However, Google allows up to 10,000 assessments per month for free, but users need to enable billing if they want to exceed that limit or access additional features. A free alternative is cloudflare turnstile, which claims not to harvest user data as google does.

    Resources:

    1. https://cloud.google.com/security/products/recaptcha?hl=en
    2. How to implement turnstile: https://medium.com/designly/a-complete-guide-to-authentication-in-next-js-14-421ec8906854
    3. Recaptcha documentation: https://cloud.google.com/recaptcha/docs
    13Blog views

    976

    share this blog
    user profile avatar

    Tech Wizard

    Published on • 🕑3 min


    My Experience with PRISMA so Far and Why I am Considering Switching to Drizzle

    I recently switched to using Prisma ORM for the backend of my blog. This decision came after encountering difficulties hosting my Ruby on Rails API for free. Most hosting platforms, including my favorite Railway, require a monthly payment, which exceeds my current budget. Here is my experience with Prisma so far.

    About Prisma

    Prisma is a next-generation ORM that makes working with databases easy for application developers.

    • Object-relational mapper
    • A way to interact with our database
    • Completely type safe

    Prisma is super easy to work with, and I was able to switch my whole database in just 4 days. The Prisma schema makes it super easy to declare relationships between models, and with Prisma seeding feature also makes it easy to populate the database with existing data.

    Here is a sample prisma schema

    sample-prisma-schema

    However, I initially struggled with the seeding process and I had to create data manually via API routes. Together with NextJS API routes, Prisma is super fun to work with. One major benefit of NextJS is that expensive queries can be cached so that refreshing the route does not re-fetch the data from the database.
    Another super cool feature of Prisma is the Prisma studio. This opens up a new tab where users can easily visualize data and even manage the data, such as creating new records, updating existing data, and deleting records. Individuals can access Prisma Studio by running.

    npx prisma studio

    prisma-studio

    Challenges

    Immediately after switching to Prisma, I realized my server was taking too long to respond. A single login request, which often took 700ms to complete, took over 10s. This delay is significant and could affect user performance. 

    Requests made with Prisma were ten times slower than normal!

    I looked around to try and understand why this was happening or some errors that I could be making. Prisma documentation suggests indexing frequently queried columns such as username and email by adding @@index([username, email]).

    Query is 5 times slower when using `findMany` compared to running identical  query via `queryRaw` · Issue #11130 · prisma/prisma · GitHub

    However, this does not solve the issue. Prisma is too slow, especially in queries that involve selecting data from more than one table.

    The database also has a cold start, which means that after the Prisma client disconnects, new requests will take time.

    PRISMA is also not designed to run on the edge, where vercel hosts their serveless functions. This implies that the servers are not up and running all the time in a serverless environment, thus the cold starts before Vercel spins the function and awakens the database.

    Here is what I have realized so far:

    • Prisma is not suited to run on the edge and thus the database sleeps when the Prisma client disconnects. Prisma takes time to connect again.
    • Every new insert via Prisma opened a database-level transaction (?). An extremely weird design choice by Prisma. This makes you exhaust your connection pool very fast.
    • There is no concept of SQL-level joins in Prisma. This means for every transaction that requires join, prisma fetches both tables, merges the data, and returns it to the user. This makes the findMany query take too long.
    • Prisma is fixing the SQL-level joins with a new feature called relation joins. However, this is still a preview feature. Users can enable this by adding this to their schema: preview features = ["relationJoins"
    • On every insert, Prisma opens a transaction where it inserts and then returns the inserted record too, even if we do not want it.
    • For every action (Create, Read, Update, and Delete) prisma returns the object by default even if you do not want it. Even for delete!
    • Prisma supports JSONB datatypes in Postgresql and MySQL. However, there is no way to update such data type. The existing way is to fetch the whole object, spread it, and then add or delete data, then post the same object again. This is utterly ridiculous.
    • Prisma has no way of hiding sensitive data, such as not returning password fields when you fetch a user object. 

    I have heard good things about some other ORMs such as Drizzle and Kysely, although they are not as easy to work with as Prisma. However, I will consider interacting with them first before making a concrete decision.

    Update:

    I switched to Prisma Accelerate and now Prisma is very fast with queries although it does not beat Active-Record.

    Maybe Prisma is intentionally slow so individuals can switch to the paid plan on Prisma Accelerate! However, I do agree that simplicity can make you get hooked.

    314Blog views

    1.4K

    share this blog
    user profile avatar

    Tech Wizard

    Published on • 🕑5 min


    Building A REST API with Prisma, NodeJS and PostgreSQL

    I once shared that I have migrated my database from Active Record using ruby on rails to a Prisma ORM and Node Js server powered by NextJS. This tutorial will create a simple API for Tesla vehicles to help you get started. Prisma is a powerful database toolkit that simplifies working with databases by providing a modern, type-safe query builder.

    We'll cover the following Prisma essentials:

    1. Connecting Prisma with a Database
    2. Setting Up Prisma Migrations
    3. Seeding the Database
    4. Implementing CRUD Operations

    Prerequisites

    Before starting, ensure you have the following:

    • Node.js installed (Version 14 or higher)
    • A PostgreSQL database (you can create a free database with Vercel or Neon DB)

    Step 1: Setting Up Your Node.js Project

    The first step is to initialize a new NodeJS project in the terminal. This project will be the foundation for the REST API you will build in this tutorial. To do this, you must first create a folder and a typescript project.

    mkdir tesla-api
    cd tesla-api
    npm init -y

    After creating a new NodeJS project, we need to install other prerequisites such as typescript and Prisma CLI.

    npm install typescript ts-node @types/node --save-dev
    npm install express prisma @prisma/client
    

    Lastly, we need to add a tsconfig.json file to make sure Typescript works correctly. You can create the file manually or use nano tsconfig.json and add the following code.

    {
      "compilerOptions": {
        "sourceMap": true,
        "outDir": "dist",
        "strict": true,
        "lib": ["esnext"],
        "esModuleInterop": true
      }
    }

    Step 2 — Setting Up Prisma with PostgreSQL

    The second step is to initialize Prisma and create our vehicle model to map with the database. We first need to add our database URL to the .env file so that Prisma knows how to connect with the database.

    nano .env
    

    Now update the .env file to add your database url from Vercel, NeonDB, or another database provider. If you are using Ubuntu, you can also run PostgreSQL locally using pgadmin. If you are on a pooled database you also need a NON-POOLING url to be used for seeding.

    //tesla-api/.env
    DATABASE_URL="postgresql://johndoe:your_password@localhost:5432/my-blog?schema=public"
    NON_POOLING_DATABASE_URL="postgresql://johndoe:your_password@localhost:5432/my-blog?schema=public"

    Make sure to change the database credentials to the ones you specified in your hosted database or localhost database. Once you’re done, save and exit the file and initialize Prisma by running. npx prisma init.

    npx prisma init
    Output
    ✔ Your Prisma schema was created at prisma/schema.prisma.
      You can now open it in your favorite editor.

    Step 3 — Defining Your Data Model and Creating Database Tables

    Now that your project is initialized, it's time to define your data model. Navigate to the prisma/schema.prisma file in your project directory. Here, you'll define your database schema using Prisma's intuitive schema language.

    datasource db {
      provider  = "postgresql"
      url       = env("DATABASE_URL")
      directUrl = env("NON_POOLING_DATABASE_URL")
    }
    
    generator client {
      provider = "prisma-client-js"
    }
    
    model Vehicle {
      id        Int     @id @default(autoincrement())
      model     String
      price     Float
      picture   String
      year      Int
      createdAt DateTime @default(now())
      updatedAt DateTime @updatedAt
    }
    

    We are defining just one model for the Vehicle with fields for model, price, picture, and year, but you can add a user model if you like. Save the changes and close the file.

    With these models in place, you can now create the corresponding tables in the database using Prisma Migrate. In your terminal, run the following command:

    npx prisma migrate dev --name init

    This command generates a new migration file based on your data model changes. The SQL migration file in the prisma/migrations/20241209084626_init/migration.sql directory has the following statements that were executed against the database.

    Step 5: Generating a Prisma client

    It is often a good practice to create a global Prisma client to prevent recreating a new instance every time. To do this, we initialize Prisma Client using npx prisma generate and create a new folder where we declare a Prisma client and export the client for use in other files.

    npx prisma generate

    Now create a file named prisma.ts under the Prisma folder and add the following code:

    //prisma.prisma.ts
    import { PrismaClient } from "@prisma/client";
    declare global {
        let prisma: PrismaClient | undefined;
      }
      const globalForPrisma = global as typeof global & { prisma?: PrismaClient };
      let prisma: PrismaClient;
      if (!globalForPrisma.prisma) {
        globalForPrisma.prisma = new PrismaClient();
      }
      prisma = globalForPrisma.prisma;
      export default prisma;

    Step 6: Seeding the Database

    Prisma allows us to seed the database if we have some seed data. To seed your database, you need to add a seed.ts file and add our seed data. In a larger project, you might need to edit the package.json to add a seed script.

    //prisma/seed.js
    import prisma from "../prisma/prisma"
    async function main() {
      await prisma.vehicle.createMany({
        data: [
          { model: 'Tesla Model S', price: '51885.17', picture: 'https://static-assets.tesla.com/configurator/compositor?&options=$MT337,$PPSW,$W40B,$IBB1&view=STUD_FRONT34&model=m3&size=1920&bkba_opt=2&version=v0028d202109300916&crop=0,0,0,0&version=v0028d202109300916', year: 2012 },
          { model: 'Tesla Model 3', price: '100990', picture: 'https://static-assets.tesla.com/configurator/compositor?&options=$MTS10,$PPSW,$WS90,$IBE00&view=FRONT34&model=ms&size=1920&bkba_opt=2&version=v0028d202109300916&crop=0,0,0,0&version=v0028d202109300916', year: 2017 },
          { model: 'Tesla Model X', price: '120990', picture: 'https://static-assets.tesla.com/configurator/compositor?&options=$MTX10,$PPSW,$WX00,$IBE00&view=FRONT34&model=mx&size=1920&bkba_opt=2&version=v0028d202109300916&crop=0,0,0,0&version=v0028d202109300916', year: 2015 },
          { model: 'Tesla Model Y', price: '65000', picture: 'https://static-assets.tesla.com/configurator/compositor?&options=$MTY07,$PPSW,$WY19B,$INPB0&view=FRONT34&model=my&size=1920&bkba_opt=2&version=v0028d202109300916&crop=0,0,0,0&version=v0028d202109300916', year: 2020 }
        ]
      });
    }
    
    main()
      .then(() => {
        console.log('Database seeded');
      })
      .catch((e) => {
        console.error(e);
        process.exit(1);
      })
      .finally(async () => {
        await prisma.$disconnect();
      });
    

    Next, run the seed script in the terminal by running the command:

    node prisma/seed.js

    Step 7: Create CRUD Operations

    The next step is to initiate a ExpressJs server to interact with the database and perform CRUD operations.

    First, create a index.ts file to add our server code.

    nano src/index.ts

    In the src/index.ts file, add the following code to create the API routes.

    import express from "express";
    import prisma from "../prisma/prisma"
    const app = express();
    app.use(express.json());
    // Get all vehicles
    app.get('/vehicles', async (req, res) => {
      const vehicles = await prisma.vehicle.findMany();
      res.json(vehicles);
    });
    // Get a vehicle by ID
    app.get('/vehicles/:id', async (req, res) => {
      const { id } = req.params;
      const vehicle = await prisma.vehicle.findUnique({
        where: { id: parseInt(id) },
      });
      res.json(vehicle);
    });
    // Create a new vehicle
    app.post('/vehicles', async (req, res) => {
      const { model, price, picture, year } = req.body;
      const newVehicle = await prisma.vehicle.create({
        data: { model, price, picture, year },
      });
      res.json(newVehicle);
    });
    // Update a vehicle
    app.put('/vehicles/:id', async (req, res) => {
      const { id } = req.params;
      const { model, price, picture, year } = req.body;
      const updatedVehicle = await prisma.vehicle.update({
        where: { id: parseInt(id) },
        data: { model, price, picture, year },
      });
      res.json(updatedVehicle);
    });
    // Delete a vehicle
    app.delete('/vehicles/:id', async (req, res) => {
      const { id } = req.params;
      await prisma.vehicle.delete({
        where: { id: parseInt(id) },
      });
      res.sendStatus(204);
    });
    // Start the server
    app.listen(3000, () => {
      console.log('Server is running on http://localhost:3000');
    });
    

    Test the server by running the following command

    npx ts-node src/index.ts
    or
    node src/index.ts

    You can modify the routes to add try catch blocks for error handling. You can also edit the package.json file to make it easier to run the server by adding a run script. Update the package.json file to add the following code.

    "scripts": {
      "build": "tsc",
      "start": "node dist/index.js",
      "dev": "ts-node src/index.ts"
    }

    Now you can start the development server using npm as follows:

    npm run dev

    Conclusion

    In this article, you created a REST API server with several different routes to create, read, update, and delete user and post data for a sample blogging application. Inside the API routes, you use the Prisma Client to send the respective queries to your database.

    As next steps, you can implement additional API routes or extend your database schema using Prisma Migrate. Visit the Prisma documentation to learn about different aspects of Prisma and explore some ready-to-run example projects using tools such as GraphQL or grPC APIs in the prisma-examples repository.

     

    20Blog views

    68

    share this blog
    user profile avatar

    the don

    Published on • 🕑2 min


    How Artificial Intelligence (AI) will Affect the Future of Education

    The arrival of artificial intelligent chat-bots that can complete student's assignments has been a game changer, at least for students. While most educational institutions are rushing to implement AI detectors, there is a possibility that current AI will develop beyond the simple metrics tested by the detectors. Here is my opinion on how AI will shape the future of education.

    Academic Dishonesty

    One possible impact of AI on education is lowering the quality of education. This means that students could easily have ChatGPT and other LLMs handle their assignments.

    student using ai

    While schools are getting clever at addressing such issues, it is possible that students would easily get away with it. Increased academic dishonesty will lead to superficial knowledge and decline in of critical thinking, problem-solving, and communication skills – essential for academic and professional success.

    Decline In Comprehension

    Students' overreliance on AI tools is likely to affect their ability to learn and remember things. More caution must be taken when examining students on a topic. Abundance of information could indeed make individuals more stupid.

    The ease and speed of access to information through AI tools might encourage students to skim over information or focus on surface-level understanding rather than delving deeper into concepts and making connections. This can hinder the development of deeper cognitive skills like analysis, synthesis, and evaluation.

    Beyond the Worries

    Despite the current challenges, education sector can also fully leverage the power of AI to accelerate learning. Use of AI tools can help provide personalized learning materials based on each student's specific needs. For example, if a student is interested in biology and ancient history, AI can create learning modules that seamlessly integrate both subjects.

    AI tools can also help students in research and explanation, potentially leading to a deeper understanding of the subject matter for students who actively engage with the information it provides. This can also an stimulate curiosity and critical thinking, making learning more engaging and encouraging independent exploration.

    However, as we look into the future, schools must be prepared to adopt AI and become smarter than their students. By being early adopters of AI, educators can help fight challenges such as academic dishonesty. Afterall, we need a thief to catch a thief.

    There is also a likelihood that legislations related to data privacy, fairness and bias, transparency and ethics will help shape how educators interact with AI and AI generated materials. These regulations will help ensure schools provide better quality education to their students and guarantee their rights

    415Blog views

    1.1K

    share this blog
    user profile avatar

    Tech Wizard

    Published on • 🕑4 min


    Opinion Article: How Will AI Video Generation Affect Crime Investigation?

     Artificial intelligence (AI) in criminal justice has been pervasive for some time and will only grow in the future. AI’s impact on the criminal justice system in 2023 is immense, with significant influence on crime monitoring and prevention, judicial and correctional systems, and many other criminal justice practices. It’s not difficult to spot AI’s impact on public safety and criminal justice, from traffic safety systems to crime forecasts, criminal pattern recognition, and more. Even those who never expect to encounter the system are impacted by the use of AI in criminal justice in some fashion.

    The use of AI in criminal justice is here to stay. As per a survey of criminal justice professionals, 48% believe AI technology will make policing more effective. Only 32% of criminal justice professionals believe AI can reduce racial bias in policing.

    While AI has many fundamental roles in the criminal justice system, one major concern why I am writing this article is the ability of AI to generate videos. The ability of AI models such as SORA to generate highly realistic videos poses a significant challenge to criminal justice investigations.

    Counterfeit Evidence

    This technology can potentially be used to create false evidence, implicate innocent individuals, or exonerate the guilty. AI videos and deepfakes are also getting super realistic, which poses a significant challenge for law enforcement to identify between real and fake videos. This will potentially increase the time taken to process legal evidence.

    Criminals may use AI to generate fake evidence, such as photos or videos, to discredit legitimate investigations or manipulate legal proceedings. This could include creating counterfeit crime scene images or doctoring surveillance footage to obstruct justice.

    While other AI models can also help analyze video evidence to identify patterns that humans might miss, this will also increase the complexity of investigations. AIs are also known to be biased and highly inaccurate, which is especially crucial in a case scenario where an erroneous judgment might deem innocent individuals guilty.

    Determining the authenticity of video evidence will require specialized expertise and resources, making investigations more complex and time-consuming.

    Identity Theft

    AI videos will make it easier for criminals to impersonate others convincingly. They can create fake identification documents or social media profiles, posing as law enforcement officers or even victims of crimes. This can lead to confusion, and false accusations, and undermine the credibility of genuine law enforcement efforts.

    Detecting AI-generated materials is a challenge to law enforcement, which implies an increase in costs and time taken to solve crimes. Attempts to regulate who can use AI will also be futile since such attempts can be deemed unlawful and discriminatory.

    Convincing the Jury

    The use of AI in criminal law is especially problematic due to the potential consequences of making liberty-depriving decisions based on an algorithm. Society may trust these algorithms too much and make decisions based on their predictions, even if the technology may not be as “intelligent” as it appears.

    There is a significant concern that such videos could easily sway the jury's opinion, effectively clouding their decisions. Previous highly charged emotional cases that have had extensive media coverage have always resulted in jury bias toward the defendants, even though the evidence might be fake or hearsay.

    ai-jury

    The rapid evolution of artificial intelligence presents both promising opportunities and daunting challenges for law enforcement agencies. To effectively navigate this dynamic landscape, several key recommendations emerge:

    •  Invest in AI Training: Law enforcement personnel must receive comprehensive training on AI technologies, their applications, and potential risks. This training should encompass both technical aspects and ethical considerations, empowering officers to make informed decisions when handling AI-generated content.
    • Collaboration with Technology Companies: Establishing partnerships with technology companies and researchers is vital. These collaborations can foster the development of AI tools specifically designed to detect and combat AI-generated threats, such as deepfakes and simulated CSAM.
    • Legislative and Policy Frameworks: Policymakers should enact clear and robust laws and regulations that criminalize the creation and distribution of AI-generated malicious content. These frameworks should also address the ethical implications and privacy concerns associated with AI in law enforcement.
    • Multidisciplinary Approach: Law enforcement agencies, technology experts, legislators, and ethical advisors must work collaboratively to strike a balance between preventing AI misuse and encouraging legitimate AI applications.
    • Public Awareness and Education: Raising public awareness about the risks associated with AI-generated content is essential. Educational campaigns can help individuals identify and report such content effectively.

    In summary, the ability to generate realistic videos using AI is a double-edged sword. These videos could help frame innocent individuals and also increase the complexity of crime investigations. When it gets difficult to differentiate what's real from fiction, innocent individuals will get hurt.

    At what point will deep fakes, AI video, and photo editing make photo and video evidence completely obsolete in a court of law? This was a sci-fi plot point in Iain Banks's Culture series novel “The Player of Games,” published in 1988.

     

    59Blog views

    1.5K

    share this blog
    user profile avatar

    Tech Wizard

    Published on • 🕑5 min


    A Complete Guide to OTP Verification

    One major challenge associated with designing your authentication system flow is ensuring users enter valid email addresses. To avoid fake users, verifying that users have entered their email addresses is necessary. Verifying email can help in enhancing other security measures such as sending password reset links or notification emails. This blog explains how to implement an OTP verification system.

    What is OTP Verification?

    A One Time Password (OTP) is a simple and smart choice for enhancing security in applications. A one-time Password is a password or code that is automatically generated and sent to a digital device to allow a single login session or transaction. Also known as a One-time PIN, one-time authorization code (OTAC), One-Time-Pass Code, or dynamic password, OTP mitigates several risks of traditional static password-based authentication.

    OTP plays an integral role in two-factor authentication systems and they are popular for validating new user accounts and resetting passwords. The user is required to input this code to confirm their identity and complete specific actions, such as accessing an account, conducting transactions, or retrieving sensitive information.

    Implementing OTP Verification

    For this tutorial, we are going to discuss how to implement OTP verification in a NextJS app using the Prisma ORM database and nodemailer. However, the tutorial could be applied to React and other databases ORM such as MongoDB and Resend.

    1. Creating an OTP Table in the Database

    If you are handling your own OTP verification without using an external provider, you will need to create a table to store the generated OTP codes. Codes must be associated with their emails, and also have an expiry time for security measures. 

    //prisma database schema
    model OTP {
      id        Int      @id @default(autoincrement())
      email     String
      code      String
      expiresAt DateTime
      createdAt DateTime @default(now())
    }
    //mongoDB
    const mongoose = require('mongoose');
    const OTPSchema = new mongoose.Schema({
      email: {
        type: String,
        required: true,
      },
      code: {
        type: String,
        required: true,
      },
      expiresAt: {
        type: Date,
        required: true,
      },
      createdAt: {
        type: Date,
        default: Date.now,
      },
    });
    const OTP = mongoose.model('OTP', OTPSchema);
    module.exports = OTP;

    2. Generating OTP Codes

    Since we now have a database table to store our OTP, we need to generate an OTP code when a user signs up or requests to reset a password. To do this, create a helper function that will be called when a user submits their email address.

    //function to create OTP code in the database
    export async function createOtpCode(email: string) {
      const otp = Math.floor(100000 + Math.random() * 900000).toString();
      try {
        const expiresAt = new Date(Date.now() + 5 * 60 * 1000); // 5 minutes expiry
        await prisma.OTP.create({
          data: {
            email,
            code: otp,
            expiresAt: expiresAt,
          },
        });
        const response = await sendVerificationEmail(email, otp);
        return response.message;
      } catch (error) {
        console.error(error);
        throw new Error(error);
      }
    }

    Here, I have created a function that creates an OTP code in the database and calls the `sendVerificationEmail` function that sends the code to the user's email using nodemailer. The send email function looks as follows:

    //emails/index.ts
    "use server";
    import nodemailer from "nodemailer";
    import {
      otpTemplate,
      welcomeTemplate,
      adminPasswordResetTemplate,
      adminRegistrationTemplate,
    } from "./template";
    const transporter = nodemailer.createTransport({
      service: "gmail",
      auth: {
        user: process.env.EMAIL_USER,
        pass: process.env.EMAIL_PASSWORD,
      },
    });
    const sender = `"TechTales" <admin@techtales.vercel.app>`;
    export const sendEmail = async (emailOptions: {
      subject: string;
      from: string;
      to: string;
      html: any;
    }) => {
      await transporter.sendMail(emailOptions);
    };
    export const sendVerificationEmail = async (email: string, otp: string) => {
      try {
        const response = await sendEmail({
          subject: `Your OTP Verification Code is ${otp}`,
          to: email,
          from: sender,
          html: otpTemplate(otp),
        });
        console.log("Email sent successfully");
        return { message: "Email sent successfully" };
      } catch (error) {
        console.error("Email delivery failed:", error);
        return { message: "Email delivery failed" };
      }
    };

    3. Verifying the OTP Code

    The next step is for the users to get the OTP code and input it on the page to verify their email address. The verification must check whether the code is related to the email provided and it has not expired. Furthermore, to avoid database overload, I opted to delete the code once the verification was successful since the code could not be reused.

    I implemented an API route `/auth/verify-token`, which uses a POST method to get the OTP and email from the user and verify the credentials.

    //api/auth/verify-token
    import prisma from "@/prisma/prisma";
    import { NextRequest, NextResponse } from "next/server";
    export async function POST(req: NextRequest, res: NextResponse) {
      const { email, code } = await req.json();
      let otpEntry: any;
      try {
        otpEntry = await prisma.OTP.findFirst({
          where: {
            email: email,
            code: code,
          },
        });
        if (!otpEntry) {
          return NextResponse.json(
            { error: "Wrong OTP Provided" },
            { status: 404 }
          );
        }
        if (new Date() > otpEntry.expiresAt) {
          return NextResponse.json(
            { error: "The OTP code has expired" },
            { status: 401 }
          );
        }
        const response = NextResponse.json(
          { message: "OTP verified successfully" },
          { status: 200 }
        );
        return response;
      } catch (error) {
        return NextResponse.json({ error: error }, { status: 404 });
      } finally {
        if (otpEntry) {
          await prisma.OTP.delete({
            where: {
              id: otpEntry.id,
            },
          });
        }
        await prisma.$disconnect();
      }
    }
    

    Verifying the OTP is as simple as sending a post request to `/api/auth/verify-token` and providing the email and OTP code in the request body. You can save the email in the sessionStorage or append it to the URL when navigating the user to the verification page.

    4. Resending the OTP

    One final step is to ensure users can resend the OTP code in case it is expired or they did not receive the code. It is also important to inform users to check the spam folder in case the email gets flagged by the provider.

    //lib/actions.ts
    //function to resend OTP email
    export async function resendOTPEmail(email: string) {
      const otp = Math.floor(100000 + Math.random() * 900000).toString();
      try {
        await prisma.OTP.deleteMany({
          where: {
            email: email,
          },
        });
        const expiresAt = new Date(Date.now() + 5 * 60 * 1000); // 5 minutes expiry
        await prisma.OTP.create({
          data: {
            email,
            code: otp,
            expiresAt: expiresAt,
          },
        });
        const response = await sendVerificationEmail(email, otp);
        return response.message;
      } catch (error) {
        console.error(error);
        throw new Error("Error sending email!");
      }
    }

    A point to note is that when a user resends an OTP and their initial OTP has not expired, the find first method will find the initial OTP and thus the re-sent code will be invalid. To counter this problem, we first delete all the OTP codes associated with the user email, create a new code, and send it to the user email. This way, if the user enters their old code, it will be invalid.

    Conclusion

    In this blog, we saw how simple it is to implement an OTP verification system without relying on external third-party providers. OTPs can be used to reset forgotten passwords, complete a transaction, sign up or log into accounts, shield against spam and bots, and verify online purchases. OTP also helps reduce friction in the customer journey. For example, lost/forgotten passwords can lead to dropoffs, and OTPs can help users quickly regain access to their accounts.

    11Blog views

    934

    share this blog
    user profile avatar

    Tech Wizard

    Published on • 🕑4 min


    How to Use Gemini API in NextJs

    AI apps are evolving rapidly, which is great news for developers and users. I'm interested in using AI to generate blog article summaries to make it easier for readers to grasp the main points before diving into the full article.

    This article discusses the process of integrating the Gemini API in NextJS and the various functionalities it offers. You'll be surprised to learn how straightforward incorporating the API into your app is. Before I begin, I'd like to shout out to Avinash Prasad for providing a simple guide."

    Step 1: Obtain the Gemini API Key

    To begin, head over to Google AI Studio and create a free GEMINI API Key. This key will enable you to communicate with various Gemini Models. Save the key in .env file as GEMINI_API_KEY.

    //.env
    GEMINI_API_KEY="YOUR_KEY_HERE"

    Step 2: Install Google Generative AI Package

    Install the Google AI JavaScript SDK enables you to use Google’s generative AI models. Make sure you are in your project’s root directory and run the following command in your terminal:

    npm install @google/generative-ai

    Step 3: Create An API Route to Handle Requests

    In the API folder, create a router handle that helps you communicate with Gemini. For this tutorial, I named the file Gemini and added a route.ts file. Requests to Gemini will go to /API/Gemini

    //api/gemini/route.ts
    //I recommend using typescript for type safety
    import { NextRequest, NextResponse } from "next/server";
    import { GoogleGenerativeAI } from "@google/generative-ai";
    export async function POST(req: NextRequest, res: NextResponse) {
      try {
        const apiKey = process.env.GEMINI_API_KEY as string;
    //to avoid type-error where typescript complains the api-key could be null
        if (!apiKey) {
          throw new Error(
            "GEMINI_API_KEY is not defined in the environment variables."
          );
        }
        const genAI = new GoogleGenerativeAI(apiKey);
        const model = genAI.getGenerativeModel({ model: "gemini-1.5-flash" }); //you can choose other models such as gemini-pro and gemini
        const { message } = await req.json();
        const result = await model.generateContent(message);
        const response = await result.response.text();
        return NextResponse.json({ message: response });
      } catch (error) {
        console.error(error);
        return NextResponse.json(
          { error: "Something went wrong" },
          { status: 503 }
        );
      }
    }
    

    Step 4: Create A Helper Function

    Since this is a post route, we need a function that receives the message body and fetches data from this route. I recommend creating a function in a lib file for reusability and type safety.

    //lib/generate
    import { baseUrl } from ".";
    type Data = {
      message: string;
    };
    export async function handleGenerate(data: Data) {
      try {
        const response = await fetch(`${baseUrl}/gemini`, {
          method: "POST",
          headers: {
            Accept: "application/json",
            "Content-Type": "application/json",
          },
          body: JSON.stringify(data),
        });
        if (!response.ok) {
          throw new Error(`HTTP error! Status: ${response.status}`);
        }
        const  data = await response.json();
        return data;
      } catch (error) {
        console.error(error);
        return null;
      }
    }
    

    Step 4: Fetching Data

    We can now import this function and call it whenever we need to contact Gemini by passing the message prop.

    //example component chat.js
    import {handleGenerate} from "@/lib/generate"
    export default function Chat(){
    return (
      <form action={handleGenerate}>
           <input type="text" name="message" id="message" placeholder="type your message here"></input>
           <button type="submit" className="add styling">Send</button>
    </form>
    )};

    This simple code uses server actions to send the message. However, we need to handle what to do with the data and might need to useState to store the response we get from the handleGenerate

    Step 5: Rendering Data

    //example component chat.js
    ("use client");
    import react, { useState } from "react";
    import { handleGenerate } from "@/lib/generate";
    export default function Chat() {
      const [message, setMessage] = useState("");
      const [response, setResponse] = useState("");
      async function handleSubmit() {
        const data = await handleGenerate(message);
        setResponse(data);
        setMessage("");
      }
      const parse = new DOMParser().parseFromString(htmlString, "text/html");
      return (
        <form action={handleSubmit}>
          <input
            type="text"
            name="message"
            value={message}
            onChange={(e) => setMessage(e.target.value)}
            placeholder="type your message here"></input>
          <button type="submit" className="add styling">
            Send
          </button>
          <div className="bg-transparent rounded mt-7 p-2 flex justify-center">
            {parse(response)}
          </div>
        </form>
      );
    }
    

    Advanced 

    Depending on your use case, you might need to stream the incoming data to the client. For example, if you are creating a chatbot. You can stream the data by using Gemini in combination with FastAPI to return chucks:

    import { NextRequest, NextResponse } from "next/server";
    import { GoogleGenerativeAI } from "@google/generative-ai";
    export async function POST(req: NextRequest, res: NextResponse) {
      try {
        const apiKey = process.env.GEMINI_API_KEY as string;
        if (!apiKey) {
          throw new Error(
            "GEMINI_API_KEY is not defined in the environment variables."
          );
        }
        const genAI = new GoogleGenerativeAI(apiKey);
        const model = genAI.getGenerativeModel({ model: "gemini-1.5-flash" });
        const { message } = await req.json();
        const result = await model.generateContentStream(message);
            for await (const chunk of result.stream) {
                const chunkText = chunk.text();
                console.log(chunkText);
             return NextResponse.json({ message: chunkText });
             }
      } catch (error) {
        console.error(error);
        return NextResponse.json(
          { error: "Something went wrong" },
          { status: 503 }
        );
      }
    }
    

    Conclusion

    Integrating the Gemini model into your app is as simple as adding the above code block. However, note there are rate limitations and you might need to modify your model to limit the tokens utilized per each response.

    Resources:

    34Blog views

    1.1K

    share this blog
    user profile avatar

    the don

    Published on • 🕑5 min


    Ten Useful CSS Features You Might not Know About

    CSS is full of new tricks and features that you might not even know about. These features can help us become better in our daily development and even solve our problems. Here are 10 CSS features that you might not know about.

    1. Color-Mix()

    CSS color-mix() has full support in all modern browsers. For me, this is one of the coolest CSS features introduced in 2022, which allows us to mix different colors without using gradients.

    The color-mix() functional notation takes two <color> values and returns the result of mixing them in a given colorspace by a given amount. 

    Functional notation: color-mix(<color-interpolation-method>, <color>[<percentage>], <color>[<percentage>])

    color-interpolation-method

    Specifies what interpolation method should be used to mix the colors. It consists of the in keyword followed by a color space name. The following three types are available:

    Example of color mix:

    2. Marker (::marker)

    If you still use::before to style list elements, you might be surprised to know there is an easier way of doing that. The ::marker CSS pseudo-element selects the marker box of a list item, which typically contains a bullet or number. It works on any element or pseudo-element set to display: list-item, such as the <li> and <summary> elements.

    li::marker {
      content: '✅ ';
      font-size: 1.2em;
    }

    Results ⤵

    ✅ Cheese

    ✅ Mango

    ✅ Avocado

    However, browser support is not great and it is currently not supported in Safari and Safari on IOS with animation or transition properties. Hopefully, it will be supported very soon.

    3. Current-Color (currentColor)

    I have often seen the currentColor property in most SVGs I work with and assumed it is an SVG feature. However, currentColor can work on any property. What if you want the border color of an element to be the same as the text color? Assuming you have a <div> whose border and the text inside it are blue, you can use currentColor to set the border to blue.

    <div style="color: blue; border: 1px dashed currentcolor;">
      The color of this text is blue.
      <div style="background: currentcolor; height:9px;"></div>
      This block is surrounded by a blue border.
    </div>
    

    Result ⤵

    The color of this text is blue.
     
    This block is surrounded by a blue border.

    4. Mix-Blend-Mode

    The mix-blend-mode CSS property sets how an element's content should blend with the content of the element's parent and the element's background.

    There are over 20 mix-blend modes, although the support for some of them such as plus-lighter and plus-darker is not great. The blend mode on SVGs is also not fully supported in all browsers.

    .img {
      mix-blend-mode: multiply;
    }

    Results ⤵

    5. Clip-Path

    We have all seen some nice-looking borders and SVGs.  The clip-path CSS property creates a clipping region that sets what part of an element should be shown. Parts that are inside the region are shown, while those outside are hidden. This can be overwhelming at first and I recommend using clippy to create your clip-paths.

    The clip path takes a basic shape such as a circle, polygon,  ellipse,rect, or a path for an SVG. You can use clip-path to turn boxes into different shapes, which can help break up the monotony of most websites, where everything is a box with straight edges.

    6. Accent Color

    If you have worked with forms, you probably know how difficult it is to change the color of checkboxes and radio inputs. The accent-color CSS property sets the accent color for user-interface controls generated by some elements. The accent color is currently supported in the input type of checkbox, range, radio, and the progress element.

    input[type='checkbox'] {
      accent-color: purple;
    }

    Results ⤵

    7. Counter 

    If you use unordered lists, they do not have any order. However, CSS counter allows you to set a counter for the <ol> and <ul> elements. CSS counters let you adjust the appearance of content based on its location in a document. For example, you can use counters to automatically number the headings on a webpage or to change the numbering on ordered lists.

    li {
      font-size: 30px;
      margin-bottom: 20px;
      counter-increment: li;
      list-style: none;
    }
    .list li::before {
      content: counter(li);
      margin-right: 10px;
      width: 30px;
      height: 30px;
      border-radius: 30%;
      display: inline-block;
      background-color: #ffa500;
      color: white;
      text-align: center;
      line-height: 30px;
    }

    Results ⤵

    1
    Bread
    2
    Milk
    3
    Eggs

    8. Any Link (:any-link)

    If you have trouble styling links, especially when they lack a href, the  :any-link CSS pseudo-class would be the best choice for you. The selector represents an element that acts as the source anchor of a hyperlink, independent of whether it has been visited.

    In other words, it matches every <a> or <area> the element that has an href attribute. Thus, it matches all elements that match :link or :visited. Take note because this means that visited links might also have the same styling.

    a:any-link {
      color: forestgreen;
      text-decoration-color: hotpink;
    }
    /*you might need to style visited links */
    a:visited {
      color: purple;
    }

    9: Empty (:empty)

    In this blog, I have a section where I render the blog summary after the user generates the summary. However, I do not want to render the summary when it is empty. This is where CSS empty selector comes in handy and avoids the need to use javascript.

    The :empty CSS pseudo-class represents any element that has no children. Children can be either element nodes or text (including whitespace). Comments, processing instructions, and CSS content do not affect whether an element is considered empty.

    .summary:empty {
      /* do not display it when it is empty */
      display: none;
    }
    /* do not confuse with blank */
    .summary:blank {
      display: block;
    }

    Take note not to confuse empty with blank. the :blank pseudo-class targets elements that have whitespace content, but no visible content. This means that an element containing only spaces, tabs, or line breaks is considered “blank” by the :blank pseudo-class, but an element containing visible content, even if it’s just a single character, is not considered blank.

    10. Inset 

    The inset property is a shorthand in CSS that combines the top, right, bottom, and left properties. It is used to position an absolutely or relatively positioned element within its containing block. This inset property has no effect on non-positioned elements.

    The inset property directly sets the distances from the edges of the element's containing block, effectively combining the functionality of the individual top, right, bottom, and left properties. You can also set inset-inlineand inset-block based on your needs.

    /* <length> values */
    inset: 10px; /* value applied to all edges */
    inset: 4px 8px; /* top/bottom left/right */
    inset: 5px 15px 10px; /* top left/right bottom */
    inset: 2.4em 3em 3em 3em; /* top right bottom left */
    inset: calc(anchor(50%) + 10px) anchor(self-start) auto auto;
    inset: auto auto anchor(center) anchor(self-end);
    /* <percentage>s of the width (left/right) or height (top/bottom) of the containing block */
    inset: 10% 5% 5% 5%;
    /* Keyword value */
    inset: auto;
    /* Global values */
    inset: inherit;
    inset: initial;
    inset: revert;
    inset: revert-layer;
    inset: unset;
    

    Conclusion

    Did you learn anything new about CSS today? Comment below with your new best features that could help save you tonnes of hours in development.

    00Blog views

    425

    share this blog
    user profile avatar

    Tech Tales Team

    Published on • 🕑5 min


    Common Mistakes that Beginners Often Make in React

    React is a popular javascript framework that is the most loved library for building user interfaces. Despite being one of the front-end developer's favorites, React introduces pitfalls that beginners often fall into. These blogs are related to state and effects and other functionalities that make React easier to work with. Here are five common mistakes beginners often make in React, along with their solutions.

    1. Mutating state

    React's state is an essential concept that allows components to manage and update their data. However, directly modifying the state is a common mistake that can lead to unexpected behavior and difficult-to-debug issues.

    An example of a mutating state is through the use of destructive array methods such as push to add an item to a list.

    const [items, setItems] = useState([1, 2, 3]);
      // ❌ Mutates an existing object
    const addItem = (item) => {
      items.push(item); // Mutating state directly
      setItems(items);
    };
    // ✅ Creates a new object
    const addItem = (item) => {
      setItems([...items, item]); // Creating a new array
    };
    

    React relies on a state variable's identity to tell when the state has changed. When we push an item into an array, we aren't changing that array's identity, and so React can't tell that the value has changed.

    Instead of modifying an existing array, I'm creating a new one from scratch. It includes all of the same items (courtesy of the ... spread syntax), as well as the newly-entered item.

    The distinction here is between editing an existing item, versus creating a new one. When we pass a value to a state-setter function like setCount, it needs to be a new entity. The same thing is true for objects.

    2. Accessing state after changing it

    State in React is asynchronous. This means that when we update the state we are not re-assigning a variable but rather scheduling a state update. Mostly common, developers will be frustrated if they console.log the new value and it is not there.

    For example:

    const [count, setCount] = useState(0);
    const increment = () => {
      setCount(count + 1);
      console.log(count); // This will log the old count, not the new one
    };
    

    This can lead to confusion when debugging because the console might not show the expected value. It can take a while for us to fully wrap our heads around this idea, but here's something that might help it click: we can't reassign the count variable, because it's a constant!
    To work with the updated state, you can use the functional form of setState, which provides the latest state:

    const increment = () => {
      setCount((prevCount) => {
        console.log(prevCount + 1); // Correctly logs the new count
        return prevCount + 1;
      });
    };

    3. Using Functions as useEffect Dependencies 

    useEffect is one of the most abused hooks and developers often use it recklessly even in areas where it is not needed. One common mistake with useEffect is failing to provide a dependency array, which leads to endless renders. 

    One point to note here is not to confuse re-renders with refresh. Since React uses a Virtual DOM, re-renders happen in the back-stage and thus developers might fail to notice.

    The following is a react useEffect example: 

    function App(){ 
        const [data, setData] = useState(null); 
        const fetchData = () => { 
             // some code 
        } 
        useEffect(() => { 
        fetchData(); //used inside useEffect 
         }, [fetchData]) 
    } 

    It is not recommended to define a function outside and call it inside an effect. In the above case, the passed dependency is a function, and a function is an object, so fetchData is called on every render.

    React compares the fetchData from the previous render and the current render, but the two aren't the same, so the call is triggered. 

    4. Props Drilling

    Props drilling in React occurs when developers pass the same props to every component one level down from its parent to the required component at the end. Thus, components become closely connected with each other and can’t be used without adding a particular prop. The fewer unnecessary interconnections between components in your code, the better.

    For example, if we need to pass a user name to a deeply nested component but the name is defined in the first parent component:

    const Grandparent = () => {
      const user = { name: 'Alice' };
      return <Parent user={user} />;
    };
    const Parent = ({ user }) => {
      return <Child user={user} />;
    };
    const Child = ({ user }) => {
      return <div>{user.name}</div>;
    };

    In this example, the user prop is passed down from Grandparent to Child through the Parent component, even though Parent doesn't need it. This kind of pattern can quickly lead to a tangled mess of props.

    To avoid props drilling, consider using React Context or state management libraries like Redux, Zustand, or Recoil. Context allows you to share data across multiple components without passing props manually through every level.

    // Create a context
    const UserContext = createContext();
    const Grandparent = () => {
      const user = { name: 'Alice' };
      return (
        <UserContext.Provider value={user}>
          <Parent />
        </UserContext.Provider>
      );
    };
    const Parent = () => {
      return <Child />;
    };
    const Child = () => {
      const user = useContext(UserContext);
      return <div>{user.name}</div>;
    };
    

    5. Changing from Uncontrolled to Controlled Inputs

    Uncontrolled components rely on the DOM to manage their state, while controlled components rely on React. Beginners sometimes switch from uncontrolled to controlled components without a clear need, adding complexity without gaining any tangible benefits.

    One major reason why developers switch to controlled inputs is the need for validations. However, we can validate inputs without the need for additional javascript simply using browser inbuilt functions. See more here a-better-way-to-validate-html-forms-without-usestate.

    Another reason (I am often guilty of this) is when we need to implement search functionality that filters our data to return the results. However, the most efficient solution to search is to store the value in search parameters. In this way, the value will not be lost on refresh.

    Developers might implement the search functionality like this:

    function SearchForm() {
      const [query, setQuery] = useState(null);
      function handleSearch (e){
        e.preventDefault()
        window.location.href=`/my-site/search?q=${query}`
      }
      return (
        <form onSubmit={handleSearch}>
          <search>
            <input
              type="search"
              value={search}
              onChange={() => setQuery(e.target.value)}></input>
          </search>
        </form>
      );
    }

    This example receives the search input and saves it in the state. When the search form is submitted, we redirect the user to the search page with the search-params.

    One simple solution is:

    function SearchForm() {
      return (
        <form action="/search/query">
          <search>
            <input type="search" name="query"></input>
          </search>
        </form>
      );
    }

    This will work the same and the form will be submitted with the query params that can be used to filter the data. Another advantage of this setup is that if we are using NextJS, this form will work as a server component and thus benefit from faster rendering.

    Conclusion

    There are many mistakes that we make in React that we are often unaware of. By understanding and avoiding these common mistakes, you can write more robust and efficient React code. Remember to practice good coding practices and explore the full range of React hooks to build high-quality user interfaces.

    21Blog views

    242

    share this blog
    user profile avatar

    diamond degesh

    Published on • 🕑9 min


    11 Lesser-Known HTML Tags That Can Enhance Your Web Development Skills

    HTML (Hypertext Markup Language) is the backbone of web development, allowing us to structure and present content on the internet. While most developers are familiar with popular HTML tags like <div> and <p>, there are lesser-known tags that can enhance the functionality and aesthetics of web pages. In this article, we'll explore 11 HTML tags that you may not be aware of but can bring added value to your web development projects.

    1. <details> and <summary>

    The <details> and <summary> tags work together to create collapsible content sections on a web page. They provide a way to hide and reveal additional information, enhancing the user experience and saving space on the page.

    • The <details> tag is used to create a container for the collapsible content. It acts as a wrapper for the content that can be expanded or collapsed.
    • The <summary> tag is used as the heading or title for the collapsible section. It is typically placed inside the <details> tag and provides a clickable element that toggles the visibility of the content.
    • When the collapsible section is collapsed, only the <summary> element is visible, usually with an arrow or a customizable marker indicating that it can be expanded. When the user clicks on the <summary> element, the content inside the <details> tag is revealed or hidden, depending on its previous state.
    • The <details> and <summary> tags can be styled using CSS to customize their appearance, such as changing the arrow icon or adding animations to the expanding and collapsing effects.
    • These tags are especially useful for displaying additional information, such as FAQs, long descriptions, or hidden content that can be optionally revealed by the user.

    For example:

    <details open="open">
    <summary>Show More</summary>
    <p>This is some additional content that will be revealed when the user clicks on the "Show More" text.</p>
    </details>

    Result ⤵

    Show More

    This is some additional content that will be revealed when the user clicks on the "Show More" text.

    The above example creates a collapsible section on the web page. Initially, only the text Show More is visible. When the user clicks on it, the <p> element containing the sentence This is some additional content that will be revealed when the user clicks on the 'Show More' text will be displayed below the summary.

    2. <mark>

    The <mark> tag is used to highlight or mark a specific portion of text within a document. It is typically used to indicate relevance, importance, or to draw attention to specific information.

    • The <mark> tag is an inline element that visually highlights the enclosed text by applying a background color or other styling, depending on the browser's default rendering.
    • This tag is commonly used in search results, where it helps users quickly identify the keywords or search terms that match their query within the displayed content.
    • The <mark> tag does not provide any semantic meaning to the enclosed text. It is purely presentational and should be used sparingly to avoid overusing visual emphasis.

    For example:

    <p>The <mark>quick brown fox</mark> jumps over the lazy dog.</p>

    Result ⤵

    The quick brown fox jumps over the lazy dog.

    In this example, the phrase quick brown fox will be visually highlighted by the browser, typically with a yellow background or other distinctive styling.

    3. <time>

    The <time> tag is used to represent a specific date, time, or duration. It provides semantic meaning to the enclosed content and can be used for various purposes, such as displaying event dates, publication timestamps, or durations of time.

    • The <time> tag is an inline element and should be used to enclose a specific time or date within the HTML document.
    • It requires the use of the datetime attribute, which specifies the date and/or time in a machine-readable format following the ISO 8601 standard. This format ensures consistency and helps search engines, screen readers, and other tools understand the intended meaning.
    • The <time> tag can be used in various scenarios, such as displaying publication dates, event times, or durations.

    For example:

    <p>The article was published on <time datetime="2023-06-14">June 14, 2023</time>.</p>

    Result ⤵

    The article was published on .

    In this example, the <time> tag is used to mark up the publication date of an article, with the datetime attribute specifying the machine-readable format. This provides semantic meaning to the date and helps search engines and assistive technologies interpret it accurately.

    4. <output>

    The <output> tag is used to show the result of a calculation or an action performed by the user on a webpage. It's often used together with forms and JavaScript to display dynamic content.

    • It is an inline element that can display the results of calculations or dynamic content.
    • The <output> tag requires a for attribute to associate it with the input element that generated the output.
    • It can also be used to display the value of form inputs or the outcome of user actions.

    For example:

    In this example, the <output> tag is used to display the result of a calculation performed based on user input. The form includes two number input fields, and when the user clicks the Calculate button, the result of the calculation is shown in the <output> element. JavaScript can be used to perform the calculation and update the <output> element dynamically.

    5. <meter>

    The <meter> tag is used to represent a measurement within a predefined range. It allows you to visually display measurements, such as progress bars or ratings, in a more meaningful way.

    • The <meter> tag requires two attributes: value and min and max. The value attribute specifies the current value of the meter, while min and max define the minimum and maximum values of the range.
    • Additionally, you can use the lowhigh, and optimum attributes to define thresholds for the meter. The low attribute represents the lower boundary of the range, high represents the upper boundary, and optimum specifies the optimal value within the range.
    • By default, browsers render the <meter> tag as a horizontal bar, with the filled portion indicating the value. However, you can customize its appearance using CSS to match your design requirements.
    • The <meter> tag can be useful in various scenarios, such as progress tracking, ratings, file upload limits, or any situation where you want to visually represent a value within a specified range.

    For example:

    <meter value="75" min="0" max="100" low="30" high="70" optimum="80" style="min-width:200px"></meter>

    Result ⤵

    80/100

    In the above example, the <meter> tag represents a value of 75 within a range of 0 to 100. The low attribute is set to 30, high to 70, and optimum to 80, allowing browsers to apply different styles based on the value's position within the range.

    6. <sub> and <sup>

    The <sub> and <sup> tags are used to represent subscript and superscript text respectively in HTML. They are typically used to display smaller text below or above the regular text, often used for mathematical equations, chemical formulas, footnotes, and other similar content.

    • The <sub> tag is an inline element that is used to render subscript text. It is commonly used for mathematical or chemical formulas where certain characters or numbers need to be displayed in a smaller size below the baseline of the surrounding text.
    • The <sup> tag is also an inline element used to render superscript text. It is typically used to display characters or numbers in a smaller size above the baseline, such as in exponent notation or footnotes.
    • These tags can be nested within other inline elements, such as <span> or <p>, to apply subscript or superscript to specific sections of text.

    For example:

    <p>The chemical formula for water is H<sub>2</sub>O.</p>
    <p>The Pythagorean theorem states that in a right triangle, c<sup>2</sup> = a<sup>2</sup> + b<sup>2</sup>.</p>

    Result ⤵

    The chemical formula for water is H2O.

    The Pythagorean theorem states that in a right triangle, c2 = a2 + b2.

    In the examples above, the <sub> tag is used to display subscript text, such as in chemical formulas like H₂O for water, while the <sup> tag is used to show superscript text, as seen in mathematical equations like c² = a² + b² for the Pythagorean theorem. These tags are useful for representing specialized notations and formatting within the context of scientific, mathematical, or linguistic content.

    7. <cite>

    The <cite> tag is used to mark up a reference or citation to a creative work within the content of a web page. It is typically used to indicate the title of a book, article, song, movie, or other artistic or intellectual creations.

    • The <cite> tag is an inline element and should be used within a paragraph or block of text where the citation or reference is being made.
    • It helps provide semantic meaning and structure to the citation, allowing search engines and assistive technologies to identify and distinguish the cited content.
    • By using the <cite> tag, you can indicate that a particular piece of text represents the title or name of a work, providing clarity and context to your readers.
    • It is important to note that the <cite> tag should not be used solely for styling purposes. Instead, it should be used when there is a genuine need to mark up a citation or reference within the content.

    For example:

    <p>In his famous novel, <cite>The Great Gatsby</cite>, F. Scott Fitzgerald explores the themes of wealth, love, and the American Dream.</p>
    <p>According to the research conducted by Johnson et al. in their article "<cite>The Impact of Climate Change on Biodiversity</cite>," rising temperatures pose a significant threat to various species.</p>

    Result ⤵

    In his famous novel, The Great Gatsby, F. Scott Fitzgerald explores the themes of wealth, love, and the American Dream.

    According to the research conducted by Johnson et al. in their article "The Impact of Climate Change on Biodiversity," rising temperatures pose a significant threat to various species.

    In the above examples, the <cite> tag is used to mark up the titles of the novel and the research article, respectively, providing a clear indication of the referenced works within the surrounding content.

    8. <kbd>

    The <kbd> tag is used to indicate user input, typically keyboard input, within the content of an HTML document. It is often used to represent keys or key combinations that can be pressed by the user.

    • The <kbd> tag is an inline element and is used to enclose the text or content that represents the user input.
    • It is commonly styled to resemble the appearance of a physical keyboard key, using CSS properties such as background color, border, and font styles.
    • The <kbd> tag is particularly useful when documenting keyboard shortcuts or providing instructions for user interactions on a website or in a web application.

    For example:

    <p>To save a document, press <kbd>Ctrl</kbd> + <kbd>S</kbd>.</p>

    Result ⤵

    To save a document, press Ctrl + S.

    This example visually represents the keyboard shortcut Ctrl + S using the <kbd> tag, making it clear to users which keys need to be pressed to perform the action of saving a document.

    9. <bdi>

    The <bdi> (Bi-Directional Isolation) tag is used to isolate a span of text that might be in a different language or have a different directionality than the surrounding text. It is particularly useful when working with multilingual content or content with mixed directionality.

    • The <bdi> tag is an inline element that indicates to the browser that the text within it should be treated as a separate unit with its own directionality.
    • This tag is particularly useful when dealing with user-generated content, such as comments or forum posts, where users might input text in different languages or scripts.
    • The <bdi> tag can also be used in conjunction with CSS styling to apply specific styles to the isolated text, providing further flexibility in customization.

    For example:

    <p><bdi>This text is in Arabic: مرحبا</bdi> , and this text is in English: Hello</p>

    Result ⤵

    This text is in Arabic: مرحبا , and this text is in English: Hello

    Here, the <bdi> tag is used to separate the Arabic text from the English text, allowing each segment to be displayed with its correct directionality. This tag ensures that the Arabic text is rendered from right to left, while the English text is rendered from left to right, providing proper visual representation for mixed-direction text.

    10. <wbr>

    The <wbr> tag, short for Word Break Opportunity, is an inline element used to specify a potential line break within a word. It is particularly useful for long words or URLs that may cause layout issues on narrow or small screens.

    • The <wbr> tag is not intended to create a visible line break but rather provides a hint to the browser that a line break can occur at that point if necessary.
    • It can be used to prevent long words or URLs from overflowing outside their container or causing horizontal scrolling.
    • When the browser encounters a <wbr> tag, it evaluates whether a line break is necessary at that point based on available space. If needed, it breaks the word at the specified position.
    • The <wbr> tag is especially helpful for responsive design, ensuring that content adapts well to different screen sizes and avoids layout issues caused by long, unbreakable words.

    For example:

    <p>The word <wbr> pneumonoultramicroscopicsilicovolcano<wbr>coniosis<wbr> is a lung disease caused by the inhalation of very fine silica dust found in volcanoes and quarries.</p>

    Result ⤵

    The word pneumonoultramicroscopicsilicovolcanoconiosis is a lung disease caused by the inhalation of very fine silica dust found in volcanoes and quarries.

    In the example above, the <wbr> tag is used to break the long word pneumonoultramicroscopicsilicovolcanoconiosis into smaller parts to enhance readability and prevent overflow.

    11. <outgroup> tag

    The <optgroup> tag is used to group related options within a select dropdown element. It allows you to organize and categorize options for easier navigation and selection.

    • The <optgroup> tag is a container element that groups related <option> tags within a <select> element.
    • It helps organize options by creating visual grouping or categorization within the dropdown menu.
    • The <optgroup> tag requires a label attribute, which specifies the name or title of the option group.
    • It can contain one or more <option> tags as its child elements, representing the individual options within the group.

    For example:

    <select style="outline: auto; padding: 5px; min-width: 200px;">
    <optgroup label="Asia">
    <option value="ph">Philippines</option>
    <option value="kr">South Korea</option>
    <option value="jp">Japan</option>
    </optgroup>
    <optgroup label="Europe">
    <option value="fr">France</option>
    <option value="de">Germany</option>
    <option value="it">Italy</option>
    </optgroup>
    <optgroup label="North America">
    <option value="us">United States</option>
    <option value="ca">Canada</option>
    <option value="mx">Mexico</option>
    </optgroup>
    </select>

    Result ⤵

    In this example, the select dropdown is grouped into three sections: AsiaEurope, and North America. Each group contains tags representing different countries within that region.

    106Blog views

    1.0K

    share this blog
    user profile avatar

    the don

    Published on • 🕑2 min


    Role of AI in Mass Censorship

    The rise of GenAI such as ChatGPT and Gemini has ushered in a new era in human revolution. This era has fairly been predicted as having catastrophic consequences for humanity. However, as people worry about AI enslaving us, they often overlook one major problem. Mass censorship!

    Search engines like Google and Bing are integrating AI, promising a smoother, more relevant online experience. But who decides what's "relevant"? The corporations behind these platforms have a troubling history of cooperating with governments to restrict information access.

    Take the example of the recent Gemini catastrophe. The launch of Gemini on Feb 2024 served to prove this point. Google took online to apologize after anti-woke heretics such as Elon Musk criticized Gemini for generating mixed-race images of American founding fathers.

    While this incident might seem isolated, it has proven that governments are more likely to weaponize AI for mass censorship.  While AI is efficient, it could be used to filter search results based on undisclosed criteria to hide dissenting ideas.

    While this might sound paranoid, these things are happening in nations such as China and South Korea. Conditions for internet users in these nations remain oppressive, with users facing criminal penalties for accessing or sharing certain information. This is a severe violation of freedom of speech.Gemini-Censorship

    Imagine what such governments could achieve with AI censorship. Governments will not only be able to filter out information and spoon-feed the public but will have the right to decide what you see and hear.

    Therefore, as AI advances, We must demand transparency from search engines about how AI algorithms rank information. We need strong legal safeguards against government influence on online searches.
    Governments are currently rushing to regulate AI. However, such regulations only serve to empower government censorship capabilities.  But as the integration of GenAI becomes ubiquitous in everyday technology it is not a given that search, word processing, and email will continue to allow humans to be fully in control.

    The perspectives are frightening.

    Imagine a world where your word processor prevents you from analyzing, criticizing, lauding, or reporting on a topic deemed “harmful” by an AI programmed to only process ideas that are “respectful and appropriate for all.”  

     

    324Blog views

    1.6K

    share this blog
    user profile avatar

    tech girl

    Published on • 🕑5 min


    The Future of Quantum Computing: What to Expect in the Next Decade

    Quantum computing has been a buzzword in the tech industry for years, promising to revolutionize everything from cryptography to artificial intelligence. But what does the future hold for this cutting-edge technology?

    As we look ahead to the next decade, it's clear that quantum computing will move from theoretical research to practical applications, impacting industries in ways we can only begin to imagine.

    Understanding Quantum Computing

    At its core, quantum computing leverages the principles of quantum mechanics to perform computations that are infeasible for classical computers. Unlike classical bits, quantum bits (qubits) can exist in multiple states simultaneously, thanks to superposition and entanglement.

    This allows quantum computers to process a vast amount of data in parallel, making them exponentially more powerful for certain tasks.  

    Quantum computing harnesses the power of quantum mechanics to help us overcome the limitations that today’s computing world has been encountering.

    Potential Applications

    1. Cryptography: One of the most anticipated applications of quantum computing is in the field of cryptography. Quantum computers have the potential to break traditional encryption methods, leading to the development of quantum-resistant cryptographic algorithms.

    2. Drug Discovery: Quantum computing could dramatically speed up the process of drug discovery by simulating molecular structures and interactions with unprecedented accuracy. This could lead to faster development of new medications and treatments for various diseases.

    3. Optimization Problems: Industries that rely on complex optimization problems, such as logistics, finance, and manufacturing, could see significant efficiency improvements. Quantum algorithms can find optimal solutions much faster than classical algorithms, reducing costs and improving performance.

    Challenges of Quantum Computing

    Despite remarkable advances, quantum computing still faces significant technological hurdles that limit its applications, scalability, and reliability at this stage. Addressing these challenges is crucial for realizing the full potential of quantum computing in the future.

    1. Decoherence and Error Correction

    One of the most pressing challenges in quantum computing is decoherence. Unlike classical computers, quantum computers are highly susceptible to noise, with qubits—quantum bits—being extremely fragile.

    Even slight perturbations, such as minor vibrations or temperature fluctuations, can disrupt the quantum state of qubits, leading to the loss of stored information.

    This phenomenon, known as decoherence, poses a significant obstacle because calculations must be completed before decoherence occurs.

    To combat decoherence, researchers are developing error-correcting codes. While error correction is well-established in classical computing, it becomes far more complex in the quantum realm.

    Quantum errors can manifest as phase shifts, bit flips, or a combination of both, making them difficult to detect and correct. Additionally, unlike classical bits, qubits cannot be copied, necessitating more sophisticated correction codes.

    Techniques such as the Shor code, the Steane code, and the Surface code are widely used to encode quantum information and protect it from errors, but they require multiple physical qubits to represent a single logical qubit, complicating the overall system.

    2. Scalability

    Scalability is another major challenge in quantum computing. For quantum systems to tackle more complex problems, the number of qubits must be increased significantly. However, connecting a large number of qubits to create larger, more powerful quantum systems is incredibly challenging.

    One potential solution lies in the use of error correction techniques, which introduce redundancy to detect and correct errors. However, implementing these techniques requires additional qubits and complex algorithms, making the scaling process even more difficult.

    3. Physical Implementation

    Quantum computers can be built using various methods, including superconducting circuits, trapped ions, and topological qubits. Each approach has its own set of difficulties, and it remains uncertain which method will prove most viable for large-scale quantum computing.

    Superconducting circuits, for example, require extremely low temperatures to maintain coherence, while trapped ions need precise control and isolation from environmental noise.

    The race to develop scalable and efficient quantum hardware continues, with each method presenting unique technical challenges that require interdisciplinary collaboration and innovation.

    4. Cost and Accessibility

    Currently, quantum computers are prohibitively expensive and require specialized environments, such as cryogenic cooling systems, to operate.

    As a result, accessibility is a significant barrier, with only a handful of research institutions and tech companies having the resources to develop and utilize quantum computers.

    One of the key challenges moving forward is to make quantum computing more accessible and affordable, enabling wider adoption and experimentation.

    5. Workforce and Expertise

    The field of quantum computing demands deep knowledge of quantum mechanics, computer science, and engineering.

    However, finding professionals who possess expertise in all three areas is difficult, leading to a talent shortage that could slow down the development and adoption of quantum computing technologies.

    Building a workforce with the necessary skills will require significant investment in education and training programs, as well as fostering collaboration between academia, industry, and government.

    The Future of Quantum Computing

    Despite the challenges, the future of quantum computing is incredibly promising. Technology giants such as IBM, Google, and Microsoft, along with numerous research institutions, are investing heavily in this field.

    These investments are driving continuous progress in increasing qubit coherence times, reducing error rates, and developing new quantum algorithms.

    As quantum computing technology matures, it is expected to become a fundamental tool for scientific research, making it possible to solve previously intractable problems.

    Governments around the world are recognizing the strategic importance of quantum computing and are increasing funding for research and development. Collaborative efforts between public and private sectors are likely to accelerate breakthroughs in this area.

    In the near future, it will be essential to identify use cases for quantum computing early on and manage expectations regarding its capabilities.

    While initial applications may be limited, as quantum computers grow in the number of qubits, their computational capacity will increase exponentially. This means that algorithms proven to work on a small scale can be applied to larger datasets as the technology advances, paving the way for unprecedented innovation in fields such as cryptography, drug discovery, and artificial intelligence.

    The growth of quantum computing is poised to have a transformative impact on society, and staying informed about developments in this field will be crucial for those looking to harness its potential.

    Conclusion

    The next decade will be crucial for the development of quantum computing. As the technology matures, we can expect to see more practical applications emerge, transforming industries and solving problems that were previously thought to be unsolvable.

    While there are still hurdles to overcome, the future of quantum computing is undoubtedly bright, and it will be fascinating to see how it shapes the world of tomorrow.

    00Blog views

    375

    share this blog
    user profile avatar

    tech girl

    Published on • 🕑3 min


    A Guide on How to Host Your Ruby on Rails Application

    Congratulations on Learning Ruby on Rails and Creating Your first Ruby on Rails Application! But wait a minute, how do you host your application on the internet?

    One of the most challenging endeavors I have faced as a Ruby on Rails developer is finding hosting websites that offer free tier hosting for students and are actually easy to use. That is why I have compiled a list of my favorite hosting platforms to help make your life easier and make you fall in love with Ruby on Rails.

    In this article, i will also compare the advantages and disadvantages of each hosting platform and give you tips on how to get the best out the listed platforms.

    1. Railway

    railway-logo

    Railway is my first choice for hosting a ruby on rails application. The platform provides new users with $5 credit, which is depleted based on the CPU usage of your web service. To host a ruby on rails application on railway, you will need to create an account either using GitHub or email, import your repository and add other necessary configurations.

    One most vital configuration is having a railway.json file and a Procfile. The railway.json file defines how railway will build your application, while the Procfile defines the instructions necessary to run the appliaction, which in this case is rails db:migrate and rails s.

    For more guidelines on how to host on railway, consider cloning this Ruby on Railway Template. You can also check out this blog deploying on railway 

    2. Render

    Render-Logo

    Render is the second most popular choice for deploying ruby on rails application for free. The platform is more common among developers, although successfully hosting on the platform could be an headache.

    Unlike railway, render provides a free instance that allows you to host a web service with no limitations as long you do not exceed the allowed bandwidth. Render also offers postgress database, which expires after a while if you fail to switch to a paid account.

    This means that your data could be lost when the database expires. Therefore, navigating such challenge would require hosting the database on a separate platform such as Supabase, Vercel or Firebase.

    The web service provided by render also sleeps after 30 minutes of inactivity and waking it might take more than 1 minute. This deliberately makes the server too slow, which I believe is an attempt by render to encourage individuals to switch to a paid plan. However, auto-sleep also helps cut costs when the server is not in use.

    To get started with render, you will need to create a render-build.sh file in your repository, which directs render how to build the app. However, render has also introduced automatic builds, which makes it very easy to deploy on the platform.

    For more information on how to deploy on render, check their Ruby On Rails Documentation or just go to their website and create a new web service.

    3. Koyeb

    Koyeb

    I recently discovered koyeb on stackoverflow. Koyeb provides a free lifetime plan for a web service that allows developers to experiment with their site. The forever free tier providers 50 active hours per month. The web service auto-sleeps after periods of inactivity, which makes it slow to respond.

    The platform also automatically runs builds using docker and does not need any instructions on how to build or configure the app. Just import the GitHub repo and that's it! However, you will need to host the database in another program such as Supabase or Vercel.

    However, I did experience some lag with Koyeb and Render, which made the database really slow. The issue is likely caused by PGbouncer which is used to distribute loads. Since with render and Koyeb you have to host your database separately, the web service gets really slow.

    As I wrap up, other sites that i have found but might not be free (not tried them out yet) include Microsoft Azure and OpenShift. However, the greatest flex is of course to self-host your application.
    Let me know of other awesome free platforms that rubyists can enjoy!

    48Blog views

    709

    share this blog
    user profile avatar

    the don

    Published on • 🕑3 min


    Data Fetching and Caching in NextJS

    In the realm of web development, data fetching stands tall as a fundamental aspect, akin to the very fabric that weaves together intricate applications. In this journey through the corridors of React and Next.js, let’s delve into the art of fetching, caching, and revalidating data, unraveling the mysteries and unveiling the potentials that lie within.

    Fetching Data on the Server with fetch

    The saga begins with the native fetch API, a trusty companion in the quest for data. Next.js, with its adept prowess, extends fetch to the server, empowering developers to configure caching and revalidating behaviors with finesse. Whether it’s within Server Components, Route Handlers, or Server Actions, the landscape is ripe for exploration.

    async function fetchData() {
      try {
        const res = await fetch('https://api.example.com/...')
        if (!res.ok) {
          throw new Error('Failed to fetch data')
        }
        return res.json()
      } catch (error) {
        console.error('Error fetching data:', error)
      }
    }

    Caching: The Guardian of Data

    As data flows into our applications, caching emerges as a stalwart guardian, ensuring swift access and reducing the burden on our sources. Next.js, ever vigilant, automatically caches fetch responses on the server, unleashing the power of the Data Cache.

    // Utilizing cache-control for caching
    fetch('https://...', { cache: 'force-cache' })

    Revalidating Data: Keeping It Fresh

    Yet, in the ever-changing landscape of data, staleness looms as a lurking shadow. Fear not, for revalidation comes to our aid, breathing life into our cache and ensuring our data remains as fresh as the morning dew. With Next.js, we wield the power to revalidate data based on time or demand, sculpting experiences that stand the test of time.

    // Revalidating at timed intervals
    fetch('https://...', { next: {cache:"force-cache", revalidate: 3600 } })

    On-Demand Revalidation: A Call to Action

    In the throes of interaction, on-demand revalidation emerges as our trusted ally. Whether it’s a form submission or an event trigger, the ability to summon forth the latest data at our command ensures our applications remain responsive and relevant.

    import { NextRequest } from 'next/server'
    import { revalidateTag } from 'next/cache'
    export async function GET(request: NextRequest) {
      const tag = request.nextUrl.searchParams.get('tag')
      revalidateTag(tag)
      return Response.json({ revalidated: true, now: Date.now() })
    }
    // Summoning on-demand revalidation
    revalidateTag('collection')
    

    Opting Out and Beyond

    Yet, in the vast tapestry of options, lies the freedom to choose. Next.js bestows upon us the power to opt out of caching, to dance to our own rhythm, and to dictate the flow of data according to our needs. From individual fetch requests to segment-wide configurations, the canvas is ours to paint.

    // Opt out of caching for all data requests in the route segment
    export const dynamic = 'force-dynamic'

    Journey Beyond: Client-Side Adventures

    As we traverse the realms of React and Next.js, we encounter the duality of client-side fetching. From the hallowed halls of Route Handlers to the enigmatic realms of third-party libraries like SWR and TanStack Query, the journey continues, each path leading to new discoveries and boundless possibilities.

    In the grand tapestry of web development, data fetching, caching, and revalidation stand as pillars of strength, guiding our journey and shaping our experiences. With Next.js as our companion, let us embark on this odyssey, where each line of code is a step closer to unlocking the full potential of the digital realm.

    216Blog views

    1.2K

    share this blog
    user profile avatar

    Tech Wizard

    Published on • 🕑6 min


    7 CSS Mistakes that Beginners Often Make

    CSS is not as simple as it looks and developers often make some mistakes that leave them struggling with what to do. CSS is perceived as an unintuitive and difficult language to work with because of these common mistakes that thwart most developers when they try to write CSS. As a result, most developers opt to use CSS frameworks such as Bootstrap and Tailwind CSS to avoid writing their own CSS.

    In this blog, we will discuss five common mistakes that developers often make. Recognizing and avoiding these mistakes will help you write CSS that:

    1. Works across devices—not just your laptop
    2. Works the first time you try it
    3. It makes you less frustrated with CSS

    Let's dive in.

    #Mistake 1: Not using CSS Reset

    This is one of my surprising discoveries and I have only realized that I have been doing CSS wrong all this time. Browsers have default styles that serve as a fallback if the stylesheet does not exist. However, these default styles are different across browsers. In any case, two browsers rarely provide identical default styling, so the only real way to ensure your styles are effective is to use a CSS reset.

    A CSS reset entails resetting (or, rather, setting) all the styles of all the HTML elements to a predictable baseline value. The beauty of this is that once you include a CSS reset effectively, you can style all the elements on your page as if they were all the same to start with.

    CSS reset is a blank slate that helps you have consistent styling across different browsers. Most often, this entails setting a margin:0 and padding:0, although there is a need to reset other elements.

    
    * {
      margin: 0;
      padding: 0;
      border: 0;
      outline: 0;
      font-weight: inherit;
      font-style: inherit;
      font-size: 100%;
      font-family: inherit;
      vertical-align: baseline;
    }
    /* remember to define focus styles! */
    :focus {
      outline: 0;
    }
    body {
      line-height: 1;
      color: black;
      background: white;
    }
    ol,
    ul {
      list-style: none;
    }
    /* tables still need 'cellspacing="0"' in the markup */
    table {
      border-collapse: separate;
      border-spacing: 0;
    }
    caption,
    th,
    td {
      text-align: left;
      font-weight: normal;
    }
    blockquote::before,
    blockquote::after,
    q::before,
    q::after {
      content: "";
    }
    blockquote,
    q {
      quotes: "" "";
    }
    

    #Mistake 2: Using px Units

    I am also actually guilty of using px units for font-sizes, margins, padding and height or weight attributes. While using px units can be fine in some instances, overreliance on them leads to accessibility issues.

    According to MDN,  Defining font sizes in px is not accessible, because the user cannot change the font size in some browsers. For example, users with limited vision may wish to set the font size much larger than the size chosen by a web designer. Avoid using them for font sizes if you wish to create an inclusive design.

    However, px units are also bad for setting height and width for content, since content might also overflow if the user increases the default font size in the browser. Using px units in-media queries also affects the layout when a user zooms in or changes the default font size. 

    🚫 Mistake

    p {
      font-size: 16px;
     /*this prevents users from resizing the font-size*/
      line-height: 20px;
      margin-bottom: 8px;
    }

    ✅ Correct

    body {
      font-size: 16px;
    }
    p {
      font-size: 1rem;
      line-height: 1.25;
      margin-bottom: 0.5em;
    }

    #Mistake 3: Using IDs as Selectors

    One of the most overlooked problems in web development is the use of over-qualifying selectors that are too specific and difficult to override. IDs selectors have more specificity in CSS, meaning you cannot override them or reuse the style in another component.

    Always write your CSS selectors with the very minimum level of specificity necessary for it to work. Including all that extra fluff may make it look safer and more precise, but when it comes to CSS selectors, there are only two levels of specificity: specific, and not specific enough.

    🚫 Mistake

    #header {
      font-size: 1em;
      line-height: normal;
    }
    

    ✅ Correct

    .header {
      font-size: 1em;
      line-height: normal;
    }

    In general, you should avoid using overly specific selectors in CSS. The CSS Specificity Tournament illustrates why it's a bad idea to use selectors that are too powerful. When a selector is very powerful in the tournament, it wins quickly and early on, which means the only way to beat it is to write an even more powerful selector.

     

    This tendency for specificity to always escalate is known as a specificity war. Similar to stockpiling nuclear weapons, no one wins in this war—things only become more difficult to de-escalate as specificity increases. The best way to avoid a full-blown specificity war is to not use highly specific selectors in the first place.

    #Mistake-4: Named Colors

    Another mistake that I discovered when doing my research is the problem with named colors. Developers often ignore that what you perceive to be a specific color looks very different across browsers.

    By saying: color: red; You’re essentially saying that the browser should display what it thinks red is. If you’ve learned anything from making stuff function correctly in all browsers it’s that you should never let the browser decide how to display your web pages.

    Instead, you should go to the effort to find the actual hex value for the color you’re trying to use. That way, you can make sure it’s the same color displayed across all browsers. You can use a color cheatsheet that provides a preview and the hex value of a color.

    🚫 Mistake

    .header {
      font-size: 1em;
      line-height: normal;
      color: red;
    }

    ✅ Correct

    .header {
      font-size: 1em;
      line-height: normal;
      color: rgb(255, 0, 0);
    }
    

    #Mistake 5: Not Using Shorthand Properties

    As a developer, one rule is to never repeat yourself. Therefore, you should find ways to minimize the number of lines of code that you write.

    One common problem with CSS is understanding shorthand properties for things like margin, padding and inset. As a confession, I also struggle with this problem and often have to look to the documentation on whether margin: 0 5px sets the margin in top-bottom or left-right.

    🚫 Mistake

    .my-cool-div {
      margin-top: 50px;
      margin-right: 0;
      margin-bottom: 50px;
      margin-left: 0;
      background-image: url(background.png);
      background-repeat: repeat-y;
      background-position: center top;
    }

    ✅ Correct

    .my-cool-div {
      margin: 50px 0;
      background: url(background.png) repeat-y center top;
    }
    

    Using shorthand CSS improves efficiency and makes it easier to maintain our code. However, this could take time to master and I recommend checking the documentation.

    #Mistake 6: Overreliance on Position Absolute

    Position absolute is that one band-aid solution that can cause more problems as it breaks the document flow. When using positions absolute, MDN recommends that you ensure that elements that are positioned with an absolute or fixed value do not obscure other content when the page is zoomed to increase text size.

    Position absolute should be the last choice since it has some effects such as pulling the element out of the flow and making it stack over other things. 

    Furthermore, elements positioned absolutely don't naturally adapt to changes in screen size or parent element dimensions, which can break the layout on different devices.

    🚫 Mistake

    .sidebar {
      position: absolute;
      top: 50px;
      right: 0;
      width: 30%;
      background-color: #e0e0e0;
      padding: 20px;
    }

    ✅ Correct

    .sidebar {
      transform: translateY(50px) translateX(0);
      /* Moves the element down by 50px */
      width: 30%;
      background-color: #e0e0e0;
      padding: 20px;
    }
    

    In this example, we see that we can achieve the same functionality without breaking the document flow by using transform to move the sidebar down by 50px.

    #Mistake 7: Collapsing Margins

    Collapsing margins can be really hard to understand and frustrating to decode since you might not understand why your applied margin or padding is not working as expected.

    The top and bottom margins of blocks are sometimes combined (collapsed) into a single margin whose size is the largest of the individual margins (or just one of them if they are equal), a behavior known as margin collapsing. Note that the margins of floating and absolutely positioned elements never collapse.

    Understanding margin collapse is essential for achieving consistent spacing in your layouts, particularly in scenarios where you want to ensure a specific amount of space between elements.

    One solution to collapsing margins is using padding, especially for child elements rather than margins. It is generally advised not to add margin to the child element, especially in JavaScript frameworks such as react since this might affect their reusability.

    You must always remember that adding a margin to a child element can affect the position of the parent element as the margins collapse.

    🚫 Mistake

    /* html */
    /* 
    <div class="element1">Element 1</div>
    <div class="element2">Element 2</div> 
    */
    .element1 {
      margin-bottom: 20px;
    }
    .element2 {
      margin-top: 30px;
    }
    /* the total margin will be 30px rather than 50px */

    ✅ Correct

    .element1 {
      margin-bottom: 20px;
      padding-bottom: 1px;
      /* Prevents collapse */
    }
    .element2 {
      margin-top: 30px;
    }
    

    Conclusion

    I hope you enjoyed this article, and that it gave you a sense of how to avoid the top most common mistakes developers make when they write CSS. There are many mistakes not covered in this blog such as separating between layout and content elements, overusing flex box and much more. Comment below with some other mistakes.

    01Blog views

    590

    share this blog
    user profile avatar

    the don

    Published on • 🕑7 min


    Is NextJs Better than React? Here Is a Comparison Between the Two

    As a React Dev, I tried my hands on NextJS and never turned back. What drew me to the platform is the server rendering and easier routing. The two frameworks go toe-to-toe, with NextJS being an advanced version of React. The debate between Next.js vs React has been around for a while.

    Comparing Next.js vs React, Next.js is a React framework, on the other hand, React is just a JavaScript library. This blog helps settle the debate by comparing the two frameworks from toe to toe.

    ⚛React

    React is one of the most well-known javascript libraries for building frontend applications. Founded by Facebook in May 2013, the library offers various useful tools to enclose routing and state management patterns alongside Redux and other libraries.

    The library allows users to build user interfaces or reusable  components. Due to its big community, React also includes other UI libraries that streamline the developer experience by allowing individuals to download ready-to-use components. React also includes hooks, APIs and server APIs.

    What is React Used For?

    • Social Media Platforms (Facebook, Instagram, Pinterest, Twitter)
    • Economy platforms (Airbnb, Lyft, Uber)
    • Media Platform (Yahoo!)
    • Online Video Streaming Platforms (Netflix)
    • SaaS Tools (SendGrid, Asana, InVisionApp, Zapier)

    Getting Started with React

    React npm package can be installed directly via the command terminal using npx. However, react create-app is outdated as other builders such as Vite provide a faster build time.

    npx create-react-app my-react-app
    cd my-react-app
    //start the server 
    npm start

    Here is a sample react code:

    import React from 'react';
    import ReactDOM from 'react-dom/client';
    function Hello(props) {
      return <h1>Hello World!</h1>;
    }
    const container = document.getElementById("root");
    const root = ReactDOM.createRoot(container);
    root.render(<Hello />)

    Key Features of React

    • JSX(JavaScript Syntax Extension) or XML 
    • Virtual DOM 
    • One-way data binding 
    • Component-Based Architecture
    • Hooks

    Advantages of React

    ✅Ease of Development: JavaScript familiarity allows for creating dynamic apps with less code.

    ✅Vast Developer Community: React has a huge developers community. Hence, they provide support and resources for learning in a quick time.

    ✅Reusable Components: React components are reusable. These allow you to load many pages recurringly while keeping their characteristics. The changes will be seen across all pages after modifying the component code.. Users can also download npm packages for existing components.

    ✅Customization: Extensible with tools like Redux for state management.

    Disadvantages of React

    ❌Starting Point: React is just a UI library, so it requires additional tools and setup to unlock its full potential.

    ❌Outdated Documentation: React’s rapid evolution means that its documentation can quickly become outdated, requiring developers to frequently relearn aspects of the library.


    NextJS

    NextJS is a popular React framework developed and maintained by Vercel. It’s developed on Node.js and Babel. Apart from that, Next.js provides static export and pre-rendering, as well as a variety of other useful features such as automatic building size optimization, faster developer compilation, and a preview mode.

    What is NextJS Used For?

    • ECommerce Websites (Nike, Stripe, Under Armor, LG, Target)
    • Marketing and News Websites (Washington Post, Realtor, AT&T, Tencent News)
    • Streaming Websites (Spotify, Netflix, Sonos, Hulu, Tiktok, HBO Max)
    • AI Chatbots (OpenAI ChatGPT, Vercel, Runway, Perplexity)

    Getting Started with NextJS

    NextJS is part of react and thus using the framework requires also using react and react-dom. Other features such as typescript and tailwind css are also added into the framework, although users can opt-out.

    //automatic installation
    npm create-next-app@latest
    //manual installation
    npm install next@latest react@latest react-dom@latest
    //start the server
    npm run dev

    In NextJS 13, the App is rendered in an app folder inside a root layout, which controls all the pages.

    export default function RootLayout({
      children,
    }: {
      children: React.ReactNode
    }) {
      return (
        <html lang="en">
          <body>{children}</body>
        </html>
      )
    }

    Key Features of NextJS

    Here are the features you can leverage to create ready-to-go applications by using Next.js:

    • Server-side Rendering (SSR)
    • Static Export (SSG)
    • Pre-rendering
    • Automatic Build Size Optimization
    • Enhanced Development Compilation

    Advantages of NextJS

    ✅Faster Development: Next.js offers many built-in components, libraries, and compatibility, allowing for quick MVP development, and enabling faster user feedback and iteration.

    ✅Enhanced User Experience: Next.js allows for highly customizable front-end development that aligns with business goals, providing a unique user experience.

    ✅SEO-friendly: The ability to develop faster and lighter static websites makes Next.js SEO-friendly, increasing the chances of ranking higher on search engines.

    ✅Super Fast Rendering: Changes can be seen in real-time as the website reloads, making it easy to track updates.

    ✅Built-in CSS: You can import CSS styles directly from a JavaScript file, which accelerates rendering.

    ✅Image Optimization: Images are automatically scaled and provided in the WebP format, optimizing them for different viewports.

    ✅ESLint Support: Developers can easily integrate ESLint using Next.js with a simple configuration with “scripts”: { “lint”: “next lint”}.

    Disadvantages of NextJS

    ❌Routing Limitations: Next.js’s file-based routing system may not be sufficient for complex projects, requiring developers to use Node.js tools for creating dynamic routes.

    ❌Limited Community Support: The Next.js developer community is smaller compared to React, making it harder to find experienced developers and resources, though it is growing.


    Comparison Between the React and NextJs

    1. Development Speed ⏩

    Next.js offers out-of-the-box features, including its compiler introduced in version 12, which accelerates development by minimizing build times. This reduces the time engineers spend waiting for code refreshes, compared to vanilla React, making the development process smoother and more efficient.

    2. Data Fetching and Load Times ⏱

    Next.js improves data fetching by preloading page data through server-side traversal of the React tree. This results in faster load times compared to React, which relies solely on client-side rendering. NextJS also automatically caches queries, making it easier to fetch data through the native fetch API.

    3. Rendering and SEO📱

    Next.js supports pre-rendering, which enhances SEO performance by serving pre-built pages, while React depends on client-side rendering, making it less efficient for SEO-focused applications.

    4. Routing 👈👉

    Next.js provides a structured, file-based routing system that simplifies setup but offers less flexibility than React, which allows for custom routing setups using libraries like React Router.

    5. Performance ⏩

    Next.js applications benefit from features like server-side rendering (SSR) and image optimization, resulting in faster performance compared to React's client-side rendering, which is less suited for high-performance apps.

    6. Documentation📜

    Both Next.js and React offer extensive documentation and learning resources. However, Next.js emphasizes "learn-by-doing" tutorials, while React offers more foundational tutorials. Create React App (CRA) simplifies setup for single-page applications (SPAs) in React.

    7. Server-side Rendering💻

    Next.js supports server-side rendering (SSR) out of the box, enabling dynamic data fetching and rendering per request. React requires additional configuration to enable SSR, making it less straightforward.

    8. Developer Community👨‍👩‍👧‍👦

    React has a larger and more active developer community, providing extensive resources and support. Next.js has a smaller but growing community, with discussions often centered around GitHub.

    9. Configuration🔧

    React's configuration is limited, especially when using Create React App, which restricts setup changes. In contrast, Next.js offers extensive configuration options, allowing more control over project settings.

    10. Maintenance 🧰

    Both Next.js and React are well-maintained with regular updates, ensuring stability and ongoing improvements.

    11. TypeScript Support🔢

    Both Next.js and React support TypeScript, but Next.js provides more built-in support for TypeScript configurations. NextJS automatically comes with Typescript, and configuration through touch tsconfig.json. In React, you can add Typescript by installing it as follows:

    npm install @types/react @types/react-dom

    12. Development Cost💰

    Both Next.js and React are open-source and free to use, making them cost-effective options for building applications. However, there are concerns about the ability to host Next.js outside Vercel and Vercel is also expensive.

    13. Experienced Developers👩‍💻

    React is more popular, making it easier to find experienced developers. Next.js developers typically have a background in React, as the framework is built on top of React.

    Comparison between NextJS and React comparison between react and nextjs


    Which is the Best Next JS or React JS?🧠

    There is no simple answer to this as it all depends on your use case. In most cases, I have found React to even perform better than nextjs. Therefore, selecting a framework or library completely depends on your project needs. React and Next.js are emerging and beneficial tools for your project, but only for performing certain tasks.

    When you go with Next.js, offers the best server-side rendering and static website development solutions. Also, it lets you manage projects easily with various tools and features.

    On the other hand, React is the best choice to develop user interfaces for single-page applications. Since it works with the layer of mobile and web apps, it allows you to create more appealing and intuitive applications.

    Next JS is a framework that holds React on its base, while React JS is an open-source JavaScript library, developed and maintained by Facebook. Next JS is used to create web applications and performs server-side rendering, whereas React JS focuses on rendering towards the DOM.

    Next.js supports Server-Side Rendering (SSR), whereas React.js supports client-side rendering, which improves the application performance.

    Next.js is a framework, used to build UI and pages for the web app with React library, while React.js as a library is a part of a framework, the UI components part.

    Next JS is easy to learn if you have a basic knowledge of React, whereas React JS is easy to learn and use if you have an understanding of JavaScript, HTML, and CSS.

    In a nutshell, Next.js offers various tools and features to minimize the development process, whereas, React.js has better resources for the front-end development of your mobile and web application.

    Conclusion

    In their ways, both React and Next.js provide significant potential for developers. React allows you to design things any way you want and is supported by a large community. Next.js makes your life easier by providing a variety of tools and conventions right out of the box, and it’s backed up by a vibrant open-source community.

    To summarise, Next.js provides more capabilities and tools for working behind the scenes, but React.js has more resources for working on the front end of your web or mobile application.

    Any project would benefit greatly from the use of React. What’s more, if, given the chance, it can scale up as well. React offers more flexibility than Next. Because it is a library, JavaScript is used. It is up to the engineer to decide whether or not to use it.

    I hope this article on Next.js vs React has given you the knowledge and some insights on how and why these technologies are used by many organizations. Best of luck with your upcoming project!

    20Blog views

    483

    share this blog
    user profile avatar

    tech girl

    Published on • 🕑8 min


    Best Programming Langauges to Learn in 2024

    As a jobless full-stack software engineer, I always dream of learning PHP so i can easily buy a Lambo like the rest of PHP developers. However, the ultimate glitch of money making as a programmer is to teach others programming - what a pyramid scheme. Consider this my new way of passing my knowldge to you. Here is a list programming langauges that are more valuable and in demand in 2024.

    1. JavaScript

    Last year JavaScript was at the top of the coding languages for beginners, StackOverflow survey report and this year it will be also one of the most popular languages among developers. Android, iOS, or desktop JavaScript is almost everywhere and in best programming languages.

    JavaScript is providing ultimate business solutions and that is the reason it is on the top of the list for a tech startup and for tech giant companies as well. If you are looking for a job quickly and easily then JavaScript opens a lot of opportunities for you in the job market.

    JavaScript is now used for both the frontend and backend side. There are so many frameworks and libraries available for JavaScript that are quite popular among web developers such as AngularJsReactVueMeteor, and a lot more.

    Key Features of JavaScript:

    • Interpreted, light-weighted, Object-oriented programming.
    • Annual updates.
    • Used for both server-side and client-side programming.
    • Compatible with several programming languages
    • 629K+ Repositories on GitHub.

    Companies working on JavaScript: Google, Facebook, Dell, eBay, PayPal, Uber

    JavaScript Code Example:

    // JavaScript program to add two numbers
    function add(a, b) {
        return a + b;
    }
    console.log(add(2, 3));  
    Output
    5
    

    2. Python

    If we talk about easy-to-read, easy-to-learn, and coding languages for beginners then nothing can beat Python to come in the list of best programming language and that makes it an excellent choice for beginners. Python is now being introduced as the very first language in the majority of universities all over the globe.

    DjangoFlask, and Pyramid these all Python frameworks that are popular among developers. Python syntax is user-friendly in comparison to other languages and that increases developers’ productivity eventually. These all are the reason it is among one of the Top Programming languages. 

    Key Features Of Python:

    • Open source and object-oriented.
    • Can be integrated with C and C++.
    • Cross-browser support.
    • Career in various fields such as Scripting, Web Development, Machine Learning, Deep Learning, Data Science, Artificial Intelligence, Robotics, and Big Data.
    • 1M+ repositories on GitHub.

    Companies working on Python: Google, Facebook, Instagram, Spotify, Paytm, Netflix, Quora.

    Python Code Example:

    # Python program to add two numbers
    def add(a, b):
        return a + b
    
    print(add(2, 3))
    Output
    5
    

    3. Java

    Whether you are in the programming field or not you must have definitely heard about this popular programming language. The reason why Java is on the list of top programming languages is that there are so many large organizations still working on this language.

    Java is widely used in Android app development and for building enterprise-scale web applications. Google has also created an excellent Java-based Android development framework – Android Studio.

    There was a little bit decline in the popularity of Java but Spring Boot (the framework of Java) is gaining enormous popularity these days because of some of the recent refinement in the frameworks done recently. The recent update in this framework made it fantastic and probably, it will boost up in the future as well.

    Key Features of Java

    Companies working on Java: HCL, Adobe, Intuit, Qualcomm, Flipkart, Amazon.

    Java Code Example:

     // Java program to add two numbers
    public class Main {
        public static void main(String[] args) {
            int a = 6, b = 3;
            System.out.println("Sum: " + (a + b)); 
        }
    }
     

    Output

    Sum: 9
    

    4. C and C++

    Surely python and JavaScript are easy-to-learn and easy-to-use languages for most of the applications but when it comes to choosing the fastest language then C and C++ are the best choices and it is one of the top programming languages in the programming world.

    A lot of low-level stuff such as operating systems, file systems, embedded systems, and kernel development can be built using C or C++. Almost all the modern and popular languages today inherit the properties of C and C++. C++ is still used in Microsoft Windows and Google projects. Apple also uses C++ language to develop its iOS operating system.

    Key Features of C and C++

    • C++ is an object-oriented programming language.
    • Availability of ready-to-use STL libraries in C++.
    • Used in Game development, GUI applications, Desktop applications, and real-time mathematical simulations.
    • 7M+ repositories for C and 560K+ repositories for C++ on Github

    Companies working on C and C++: eBay, Spotify, Adobe, Oracle, HP, Huawei, IBM, PhonePe

    C Code Example:

     // C program to add two numbers
    #include <stdio.h>
    int main() {
        int a = 2, b = 5;
        printf("Sum: %d", a + b);  
    }
     

    Output

    Sum: 7

    C++ Code Example:

    // C++ program to add two numbers
    #include <iostream>
    int main() {
        int a = 2, b = 3;
        std::cout << "Sum: " << a + b;  
        return 0;
    }
    Output
    Sum: 5

    5. GoLang

    GoLang was developed by Google and it is also a simple language and top programming Languages like Python so people who love to work on Python, they will definitely love this language as well. This language is pretty much already popular and scaling quite a lot at the backend services.

    In past years this language didn’t get much popularity but in 2024 it will be rising quite a lot. Go language is more efficient than C++ and it provides features to write concurrent programs that are difficult in other programming languages. Revel, Beego, Martini, Gin all are popular frameworks of this language.

    Key Features Of GoLang:

    • Excellent support for multithreading.
    • Fast and easy to learn syntax.
    • Ideal for building SPAs (single-page applications).
    • Can be used in a Distributed SystemBig dataCloud Computing, and other large-scale or complex applications.
    • 729K+ repositories on GitHub.

    Companies working on Golang: Uber, Google, Dailymotion, Fabric, Medium.

    GoLang Code Example:

     // Go program to add two numbers
    package main
    
    import "fmt"
    
    func add(a int, b int) int {
        return a + b
    }
    
    func main() {
        fmt.Println("Sum:", add(2, 3)) 
    }
     

    Output

    Sum: 5
    

    6. Swift

    Swift programming language is developed by Apple used to develop iOS applications. We all know the popularity of iOS applications in the market so it’s not going anywhere in 2024 as well. It is best programming languages among iOS development languages.

    Earlier we just had one single option, Swift, to enter iOS development but now we also have the option of Flutter and React native in the iOS market so you will see a little bit of a decline in the popularity of this language. Still, some of the things can only be done in Swift language (ex-payment stuff) so definitely, it’s worth learning Swift programming language. Cocoa and CloudKit these two are popular frameworks of Swift programming language.

    Key Features of Swift:

    • Used in iOS applications, MacOS development, TvOS development, and the whole Apple ecosystem.
    • Scalable and easy to add new features.
    • Easy-to-read syntax
    • Automatic memory management prevents memory leaks.
    • Fast in comparison of Objective-C and Python.
    • 161K+ repositories on GitHub

    Companies working on Swift: Apple, Amazon, Walmart, Uber, Slack.

    Swift Code Example:

    // Function to add two numbers directly from arguments
    func add(_ num1: Int, _ num2: Int) -> Int {
      return num1 + num2
    }
    
    // Example usage (directly passing values)
    let sum = add(10, 20)
    
    print("The sum is: \(sum)")
    Output
    The sum is: 30
    

    7. Kotlin

    Kotlin was one of the best programming languages in 2024 and the popularity will definitely increase in 2025 as well. When it comes to Android app development Kotlin has become a recent choice for developers.

    It can be used with both frontend and backend frameworks. The language comes with features such as interoperability with Java as well as Android Studio support. You can do amazing things with fewer bugs and fewer lines of code using Kotlin.

    Some of the popular frameworks are Ktor, Vertex, and Spring. You all know the popularity of Android in the market so Kotlin opens a lot of job opportunities to the developers. 

    Key Features of Kotlin:

    • Object-oriented and cross-platform programming language.
    • Secure and flexible.
    • Easy to debug.
    • 79K+ repositories on GitHub.

    Companies working on Kotlin: Airtel, Lenskart, Pinterest, Basecamp, Slack, Trello, Google, Netflix.

    Kotlin Code Example:

    // Kotlin program to add two numbers
    fun add(a: Int, b: Int): Int {
        return a + b
    }
    
    fun main() {
        println("Sum: ${add(2, 3)}")  // Output: Sum: 5
    }

    8. C#

    C# is the one of the top programming languages that is developed by Microsoft and it is still a quite popular programming language used in web development, game development (X-box, virtual reality, and Unity 3D games), and in Windows applications.

    It has a comprehensive set of libraries that makes the execution and compilation of the program very fast. It is majorly used with the Dot Net framework(.NET). 

    Key Features of C#:

    • General purpose object-oriented programming language.
    • Fully integrated with the .NET library.
    • 19K+ repositories on GitHub.

    Companies working on C#: Intellectsoft, Philips, Capgemini.

    C# Code Example:

    // C# program to add two numbers
    using System;
    class Program {
        static void Main() {
            int a = 2, b = 3;
            Console.WriteLine("Sum: " + (a + b)); 
        }
    }

    Output

    Sum: 5
    

    9. Rust

    Rust is a systems programming language known for its performance and safety, particularly safe concurrency. It has a strong focus on memory safety without using garbage collection. Rust is gaining popularity among system developers and is considered a potential replacement for languages like C and C++.

    Key Features of Rust:

    • Memory safety guarantees without a garbage collector
    • High performance for system-level programming
    • Concurrency without data races
    • Rich type system and ownership model
    • 95K+ repositories on GitHub

    Companies working on Rust: Mozilla, Dropbox, Yelp, Cloudflare, Prisma, npm

    Rust Code Example:

    fn main() {
        let a = 5;
        let b = 10;
    
        let sum = a + b;
    
        println!("The sum of {} and {} is {}", a, b, sum);
    }
    Output
    The sum of 5 and 10 is 15
    

    10. PHP

    A lot of people agree that PHP is losing its popularity day by day but we need to mention that it is still highly ranked in the market PHP is a cheap, free, and easy-to-use language. Approx. 70-80% of websites (Ex: Facebook, Wikipedia) are still running on PHP so there is a huge demand for PHP developers in the market.

    A lot of developers or freelancers are using this language for web applications. Beginners can also choose this language because there is less competition in the market due to the popularity of Python and JavaScript languages.

    CodeignitorLaravel, CakePHP, and Symfony all are popular frameworks of PHP to make dynamic web applications. 

    Key Features Of PHP:

    • Functional and Object-Oriented Programming
    • Platform independent.
    • Easy to get started for making web pages.
    • A lot of automation tools are available for testing and deployment.
    • 540K+ repositories on Github

    Companies working on PHP: Oracle, HCL, Motorola, Facebook.

    PHP Code Example:

    <?php
    $number1 = 10;
    $number2 = 20;
    $sum = $number1 + $number2;
    echo "The sum of $number1 and $number2 is: $sum";
    ?>
    Output
    The sum of 10 and 20 is: 30

    Top 10 Best Programming Languages to Learn in 2024 – Comparison Table

    Programming LanguageKey FeaturesPopular UsesCompanies Using ItAverage Salary
    JavaScriptVersatile, client-side scripting, frameworksWeb development, front-end & back-endGoogle, Facebook, PayPal, Uber, Netflix$110,000
    PythonEasy-to-learn, versatile, extensive librariesWeb development, AI, ML, data scienceGoogle, Facebook, Instagram, Spotify, Netflix$120,000
    JavaObject-oriented, platform-independentAndroid apps, enterprise-scale applicationsAmazon, Flipkart, Adobe, Intuit, Qualcomm$115,000
    C/C++Fast, efficient, system programmingOperating systems, game development, embedded systemseBay, Spotify, Adobe, Oracle, IBM$125,000
    GoConcurrency support, efficientBackend services, large-scale applicationsGoogle, Uber, Medium, Dailymotion, Fabric$130,000
    SwiftiOS/macOS development, modern syntaxiOS applications, Apple ecosystemApple, Amazon, Uber, Slack, Walmart$115,000
    KotlinInteroperable with Java, concise syntaxAndroid apps, backend developmentGoogle, Pinterest, Trello, Slack, Netflix$110,000
    C#Object-oriented, .NET integrationWeb development, game development, Windows applicationsMicrosoft, Intellectsoft, Philips, Capgemini$120,000
    RustMemory safety, system programmingSystem software, high-performance applicationsMozilla, Dropbox, Discord, Coursera, AWS$130,000
    PHPServer-side scripting, easy integrationWeb development, dynamic websites, content management systemsFacebook, Wikipedia, WordPress, Slack, Mailchimp$105,000

    Note on Average Salary: The average salary figures provided are approximate and can vary based on factors such as location, level of experience, and specific industry demands. They serve as a general guideline to understand the earning potential associated with each programming language.

     

    513Blog views

    1.6K

    share this blog
    user profile avatar

    Tech Wizard

    Published on • 🕑6 min


    Five Must Know CSS Tricks to Save You Time

    HTML & CSS are the predominant languages for any newbie front-end developer to learn. CSS or Cascading Style Sheets is the language we use to style an HTML document. CSS describes how HTML elements should be displayed. However, CSS is not as easy as it looks, and mastering it takes time. Here are some 5 tricks that can help make you a css pro.

    1. Styling Images

    When it comes to web design, captivating visuals can make all the difference. Images play a crucial role in creating an engaging and memorable user experience.

    Styling images properly could help reduce the loading time for images. Despite setting width, height, and alt properties, there are other advanced CSS features for images such as aspect ratio that help set the responsiveness. Here is how to properly style images according to Kevin Powell.

    .img {
       max-width: 100%;
       height: auto;
       vertical-align:middle;
       font-style: italic;
       background-repeat:no-repeat;
       background-cover: cover;
       shape-margin:0.75rem;
    }

    Max-width and height auto-properties are important to help ensure the image is responsive and stop the image from overflowing. There is a difference when you set the width and max-width to 100%. using width: 100% allows the image to stretch or shrink to fit the container’s width, while max-width: 100% ensures the image does not exceed its original size but can still scale down to fit within the container.

    Vertical-align is a replacement for a display block that helps preserve the line height but moves the image down vertically so it no longer seems like it has uneven spacing. The font-style italic is used to style the image description and thus differentiate the alt text from the rest of the text. If need be, you can also style this using the image[alt] selector.

    You might be wondering why we need the background image for an image. Kevin explained that the background image background-cover: cover and background-repeat: no-repeat helps set a placeholder (low-resolution of the image) to serve as a skeleton loader when the user is on a slow network.

    However, another solution for this would be to use webp images or convert your images to progressive jpeg using tools such as Optimizilla or Riot. This will help the images load faster and therefore no need for a skeleton loader.

    Lastly, the shape margin is useful especially when floating an image. This gives so spacing to the image and in the current setup, it does not do anything unless you end up floating the image.

    2. Scroll Based Animation

    We have all seen those fancy websites where content is updated dynamically as you scroll. You might think that this requires a lot of JavaScript to achieve, while in the real sense, you can use CSS tricks to achieve similar effects.

    One alternative to this is to use a popular library called animate-on-scroll but the library has not been touched in seven years and only has 49 downloads. Another alternative is to use animate-on-scroll-framer which also has 3 downloads.

    Upon further research, I also found a CSS feature named scroll-timeline although it is also not supported anywhere. Looks like we have to do this ourselves using Intersection Observer API.

    To use the intersection observer api, we need some javascript code that applies a class when the element is intersecting. We will add a class of hidden to all elements we want to animate on scroll and use the observer to add a class of show when the element is intersecting.

    const observer = new IntersectionObserver((entries) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          entry.target.classList.add("show");
        } else {
          entry.target.classList.remove("show");
        }
      });
    });
    const hiddenElements = document.querySelectorAll(".hidden");
    hiddenElements.forEach((element) => observer.observe(element));

    We need to add a class of hidden to a section and then animate the section on scroll. It is important to ensure each section that you want to animate takes the full viewport height for better scroll behavior. 

    .section-to-animate{
      min-height: 100dvh;
    }
    .hidden {
      opacity: 0;
      transition: all 1s ease-in-out; /* fade animation */
      filter: blur(0);
      transform: translateY(-100%);
    }
    .show {
      opacity: 1;
      filter: blur(1);
      transform: translateX(0);
      transition-delay: 0.2s;
    }
    @media (prefers-reduced-motion) {
      .hidden {
        transition: none; /* be polite */
      }
    }
    

    For more advanced cases that make you look fancy, look at this pen and do not forget to fork it.

    3. CSS Variables

    CSS Variables enhance efficiency by allowing you to declare variables with local or global scope, change the variables with JavaScript, and change the variables based on media queries. A good way to use these variables is when declaring colors.

    We can declare global variables using the selector in CSS :root selector and adding the variable to use using the var function. We can create fallback variables and declare local variables that override the global variable on a component.

    /* global */
    :root {
      --primary-color: #3498db;
      --secondary-color: #2ecc71;
      --font-size: 16px;
      --padding: 10px;
      --color: white;
    }
    /* local */
    .button {
      --color: whitesmoke;
    }
    body {
      background-color: var(--primary-color);
      color: var(--secondary-color);
      font-size: var(--font-size);
      padding: var(--padding);
    }
    .button {
      background-color: var(--primary-color);
      padding: calc(var(--padding) * 2); /* Using a calculation with the variable */
      font-size: var(--font-size);
    }
    /* using a fallback value */
    body {
      background-color: var(--primary-color, skyblue);
    }
    

    This would also work great using media queries. The variables can be modified using a media query to ensure a responsive design. This could range from updating color in dark and light modes and changing font size in small devices. For more knowledge, check out this tutorial guide: CSS Variables - An Introduction to CSS Custom Properties

    :root {
      --font-size: 16px;
    }
    @media (min-width: 768px) {
      :root {
          --font-size: 18px;
      }
    }
    @media (min-width: 1024px) {
      :root {
          --font-size: 20px;
      }
    }
    body {
      font-size: var(--font-size);
    }
    

    4. Responsive Font Size

    Responsive design is one of the major requirements in modern web design. Making sure the text changes as device width changes often involves using a lot of media queries to change the font sizes. However, there are simpler solutions like using CSS viewport width and clamp() function which is currently supported in all browsers.

    We use viewport units to size our text to ensure the typography is responsive to the device's width. Instead of setting custom font sizes for each device using media queries, we can ensure that our text is responsive and increases or decreases as device width changes. 

    However, the viewport text can get very small on smaller devices or very large on larger devices, and thus the a need to combine this with clamp(). Another problem with viewport units is that you cannot zoom in or out, and thus accessibility features might not work.

    The clamp() CSS function clamps a middle value within a range of values between a defined minimum bound and a maximum bound. The function takes three parameters: a minimum value, a preferred value, and a maximum allowed value.

    :root {
      --min-font-size: 1.2px;
      --max-font-size: 8rem;
      --font-xl: clamp(3.5rem, 12vw+1rem, 8rem);
      --font-md: 2rem;
      --font-sm: 1.5rem;
    }
    h1 {
      font-size: clamp(var(--min-font-size), 6vw, var(--max-font-size));
    }
    p {
      font-size: clamp(var(--font-sm), 3vw, var(--font-md));
    }

    5. CSS Based Validations

    If you have ever dealt with forms, then you understand the need to validate form inputs and show errors to users without JavaScript. Errors could include setting a red background color if the input is invalid, and a green when the input is valid. This should be done in combination with HTML patterns, maxLength, and types.

    One major problem is that if we give a form input a required attribute and use CSS invalid property, the form will appear as invalid even when the user has not typed anything. Of course, this is a bad experience for the user. To fix this, new CSS features such as user-invalid and placeholdershown property.

    /* the old way */
    input:invalid {
      border: 1px solid red;
      background-color: #ff7f7f;
    }
    input:valid {
      border: 1px solid green;
      background-color: lightgreen;
    }
    /* show on user input */
    input:user-invalid {
      border: 1px solid red;
      background-color: #ff7f7f;
    }
    input:user-valid {
      border: 1px solid green;
      background-color: lightgreen;
    }
    /* user-valid and user-invalid has low browser support */
    input:not(:placeholder-shown):invalid {
      border: 1px solid red;
      background-color: #ff7f7f;
    }
    input:not(:placeholder-shown):valid {
      border: 1px solid green;
      background-color: lightgreen;
    }
    /* placeholder-shown has great browser support */

    You can play around with this code in Codepen. Here are the results.

    Conclusion

    We have discussed some simple CSS tricks that could be lifesaving. These tricks could help you avoid overusing JavaScript for simple tasks that can be accomplished by just CSS. Follow me and sign up to be a Tech Tales member today to learn more and also share some tricks in the comments.

    01Blog views

    468

    share this blog
    user profile avatar

    tech girl

    Published on • 🕑6 min


    A Detailed Guide on How to Create Ruby on Rails Application (API)

    If you know me well, I am that ruby girl that enjoys working with ruby on rails. As a language designed to make developers happy, rails surely offer alot of flexibility to developers, including some generators that can generate anything with just one line of code! This guide will discuss how to create a ruby on rails api, assuming you have rails installed.

    Ruby on Rails API refers to the application programming interface (API) framework provided by the Ruby on Rails (Rails) web application framework. It allows developers to build and expose APIs for their web applications efficiently.

    Why Choose Rails for API Development?

    1. ActiveRecord ORM

    Rails includes ActiveRecord, a robust Object-Relational Mapping (ORM) system that simplifies database interactions. It allows you to work with databases using Ruby objects and eliminates the need to write complex SQL queries for most operations.

    2. Convention Over Configuration

    Rails is built around the principle of "Convention Over Configuration," meaning it provides sensible defaults, reducing the decision-making and configuration developers need to do.

    3. Rich Ecosystem of Gems

    Rails has a vast ecosystem of gems (libraries) that extend its functionality. Whether you need authentication, background processing, or payment integration, there’s likely a gem that fits your needs.

    4. Scaffolding

    Rails provides generators that can create models, controllers, views, and even tests for you. This feature helps to quickly spin up resources, allowing you to focus more on building the core functionality of your application.

    5. Built-in Security Features

    Rails includes many security features, such as protection against SQL injection, Cross-Site Scripting (XSS), and Cross-Site Request Forgery (CSRF).

    Step-by-Step Guide to Building an API

    For this tutorial, we are going to build a simple ruby API for Tesla that returns a list of their vehicle models with the model name, year of manufacture, picture, and price.

    Step 1: Create a New Rails Project

    Assuming you have installed ruby on rails, open the terminal and run:

    rails new tesla --api --skip-test-unit && cd tesla

    If you do not have rails installed, see here how to install or run the following command:

    gem install rails

    2. Generating the Vehicle Model and Controller

    Next, we need to leverage the power of rails to scaffold models and get started quicker. Rails come with different commands, which you can view by running rails --help. One of those commands is rails generate which uses rails generator to create assets model routes channel controller generator based on existing templates.

    We will create our model, controller, and routes using the rails generator to make things easier.

    rails generate scaffold Vehicle name:string year_of_manufacture:integer price:decimal picture:string --no-test-framework
    

    This command will create:

    • A Vehicle model with attributes: name, year_of_manufacture, price, and picture.
    • A VehiclesController with all the standard RESTful actions.
    • The necessary routes for the vehicles resource

    3. Running Migrations

    Out of the box, rails works with SQLite3 database and thus you need to ensure you have it installed or provide an alternative database such as Postgres when setting up the app. You can also edit the database.yaml file to add your database URL. For this scenario, we will work with the default database.

    We need to use rails:migrate to run migrations for our database using activerecord. Rails will automatically create a database for you if it does not exist and create vehiclestable with the specified columns.

    rails db:migrate

    Step 4: Creating Seed Data 🌱 (Optional)

    To populate your database with some initial data, you can create a seed file. Rails provides a convenient way to seed the database with data you can use for testing or development. To add data, open db/seeds.rb. You’ll see that there are already some examples there, but we’ll need to delete these and add our own:

    Here is a sample seed data:

    Vehicle.create!([
      { name: 'Tesla Model S', price: '51885.17', picture: 'https://static-assets.tesla.com/configurator/compositor?&options=$MT337,$PPSW,$W40B,$IBB1&view=STUD_FRONT34&model=m3&size=1920&bkba_opt=2&version=v0028d202109300916&crop=0,0,0,0&version=v0028d202109300916', year_of_manufacture: 2012 },
      { name: 'Tesla Model 3', price: '100990', picture: 'https://static-assets.tesla.com/configurator/compositor?&options=$MTS10,$PPSW,$WS90,$IBE00&view=FRONT34&model=ms&size=1920&bkba_opt=2&version=v0028d202109300916&crop=0,0,0,0&version=v0028d202109300916', year_of_manufacture: 2017 },
      { name: 'Tesla Model X', price: '120990', picture: 'https://static-assets.tesla.com/configurator/compositor?&options=$MTX10,$PPSW,$WX00,$IBE00&view=FRONT34&model=mx&size=1920&bkba_opt=2&version=v0028d202109300916&crop=0,0,0,0&version=v0028d202109300916', year_of_manufacture: 2015 },
      { name: 'Tesla Model Y', price: '65000', picture: 'https://static-assets.tesla.com/configurator/compositor?&options=$MTY07,$PPSW,$WY19B,$INPB0&view=FRONT34&model=my&size=1920&bkba_opt=2&version=v0028d202109300916&crop=0,0,0,0&version=v0028d202109300916', year_of_manufacture: 2020 }
    ])

    Then, run the seed file to populate your database:

    rails db:seed

    Step 5: Customizing the Controller

    The rails generate command automatically generates a controller with all the methods. However, we need some additional modifications to rescue from activerecord errors and also restrict the types of params we accept when creating a new vehicle.

    Navigate to /app/controllers/vehicle_controller.rb and add the following code:

    class VehiclesController < ApplicationController
      rescue_from ActiveRecord::RecordNotFound, with: :render_not_found
      rescue_from ActiveRecord::RecordInvalid, with: :render_unprocessable_entity
      # GET /vehicles
      def index
        @vehicles = Vehicle.all
        if params[:name].present?
          @vehicles = @vehicles.where(name: params[:name])
        end
        if params[:year_of_manufacture].present?
          @vehicles = @vehicles.where(year_of_manufacture: params[:year_of_manufacture])
        end
        if params[:price].present?
          begin
            @vehicles = @vehicles.where(price: params[:price])
          rescue ArgumentError
            render json: { error: 'Invalid price parameter' }, status: :bad_request
            return
          end
        end
        render json: @vehicles
      end
      # GET /vehicles/:id
      def show
        @vehicle = Vehicle.find(params[:id])
        render json: @vehicle
      end
      # POST /vehicles
      def create
        @vehicle = Vehicle.create!(vehicle_params)
        render json: @vehicle, status: :created
      end
      # PATCH/PUT /vehicles/:id
      def update
        @vehicle = Vehicle.find(params[:id])
        @vehicle.update!(vehicle_params)
        render json: @vehicle
      end
      # DELETE /vehicles/:id
      def destroy
        @vehicle = Vehicle.find(params[:id])
        @vehicle.destroy!
        head :no_content
      end
      private
      def vehicle_params
        params.require(:vehicle).permit(:name, :year_of_manufacture, :price, :picture)
      end
      def render_not_found
        render json: { errors: ['Vehicle not found'] }, status: :not_found
      end
      def render_unprocessable_entity(invalid)
        render json: { errors: invalid.record.errors }, status: :unprocessable_entity
      end
    end

    This sample has been modified with extra safety and error handling when a record is not found or cannot be created. The index action has also been updated to handle query parameters for filtering the results. It also includes error handling for invalid price parameters.

    Step 5: Start the Server and Get the Data

    While you could have started the server earlier on by running rails s, the page would only show the welcome page for rails. Now since we have data, start the server and go to /vehicles to make a get request and return the list of vehicles.

    rails s
    #test with curl
    curl http://localhost:3000/vehicles

    You can also test the API using postman or thunderbird extension in vs code for the get, create, update and delete commands. Furthermore, you can debug or even create new vehicles in the database in the rails console by running rails c

    ruby-on-rails image

    Step 6: Modifying Routes

    Rails can display a list of all created routes if you run rails routes, which is useful for tracking down routing problems in your app, or giving you a good overview of the URLs in an app you're trying to get familiar with.

    You also have the freedom of renaming your routes any way you like, for example instead of the create route for users, you can rename the route signup and then map it to the users create controller. We can do this by modifying the config/routes.rb file.

    Here is an Example:

    Rails.application.routes.draw do
      resources :vehicles
      resources :users
      post '/signup', to: 'users#create'
      # Defines the root path route ("/")
    end

    Step 7: Serializing data

    We all know it is annoying to return irrelevant data such as created_at_date and updated_at_date in API requests unless we need such data. Luckily, ActiveModel::Serializer allows us to state which data we want to return in our API requests, thus making the response time even faster.

    To use the gem, we need to add it to the gem file and run bundle install. The bundle install command in ruby on rails projects is used to install the necessary gems (ruby libraries or packages) specified in the project’s Gemfile.

    gem 'active_model_serializers'
    bundle install

    Next, we need to generate a serializer for our desired model, which in this case is the vehicle model. Remeber to use Capitalization while referring to a model and lowercase when referring to the table. For example, the model is named Vehicle while its associated table in the database is named vehicle

    rails generate serializer Vehicle

    This will create a file app/serializers/vehicle_serializer.rb. Update this file to specify the attributes you want to include in the JSON response:

    class VehicleSerializer < ActiveModel::Serializer
      attributes :id, :name, :year_of_manufacture, :price, :picture
    end

    Conclusion

    With Rails, creating a RESTful API is both efficient and enjoyable. Its built-in features like ActiveRecord, the rich ecosystem of gems, and the convention-over-configuration philosophy make Rails a powerful tool for building APIs. In this guide, we’ve built a simple Tesla API, showcasing how easy it is to get up and running with Rails.

    There is much more about rails that I have not covered here but this can get you going in no time. Hope you enjoyed this tutorial.

    Resources

    1. Getting started with ruby on rails [external link]
    2. Ruby on Rails API tutorial [youtube]
    11Blog views

    465

    share this blog
    user profile avatar

    the don

    Published on • 🕑6 min


    Handling Authentication with JWT in NextJs

    Authentication is crucial in every app, and ensuring sufficient security is vital whether you are creating a small app or a production ready deployment. Understanding auth concepts such as hashing, cryptography and so on could be challenging, but luckily there are few libraries that simplify the process.

    For this blog, I will explain how I have implemented authentication in my app using json web token and server actions in NextJs. Since NextJS is a fullstack app, the concept of CORS will not be covered here. 

    To begin we need to install the relevant libraries. This include jsonwebtoken, jose, and bcrypt.js. There are vital to encoded and decode user password stored in the database. I am using a postgress database with PRISMA orm.

    To get started, assuming you have all the necessary setup (NextJS app and database), run the following command:

    npm i jsonwebtoken bcrypt jose

    Jose is similar to jsonwebtoken but also works in browser environment, enabling you to decode the token if you need the data in the frontend.

    Next, we are going to create a JWT_SECRET that will be used to hash the passwords. You can set this to any random number or use openssl to generate the token by running the command:

    openssl rand -base64 32

    Save the token in .env file, without the .local prefix to ensure it is not exposed into the browser environment. 

    NOTE: It’s crucial that you keep this key private and only accessible to the server. You can use a dot env provider or keep it in a secure location. Be sure you set it in Next.js without the NEXT_PUBLIC prefix.

    If you accidentally leak the key to the client, then an attacker could use your key to sign bogus credentials with whatever role they like and gain full access to your platform!

    Next we are going to tap into the power of middleware in NextJs. Middleware is the cornerstone of our authentication system, designed to protect routes that require authentication.

    By implementing this, you ensure that only authenticated users can access certain parts of your application, safeguarding sensitive information and user privacy.

    NextJS already includes a middleware.js file but if it does not exist, create one in the root directory and name it middleware.js. Add the following code to the middleware.

    import { NextResponse, NextRequest } from "next/server";
    import * as jose from "jose";
    
    const JWT_SECRET = new TextEncoder().encode(process.env.JWT_SECRET);
    
    export async function middleware(request: NextRequest) {
      const path = request.nextUrl.pathname;
      const isProtectedPath =
        path.startsWith("/profile") ||
        path.startsWith("/admin") ||
     
    
      const isPublicPath =
        path.startsWith("/login") ||
        path.startsWith("/register") 
      const token = request.cookies.get("token");
      let userData = null;
      if (token) {
        try {
          const { payload } = await jose.jwtVerify(token.value, JWT_SECRET);
          userData = payload;
        } catch (error) {
          console.error("Invalid token:", error.message);
        }
      }
      const isAdmin = userData?.role == "admin";
      // redirect users to homepage if they are not admin
      if (path.startsWith("/admin") && !isAdmin) {
        return NextResponse.redirect(new URL("/", request.nextUrl));
      }
      if (path === "/admin" && isAdmin) {
        return NextResponse.redirect(
          new URL("/admin/dashboard?tab=0", request.nextUrl)
        );
      }
      if (isProtectedPath && !userData) {
        return NextResponse.redirect(
          new URL("/login", request.nextUrl)
        );
      } else if (userData && isPublicPath) {
        //prevent users from visiting login page if they are already logged in
        return NextResponse.redirect(new URL("/", request.nextUrl));
      }
    }
    
    export const config = {
      matcher: [
        "/",
        "/login",
        "/signup",
        "/register",
        "/profile",
        "/profile/:path*",
        "/admin",
        "/admin/:path*",
      ],
    };
    

    Note we are using jose instead of jwt since we need to read user data rather than just check if the token exists. If we just check if the token exists, a user can create a token with nothing and be authenticated.

    The matcher object configures the path that you want the API to match. You can modify the protected and public routes, and make sure to include them in the matcher function.

    Next we are going to create a login functionality that utilizes PRISMA to find and authenticate the user and return a http only cookie in the response body. It is better to create this in an api route.

    Here is the login function in a file called /api/auth/login:

    import bcrypt from "bcryptjs";
    import prisma from "@/prisma/prisma";
    import jwt from "jsonwebtoken";
    import { NextRequest, NextResponse } from "next/server";
    
    export async function POST(req: NextRequest, res: NextResponse) {
      const { email, password } = await req.json();
      try {
        // Check if the user exists
        const user = await prisma.user.findUnique({
          where: {
            email: email.toLowerCase(),
            deleted: false,
          },
        });
    
        // Compare the password
        if (user) {
          const isPasswordValid = await bcrypt.compare(
            password,
            user.password_digest
          );
          if (!isPasswordValid) {
            return NextResponse.json(
              { error: "Invalid password, please try again!" },
              { status: 401 }
            );
          } else {
            // Generate a JWT token
            const token = jwt.sign(user, process.env.JWT_SECRET, {
              expiresIn: "8h",
            });
            // Return user details and token
            const response = NextResponse.json(user, { status: 202 });
            response.cookies.set("token", token, { httpOnly: true });
            return response;
          }
        } else {
          return NextResponse.json(
            { error: "No user with matching email found" },
            { status: 404 }
          );
        }
      } catch (error) {
        console.error(error);
        return NextResponse.json(
          { error: "Internal server error" },
          { status: 500 }
        );
      } finally {
        await prisma.$disconnect();
      }
    }
    

    You can add some more complicated functionalities, such as checking the request ip address to rate limit the user. If you wish to add a rate limiter in the login function, you can get user ip address by doing the following:

    const rateLimitMap = new Map();
    //creates a map to store the requests
     const ip = req.ip || req.headers.get("X-Forwarded-For");
      const limit = 3; // Limiting requests to 3 login attempts per minute per IP
      const windowMs = 60 * 1000; // 1 minute
      const suspensionMs = 5 * 60 * 1000; // 5 minutes
      // Function to limit requests to 3 login attempts per IP
      const now = Date.now();
      if (!rateLimitMap.has(ip)) {
        rateLimitMap.set(ip, { count: 0, lastReset: now, suspendedUntil: null });
      }
      const ipData = rateLimitMap.get(ip);
      // Check if the IP is currently suspended
      if (ipData.suspendedUntil && now < ipData.suspendedUntil) {
        return NextResponse.json(
          { error: "Too Many Requests. Try again after 5 minutes" },
          { status: 429 }
        );
      }
      if (now - ipData.lastReset > windowMs) {
        ipData.count = 0;
        ipData.lastReset = now;
      }
      if (ipData.count >= limit) {
        ipData.suspendedUntil = now + suspensionMs;
        return NextResponse.json(
          { error: "Too Many Requests. Try again after 5 minutes" },
          { status: 429 }
        );
      }
      ipData.count += 1;

    I know this is alot of if requests, I am guilty but you can also streamline this code to make it more efficient. In the register route, you can use the same functionality in the login route to return the http code. 

    Now we need to create a helper function that you can call to get the user. Remember this function cannot return the user in the frontend, it will only work in the server.

    // file path /lib/decodeToken
    import { NextRequest, NextResponse } from "next/server";
    import jwt from "jsonwebtoken";
    export const getDataFromToken = (request: NextRequest) => {
      try {
        const token = request.cookies.get("token")?.value || "";
        const decodedToken: any = jwt.verify(token, process.env.JWT_SECRET);
        return decodedToken;
      } catch (error: any) {
        throw new Error(error.message);
      }
    };
    

    This function enables you to decode the token but does not account for scenarios where the token exists but is expired and you might need to further modify it to handle such scenarios. 

    To get user data, create a route (/api/me) where you can fetch the user data each time there is a logged in user. This route will receive the request cookies and use decodeToken function to return user data:

    import { getDataFromToken } from "@/lib/decodeToken";
    import { NextRequest, NextResponse } from "next/server";
    export async function GET(req: NextRequest, res: NextResponse) {
      try {
        const userData = await getDataFromToken(req);
        let responseData = userData;
        if (!userData || !userData) {
          return NextResponse.json(
            { error: "Unauthorized request" },
            { status: 401 }
          );
        } 
          return NextResponse.json(userData, { status: 200 });
      } catch (error) {
        return new NextResponse(null, { status: 400 });
      } 
    }
    

    With the current setting, you can fetch user data and save it in context each time the user logs in. This ensures that components that need user data have access to the data.

    Creating Logout Route

    Creating a logout route is as easy as just deleting the token. Create a new route in /api/auth/logout and add this code:

    import { NextResponse, NextRequest } from "next/server";
    export async function GET(res: NextRequest) {
      try {
        const response = NextResponse.json({
          message: "Logout Successful",
          success: true,
        });
        response.cookies.delete("token");
        return response;
      } catch (error) {
        return NextResponse.json({ error: "Something went wrong" }, { status: 500 })
    }

    Conclusion

    We’ve covered the use of JWTs for efficient user authentication, storing user data in cookies for quick access, and the importance of custom middleware for route protection. 

    Remember, the journey to secure and efficient authentication is ongoing and ever-evolving. The strategies and tools we’ve discussed are at the forefront of current best practices, providing a strong foundation for your Next.js applications.

    However, the world of web security is dynamic, so staying updated with the latest trends and updates is crucial. Adding the rate limiter is also necessary to protect the login route from brute attack.

     

    33Blog views

    1.1K

    share this blog
    user profile avatar

    the don

    Published on • 🕑2 min


    My Opinion on Whether AI Will Take Our Jobs as Developers

    There have been significant concerns among software developers on what the future of software development holds.

    The rise of various AI programs such as ChatGPT, Google Bard, Google Duet, Google Gemini, Amazon CodeWhisper and GitHub Copilot has revolutionized how developers write code. These programs have increased concerns on whether AI will replace programmers in the future.  

    The field of programming is undergoing a significant transformation with the rise of AI and no-code websites. Undoubtedly, as these technologies continue to evolve, they will revolutionize the game.

    I cannot help but think about the looming shadow of AI and it's potential impact on our careers. Will robots steal our jobs, leaving us jobless and obsolete? Or will they become our collaborators, empowering us to reach new heights of productivity?

    I believe that the future lies somewhere in between AI and Programmers. Current AI programs are not fully developed to take developers jobs. Sure, they can handle repetitive tasks and generate basic code, but true creativity, problem-solving, and critical thinking remain firmly in a human aspect.

    These models are largely trained with pre-existing data and thus their knowledge is restricted to what we already know. For such reasons, AI Programs cannot create new knowledge or invent something new. 

    However, they can help empower developers code better and more efficiently. Existing AI programs such as GitHub Copilot are highly effective in helping debug programs, complete code and enhance code optimization.

    AI has the potential to automate repetitive and mundane programming tasks, enabling programmers to focus on more creative and complex problem-solving. Thus, the only person that can steal our jobs is a programmer who has mastered the art of using AI programs to enhance their productivity.

    By automating tedious tasks and generating code snippets, AI makes developers work faster and more effectively. This means that developers can complete their projects faster with aid of AI. Such increased efficiency will with no doubt increase competition for the available jobs.

    Super Programmers who will be powered by AI will thus be better positioned to compete for the jobs. Thus, as AI takes over routine tasks, programmers will need to adapt and embrace new roles that involve overseeing AI systems, designing complex algorithms, and applying their expertise to tackle challenging problems.

    Conclusion

    The future of programming might look scary but we all possess the tools required to navigate this intricate future. With aid of AI, developers can maximize their efficiency and earnings and help design AI systems.

    We need to embrace this change, learning to leverage AI's power while honing our unique human strengths. Only then can we thrive in this new era of collaboration between man and machine.

    What are your thoughts on AI and its impact on the developer community? Share your opinions in the comments below!

    411Blog views

    888

    share this blog
    user profile avatar

    tech girl

    Published on • 🕑4 min


    A Better Way to Validate HTML Forms Without Usestate

    Form validation is a crucial aspect of web development, ensuring that users input data correctly before submitting it. Traditionally, developers often manage validation by storing error states in JavaScript and then displaying those errors to the user. While this method works, it can be cumbersome, especially as the complexity of forms grows

    If you are a react dev or use other javascript frameworks like me, you often set a custom error state to track whether a field has an error and display the error message to the user. Something like this:

    export default function Form() {
      const [error, setError] = useState(null);
      const [email, setEmail] = useState("");
      const emailRegex =  /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/;
      async function handleSubmit(e) {
        e.preventDefault();
        setError("");
        try {
          // check if the email matches the regex
          if (!emailRegex.test(email)) {
            setError("Please enter a valid email address");
          } else {
            // do something with the email
          }
        } catch (error) {}
      }
      return (
        <form onSubmit={handleSubmit}>
          <div className="px-6">
            <div className="space-y-2 py-2">
              <label className="font-bold " htmlFor="email">
                Enter Your Email
              </label>
              <input
                className="h-10 w-full p-2 border"
                id="email"
                name="email"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                placeholder="you@example.com"
                disabled={loading}
                required
                type="email"
              />
            </div>
            <div className="h-5 min-h-5 max-h-5">
              {error ? (
                <p className="text-orange-600 text-sm  ">
                  <span>{error}</span>
                </p>
              ) : null}
            </div>
            <button
              className="px-4 bg-blue-500 text-white rounded-md "
              type="submit"
              title="continue">
              Continue
            </button>
          </div>
        </form>
      );
    }
    

    The problem with this implementation is that we are unnecessarily using useState to store the error and then render the error in a div. When the div appears, there is a slight layout shift. Furthermore, if you are used to this design, you might find it hard to validate forms when using JavaScript with no frameworks.

    One of the major reasons why I found myself using this design is that the native email validation provided by HTML is not enough. For example, setting the input type='email' will indicate that emails ending with numbers are valid as long as they end with something. Thus, something@some.some285 would be a valid email input, although we both know it is not. 

    Furthermore, pattern attributes cannot be passed to all HTML inputs, which adds another complexity. I have also experienced a challenge where the pattern attribute does not work on email inputs, although the solution to this is to escape the '/' in the regex pattern.

    <form>
      <input type="email" placeholder="enter your email" 
         pattern="^[A-Za-z0- 9._+\-']+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}$" 
         required>
      <button>submit</button>
    </form>

    A Better Solution: Using checkValidity and setCustomValidity

    Instead of manually tracking errors, you can leverage the browser’s built-in validation using checkValidity and setCustomValidity. Here’s how it works:

    • checkValidity: This method checks if a form element meets all its validation constraints. It returns true if the element is valid and false if it isn't.

    • setCustomValidity: This method allows you to set a custom error message that will be displayed when the form is invalid. If you pass an empty string, it clears the custom error, making the field valid again.

    Here is an example of how you can use customValidity to set your custom error messages:

    <body>
        <form style="padding: 5px">
          <label for="email">Email:</label>
          <input
            type="email"
            id="email"
            name="email"
            required
            style="border: 1px solid black" />
          <br />
          <button
            type="submit"
            style="
              background-color: aqua;
              border-radius: 8px;
              padding: 2px 5px;
              margin-top: 5px;
            ">
            Submit
          </button>
        </form>
        <script>
          const emailInput = document.getElementById("email");
          const emailRegex = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/;
          emailInput.addEventListener("input", () => {
            if (emailInput.value === "") {
              emailInput.setCustomValidity("Email is required");
            } else if (!emailRegex.test(emailInput.value)) {
              emailInput.setCustomValidity("Please enter a valid email address");
            } else {
              emailInput.setCustomValidity(""); // Clears any custom errors
            }
            emailInput.reportValidity(); // Optionally display the error message immediately
          });
        </script>
      </body>
    

    Benefits of This Approach

    1. Simplified Code: By relying on the browser’s validation mechanisms, you avoid the need to manually track and manage error states. This leads to cleaner and more maintainable code.

    2. Better User Experience: Custom error messages can be displayed directly in the form without the need for additional UI elements. This makes the validation process feel more integrated and user-friendly.

    3. Consistency: Since the browser handles validation, you get consistent behavior across different form elements and input types. This can also allow you to set validation into other fields such as textarea where patterns are not natively supported.

    4. Accessibility: Built-in validation is generally more accessible, as it works with screen readers and other assistive technologies out of the box.

    5. Using State: We can eliminate the need to use useState to track user input and thus make our forms server components with working validation.

    You can also be more aggressive and choose to harass your users and make it fun for you of course.

    function validate(inputID) {
      const input = document.getElementById(inputID);
      const validityState = input.validity;
      if (validityState.valueMissing) {
        input.setCustomValidity("You gotta fill this out, yo!");
      } else if (validityState.rangeUnderflow) {
        input.setCustomValidity("We need a higher number!");
      } else if (validityState.rangeOverflow) {
        input.setCustomValidity("Thats too high!");
      } else {
        input.setCustomValidity("");
      }
      input.reportValidity();
    }
    

    Conclusion

    Form validation is an essential part of web development, but it doesn't have to be complicated. By using checkValidity and setCustomValidity, you can leverage the power of HTML5’s built-in validation to simplify your code and improve the user experience. This approach eliminates the need to manually manage error states, making your forms easier to maintain and more reliable.

    Next time you’re working on a form, consider using these methods to streamline your validation process and let the browser do the heavy lifting for you.

    00Blog views

    371

    share this blog
    user profile avatar

    the don

    Published on • 🕑7 min


    Top 5 Best CSS Frameworks for Developers In 2024

    Writing semantic CSS is often hated by developers as it can lead to a lot of bugs and zombie code that unnecessarily bloats the code base. Maintaining a large website with custom CSS is also overwhelming. Luckily, there are CSS frameworks that also come with pre-styled components and thus make web dev faster.

    CSS frameworks are pre-prepared libraries that are meant to be used to speed up the process of building websites or web applications. CSS frameworks are used to create familiar and consistent user interfaces, simplify responsive design, and enhance collaboration among development teams.

    CSS frameworks come in three different categories: components-based, utility-first, and css-in-js frameworks. Components-based frameworks offer a set of pre-built UI components that developers can plug into their applications to assemble interfaces quickly. The goal is to provide a modular and reusable design system that can help you create consistent and visually appealing web apps without starting from scratch every time.

    Utility-first libraries focus on functionality and thus offer CSS classes that can be used in the application to style components. Unline components-based frameworks, these libraries do not offer any component, but classes can be reused.

    Lastly, the css-in-js frameworks utilize the dynamic nature of JavaScript to provide a way of writing interactive CSS styles that are performant and based on user data and interactions.

    5 Best CSS Frameworks to Use

    1. Bootstrap

    Bootstrap is a popular component-based framework originally developed by Twitter(now X) and open-sourced in 2011. Bootstrap is one of the most widely used CSS frameworks, with a focus on responsive, mobile-first web design.

    Bootstrap offers a robust collection of CSS and JavaScript components, such as its grid system and responsive UI components like buttons, navigation menus, and forms, that streamline the process of building clean and consistent web layouts.

    It also has a large community making it easy to find documentation and help. However, Bootstrap can lead to websites that look similar to each other since it is so widely used and its large size can lead to slow loading time. Another consideration is that Bootstrap's default styles may require customization to fit with the design aesthetic of a particular project.

    bootstrap

    How to Use Bootstrap

    To get started, you can add the bootstrap CDN in the header of your HTML, or install the package if you are using single-page applications such as React.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link
          href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
          rel="stylesheet"
          integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
          crossorigin="anonymous" />
        <title>Bootstrap tutorial</title>
        <script
          src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
          integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
          crossorigin="anonymous"></script>
      </head>
      <body>
        <ul
          class="nav nav-pills nav-fill gap-2 p-1 small bg-primary rounded-5 shadow-sm"
          id="pillNav2"
          role="tablist"
          style="
            --bs-nav-link-color: var(--bs-white);
            --bs-nav-pills-link-active-color: var(--bs-primary);
            --bs-nav-pills-link-active-bg: var(--bs-white);
          ">
          <li class="nav-item" role="presentation">
            <button
              class="nav-link active rounded-5"
              id="home-tab2"
              data-bs-toggle="tab"
              type="button"
              role="tab"
              aria-selected="true">
              Home
            </button>
          </li>
          <li class="nav-item" role="presentation">
            <button
              class="nav-link rounded-5"
              id="profile-tab2"
              data-bs-toggle="tab"
              type="button"
              role="tab"
              aria-selected="false">
              Profile
            </button>
          </li>
          <li class="nav-item" role="presentation">
            <button
              class="nav-link rounded-5"
              id="contact-tab2"
              data-bs-toggle="tab"
              type="button"
              role="tab"
              aria-selected="false">
              Contact
            </button>
          </li>
        </ul>
      </body>
    </html>
    

    You can also install the bootstrap npm package or gem and import only the needed code by running npm install bootstrap @latest or gem install bootstrap -v 5.3.3. This helps minimize the code and thus increase loading time.

    //src/index.js
    import 'bootstrap/dist/css/bootstrap.min.css';
    import React from 'react';
    function App() {
      return (
        <div className="container">
          <h1>Hello, Bootstrap in React!</h1>
          <button className="btn btn-primary">Click Me</button>
        </div>
      );
    }
    export default App;

    2. Tailwind CSS

    Tailwind CSS is by far my best CSS framework and could be at the top of the list, but then I would be biased. Tailwind CSS is a popular utility-first CSS framework that provides a set of pre-defined classes that can be used to style HTML elements.

    Unlike Bootstrap, Tailwind is not opinionated and thus gives developers a lot of flexibility. Tailwind CSS is highly customizable and allows you to configure and modify various aspects of the framework to suit your specific needs. It also scales well as unused classes are purged during build time.

    However, Tailwind CSS can also cause your code to look like blasphemy. Since Tailwind CSS relies on pre-defined classes, it can result in more HTML markup than is necessary, which may make the HTML code more complex and harder to maintain.

    Furthermore, without careful consideration, it's easy to overuse Tailwind CSS classes, resulting in bloated CSS and HTML files, which can negatively impact website performance.

    tailwind css

    How to Use Tailwind CSS

    You can use Tailwind CSS through a CDN by adding the CDN link in the head of your document or by installing it using npm i tailwindcss and npx tailwindcss init. Tailwind also offers components but they are in paid plans, although other popular libraries such as daisy UI , FlowBite, Prelineand Shad CN provide free Tailwind-styled components.

    Here is a sample code using the CDN link:

    <!doctype html>
    <html>
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <script src="https://cdn.tailwindcss.com"></script>
    </head>
    <body>
      <h1 class="text-3xl font-bold underline">
        Hello world!
      </h1>
    </body>
    </html>

    3. Material UI

    Material UI is a component-based library for building React ⚛️Applications built and maintained by Google. Material UI offers a modern and visually appealing design system. It features a suite of customization options that make it easy for developers to implement custom design systems on top of the library, making it a popular choice for creating consistent UIs in React applications.

    However, Material UI suffers the same fate as Bootstrap in that it is opinionated and websites styled with Material UI tend to look the same. Using pre-styled components can limit your design choices, and Material UI can also increase loading time.

    material-ui

    How to Use Material UI

    To use Material UI, you need to install the npm package for one of the core UI libraries, with a choice between material UI, Joy UI, Base UI, and MUI system. The package can be installed by running the npm command:

    npm install @mui/material @emotion/react @emotion/styled

    You can then import and use components that you need and let the library worry about styling them.

    import Button from "@mui/material/Button";
    export default function Button() {
      return (
          <Button variant="contained">Hello World</Button>
      );
    }
    

    4. Foundation

    Foundation is a css-in-js library that brags about being "the most advanced responsive front-end framework in the world". It includes a wide range of pre-designed components and a responsive grid system. It also includes JavaScript plugins for added functionality.

    It includes common UI components like Bootstrap but is more utility-focused and gives developers more options for customizing components. With almost too many features, it can be considerably more complex and harder to fully understand how everything works compared to other frameworks.

    The framework is less popular and its documentation is less comprehensive compared to other frameworks. Furthermore, Foundation has a smaller user community compared to Bootstrap, so finding support and resources can be more challenging. Some of its features can be less intuitive to use than Bootstrap's.

    foundation

    How to Use Foundation UI

    You can install Foundation in your project with a package manager.

    npm install foundation-sites

    Now you can use its styles and components in your application. Note that you do not import anything but rather utilize its pre-styled classes. 

    <div class="card" style="width: 300px">
      <div class="card-divider">This is a header</div>
      <img src="assets/img/generic/rectangle-1.jpg" />
      <div class="card-section">
        <h4>This is a card.</h4>
        <p>It has an easy to override visual style.</p>
      </div>
    </div>

    Since you will probably never use this library, here is a Codepen of a sample of how the library-styled components look like:

    5. Mantine UI

    I am not sure whether this library makes the list since it is fairly unpopular. Mantine UI is a new CSS framework that includes more than 100 customizable components and 50 hooks to cover you in any situation. The library has over 360,295 weekly downloads on npm.

    Unlike other libraries, Mantine comes with everything in one package, including state management utils, tables with pagination, forms with verification, a rich text editor, spotlight, and DOM utils. Mantine also allows you to install only the library that you are using, with an example of @mantine/core, @mantine/hooks, @mantine/utils, @mantine/styles, @mantine/prism, and @mantine/datatable among others.

    However, the library is fairly new and thus lacks community support although it is expected to reach a wider audience. If you are working on side projects or your personal projects or if you want to give a life to your idea quickly then you can try this.

    mantine-ui

    How to Use Mantine UI

    You can use Mantine UI by installing parts of the library that you need using your package manager.

    npm install @mantine/core @mantine/hooks @mantine/form

    The library supports various React Frameworks such as vite, gatsby, NextJs, and Remix, and provides templates that are ready to use. After installing the framework, you need to import the CSS file into your root file.

    //app.jsx
    // core styles are required for all packages
    import '@mantine/core/styles.css';
    
    // other css files are required only if
    // you are using components from the corresponding package
    // import '@mantine/dates/styles.css';
    // import '@mantine/dropzone/styles.css';
    // import '@mantine/code-highlight/styles.css';
    

    After this, you need to wrap your page with a Mantime provider to get access to all Mantine functionalities such as themes, although this is not necessary. Alternatively, you can directly import the components that you need and use them in your app.

    import { createTheme, MantineProvider } from '@mantine/core';
    const theme = createTheme({
      /** Put your mantine theme override here */
    });
    function Demo() {
      return (
        <MantineProvider theme={theme}>
          {/* Your app here */}
        </MantineProvider>
      );
    }
    //Your App component
    import { PinInput } from '@mantine/core';
    function OneTimeCodeInput() {
      return <PinInput oneTimeCode />;
    }

    Conclusion

    In this blog, we have explored some of the 5 most popular and use CSS libraries/frameworks in 2024. These Libraries can be time-saving as they allow you to quickly bootstrap applications. When choosing the right framework, you need to consider customizability, learning curve, community support, and how the library fits into your project.

    Don't choose a framework because it makes your work easier, rather because it fits well with your project!

    00Blog views

    396

    share this blog
    user profile avatar

    the don

    Published on • 🕑4 min


    Tips and Tricks for Mastering Typography

    As a developer, you either accept that you suck at typography, or choose to live your life watching a random guy explain how to choose typography on YouTube. I have seen numerous videos and spent several hours watching tutorials on how to choose fonts.

    Various youtubers have made videos explaining the self-proclaimed rules of choosing typefaces. However, watching these videos will not help you choose the best fonts, rather leave you more confused and out of options. The choice of the font really depends on the style of the website, the target audience and the intended message.

    However, it is increasingly difficult to find good-looking free fonts. Sans based fonts are most go to fonts for the modern websites, although some designers think the system fonts are a better alternative due to their stability.

    typography-choices

    Typography is everywhere we look. It's in the books we read, on the websites we visit, even in everyday life—on street signs, bumper stickers, and product packaging. But what exactly is typography? Simply put, typography is the style or appearance of text. It can also refer to the art of working with text—something you probably do all the time if you create documents or other projects for work, school, or yourself.

    Watch the video below to learn more about typography.

    Common types of fonts

    Typography can be an intimidating subject, but it doesn't have to be. You only need to know a little to make a big difference in the stuff you do every day. So let's get started. First, some common types of fonts and what you need to know about them.

    Serif fonts

    Serif fonts have little strokes called serifs attached to the main part of the letter.

    example of a serif font

    Because of their classic look, they're a good choice for more traditional projects. They're also common in print publications, like magazines and newspapers.

    serif fonts in a magazine

    Sans serif fonts

    Sans serif fonts don't have that extra stroke—hence the name, which is French for without serif.

    sans serif fonts

    This style is considered more clean and modern than serif fonts. Also, it tends to be easier to read on computer screens, including smartphones and tablets.

    sans serif fonts on a website

    Display fonts

    Display fonts come in many different styles, like script, blackletter, all caps, and just plain fancy.

    display fonts

    Because of their decorative nature, display fonts are best for small amounts of text, like titles and headers and more graphic-heavy designs.

    using display fonts

    Choosing a font

    In a way, fonts have their own language. They all have something to say beyond the words on the page. They can come across as casual or neutral, exotic or graphic. That's why it's important to think about your message, then choose a font that fits.

    choosing a font style

    Fonts to avoid

    Some fonts come with extra baggage, including Comic Sans, Curlz, and Papyrus. There's nothing particularly wrong with these fonts—they just have a certain reputation for being outdated and overused.

    commonly overused fonts

    If you find yourself tempted by them, think twice and consider using something else. There are many fonts with a similar look and feel that are less likely to detract from your message.

    Combining fonts

    When deciding which fonts to use, less is more. It's best to limit yourself to one or two per project. If you need more contrast, try repeating one of your fonts in a different size, weight, or style. This trick is practically foolproof for creating interesting combinations that work.

    combining different fonts

    You've probably heard that opposites attract. The same is true for fonts. Don't be afraid to combine font styles that are different but complementary, like sans serif with serif, short with tall, or decorative with simple. This can be challenging at first, but don't despair. Look to other designs for inspiration, and soon you'll get the hang of it.

    common font combinations

    Other important terms

    Maybe you've heard terms like kerningleadingtracking, and hierarchy. For those with more experience, these concepts are essential for creating professional-looking designs. As a beginner, you don't need to know everything about these terms—just enough to inform your work and help you talk about design with more confidence.

    talking about design to a crowd

    Hierarchy

    Hierarchy is used to guide the reader's eye to whatever is most important. In other words, it shows them where to begin and where to go next using different levels of emphasis.

    text hierarchy

    Establishing hierarchy is simple: Just decide which elements you want the reader to notice first, then make them stand out. High-level items are usually larger, bolder, or different in some way. Remember to keep it simple and stick to just a few complementary styles.

    using hierarchy on a business card

    Leading

    Leading (rhymes with wedding) is the space between lines of text, also known as line spacing.

    leading, or line spacing

    If you're not sure how much line spacing to use, don't fret—the default is usually fine. The goal is to make your text as comfortable to read as possible. Too much or too little spacing, as in the example below, can make things unpleasant for the reader.

    too much or little line spacing makes the text hard to read

    Tracking

    Tracking is the overall space between characters, sometimes called character spacing. Most programs let you condense or expand this depending on your needs.

    text tracking, or character spacing

    In some designs, you might adjust your tracking to create a certain artistic effect. It can also help you fix fonts that are poorly spaced to begin with.

    adjusting tracking

    Kerning

    Kerning is the space between specific characters. Unlike tracking, it varies over the course of the word because each letter fits together differently.

    example of kerning

    Some fonts have what we call bad kerning, making certain letters look improperly spaced. If a font you're using has bad kerning, it's best to cut your losses and choose something else.

    example of bad font kerning

    Putting it all together

    Well-crafted text can mean the difference between something ordinary and something extraordinary—even if you're just getting started with design. All it takes is an interest in typography and you'll start to notice more, see more, and be able to do more in your own work.

    example of different projects

    Ultimately, your ideal font choice might be like a barber. You need to die with it. Here is my current font list:

    Futura, Century,  Garamond, Montserrat, Quattrocento, Noto Sans, Poppins, Satoshi, Inter, Public Sans and Barlow

    Let me know what your current font list choice looks like, maybe I could be inspired!

    38Blog views

    1.9K

    share this blog
    user profile avatar

    Tech Wizard

    Published on • 🕑3 min


    Authentication in NextJS Part 2: UseContext

    This blog is a continuation of the previous blog on handling auth in next js where we discussed the use of JWT tokens in server actions to fetch user data. In the blog, we talked about creating an api roiute (/api/me) where we can use context to fetch user data. This blog discusses how to do that.

    What is Context-API?

    Context-API is a way to make a global store in an application where we can store data and variables. The variables and data which are in the context can be accessed from any page or component without manually passing the props from the parent component to the child component.

    Why use Context-API?

    Although there are many ways to achieve this functionality in our application, context API has its own place and advantages. These are some of the benefits of using it over others.

    • If we do not use context API or any other library and simply pass props from parents to the child and then from this child to another child, it will become a very hectic and bad way to write code as the number of children and props increases.
    • Context API is very light and fast in comparison to other state management libraries like redux and recoil as it is inbuilt in Next.js.

    Using the Context-API effectively

    As you know by now, NextJS leverages the power of server side rendering to make the page faster. Since every page is a server code by default, useContext is not supported in pages that have not specifically declared "use client" at the top. 

    There are three main steps in creating the global store using context API and making the user information available globally.

    Step 1: Creating the context

    Create a folder in the outmost directory of your app and name it providers. In this folder, add an index.js file, where we will create a user context that will be exported to pages that need to check whether the user exists.

    //index.js
    "use client";
    import { createContext, useContext, useEffect, useState } from "react";
    const UserContext = createContext({});
    export function UserContextProvider({ children }) {
      const [user, setUser] = useState(null);
      useEffect(() => {
        const fetchUser = async () => {
          try {
            const response = await fetch(`${baseUrl}/me`);
            const data = await response.json();
            setUser(data);
          } catch (error) {
            console.error("Failed to fetch user", error);
          }
        };
          fetchUser();
      }, []);
      return <UserContext.Provider value={user}>{children}</UserContext.Provider>;
    }
    // Make useUserContext Hook to easily use our context throughout the application
    export function useUserContext() {
      return useContext(UserContext);
    }
    

    Step 2: Wrapping our app in Context

    To ensure that each component can have access to the user object, we need to wrap our layout.ts file with the context provider. In the layout.js file, add the following code:

    import "../globals.css";
    import { UserContextProvider } from "@/providers";
    export const metadata = {
      title: "",
      description:  "",
    };
    export default function RootLayout({ children }) {
      return (
        <html lang="en">
          <body>
            <UserContextProvider>
                <main>
                  {children}
                </main>
            </UserContextProvider>
          </body>
        </html>
      );
    }
    


    Step 3: Using the Context

    The last step is ensuring that components that need access to context can have such access. Ensure that any component using context is a client component. For example, let add context to the navbar:

    // components/NavBar.js
    "use client";
    Import dynamic from 'next/dyanmic';
    import { useUserContext } from '../context/user';
    export const dynamic = "force-dynamic";
    export default function NavBar() {
     // Getting user object using useUserContext Hook
      const user  = useUserContext();
      return (
        <div className="container">
            <h1>NavBar</h1>
            <p>Logged in User: <strong>{user?.name}</strong></p>
            <p>User token: <strong>{user?.token}</strong></p>  
        </div>
      )
    }

    Conclusion:

    If we want an easy, fast, and lightweight store for our project, then context-API is the best choice. Remember to add additional checks on whether the user is present to prevent errors. For example, in my code i check if the user token exists but has expired so I can tell users their session has expired.

    12Blog views

    762

    share this blog
    user profile avatar

    the don

    Published on • 🕑3 min


    Top 10 Resources to Supercharge Your Web Development Journey

    Web development can be difficult, but with the right tools the journey could be a smooth ride. There are various resources available for developers, with the rise of AI making it even easier for web developers to bootstrap applications. Here are top 10 resources that you will wish you knew earlier.

    1. Next.js:

    Next.js is a React framework highly recommended by the React team for building React applications. Next.js is super fast as it enables static site generation( This thing does not have a single html page, wow). Next.js has several developer tools, such as server-side rendering, making routing and authentication seamless. It's great for SEO and performance and has many built-in features that make development easier. However, Next also comes with some challenges, such as errors that are not easy to read and pre-rendering, which fetches data after navigating to a page; thus, if you need to change something during the next navigation, this becomes challenging.

    2. Sanity.io:

    Sanity.io is a schematic database that empowers web development without building custom backends. It offers an intuitive content management system (CMS) and an API for quickly creating and managing content. Sanity.io allows developers to focus on front-end development while seamlessly integrating with their preferred backend data. This site is super helpful, especially if you are building a blog.

    3. Tailwind CSS:

    At first, tailwind css looks like blasphemy, with many bloated html classes that make your code difficult to read. However, tailwind s a utility-first CSS framework that makes it easy to style your web pages. It's great for beginners and experienced developers and is very flexible. Tailwind allows for code reusability through the @apply directive and also has a UI library (Tailwind UI) that can supercharge web development without writing any CSS.

    4. Material and Daisy UI:

    Material UI and Daisy UI are powerful UI component libraries that offer a rich selection of pre-designed and customizable components. Material UI adheres to the Material Design guidelines, while Daisy UI provides a lightweight and elegant component set. Both libraries save developers time by offering ready-to-use components for their web applications.

    5. Framer.io:

    Framer is similar to Figma but has an AI tool that generates a website design super-fast. Using a framer, you can generate your design inspiration within seconds. Framer also allows you to customize the generated site to your preference. Other similar tools include Wix.com and Durable.

    6. Webflow:

    The age of no-code websites is here, and webflow is the king in this arena. Webflow is a visual web design and development tool that bridges the gap between design and development. It allows developers to create responsive websites without writing code, providing a drag-and-drop interface, powerful styling options, and a content management system (CMS). Furthermore, Webflow also allows you to add javascript code for interactivity and host your website for free.

    7. Firebase and Supabase:

    Firebase is a google cloud platform that helps build and deploy websites. However, the most useful Firebase feature is hosting web APIs and allowing users to sign in using their Google accounts (This is similar to what is offered by Auth0 ). However, firebase also provides hosting, real-time database, authentication, and cloud functions. Firebase simplifies backend development and empowers developers to focus on creating exceptional front-end experiences. Supabase is a free alternative to firebase.

    8. Express.js:

    Express is a JavaScript library for backend development integrated with node.js. Express helps build the backend with javascript and makes it easier to deploy APIs. It simplifies building web applications and APIs by providing robust features and middleware. Express.js is highly extensible and widely used in the Node.js ecosystem, making it an excellent choice for web developers.

    9. Midjourney:

    First, mid-journey is only partially free and available in their discord channel. Midjourney is a popular AI tool enabling individuals to generate text images. Most developers use Midjourney to inspire their designs and create stunning visuals and 3D Models. If you do not know Photoshop, mid-journey got you covered. For free alternatives, check DALLE.E and Blue WIllow (available on discord)

    10. JQuery:

    JQuery can be less useful when using frameworks such as React. However, while building sites with vanilla javascript, JQuery makes selecting DOM elements, event handling, and animation easier. For example, to select an h1 tag using JQuery, we use a dollar sign $(h1).

    Other tools not mentioned in this list include vercel v0, which helps develop frontend designs and codes, AI tools such as Gemini and Bing, Google Fonts, Vercel and many more. Kindly share your favorite resources below.

    78Blog views

    2.0K

    share this blog