Construct Your Personal ChatGPT Clone with React and the OpenAI API — SitePoint







On this tutorial, we’ll stroll via find out how to construct a customized Chatbot software that can enable us to ask questions and obtain high-quality solutions. The bot will bear in mind earlier prompts, simulating context-aware dialog.

A GIF animation showing our finished bot in action

Chatbots have turn out to be indispensable instruments for companies and builders searching for to enhance buyer interactions and streamline consumer experiences in in the present day’s quickly evolving digital panorama.

OpenAI’s ChatGPT has reworked from a cutting-edge experiment right into a powerhouse in chatbot growth. Its meteoric rise to success is nothing in need of exceptional, fascinating customers worldwide.

The demo code of this undertaking is on the market on CodeSandbox. You’ll have to offer your individual OpenAI API key within the .env file to check it stay. To get one, create an account on the OpenAI, log in, navigate to the API keys and generate a brand new API key.

Desk of Contents

Planning Options and UI

Our software will likely be primarily based on React, and we’ll use OpenAI API to entry the information and use CSS modules for styling.

Using React will enable us to create a dynamic and responsive consumer interface, enhancing the general consumer expertise.

The OpenAI API will allow us to acquire entry to superior language processing capabilities, offering information for creating insightful interactions.

Moreover, CSS modules will enable us to keep up a modular design, facilitating environment friendly growth and customization of the app.

The options we’ll be implementing embrace:

  • A chosen enter space the place customers will be capable of craft prompts, inviting contextually related inquiries.
  • A Submit button that can enable customers to submit their prompts to the API, initiating the dialog course of.
  • Message gadgets that will likely be showcased as chat-style messages inside the dialog window, enhancing the interactive chat expertise.
  • Message gadgets to show ChatGPT replies that can present a conversational circulate.
  • A Historical past characteristic that can listing all the consumer’s current prompts. This can even enable customers to revisit earlier conversations.
  • A Clear button that can enable the removing of generated content material, providing a clear slate for brand new conversations.

The picture under reveals our component-based wireframe.

A wireframe of the app's interface

The entire software will likely be wrapped in the principle container, which is able to maintain all the parts collectively. It is going to be additional divided right into a two-column structure.

The primary column will embrace all the messages from the consumer and ChatGPT. On the backside of the column, there will likely be an enter space and a button for submitting the immediate.

The second column will maintain the historical past of all the current prompts. On the backside of the column, there will likely be a Clear button that can enable the consumer to wipe the generated content material.

Selecting a Colour Scheme

The applying design will prioritize the benefit of content material notion. This may enable us to offer a few vital advantages:

  • Customers will be capable of rapidly comprehend the offered info, resulting in a extra intuitive and user-friendly expertise.
  • It would additionally improve accessibility, guaranteeing that people of various backgrounds and talents will be capable of simply navigate and have interaction with the content material.

The picture under reveals our coloration scheme.

Our five-color scheme: black, dark gray, lime-green, peach and white

The background of the appliance will likely be black, whereas the messages, historical past gadgets, and enter type will likely be darkish grey.

The textual content on the messages and enter backgrounds will likely be white, offering a pleasant distinction and make textual content simple to learn.

To present the app some highlights, the column titles, Submit button, and response message avatars will use a shiny, lime-green tone.

To accent the Clear button, a gentle pink tone will likely be used. This can even assist customers keep away from clicking the button unintentionally.

Setting Up the React App

We’ll use create-react-app to create our software. Run npx create-react-app react-chatgpt to create a brand new React undertaking.

Look ahead to a minute for the setup to finish, after which change the working listing to the newly created folder by cd react-chatgpt and run npm begin to begin the developer server.

This could open up our undertaking in our default browser. If not, navigate to http://localhost:3000 to open it manually. We ought to be offered with the React welcome display screen, as pictured under.

React welcome screen

Including World Kinds

We’ll add international styling to determine a constant and unified visible look throughout all parts of the appliance.

Open index.css and embrace the next styling guidelines:

