Build a Twitter clone with Strapi
Published: 2023-07-01 00:09:20

by [Marvel Ken](https://blog.openreplay.com/authors/marvel-ken)

<blockquote><em>Content Management Systems can serve lots of purposes in different applications, making it easier for users/developers to monitor and manage an application’s content. This article will demonstrate StrapiCMS in action by building a Twitter clone application.</em></blockquote>

Strapi is a headless CMS capable of being integrated into web and mobile applications. The content can easily be accessed using simple API requests. With Strapi, the developer can easily build flexible user interfaces and append content from the CMS. Strapi provides a dashboard where users can view all content pertaining to applications built with Strapi, making it easy for non-developers to manage content.

## Getting started

To get started, we will clone the starter repo which contains the front-end code of our application, built with the React.js framework. Our Twitter clone will have a newsfeed and tweet creation section. We will also be able to create and view tweets from our application. All content displayed in our application will be managed using the Strapi CMS. 

To clone the repository from [GitHub](https://github.com/marvelken/Twitter-Starter-Code), enter the following command in the CLI:
```bash
git clone https://github.com/marvelken/Twitter-Starter-Code.git
```
Our project directory has the `App.js` file and different components that make up our application. The application components are: `Feed.css`, `Feed.js`, `Post.css`, `Post.js`, `serviceWorker.js`, `Sidebar.css`, `Sidebar.js`, `SidebarOption.css`, `SidebarOption.js`, `TweetBox.css`, `TweetBox.js`, `Widget.css`, `Widget.js`.
The components will perform the following tasks:

- `Feed.js` will contain the structure for tweets to be displayed on the webpage and will also house the `TweetBox.js`  component, which contains the input fields for creating new tweets. Each individual tweet to be displayed in our application will be rendered using the `Post.js` component.
- `Sidebar.js` and `SidebarOption.js` are the components responsible for our Twitter sidebar on the website.
- The `Widget.js` component contains a few tweets received from Twitter and embedded into our application.

If you run the application with the `npm start` command and open the result in your browser, you will get a result similar to the below image:

![-](https://blog.openreplay.com/images/build-a-twitter-clone-with-strapi/images/89XuFnT.png)

## Setting up Strapi

To manage our Twitter content for our application, we will use Strapi. To get started, we will first need to install an instance of Strapi with the following commands in CLI:
```bash
npx create-strapi-app@latest twitter-content --quickstart
```
This command creates a project directory, `twitter-content,` with Strapi installed. Once the installation is completed, an instance of Strapi is automatically opened for us in our browser, and we will see a page similar to the image below:

![-](https://blog.openreplay.com/images/build-a-twitter-clone-with-strapi/images/YTjKIvv.png)

Here, we are required to get authenticated to access our CMS. After logging in, we are navigated to the user dashboard:

![-](https://blog.openreplay.com/images/build-a-twitter-clone-with-strapi/images/pPocnnE.png)

Here, we can set up our Twitter content structure. Click on `Create your first Content type`. The name of our collection type is “twitter content”. This collection will have the following fields, with all text fields being set as required:

![-](https://blog.openreplay.com/images/build-a-twitter-clone-with-strapi/images/MFxgW2W.png)

Click on the `Save` button to create the collection.


## Populating the Created Collection

Before linking our application to our CMS, we will add some content to the collection, which we will then fetch and display in our application. To add content to the collection, click `Content Manager` from the left sidebar. A new page where we can create new content opens up. Add whatever content you desire using the fields defined earlier for our collection type. 

![-](https://blog.openreplay.com/images/build-a-twitter-clone-with-strapi/images/wTIFHIN.png)

You can add as much tweet content as you want by clicking on the `Save` and `Publish` buttons after every entry. 

To make CMS content available to our React.js front-end, we will need to make the following changes to the `public` role in the `users and permissions` section of our StrapiCMS settings:

![-](https://blog.openreplay.com/images/build-a-twitter-clone-with-strapi/images/AtlEsu8.png)



<div style="background-color:#efefef; border-radius:8px; padding:10px; display:block;">
<hr/>
<h3><em>Session Replay for Developers</em></h3> 
<p><em>Uncover frustrations, understand bugs and fix slowdowns like never before with <strong><a href="https://github.com/openreplay/openreplay" target="_blank">OpenReplay</a></strong> — an open-source session replay suite for developers. It can be <strong>self-hosted</strong> in minutes, giving you complete control over your customer data.</em></p>
<img alt="OpenReplay" style="margin-top:5px; margin-bottom:5px;" width="768" height="400" src="https://raw.githubusercontent.com/openreplay/openreplay/main/static/openreplay-git-hero.svg" class="astro-UXNKDZ4E" loading="lazy" decoding="async">
<p><em>Happy debugging! <a href="https://openreplay.com" target="_blank">Try using OpenReplay today.</a></em><p>
<hr/>
</div>



## Fetching Tweets from the CMS

We will create an API fetch request using Axios in our `Feed.js` file to fetch tweets from our CMS. We will map through the returned API response and display the tweets with the post component.
```jsx
import axios from "axios";
//...
 const [posts, setPosts] = useState([]);
  useEffect(() => {
  //fetch data from the CMS and set the value of the posts state to the response
   const getTweets = async () => {
    await axios.get("http://localhost:1337/api/twitter-contents?populate=*").then((res) => {
      setPosts(res.data.data);
    })
  }
  getTweets();
  }, []);
// we can return the response in our component when we map through the posts state
{posts && posts.map((post) => (
  <Post
    key={post.attributes.ic}
    displayName={post.attributes.displayname}
    username={post.attributes.username}
    verified={true}
    text={post.attributes.description}
    avatar={`http://localhost:1337${post.attributes.userimage.data.attributes.url}`}
    image={`http://localhost:1337${post.attributes.postimage.data.attributes.url}`}
  />
))}
```
With this, we get the content from our CMS displayed in the browser when we run our application:

![-](https://blog.openreplay.com/images/build-a-twitter-clone-with-strapi/images/ln3OFCW.png)

## Creating New Tweets

To create new tweets, in our `TweetBox.js` file, we will create a request to take in the value of our input fields and post it to our Strapi collection.
```jsx
const handleFileChange = (e) => {
console.log(e.target.files);
setTweetImage(e.target.files[0]);
};
const uploadImage = async (e) => {
try {
  const formData = new FormData(e.target);
  formData.append("files", tweetImage);
  console.log({ image: formData.get("files") });
  const res = await axios({
    url: "http://localhost:1337/api/upload",
    method: "POST",
    data: formData,
  });
  console.log({ res });
  return res.data;
} catch (error) {
  console.log({ error });
  return null;
}
};
const sendTweet = async (event) => {
event.preventDefault();
if (tweetMessage !== "") {
  const fileData = await uploadImage(event);
  if (!fileData) throw Error("image upload failed");
  try {
    const [{ id }] = fileData;
    console.log({ id });
    const res = await axios({
      method: "POST",
      url: "http://localhost:1337/api/twitter-contents",
      data: {
        data: {
          displayname: "Marvel Ken",
          username: "captainmarvel",
          userimage: "3",
          description: tweetMessage,
          postimage: id,
        },
      },
    });
    console.log({ res });
    window.location.reload();
  } catch (error) {
    console.log({ error });
  }
} else {
  alert("Enter tweet caption")
}
};
```
We captured the user text and image from the input fields in the code above. We uploaded the image using the `upload` route, then we made a post request to Strapi, adding the image id in the `postimage` field. With this, we can now add new tweets to our Strapi collection. Below is the final output of the program:

For the login:
![-](https://blog.openreplay.com/images/build-a-twitter-clone-with-strapi/images/image01.gif)

Adding new tweet:
![-](https://blog.openreplay.com/images/build-a-twitter-clone-with-strapi/images/image02.gif)


## Conclusion

We have come to the end of this tutorial. In this tutorial, we built a Twitter clone using React.js and StrapiCMS, with features to create and view tweets.