Skip to main content
This tutorial will guide you through building an on-chain guestbook called MemoBoard. Users can post public messages, and the application prioritizes human-readable identity by resolving .init usernames. By the end of this tutorial, you will have:
  • Generated and verified a Rust smart contract for the guestbook.
  • Deployed the contract to your live appchain.
  • Scaffolded and connected a React frontend.
  • Verified the on-chain functionality.

Your Project Structure

The following steps will instruct your AI agent to create these directories inside your my-initia-project folder:
Project Structure
Prerequisite: Ensure you have a Wasm-compatible appchain running locally. If you haven’t launched one yet, complete the Set Up Your Appchain first.

Readiness Check

Before you start, verify that your local infrastructure is healthy.
Prompt: Check local infrastructure health

Step 1: Create and Unit Test the Smart Contract

Instruct your AI agent to create the Rust (Wasm) contract using the initia-appchain-dev skill. Your AI agent will generate the contract and automatically run unit tests to ensure the logic is sound.
Prompt: Create and test the MemoBoard contract
Your AI agent will generate the memoboard project and confirm that the Rust tests pass.
If you prefer to see the Rust logic, here is a simplified but schema-accurate version of what your AI agent would generate. If doing this manually, save the following code in src/contract.rs inside your memoboard directory (ensure src/lib.rs exports the contract module).First create and enter the project directory:
Important: Ensure your Cargo.toml includes the following [lib] section to correctly generate the Wasm binary:
Cargo.toml
Also ensure Cargo.toml includes these dependencies and features required by the example contract:
Cargo.toml
src/contract.rs

Step 2: Deploy to Your Appchain

Now that the logic is verified, build and publish the contract to your appchain using the Gas Station account.
Prompt: Deploy the MemoBoard contract
1. Build and Store the Code:Standard cargo build binaries often fail validation on-chain. For WasmVM deployment, it is strongly recommended to use the CosmWasm Optimizer.Note for Apple Silicon (M1/M2/M3): Use cosmwasm/optimizer-arm64:0.17.0.
Optimizer Build Command
The optimized binary will be located in ./memoboard/artifacts/memoboard.wasm. Now, store the code:
Store Wasm Code
2. Retrieve the Code ID and Instantiate:If the code_id is not returned directly, wait for 5 seconds for indexing and then query the transaction hash:
Get Code ID
Then, instantiate the contract:
Instantiate Contract
3. Retrieve the Contract Address:Wait for 5 seconds for indexing and then query the transaction hash:
Get Contract Address

Step 3: Smoke Test the Deployed Contract On-Chain

Before frontend integration, smoke test your deployed contract directly on chain.
Prompt: Smoke test the MemoBoard contract
Submit one message transaction, then query contract state to confirm it was persisted on chain.
Post Message
Query Messages

Step 4: Create a Frontend

Let’s create a UI to display and post messages. 1. Scaffold the Frontend:
Prompt: Scaffold the MemoBoard frontend
2. Connect to Appchain:
Prompt: Connect the frontend to the MemoBoard contract
If you prefer to set up the frontend manually, follow these steps:1. Create the Project and Install Dependencies:
2. Configure Vite Polyfills: Update vite.config.js to include the Node polyfills:
vite.config.js
Create the frontend files in this order so the imports line up cleanly:
  1. vite.config.js
  2. .env
  3. src/main.jsx
  4. src/Board.css
  5. src/Board.jsx
  6. src/App.jsx
3. Gather Runtime Values for Frontend Config: Right before creating .env, collect the values you will use:
Gather Frontend Values
4. Add Runtime Configuration: Create a .env file in memoboard-frontend so the chain metadata, endpoints, and live contract address are explicit:
.env
5. Set up Providers in main.jsx:
src/main.jsx
6. Create the Board.jsx Component: Create src/Board.jsx and src/Board.css with the following content:src/Board.css:
src/Board.css
src/Board.jsx:
src/Board.jsx
7. Create App.jsx: Create the app shell that renders the board and owns the wallet button:
src/App.jsx

Step 5: Wallet Funding and UI Verification

Ask your AI agent to fund your browser wallet, then verify frontend behavior manually in the browser:
  1. Start the frontend:
Start Vite Dev Server
Check the browser console if you encounter issues.
  1. Open your browser wallet and copy your address (init1...).
  2. Give this prompt to your AI agent, replacing <YOUR_WALLET_ADDRESS> with the address you just copied:
  1. Connect your wallet in memoboard-frontend.
  2. Post a message from the UI.
  3. Confirm it appears in the message list after refresh.
  4. If your UI supports it, verify sender identity rendering matches expectations.
If you get stuck, see the Debugging Workflow guide.

🪢 Native Feature: Initia Usernames

To make your MemoBoard natively integrated with the Initia stack, you can replace long, complex addresses with human-readable Initia Usernames (e.g., vitalik.init).

Step 6: Register Your .init Name

Before updating your code, you should register a primary username for your wallet on the Initia testnet.
  1. Navigate to app.testnet.initia.xyz/usernames and connect your browser wallet.
  2. In the Find a username search box, enter your desired name. If it is available, you will see a green Available checkmark.
  3. Crucial: Ensure the Set as primary name checkbox is selected.
  4. Click Register and approve the transaction. Once resolved, your new .init name will appear in the top-right corner of the Initia App.

Step 7: Update the Frontend

Your AI agent knows how to integrate Initia Usernames. Simply ask it to update your board.
Prompt: Add Initia username support
The useInterwovenKit() hook provides the username for the currently connected wallet, and useUsernameQuery(address) resolves usernames for other sender addresses. This requires @initia/interwovenkit-react 2.4.6 or newer. To implement this, update your wallet button component (for example src/App.jsx) and your board message list like this:
Hook Placement: Keep useUsernameQuery(address) inside a child row component like MessageRow. Do not call it directly inside a parent component’s .map() callback.
If you want the complete finished frontend after applying the manual steps above, use the consolidated reference below.
If you want a single copyable end-state after completing the manual steps above, use this consolidated reference. It combines:
  • live Wasm contract query and execute flow,
  • wallet connect/display via App.jsx,
  • runtime config from .env, and
  • Initia username support for the connected wallet and sender rows.
src/Board.jsx
src/Board.jsx
src/App.jsx
src/App.jsx

Native Feature Verification

  1. Connect your wallet in memoboard-frontend.
  2. Confirm the header button shows your .init username (not only a truncated address).
  3. Post a message and confirm the sender label for your message uses your username.

Next Steps

Now that you’ve mastered a Wasm application, you’re ready to build your own idea! Ensure your project meets all the Submission Requirements before submitting.