Quickstart

Build your first Stacks app with wallet connectivity in 5 minutes

What you'll learn

In this quickstart, you'll build a simple web app that connects to a Stacks wallet and sends a transaction. By the end, you'll understand:

How to connect to Stacks wallets like Hiro Wallet or Xverse
How to authenticate users and manage sessions
How to build and broadcast a STX transfer transaction
How to handle transaction results and errors

Prerequisites

Node.js 18+ installed on your machine
A Stacks wallet installed (Hiro Wallet or Xverse)
Basic knowledge of React (we'll use Next.js)

Quickstart

Create a new Next.js app

Start by creating a new Next.js application with TypeScript:

Terminal
$
npx create-next-app@latest my-stacks-app --typescript --tailwind --app
[32m✔[0m Would you like to use ESLint? … No / [1mYes[0m
[32m✔[0m Would you like to use `src/` directory? … No / [1mYes[0m
[32m✔[0m Would you like to customize the default import alias? … [1mNo[0m / Yes
[32mCreating a new Next.js app in[0m [1m./my-stacks-app[0m

Navigate to your project directory:

Terminal
$
cd my-stacks-app

Install Stacks.js packages

Add the necessary Stacks.js packages to your project:

Terminal
$
npm install @stacks/connect @stacks/transactions @stacks/network
[32madded[0m 47 packages in 3s

These packages provide:

  • @stacks/connect - Wallet connection and transaction broadcasting
  • @stacks/transactions - Transaction building utilities
  • @stacks/network - Network configuration (mainnet/testnet)

Set up authentication

Create a new file for authentication setup:

src/app/lib/auth.ts
import { AppConfig, UserSession } from '@stacks/connect';
const appConfig = new AppConfig(['store_write', 'publish_data']);
export const userSession = new UserSession({ appConfig });
export const appDetails = {
name: 'My Stacks App',
icon: '/logo.png', // You can add a logo to your public folder
};

The AppConfig defines what permissions your app needs, and UserSession manages the user's authentication state.

Create a wallet connection component

Replace the contents of your main page with a wallet connection interface:

src/app/page.tsx
'use client';
import { useState, useEffect } from 'react';
import { showConnect, showSTXTransfer } from '@stacks/connect';
import { StacksTestnet } from '@stacks/network';
import { AnchorMode } from '@stacks/transactions';
import { userSession, appDetails } from './lib/auth';
export default function Home() {
const [mounted, setMounted] = useState(false);
const [userData, setUserData] = useState<any>(null);
useEffect(() => {
setMounted(true);
if (userSession.isUserSignedIn()) {
setUserData(userSession.loadUserData());
}
}, []);
const connectWallet = () => {
showConnect({
appDetails,
onFinish: () => {
setUserData(userSession.loadUserData());
},
userSession,
});
};
const disconnectWallet = () => {
userSession.signUserOut();
setUserData(null);
};
const sendSTX = () => {
showSTXTransfer({
recipient: 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM',
amount: '1000000', // 1 STX in microSTX
memo: 'Hello from Stacks.js!',
network: new StacksTestnet(),
anchorMode: AnchorMode.Any,
onFinish: (data) => {
console.log('Transaction broadcast!', data);
alert(`Transaction sent! ID: ${data.txId}`);
},
onCancel: () => {
console.log('Transaction canceled');
},
});
};
if (!mounted) return null;
return (
<main className="flex min-h-screen flex-col items-center justify-center p-24">
<div className="max-w-md w-full space-y-8">
<h1 className="text-4xl font-bold text-center">My Stacks App</h1>
{!userData ? (
<button
onClick={connectWallet}
className="w-full bg-blue-600 text-white py-3 px-6 rounded-lg hover:bg-blue-700"
>
Connect Wallet
</button>
) : (
<div className="space-y-4">
<div className="bg-gray-100 p-4 rounded-lg">
<p className="text-sm text-gray-600">Connected as:</p>
<p className="font-mono text-sm break-all">
{userData.profile.stxAddress.testnet}
</p>
</div>
<button
onClick={sendSTX}
className="w-full bg-green-600 text-white py-3 px-6 rounded-lg hover:bg-green-700"
>
Send 1 STX
</button>
<button
onClick={disconnectWallet}
className="w-full bg-red-600 text-white py-3 px-6 rounded-lg hover:bg-red-700"
>
Disconnect
</button>
</div>
)}
</div>
</main>
);
}

Run your app

Start the development server:

Terminal
$
npm run dev
[32m▲ Next.js 14.0.0[0m
[90m- Local:[0m http://localhost:3000

Open http://localhost:3000 in your browser. You should see:

  1. 1A "Connect Wallet" button
  2. 2After connecting, your testnet address
  3. 3A button to send 1 STX (testnet STX)

Make sure your wallet is set to testnet mode for this example. You can get free testnet STX from the Stacks faucet.

Understanding the code

Let's break down what's happening in the code:

Authentication setup

const appConfig = new AppConfig(['store_write', 'publish_data']);

This configures what permissions your app needs. Common scopes include:

  • store_write - Store encrypted data
  • publish_data - Publish data to Gaia storage

Wallet connection

showConnect({
appDetails, // Your app's name and icon
onFinish: () => {
// Called when user approves connection
},
userSession, // Manages authentication state
});

The showConnect function opens the wallet popup for users to approve the connection.

Sending transactions

showSTXTransfer({
recipient: 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM',
amount: '1000000', // Amount in microSTX
network: new StacksTestnet(),
anchorMode: AnchorMode.Any,
onFinish: (data) => {
// Called after user approves and broadcasts
},
});

This creates a STX transfer transaction and opens the wallet for user approval.

Next steps

Now that you have a working Stacks app, explore these topics: