How To Build A User Interface For DAO Smart Contract pt.1
Somnia empowers developers to build applications for mass adoption. Smart Contracts deployed on the Somnia Blockchain will sometimes require building a User Interface. This guide will teach you how to build a user interface for a DAO Smart Contract using Next.js and React Context. It is divided into three parts. At the end of this guide, you’ll learn how to:
Initialize a Next.js project.
Set up a global state using the Context API (
useContext
hook).Add a global NavBar in
_app.js
so it appears on every page.
You will have a basic skeleton of a DApp, ready for READ/WRITE operations and UI components —topics we’ll cover in the subsequent articles.
Pre-requisites:
This guide is not an introduction to JavaScript Programming; you are expected to understand JavaScript.
To complete this guide, you will need MetaMask installed and the Somnia DevNet added to the list of Networks. If you have yet to install MetaMask, please follow this guide to Connect Your Wallet.
Create Your Next.js Project
To create a NextJS project, run the command:
Accept the prompts and change directory into the folder after the build is completed.
This gives you a minimal Next.js setup with a pages folder (holding your routes), a public folder (for static assets), and config files.
(Optional) Add Tailwind CSS
If you plan to style your app with Tailwind, install and configure it now:
Then edit your tailwind.config.js:
Finally, include Tailwind in styles/globals.css:
Setting Up a React Context for Global State
In many DApps, including this one, developers will manage Wallet connection and State globally so each page and component in the project can access it without repetitive code. This can be achieved by a Context following React patterns.
Create a folder and name it
contexts
at the project root or insidepages
directory.Inside it, create a file called
walletcontext.js
add the following code to the file:
We parse three class methods from React: createContext
, useContext
, anduseState
createContext
is used to create a context that components can provide or read. In this example, we assign createContext
to the WalletContext
variable and call the Provider
method on each State and Function to make them available throughout the application.
useWallet()
is a custom hook, so any page or component can do:
to access the global wallet state i.e. any of the Wallet.Provider
methods
connectToMetaMask()
triggers the MetaMask connection flow.
WalletProvider
manages State and Methods in the application.
Creating a Global NavBar in _app.js
Next.js automatically uses pages/_app.js
to initialize every page. We will wrap the entire app in the WalletProvider
inside _app.js
and inject a NavBar
menu that appears site-wide in the application
Create the _app.js
and add the code:
_app.js
and add the code:<WalletProvider>
wraps the entire <Component />
tree so that every page can share the same wallet state.
<NavBar />
is placed above <main>
, so it’s visible on all pages. We give <main>
a pt-16 to avoid content hiding behind a fixed navbar.
NavBar
Create a sub directory components and add a file called navbar.js
Add the code:
It uses useWallet()
to read the global connected
and address
states, and the disconnectWallet
function. The truncated address
is displayed if a user is logged into the App or “Not connected” otherwise. A Logout button calls disconnectWallet()
to reset the global state.
Test Your Setup
Start the dev server:
Open http://localhost:3000 in a Web Browser. You should see your NavBar at the top.
Because we haven’t built any advanced pages yet, you will see a blank home page. The important part is that your WalletContext and global NavBar are in place and ready for the next steps.
5. Next Steps
Article 2 shows you how to implement READ/WRITE operations (e.g., deposit, create proposals, vote, etc.) across different Next.js pages—using the same WalletContext to handle contract calls.
Article 3 will focus on UI components, like forms, buttons, and event handling, tying it all together into a polished user interface.
Congratulations! You have a clean foundation, a Next.js project configured with Tailwind, a global context to manage wallet states, and a NavBar appearing across all routes. This sets the stage for adding contract interactions and advanced UI flows in the subsequent articles. Happy building!
Last updated