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>&nbsp;Mint an NFT&nbsp;</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> ); } ```