@import url("");

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: "Varela Spherical", sans-serif;

physique {
  background-color: #121212;

First, we import the Varela Spherical font and set the entire app to make use of it.

We additionally take away any pre-defined margins and paddings, in addition to set box-sizing to border-box so the app appears to be like the identical on completely different browsers.

Lastly, we set the background of the physique to a darkish tone, which permits us to spotlight the content material of the appliance.

We’ll want a few avatars to symbolize the authors of the messages from the consumer and OpenAI API. This fashion, they’ll be simpler to tell apart.

Create a brand new icons folder contained in the src listing and embrace the bot.png and consumer.png icons.

You may obtain samples from icons listing right here, or you should utilize customized ones from websites like FlatIcon or Icons8, so long as you retain the above file names.

Constructing the Parts

First, we’d like a well-organized file construction that matches the wireframe design.

We’ll use the terminal to create the required folder and element recordsdata. Every element may have its personal JavaScript file for performance and CSS file for styling.

Change the working listing within the src folder by working cd src after which run the next command:

mkdir parts && cd parts && contact Message.js Message.module.css Enter.js Enter.module.css Historical past.js Historical past.module.css Clear.js Clear.module.css

The command above will first create a /parts/ folder, then change the working listing to it, and create all the required recordsdata inside it.

The Message element

The Message element will show consumer prompts and API responses inside the dialog, facilitating the real-time trade of data between the consumer and the chatbot.

Open the Message.js file and embrace the next code:

import bot from "../icons/bot.png";
import consumer from "../icons/consumer.png";

import types from "./Message.module.css";

export default perform Message({ position, content material }) {
  return (
    <div className={types.wrapper}>
          src={position === "assistant" ? bot : consumer}
          alt="profile avatar"
        <p>{content material}</p>

First, we import the downloaded icons for avatars after which import the exterior CSS guidelines for styling.

After that, we create the wrapper for the Message element, which is able to include each icons and textual content content material.

We use the position prop within the conditional to show the suitable avatar because the picture src.

We additionally use the content material prop, which will likely be handed in because the textual content response from the OpenAI API and consumer enter immediate.

Now let’s fashion the element so it appears to be like like a chat message! Open the Message.module.css file and embrace the next guidelines:

.wrapper {
  show: grid;
  grid-template-columns: 60px auto;
  min-height: 60px;
  padding: 20px;
  margin-bottom: 20px;
  border-radius: 10px;
  background-color: #1b1b1d;

.avatar {
  width: 40px;
  peak: 40px;

We divide the structure into two columns, with the avatars proven within the fixed-width container on the proper and the textual content on the left.

Subsequent, we add some padding and margin to the underside of the message. We additionally fashion the message to have spherical borders and set the background to darkish grey.

Lastly, we set the avatar icon to a hard and fast width and peak.

The Enter element

The Enter element will likely be an interface aspect designed to seize consumer queries, serving because the means via which customers work together and have interaction with the chatbot.

Open the Enter.js file and embrace the next code:

import types from "./Enter.module.css";

export default perform Enter({ worth, onChange, onClick }) {
  return (
    <div className={types.wrapper}>
        className={types.textual content}
        placeholder="Your immediate right here..."
      <button className={types.btn} onClick={onClick}>

We first import the exterior stylesheet to fashion the element.

We return the element wrapper that features the enter subject for the consumer prompts and the button to submit it to the API.

We set the placeholder worth to be displayed when the enter type is empty, and create the worth prop to carry the entered immediate, in addition to the onChange prop that will likely be referred to as as soon as the enter worth modifications.

For the button, the onClick prop will likely be referred to as as soon as the consumer clicks on the button.

Now let’s fashion the element in order that the enter space appears to be like lovely and the consumer is inspired to offer prompts! Open the Enter.module.css file and embrace the next guidelines:

.wrapper {
  show: grid;
  grid-template-columns: auto 100px;
  peak: 60px;
  border-radius: 10px;
  background-color: #323236;

.textual content {
  border: none;
  define: none;
  background: none;
  padding: 20px;
  coloration: white;
  font-size: 16px;

.btn {
  border: none;
  border-radius: 0 10px 10px 0;
  font-size: 16px;
  font-weight: daring;
  background-color: rgb(218, 255, 170);

.btn:hover {
  cursor: pointer;
  background-color: rgb(200, 253, 130);

We set the wrapper to be divided into two columns, with a hard and fast width for the button and the remainder of the accessible width devoted to the enter space.

We additionally outline the particular peak of the element, set the rounded borders for it, and set the background to darkish grey.

For the enter space, we take away the default border, define, background and add some padding. We set the textual content coloration to white and set a selected font measurement.

The Historical past element

The Historical past element will show the sequence of previous consumer and chatbot interactions, offering customers with a contextual reference of their dialog.

Open the Historical past.js file and embrace the next code:

import types from "./Historical past.module.css";

export default perform Historical past({ query, onClick }) {
  return (
    <div className={types.wrapper} onClick={onClick}>
      <p>{query.substring(0, 15)}...</p>

We first import the exterior fashion guidelines for the element. Then we return the wrapper that can embrace the textual content.

The textual content worth will likely be handed in as a query prop from the consumer immediate, and solely the primary 15 characters of the textual content string will likely be displayed.

Customers will likely be allowed to click on on the historical past gadgets, and we’ll cross the onClick prop to manage the clicking habits.

Now let’s fashion the element to make sure it’s visually interesting and matches properly within the sidebar! Open the Historical past.module.css file and embrace the next guidelines:

.wrapper {
  padding: 20px;
  margin-bottom: 20px;
  border-radius: 10px;
  background-color: #1b1b1d;

.wrapper:hover {
  cursor: pointer;
  background-color: #323236;

We set some padding, add the margin to the underside, and set the rounded corners for the historical past gadgets. We additionally set the background coloration to darkish grey.

As soon as the consumer hovers over the merchandise, the cursor will change to a pointer and the background coloration will change to a lighter shade of grey.

The Clear element

The Clear element will likely be a UI aspect designed to reset or clear the continued dialog, offering customers with a fast approach to begin a brand new interplay with out navigating away from the present interface.

Open the Clear.js file and embrace the next code:

import types from "./Clear.module.css";

export default perform Clear({ onClick }) {
  return (
    <button className={types.wrapper} onClick={onClick}>

We first import the exterior stylesheet to fashion the element.

We return the button that can enable customers to clear the content material of the appliance. We’ll cross the onClick prop to attain the specified habits.

Now let’s fashion the element to make it stand out and scale back the probabilities of customers urgent it unintentionally! Open the Clear.module.css file and embrace the next guidelines:

.wrapper {
  width: 100%;
  peak: 60px;
  background-color: #ff9d84;
  border: none;
  border-radius: 10px;
  font-size: 16px;
  font-weight: daring;

.wrapper:hover {
  cursor: pointer;
  background-color: #ff886b;

We set the button to fill the accessible width of the column, set the particular peak, and set the background coloration to delicate pink.

We additionally take away the default border, set the rounded corners, set a selected font measurement, and make it daring.

On hover, the cursor will change to a pointer and the background coloration will change to a darker shade of pink.

Constructing the Consumer Interface

Within the earlier part, we constructed all the vital parts. Now let’s put them collectively and construct the consumer interface for the appliance.

We’ll configure their performance to create a useful and interactive chatbot interface with organized and reusable code.

Open the App.js file and embrace the next code:

import { useState } from "react";

import Message from "./parts/Message";
import Enter from "./parts/Enter";
import Historical past from "./parts/Historical past";
import Clear from "./parts/Clear";

import "./types.css";

export default perform App() {
  const [input, setInput] = useState("");
  const [messages, setMessages] = useState([]);
  const [history, setHistory] = useState([]);

  return (
    <div className="App">
      <div className="Column">
        <h3 className="Title">Chat Messages</h3>
        <div className="Content material">
          {, i) => {
            return <Message key={i} position={el.position} content material={el.content material} />;
          onChange={(e) => setInput(e.goal.worth)}
          onClick={enter ? handleSubmit : undefined}
      <div className="Column">
        <h3 className="Title">Historical past</h3>
        <div className="Content material">
          {historical, i) => {
            return (
              <Historical past
                onClick={() =>
                    { role: "user", content: history[i].query },
                    { position: "assistant", content material: historical past[i].reply },
        <Clear onClick={clear} />

First, we import the useState hook that we’ll use to trace the information state for the appliance. Then we import all of the parts we constructed and the exterior stylesheet for styling.

Then we create the enter state variable to retailer the consumer immediate enter, messages to retailer the dialog between the consumer and ChatGPT, and historical past to retailer the historical past of consumer prompts.

We additionally create the principle wrapper for the entire app that can maintain two columns.

Every column may have a title and content material wrapper that can embrace the dialog messages, enter space, and Submit button for the primary column and historical past gadgets and the Clear button for the second column.

The dialog messages will likely be generated by mapping via the messages state variable and the historical past gadgets — by mapping via the historical past state variable.

We set the enter onChange prop to replace the enter state variable every time consumer enters any worth within the enter type.

As soon as the consumer clicks the Ship button, the consumer immediate will likely be despatched to the OpenAI API to course of and obtain the reply.

For the historical past gadgets, we set the onClick prop in order that the messages state variable will get up to date to the particular immediate and reply.

Lastly, for the Clear button, we cross the onClick prop a perform that can clear each the message and historical past values, clearing the appliance information.

Creating the App Structure

On this part, we’ll organize the consumer interface parts to create an intuitive construction for efficient consumer interplay.

Open App.css and embrace the next styling guidelines:

.App {
  show: grid;
  grid-template-columns: auto 200px;
  hole: 20px;
  max-width: 1000px;
  margin: 0 auto;
  min-height: 100vh;
  padding: 20px;

.Column {
  coloration: white;

.Title {
  padding: 20px;
  margin-bottom: 20px;
  border-radius: 10px;
  coloration: black;
  background-color: rgb(218, 255, 170);

.Content material {
  peak: calc(100vh - 200px);
  overflow-y: scroll;
  margin-bottom: 20px;

::-webkit-scrollbar {
  show: none;

We break up the principle app wrapper into two columns, separated by a niche by utilizing CSS grid structure, and we set the left column for historical past gadgets to a hard and fast width.

Subsequent, we set the wrapper to by no means exceed a sure width, middle it on the display screen, make it use all the display screen viewport peak, and add some padding inside it.

For every column’s contents, we set the textual content coloration to white.

For the column titles, we set some padding, add the underside margin, and set the rounded corners. We additionally set the title aspect background coloration to lime-green and set the textual content coloration to black.

We additionally fashion the columns themselves by setting the rule that the content material shouldn’t exceed a sure peak and set the content material to be scrollable if it reaches exterior the peak. We additionally add a margin to the underside.

We additionally cover the scrollbars, in order that we don’t must fashion them to override the default values for every browser. This rule is non-obligatory and we might go away it out.

Getting the API Key from OpenAI

For those who haven’t already arrange your individual API key for the Sandbox within the introduction of this tutorial, make sure that to create an account on the OpenAI web site.

Subsequent, log in and navigate to the API keys and generate a brand new API key.

setting up an api key

Copy the important thing to the clipboard and open your undertaking.

Create a brand new .env file in your undertaking root and paste the worth for the next key like so:


Getting ready the Request Name to OpenAI API

By way of the OpenAI API, our chatbot will be capable of ship textual prompts to the OpenAI server, which is able to then course of the enter and generate human-like responses.

That is achieved by leveraging a strong language mannequin that’s been skilled on numerous textual content sources. By offering the mannequin with a dialog historical past and the present consumer immediate, our chatbot will obtain context-aware responses from the API.

On this part, we’ll put together the request and implement the decision to the API to obtain the response and set the information to the state variable we outlined earlier.

Open the App.js once more and add the next code:

export default perform App() {

  const handleSubmit = async () => {
    const immediate = {
      position: "consumer",
      content material: enter,

    setMessages([...messages, prompt]);

    await fetch("", {
      methodology: "POST",
      headers: {
        Authorization: `Bearer ${course of.env.REACT_APP_OPENAI_API_KEY}`,
        "Content material-Sort": "software/json",
      physique: JSON.stringify({
        mannequin: "gpt-3.5-turbo",
        messages: [...messages, prompt],
      .then((information) => information.json())
      .then((information) => {
        const res = information.decisions[0].message.content material;
        setMessages((messages) => [
            role: "assistant",
            content: res,
        setHistory((historical past) => [...history, { question: input, answer: res }]);

  const clear = () => {

  return <div className="App">

First, we create a separate handleSubmit perform, which will likely be executed as soon as the consumer has entered the immediate within the enter type and clicks the Submit button.

Inside handleSubmit, we first create the immediate variable that can maintain the position consumer and the immediate itself as an object. The position is vital as a result of, when storing our messages, we’ll must know which of them are consumer messages.

Then we replace the messages state variable with the consumer immediate.

Subsequent, we make an precise fetch name to the endpoint to entry the information from the OpenAI API.

We specify that it’s a POST request, and set the headers with the authorization token and the content material sort. For the physique parameters, we specify which API mannequin to make use of, and we cross the messages variable because the content material from the consumer.

As soon as the response is acquired, we retailer it within the res variable. We add the article consisting of the position assistant and the response itself to the message state variable.

We additionally replace the historical past state variable with the article, with the query and corresponding reply because the keys.

After the response is acquired and state variables are up to date, we clear the enter state variable to organize the enter type for the following consumer immediate.

Lastly, we create a easy clear perform to clear the messages and historical past state variables, permitting the consumer to clear the information of the appliance.

Testing the Utility

At this level, we should always have created a totally useful chat software! The very last thing left to do is to check it.

First, let’s attempt to ask ChatGPT a single query.

A question asked via our new app

The animation above reveals a query being submitted and a solution being acquired.

Now let’s attempt to create a dialog.

Submitting multiple questions

As proven within the animation above, the chatbot remembers the context from the earlier messages, so we will communicate with it whereas being absolutely context-aware.

Now let’s see what occurs as soon as we click on on the Historical past button.

Clicking on the History button

Discover how the chat switches to the respective consumer immediate and reply. This may very well be helpful if we need to resume the dialog from a selected level.

Lastly, let’s click on on the Clear button.

Clicking on the Clear button

As anticipated, the contents of the app are cleared. It is a helpful choice when there’s loads of content material and the consumer desires to begin recent.


On this tutorial, we’ve realized find out how to create an easy-to-use consumer interface, find out how to construction our code by way of parts, find out how to work with states, find out how to make API calls, and find out how to course of the acquired information.

With the mixture of superior pure language processing capabilities of the OpenIAI API and the flexibleness of React, you’ll now be capable of create refined chatbot purposes that you may customise additional to your liking.

Discover that this tutorial shops the API key on the frontend, which could not be safe for manufacturing. If you wish to deploy the undertaking, it will be advisable to create an Specific server and use the API key there.

Additionally, if you’d like the historical past prompts to be accessible after the following preliminary launch, you may retailer after which learn them from native storage, and even join a database to your app and retailer and skim information from there.


Supply hyperlink

Share this


Google Presents 3 Suggestions For Checking Technical web optimization Points

Google printed a video providing three ideas for utilizing search console to establish technical points that may be inflicting indexing or rating issues. Three...

A easy snapshot reveals how computational pictures can shock and alarm us

Whereas Tessa Coates was making an attempt on wedding ceremony clothes final month, she posted a seemingly easy snapshot of herself on Instagram...

Recent articles

More like this


Please enter your comment!
Please enter your name here