Let's build Advice Generator App using React.js & Tailwind CSS.

In this tutorial, I will show you how you can build an Advice Generator App, It's one of the Frontend Mentor challenge projects .

Featured Image for Blog Post
Featured Image for Blog Post

Hello everyone,  I hope you all are doing well.  I am back with another exciting web dev project, which will help to learn some new web dev skills as a Front-end developer.

In this tutorial, I will show you how you can build an Advice Generator App, It's one of the  Frontend Mentor challenge projects and our goal is to make it look like the design given by the Frontend Mentor.

Here is the link to the FrontendMentor challenge that we will build.

So without any further talk, Let's start building it 🚀.

Step-1 Initializing the Project


Create a new next-js app with Tailwind CSS bootstrapped in it.

You can use this one-line command to create a new nextjs app with TypeScript and Tailwind CSS.

npx create-next-app -e with-tailwindcss my-project-name

You can name your project whatever you want, I will name it an Advice Generator App.

💡
We are using TypeScript in this Project, so we have to explicitly define all the props, constants & function data types.

Now after creating the project open it in Vs Code or any IDE that you prefer.

Find the index.tsx file inside pages directory. and delete everything and paste the given code below.

import type { NextPage } from 'next'
import Head from 'next/head'

const API="https://api.adviceslip.com/advice";

const Home: NextPage = () => {

return (
    <div className="flex min-h-screen flex-col items-center bg-[#1e1f29]">
      <Head>
        <title>Advice Generator App</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>


)}

export default Home;

In this project we are using Manrope font, so for that, we need to import this font from google fonts.

And for the API part, we are going to use Advice Slip API, which is a free API.

As you can see in the above code we have added a constant name API with the value of the API link

After that visit the globals.css file inside the styles folder and import a google font link (Manrope Font) at the top of the file inside it.

@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@600;700&display=swap');


@tailwind base;
@tailwind components;
@tailwind utilities;

So, now to use the font inside our app, we need to add it as a  custom font inside the tailwindcss.config.js file.

module.exports = {
  content: [
    './pages/**/*.{js,ts,jsx,tsx}',
    './components/**/*.{js,ts,jsx,tsx}',
  ],
  theme: {
    extend: {
      fontFamily:{
        manrope:["Manrope"],
      }
    },
  },
  plugins: [],
}

Step-2  Creating the Components

If you see the design given by the Frontend Mentor Challenge, there are only two components that you can make.

  1. AdviceCard.tsx
  2. CircularButton.tsx

So, now create the components folder inside your project folder and create two files with the names AdviceCard.tsx and CircularButton.tsx .

First, we will create the CircularButton component and then the AdviceCard component.

Inside CircularButton.tsx

import React from 'react'

interface Prop {
    handleAdvice():void,
}

export const CircularButton = ({handleAdvice} : Prop) => {
    return (
        <button onClick={handleAdvice} className=" bg-emerald-400 px-4 py-4 rounded-full text-green-900 hover:bg-green-200 hover:text-emerald-500  hover:shadow-xl hover:shadow-emerald-600 hover:scale-105 transition duration-300 ease-in">
            <svg xmlns="http://www.w3.org/2000/svg" className="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="3">
                <path strokeLinecap="round" strokeLinejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
            </svg>
        </button>
    )
}

In the above code as you can see we have added a prop handleAdvice, which is a function that will fetch new Advice data every time the button gets clicked.

Inside AdviceCard.tsx

import React from 'react'
import { CircularButton } from './CircularButton';

interface TextProps {
    id: number,
    adviceText: string,
    handleAdvice(): void,
}

