Inspiration
Twitter was most definitely an inspiration for the project. Since Pragma is essentially a web 3 version of Twitter, most of the core features from it had been integrated into the project in a decentralised manner that utilises the Polygon blockchain. The user interface is also inspired by Twitter's however simplified and more futuristic.
What it does + How it works
Much like Twitter, Pragma is a social media app. However, it does not rely on a central database to store its data, instead it uses the blockchain and NFTs. There are 2 smart contracts, one for the user data and the other for the NFT posts.
The user data smart contract keeps track of all user information including username, bio, banner, profile pic, followers and following. This is all done in a decentralised manner on the Mumbai test network and when a user wants to change their bio for example, it is very easy to do in the settings page of Pragma.
The NFT post smart contract is an ERC-721 NFT contract that uses the Open zeppelin library. It has a function where users can mint an NFT with a custom name, description and image link. When a user makes a post on the home page, they are interacting with this function and if an image is attached, it is uploaded to IPFS first, and then that link along with the other data goes onto the blockchain.
How I built it
To start the project, I setup everything. This included setting up a basic NextJS site that uses TailwindCSS and setting up Hardhat for smart contracts. During this time, I also made some drafts for the smart contracts, especially the NFT post one.
I then went onto building out the start of the user interface with ReactJS and TailwindCSS as well as implementing Moralis authentication to the app. While building the UI, I mainly focussed on the sidebar and getting a basic layout for Pragma and key design colours and styles. Since the sidebar would be one of the places I wanted users to be able to connect MetaMask, it was the first place I used Moralis. The Moralis SDK made it very easy to implement this core feature in addition to all the other blockchain related things that I would have to make later in the project
After getting some parts of the sidebar finished, I coded the settings page and user data smart contract that it would have to interact with. The user data contract was fairly easy to build as all it required was a mapping where addresses map to a structure containing that user addresses data such as username, bio, profile picture and banner. At the time, the following feature was still a work in progress so I did not focus on it. I then took the smart contract and made a settings page where users could interact with the contract and change their user data while signed in. To interact with the smart contracts, I used the Moralis web 3 execute function.
Now that there was user data, I could add a username and profile picture to the sidebar in addition to working on the profile page. In order to get the data from the blockchain, I again used Moralis. I stored this data in a ReactJS context and it would be fetched every time the user connected there wallet or loaded the site and was authenticated already. This made it easier to access data in the profile and sidebar to build out the UI as I wouldn't have to fetch it multiple times.
Once I had finished the profile page, it was time to work on the home page and NFT mint post functionality. This consisted of refining the smart contract I made while starting Pragma, implementing a top section of the home page where you could create posts and finally a feed that showed all of the NFT posts part of the collection. The post part used similar things as the settings page input fields did as they both had to interact with something on the Polygon Mumbai network. To display the feed, all I needed to do was fetch all NFTs from the contract address of the post NFT contract using one of the Moralis API's. I also had to fetch the posters data so that it could be displayed with the post. This led to a few problems I will discuss in the Challenges I ran into section.
When the home page was done, I worked on making the accounts page which could be queried with an address and show that address' profile. Seeing as the profile used many similar UI features, I just broke the homepage into a few components that would receive data to display. This meant that I had to restructure the profile page and it would feed data to a component that displays the profile page. For the accounts page, it would fetch the queried address' user data and feed it to a profile component to display.
Finishing the accounts page was a big relief as it meant I had built or the essential features I wanted. Seeing that I had quite some time left before the deadline, I went on to build the following functionality, ability to view other user profiles, improve the user interface and also improve upon the code I had written. This time was basically just used for finishing touches, testing and fixing bugs.
Challenges I ran into
One of the larger challenges I encountered had to do with loading posts along with the poster's user data. This challenge consisted of two problems. The first was that posts would get reloaded every time someone went to the homepage or switched pages then went back to the homepage. To solve this I did something somewhat similar to what I did with the user data context in the sense that Post NFTs would be fetched from the Moralis API in a context when the site loads so that it only gets fetched once. This also meant I would have to get the accounts that posted the NFTs user data. To do this, I first created a context that stored user data in an object and when the posts would fetch, it would load the user data as well. This however meant that the NFTs of the user were also be being loaded which I did not need to show on the home page. Loading these NFTs required quite a lot from the API and would end up rate limiting the API making there be limited data to show. To solve this second problem, I made it so that the NFTs only fetch when a user goes to that user's profile page.
Another problem I ran into had to do with the follow and unfollow functionality. According to the smart contract, users could follow people multiple times as followers were tracked with numbers. After a bit of trial and error I found a solution. This was to store who users were following and their followers in arrays. This meant that every time someone wanted to follow someone, it would check if they were already following them and if so they would not end up following them.
Accomplishments that I'm proud of
I'm very proud of the overall project. I feel that the user interface is clean, structure of code is good and that the project works well. It is definitely the best and most complicated project I have ever built as I am relatively new to blockchain and web development. I'm also proud about how much I learnt building it.
What I learned
After building Pragma, I learnt a lot; both about blockchain dev and web dev. In terms of blockchain, I learnt more about Hardhat as it was something I was quite unfamiliar with. I learnt how to deploy with Hardhat, configure different networks and verify contracts on Etherscan systematically. Hardhat was definitely a large step up from the Remix IDE. Although I did code smart contracts, the project was much more frontend heavy so in terms of how I design websites, I think I learnt a lot. Something in particular I learnt related to design, was making a notification. It also taught be about time in react as it had a time bar showing how long before the notification would go away. I also learnt how contexts work in ReactJS and how I can utilise them for my project.
Improvements that could be made
One large improvement that I could've added but sadly didn't get time to do was displaying who a user is following and who their followers are (along with those accounts user data). I think this would just slightly improve the site and give it one more cool feature.
Another improvement might have to do with inappropriate posts as there are no guidelines and if someone posts something inappropriate, there is no way of taking it off the blockchain. However, some might argue this is a good thing as an idea of blockchain/decentralisation is that everything is open and not censored.
Built With
- hardhat
- javascript
- moralis
- nextjs
- react
- solidity
- tailwindcss
Log in or sign up for Devpost to join the conversation.