1. Run `npx create-web3-dapp@latest`
2. Go to `globals.css` and delete everything
3. Go to https://tailwindcss.com/docs/guides/nextjs
4. In your terminal, run `npm install -D tailwindcss postcss autoprefixer`
5. Then run `npx tailwindcss init -p`
6. Then run `npm @babel/core@">=7.0.0 <8.0.0" react-is@">= 16.8.0"` (your terminal should call this dependency req out!)
7. Add the following code to your `globals.css` file:
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```
8. In the `tsconfig.json` file, replace `lines 22-24` with:
```json
"baseUrl": "./",
"paths": {
"@common/*": ["common/*"],
"@public/*": ["public/*"]
}
```
9. Add the `/common` folder to your projec root
10. Move the `/navigation` folder located in `/components/instructionsComponent` into the `/common` folder in the root of your project (you will need to update the imports in `layout.tsx`!)
11. Go to https://walletconnect.com/ and create an account
12. Create a new project and copy-paste the `Project Id` into a brand new variable in your `.env.local` file - in this format:
```
WALLET_CONNECT_PROJECT_ID=<YOUR_WALLET_CONNECT_PROJECT_ID>
```
> Don't use spaces or quotes! Just use the same format you see right above.
13. Then, go to your `layout.tsx` and change `line 11` to:
```javascript
process.env.WALLET_CONNECT_PROJECT_ID!
```
> The exclamation mark is necessary for Typescript to be happy!
13. BUG!!! Run `npm i --save-dev tap` in order to stop seeing the stupid bug
14. In order to protect users, add the following on `line 12` of your `layout.tsx` file:
```javascript
chains: [sepolia],
```
15. Make sure to import `{ sepolia }` from `wagmi` NOT `viem`, like this at the top of the `layout.tsx`:
```javascript
import { WagmiConfig, createConfig, sepolia } from "wagmi";
```
16. We forgot about DaisyUI! (https://daisyui.com/docs/install/)
17. Run `npm i -D daisyui@latest`
18. Add the following on `line 12` of the `tailwind.config.css` file:
```javascript
plugins: [require("daisyui")],
```
19. After so many installations, you might need to run `CTRL+C` in your terminal to terminate the running server process
20. Run `npm run dev` again to start up a fresh `localhost:3000`
21. Create a new folder in the `/common` folder called `/hooks`
22. Inside the `/hooks` folder, create a new file called `useTheme.tsx`
23. Copy-paste the following in that file:
```javascript
import { useState } from "react";
export default function useTheme() {
type Theme = "light" | "dark";
const [theme, switchTheme] = useState<Theme>("light");
return { theme, switchTheme };
}
```
24. Now, in the `layout.tsx` add the following on `line 28` (right above the `return (` line):
```javascript
const { theme } = useTheme();
```
25. Add a new folder called `/api` inside the `/app` folder
26. Inside the newly-created `/api` folder, create a new folder called `/get-user-nfts` and create a file called `route.ts` inside that
> This will be the route to query a user's NFTs using the Alchemy SDK
27. Inside the `route.ts`, copy-paste the following:
```javascript
import { NextRequest, NextResponse } from "next/server";
const { Alchemy, Network } = require("alchemy-sdk");
const settings = {
apiKey: process.env.ALCHEMY_API_KEY,
network: Network.ETH_SEPOLIA,
};
const alchemy = new Alchemy(settings);
export async function POST(request: NextRequest) {
const body = await request.json();
const { address } = body;
const nfts = await alchemy.nft.getNftsForOwner(address);
console.log(nfts);
return NextResponse.json({
data: nfts,
});
}
```
27. In your terminal, run `npm i alchemy-sdk`
28. In the `/common` folder, create a brand new folder called `/nft` and in that folder create a new file called `WalletDisplay.tsx`, copy-paste the following:
```javascript
import Loader from "@common/utils/Loader";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import { useAccount } from "wagmi";
interface Nft {
contract: object;
tokenId: string;
tokenType: string;
title: string;
description: string;
media: object;
}
interface Data {
ownedNfts: Nft[];
length: number;
}
export default function WalletDisplay() {
const [ownedNftsArray, setOwnedNftsArray] = useState<Data | null>(null);
const { address } = useAccount();
const [isLoading, setIsLoading] = useState(true);
const router = useRouter();
useEffect(() => {
fetchUserNfts();
}, []);
async function fetchUserNfts() {
setIsLoading(true);
try {
const data = { address: address };
const response = await fetch("/api/get-user-nfts/", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
const messageResponse = await response.json();
console.log(messageResponse.data.ownedNfts);
setOwnedNftsArray(messageResponse.data.ownedNfts);
setIsLoading(false);
} catch (error) {
console.error("Error fetching NFTs:", error);
}
}
function truncateDescription(description: string, wordCount: number) {
const words = description.split(" ");
if (words.length > wordCount) {
const truncatedWords = words.slice(0, wordCount);
return `${truncatedWords.join(" ")} ...`;
}
return description;
}
return (
<div>
{isLoading ? (
<div className="flex items-center justify-center mt-[-350px]">
<Loader />
</div>
) : ownedNftsArray && ownedNftsArray.length >= 1 ? (
<div className="flex flex-col items-center">
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4 mx-12 mb-6">
{ownedNftsArray &&
Array.isArray(ownedNftsArray) &&
ownedNftsArray.map((nft, index) => (
<div
key={index}
className="bg-base-100 rounded-lg shadow-xl max-w-[250px] max-h-[600px] overflow-hidden"
>
<figure>
<img
src={
nft.tokenUri && nft.tokenUri.gateway
? nft.tokenUri.gateway
: ""
}
alt="user nft image"
className="w-full max-h-[300px]"
/>
</figure>
<div className="p-4">
<h2 className="text-xl font-semibold mb-2">{nft.title}</h2>
<p className="">
{truncateDescription(nft.description, 25)}
</p>
</div>
</div>
))}
</div>
<div>
<div className="btn" onClick={() => router.push("/mint-nft")}>
Mint
</div>
</div>
</div>
) : (
<div>
<div className="flex flex-col items-center justify-center mx-8 mt-32">
Your smart contract wallet does not own any NFTs yet! 🤯
<div className="flex mt-4">
Mint one by selecting the <b> Mint an NFT </b> tab. ⬆️
</div>
</div>
</div>
)}
</div>
);
}
```
29. In the `/common` folder, create a new folder called `/utils` and within that a file called `Loader.tsx`, copy-paste the following inside:
```javascript
export default function Loader() {
return (
<div className="flex justify-center items-center min-h-screen">
<span className="loading loading-spinner loading-lg text-[#0a0ad0]"></span>
</div>
);
}
```