export const AdviceCard = ({ adviceText, id , handleAdvice }: TextProps) => {
    return (
        <div className="relative w-[380px] md:w-[450px] md:h-[280px] bg-[#323a49] mt-20 px-8 pt-8 pb-16  rounded-xl flex flex-col justify-center items-center ">
            <p className="text-md md:text-lg uppercase font-medium  text-emerald-400 absolute top-8 mx-auto ">
                Advice
                {"  "}
                <span className=" font-bold  ml-2 ">
                    #{id}
                </span>
            </p>
            <div className="text-lg md:text-2xl font-manrope font-semibold text-gray-300 leading-8 text-center mt-4">
                "{adviceText}"
            </div>
            <hr className="w-[380px] border-t-1  border-gray-500 mt-8 absolute bottom-16 mx-auto" />
            <div className="absolute -bottom-[30px] mx-auto ">
            <CircularButton handleAdvice={handleAdvice} />
            </div>
        </div>
    )
}

In this component also we are passing three props as you can see.

The three props are:

  1. advice text
  2. id
  3. handleAdvice

Now we have made both the components,  it's time to code the logic for fetching the API and displaying the data that we will get from it.

Step-3 Fetching the API

So basically, the API returns a single object which contains two fields the id and the adviceText field.

Now, visit the index.js file inside the Pages folder and create two  constants with the useState hook inside the Home function, and set their default values as given below.

const [adviceText ,setAdviceText] =useState<string>("Never regret.
  If it's good, it's wonderful. If it's bad, it's experience.");
 
const [adviceId, setAdviceId] = useState<number>(143);

And also don't forget to import useState from the react library.

Now after that create an arrow function with the name fetchAdvice() and inside it fetch the API using the inbuilt fetch() function and store the result inside the constant name data.

After that set the two pieces of the state with the value coming from the API  and also create a function name handleAdvice() and call the fetchAdvice() inside it.

const [adviceText ,setAdviceText] =useState<string>("Never regret.
If it's good, it's wonderful. If it's bad, it's experience.");
  const [adviceId, setAdviceId] = useState<number>(143);

  const fetchAdvice = async () => {

      const res = await fetch(API);
      const data= await res.json();

      setAdviceId(data.slip.id);
      setAdviceText(data.slip.advice);
    };
     
  
  const handleAdvice= () => {
    fetchAdvice();
  };

Step-4  Import the components  and pass the Props

At last, import the two components from the components folder and add those inside the Home function.

After all that the index.tsx will look something like this:

Inside index.tsx

import type { NextPage  } from 'next'
import Head from 'next/head'
import { useState } from 'react';
import { AdviceCard } from '../components/AdviceCard'



const API="https://api.adviceslip.com/advice";

const Home: NextPage= () => {

  const [adviceText ,setAdviceText] =useState<string>("Never regret. If it's good, it's wonderful. If it's bad, it's experience.");
  const [adviceId, setAdviceId] = useState<number>(143);

  const fetchAdvice = async () => {

      const res = await fetch(API);
      const data= await res.json();

      setAdviceId(data.slip.id);
      setAdviceText(data.slip.advice);
    };
     
  
  const handleAdvice= () => {
    fetchAdvice();
  };

  return (
    <div className="flex min-h-screen bg-gray-800 flex-col items-center py-2">
      <Head>
        <title>Advice Generator App</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <h1 className="text-emerald-200 font-bold text-2xl md:text-4xl font-manrope mt-4 rounded-xl hover:rounded-xl hover:shadow-lg hover:shadow-emerald-600 hover:bg-emerald-500 hover:text-emerald-100 px-4 py-2 transition duration-300 ease-in ">
        Advice Generator App
        </h1>
      {/* <CircularButton /> */}
      <AdviceCard id={adviceId} adviceText={adviceText}  handleAdvice={handleAdvice} />
    </div>
  )
}

export default Home

Conclusion

Hope you were able to build this Advice Generator App.  Feel free to follow me on Twitter and share this if you like this project 😉.

I hope you like this project and enjoyed building it, I would appreciate ✌️ it if you could share this blog post.

If you think that this was helpful and then please do consider visiting my blog website nextjsdev.com and do follow me on Twitter and connect with me on LinkedIn.

If you were stuck somewhere and not able to find the solution you can check out my completed Github Repo here.

Thanks for your time to read this project, if you like this please share it on Twitter and Facebook or any other social media and tag me there.

I will see you in my next blog ✌️. Till then take care and keep building projects.

Some Useful Link:

Connect with me: