Nuxt
AppKit has support for Wagmi and Ethers v6 on Ethereum, @solana/web3.js on Solana and Bitcoin.
Choose one of these to get started.
AppKit for Nuxt requires SSR compatibility considerations. Make sure to use the <client-only>
wrapper and configure your Nuxt app appropriately.
Installation
npm install @reown/appkit @reown/appkit-adapter-wagmi wagmi viem @wagmi/vue @tanstack/vue-query
npm install @reown/appkit @reown/appkit-adapter-wagmi wagmi viem @wagmi/vue @tanstack/vue-query
npm install @reown/appkit @reown/appkit-adapter-ethers ethers
npm install @reown/appkit @reown/appkit-adapter-solana
npm install @reown/appkit @reown/appkit-adapter-bitcoin
Cloud Configuration
Create a new project on Reown Cloud at https://cloud.reown.com and obtain a new project ID.
Don’t have a project ID?
Head over to Reown Cloud and create a new project now!
Implementation
Nuxt Wagmi Example Check the Nuxt Wagmi example
For this example, we’ll be using Wagmi and Viem with Nuxt.
First, configure your Nuxt application for SSR compatibility by updating your nuxt.config.ts
:
export default defineNuxtConfig ({
ssr: false ,
modules: [ '@wagmi/vue/nuxt' ] ,
runtimeConfig: {
public: {
projectId: process . env . NUXT_PROJECT_ID
}
}
})
Create Nuxt plugins for vue-query and wagmi setup:
// plugins/1.vue-query.ts
import { defineNuxtPlugin } from '#imports'
import { QueryClient , VueQueryPlugin } from '@tanstack/vue-query'
export default defineNuxtPlugin ( nuxt => {
const queryClient = new QueryClient ({
defaultOptions: { queries: { staleTime: 5000 } }
})
nuxt . vueApp . use ( VueQueryPlugin , {
queryClient ,
enableDevtoolsV6Plugin: true
})
} )
// plugins/2.wagmi.ts
import { WagmiPlugin } from '@wagmi/vue'
import { defineNuxtPlugin } from 'nuxt/app'
import { wagmiAdapter } from '~/config/appkit'
export default defineNuxtPlugin ( nuxtApp => {
nuxtApp . vueApp . use ( WagmiPlugin , { config: wagmiAdapter . wagmiConfig })
} )
Create your AppKit configuration:
// config/appkit.ts
import { WagmiAdapter } from '@reown/appkit-adapter-wagmi'
import { mainnet , arbitrum } from '@reown/appkit/networks'
export const projectId = process . env . NUXT_PROJECT_ID || 'YOUR_PROJECT_ID'
export const networks = [ mainnet , arbitrum ]
export const wagmiAdapter = new WagmiAdapter ({
networks ,
projectId
})
Then in your app.vue
file, set up AppKit:
< script setup lang = "ts" >
import { createAppKit } from '@reown/appkit/vue'
import { wagmiAdapter , networks , projectId } from './config/appkit'
createAppKit( {
adapters : [ wagmiAdapter ],
networks ,
projectId ,
metadata : {
name: 'AppKit Nuxt Wagmi Example' ,
description: 'AppKit Nuxt Wagmi Example' ,
url: 'https://reown.com/appkit' ,
icons: [ 'https://avatars.githubusercontent.com/u/179229932?s=200&v=4' ]
}
} )
</ script >
< template >
< client-only >
< div class = "page-container" >
< h1 > Nuxt Wagmi Example </ h1 >
< appkit-button />
</ div >
</ client-only >
</ template >
Make sure to set your NUXT_PROJECT_ID
environment variable which you can get from Reown Cloud .
The ssr: false
configuration and <client-only>
wrapper ensure AppKit works correctly with Nuxt’s SSR environment.
Nuxt Wagmi Example Check the Nuxt Wagmi example
For this example, we’ll be using Wagmi and Viem with Nuxt.
First, configure your Nuxt application for SSR compatibility by updating your nuxt.config.ts
:
export default defineNuxtConfig ({
ssr: false ,
modules: [ '@wagmi/vue/nuxt' ] ,
runtimeConfig: {
public: {
projectId: process . env . NUXT_PROJECT_ID
}
}
})
Create Nuxt plugins for vue-query and wagmi setup:
// plugins/1.vue-query.ts
import { defineNuxtPlugin } from '#imports'
import { QueryClient , VueQueryPlugin } from '@tanstack/vue-query'
export default defineNuxtPlugin ( nuxt => {
const queryClient = new QueryClient ({
defaultOptions: { queries: { staleTime: 5000 } }
})
nuxt . vueApp . use ( VueQueryPlugin , {
queryClient ,
enableDevtoolsV6Plugin: true
})
} )
// plugins/2.wagmi.ts
import { WagmiPlugin } from '@wagmi/vue'
import { defineNuxtPlugin } from 'nuxt/app'
import { wagmiAdapter } from '~/config/appkit'
export default defineNuxtPlugin ( nuxtApp => {
nuxtApp . vueApp . use ( WagmiPlugin , { config: wagmiAdapter . wagmiConfig })
} )
Create your AppKit configuration:
// config/appkit.ts
import { WagmiAdapter } from '@reown/appkit-adapter-wagmi'
import { mainnet , arbitrum } from '@reown/appkit/networks'
export const projectId = process . env . NUXT_PROJECT_ID || 'YOUR_PROJECT_ID'
export const networks = [ mainnet , arbitrum ]
export const wagmiAdapter = new WagmiAdapter ({
networks ,
projectId
})
Then in your app.vue
file, set up AppKit:
< script setup lang = "ts" >
import { createAppKit } from '@reown/appkit/vue'
import { wagmiAdapter , networks , projectId } from './config/appkit'
createAppKit( {
adapters : [ wagmiAdapter ],
networks ,
projectId ,
metadata : {
name: 'AppKit Nuxt Wagmi Example' ,
description: 'AppKit Nuxt Wagmi Example' ,
url: 'https://reown.com/appkit' ,
icons: [ 'https://avatars.githubusercontent.com/u/179229932?s=200&v=4' ]
}
} )
</ script >
< template >
< client-only >
< div class = "page-container" >
< h1 > Nuxt Wagmi Example </ h1 >
< appkit-button />
</ div >
</ client-only >
</ template >
Make sure to set your NUXT_PROJECT_ID
environment variable which you can get from Reown Cloud .
The ssr: false
configuration and <client-only>
wrapper ensure AppKit works correctly with Nuxt’s SSR environment.
In your Nuxt application, set up the following configuration for Ethers integration.
First, configure your nuxt.config.ts
for SSR compatibility:
export default defineNuxtConfig ({
ssr: false ,
runtimeConfig: {
public: {
projectId: process . env . NUXT_PROJECT_ID
}
}
})
Then in your app.vue
file set up the following configuration:
< script setup lang = "ts" >
import { createAppKit } from '@reown/appkit/vue'
import { EthersAdapter } from '@reown/appkit-adapter-ethers'
import { mainnet , arbitrum } from '@reown/appkit/networks'
const config = useRuntimeConfig()
const projectId = config.public.projectId
const metadata = {
name : 'My Nuxt App' ,
description : 'My Nuxt App description' ,
url : 'https://mywebsite.com' ,
icons : [ 'https://avatars.mywebsite.com/' ]
}
createAppKit( {
adapters : [ new EthersAdapter ()],
networks : [ mainnet , arbitrum ],
metadata ,
projectId ,
features : {
analytics: true
}
} )
</ script >
< template >
< client-only >
< div class = "page-container" >
< h1 > Nuxt Ethers Example </ h1 >
< appkit-button />
</ div >
</ client-only >
</ template >
Make sure that the url
from the metadata
matches your domain and subdomain. This will later be used by the Verify API to tell wallets if your application has been verified or not.
The ssr: false
configuration and <client-only>
wrapper ensure AppKit works correctly with Nuxt’s SSR environment.
In your Nuxt application, set up the following configuration for Solana integration.
First, configure your nuxt.config.ts
for SSR compatibility:
export default defineNuxtConfig ({
ssr: false ,
runtimeConfig: {
public: {
projectId: process . env . NUXT_PROJECT_ID
}
}
})
Then in your app.vue
file set up the following configuration:
< script setup lang = "ts" >
import { createAppKit } from '@reown/appkit-solana/vue'
import { SolanaAdapter } from '@reown/appkit-adapter-solana'
import { solana , solanaTestnet , solanaDevnet } from '@reown/appkit/networks'
const config = useRuntimeConfig()
const projectId = config.public.projectId
const metadata = {
name : 'AppKit Nuxt' ,
description : 'AppKit Nuxt Solana Example' ,
url : 'https://example.com' ,
icons : [ 'https://avatars.githubusercontent.com/u/179229932' ]
}
const solanaWeb3JsAdapter = new SolanaAdapter()
createAppKit( {
adapters : [ solanaWeb3JsAdapter ],
metadata ,
networks : [ solana , solanaTestnet , solanaDevnet ],
projectId
} )
</ script >
< template >
< client-only >
< div class = "page-container" >
< h1 > Nuxt Solana Example </ h1 >
< appkit-button />
</ div >
</ client-only >
</ template >
Make sure that the url
from the metadata
matches your domain and subdomain. This will later be used by the Verify API to tell wallets if your application has been verified or not.
The ssr: false
configuration and <client-only>
wrapper ensure AppKit works correctly with Nuxt’s SSR environment.
AppKit Bitcoin provides a set of Vue components and composables to easily connect Bitcoin wallets with your Nuxt application.
First, configure your nuxt.config.ts
for SSR compatibility:
export default defineNuxtConfig ({
ssr: false ,
runtimeConfig: {
public: {
projectId: process . env . NUXT_PROJECT_ID
}
}
})
In your app.vue
file set up the following configuration:
< script setup lang = "ts" >
import { createAppKit } from '@reown/appkit/vue'
import { BitcoinAdapter } from '@reown/appkit-adapter-bitcoin'
import { bitcoin } from '@reown/appkit/networks'
const config = useRuntimeConfig()
const projectId = config.public.projectId
const networks = [bitcoin]
const bitcoinAdapter = new BitcoinAdapter( {
projectId
} )
const metadata = {
name : 'AppKit Nuxt' ,
description : 'AppKit Nuxt Bitcoin Example' ,
url : 'https://example.com' ,
icons : [ 'https://avatars.githubusercontent.com/u/179229932' ]
}
createAppKit( {
adapters : [ bitcoinAdapter ],
networks ,
metadata ,
projectId ,
features : {
analytics: true ,
email: false ,
socials: []
}
} )
</ script >
< template >
< client-only >
< div class = "page-container" >
< h1 > Nuxt Bitcoin Example </ h1 >
< appkit-button />
</ div >
</ client-only >
</ template >
Bitcoin Provider Interface export interface BitcoinConnector extends ChainAdapterConnector , Provider {
getAccountAddresses () : Promise < BitcoinConnector . AccountAddress []>;
signMessage ( params : BitcoinConnector . SignMessageParams ) : Promise < string >;
sendTransfer ( params : BitcoinConnector . SendTransferParams ) : Promise < string >;
signPSBT (
params : BitcoinConnector . SignPSBTParams
) : Promise < BitcoinConnector . SignPSBTResponse >;
}
Parameters SignMessageParams SignMessageParams SignPSBTParams export type SignMessageParams = {
/**
* The message to be signed
*/
message : string
/**
* The address to sign the message with
*/
address : string
}
export type SignMessageParams = {
/**
* The message to be signed
*/
message : string
/**
* The address to sign the message with
*/
address : string
}
export type SendTransferParams = {
/**
* The amount to be sent in satoshis
*/
amount : string
/**
* The address to send the transfer to
*/
recipient : string
}
export type SignPSBTParams = {
/**
* The PSBT to be signed, string base64 encoded
*/
psbt : string
signInputs : {
/**
* The address whose private key to use for signing.
*/
address : string
/**
* Specifies which input to sign
*/
index : number
/**
* Specifies which part(s) of the transaction the signature commits to
*/
sighashTypes : number []
}[]
/**
* If `true`, the PSBT will be broadcasted after signing. Default is `false`.
*/
broadcast ?: boolean
}
Responses AccountAddress SignPSBTResponse export type AccountAddress = {
/**
* Public address belonging to the account.
*/
address : string
/**
* Public key for the derivation path in hex, without 0x prefix
*/
publicKey ?: string
/**
* The derivation path of the address e.g. "m/84'/0'/0'/0/0"
*/
path ?: string
/**
* The purpose of the address
*/
purpose : 'payment' | 'ordinal' | 'stx'
}
export type AccountAddress = {
/**
* Public address belonging to the account.
*/
address : string
/**
* Public key for the derivation path in hex, without 0x prefix
*/
publicKey ?: string
/**
* The derivation path of the address e.g. "m/84'/0'/0'/0/0"
*/
path ?: string
/**
* The purpose of the address
*/
purpose : 'payment' | 'ordinal' | 'stx'
}
export type SignPSBTResponse = {
/**
* The signed PSBT, string base64 encoded
*/
psbt : string
/**
* The `string` transaction id of the broadcasted transaction or `undefined` if not broadcasted
*/
txid ?: string
}
The ssr: false
configuration and <client-only>
wrapper ensure AppKit works correctly with Nuxt’s SSR environment.
Trigger the modal
The recommended way to trigger the modal in Nuxt is to use the <appkit-button />
web component wrapped in <client-only>
for SSR compatibility:
< template >
< client-only >
< div class = "appkit-buttons-container" >
< appkit-button />
</ div >
</ client-only >
</ template >
The <appkit-button />
is a web component that’s automatically registered when AppKit is initialized. The <client-only>
wrapper ensures it only renders on the client side, preventing SSR hydration issues.
Alternative approaches
You can also trigger the modal programmatically using the AppKit composables:
< script setup lang = "ts" >
import { useAppKit } from '@reown/appkit/vue';
const { open } = useAppKit();
function openModal() {
open ();
}
function openConnectModal() {
open ({ view: 'Connect' });
}
function openAccountModal() {
open ({ view: 'Account' });
}
</ script >
< template >
< client-only >
< button @click="openModal">Open Modal</button>
<button @click="openConnectModal">Connect Wallet</button>
<button @click="openAccountModal">View Account</button>
</client-only>
</template>
Or use other AppKit web components:
< template >
< client-only >
< appkit-connect-button />
< appkit-account-button />
< appkit-network-button />
</ client-only >
</ template >
To open AppKit you can use our web component or build your own button with AppKit composables .
Web Components Composables Web components are global html elements that don’t require importing. Make sure to wrap them in <client-only>
for SSR compatibility.
< template >
< client-only >
< appkit-button />
</ client-only >
</ template >
You can also use <appkit-connect-button>
and <appkit-account-button>
components.
Web components are global html elements that don’t require importing. Make sure to wrap them in <client-only>
for SSR compatibility.
< template >
< client-only >
< appkit-button />
</ client-only >
</ template >
You can also use <appkit-connect-button>
and <appkit-account-button>
components.
You can trigger the modal by calling the open
method from useAppKit
composable.
< script setup lang = "ts" >
import { useAppKit } from '@reown/appkit/vue'
const { open } = useAppKit()
function openModal() {
open ()
}
</ script >
< template >
< client-only >
< button @click="openModal">Open Modal</button>
</client-only>
</template>
Learn more about the AppKit composables here
To open AppKit you can use our web component or build your own button with AppKit composables .
Web Components Composables Web components are global html elements that don’t require importing. Make sure to wrap them in <client-only>
for SSR compatibility.
< template >
< client-only >
< appkit-button />
</ client-only >
</ template >
You can also use <appkit-connect-button>
and <appkit-account-button>
components.
Web components are global html elements that don’t require importing. Make sure to wrap them in <client-only>
for SSR compatibility.
< template >
< client-only >
< appkit-button />
</ client-only >
</ template >
You can also use <appkit-connect-button>
and <appkit-account-button>
components.
You can trigger the modal by calling the open
method from useAppKit
composable.
< script setup lang = "ts" >
import { useAppKit } from '@reown/appkit/vue'
const { open } = useAppKit()
function openModal() {
open ()
}
</ script >
< template >
< client-only >
< button @click="openModal">Open Modal</button>
</client-only>
</template>
Learn more about the AppKit composables here
You can trigger the modal by calling the open
method from AppKit composables.
< script setup lang = "ts" >
import { useAppKit } from '@reown/appkit/vue'
const { open } = useAppKit()
function openModal() {
open ()
}
</ script >
< template >
< client-only >
< button @click="openModal">Open Modal</button>
</client-only>
</template>
You can also select the modal’s view when calling the open
function.
< script setup lang = "ts" >
import { useAppKit } from '@reown/appkit/vue'
const { open } = useAppKit()
function openConnectModal() {
open ({ view: 'Connect' })
}
function openAccountModal() {
open ({ view: 'Account' })
}
</ script >
< template >
< client-only >
< button @click="openConnectModal">Connect Wallet</button>
<button @click="openAccountModal">View Account</button>
</client-only>
</template>
You can trigger the modal by calling the open
method from AppKit composables.
< script setup lang = "ts" >
import { useAppKit } from '@reown/appkit-solana/vue'
const { open } = useAppKit()
function openModal() {
open ()
}
</ script >
< template >
< client-only >
< button @click="openModal">Open Modal</button>
</client-only>
</template>
You can also select the modal’s view when calling the open
function.
< script setup lang = "ts" >
import { useAppKit } from '@reown/appkit-solana/vue'
const { open } = useAppKit()
function openConnectModal() {
open ({ view: 'Connect' })
}
function openAccountModal() {
open ({ view: 'Account' })
}
</ script >
< template >
< client-only >
< button @click="openConnectModal">Connect Wallet</button>
<button @click="openAccountModal">View Account</button>
</client-only>
</template>
You can trigger the modal by calling the open
method from AppKit composables.
< script setup lang = "ts" >
import { useAppKit } from '@reown/appkit/vue'
const { open } = useAppKit()
function openModal() {
open ()
}
</ script >
< template >
< client-only >
< button @click="openModal">Open Modal</button>
</client-only>
</template>
You can also select the modal’s view when calling the open
function.
< script setup lang = "ts" >
import { useAppKit } from '@reown/appkit/vue'
const { open } = useAppKit()
function openConnectModal() {
open ({ view: 'Connect' })
}
function openAccountModal() {
open ({ view: 'Account' })
}
</ script >
< template >
< client-only >
< button @click="openConnectModal">Connect Wallet</button>
<button @click="openAccountModal">View Account</button>
</client-only>
</template>
Blockchain Interaction
You need to install @wagmi/core to interact with smart contracts:
Wagmi actions can help us interact with wallets and smart contracts:
For this use case, we need to import the wagmiConfig
from our AppKit WagmiAdapter configuration.
import { readContract } from "@wagmi/core" ;
import { USDTAbi } from "../abi/USDTAbi" ;
const USDTAddress = "0x..." ;
const data = readContract ( wagmiConfig , {
address: USDTAddress ,
abi: USDTAbi ,
functionName: "totalSupply" ,
args: [],
});
Read more about Wagmi actions for smart contract interaction here .
You need to install @wagmi/core to interact with smart contracts:
Wagmi actions can help us interact with wallets and smart contracts:
For this use case, we need to import the wagmiConfig
from our AppKit WagmiAdapter configuration.
import { readContract } from "@wagmi/core" ;
import { USDTAbi } from "../abi/USDTAbi" ;
const USDTAddress = "0x..." ;
const data = readContract ( wagmiConfig , {
address: USDTAddress ,
abi: USDTAbi ,
functionName: "totalSupply" ,
args: [],
});
Read more about Wagmi actions for smart contract interaction here .
Ethers can help us interact with wallets and smart contracts:
import { BrowserProvider , Contract , parseEther } from "ethers" ;
import { useAppKitProvider , useAppKitAccount } from "@reown/appkit/vue" ;
const { walletProvider } = useAppKitProvider ( "eip155" );
const { address } = useAppKitAccount ();
if ( ! walletProvider ) throw Error ( "No provider found" );
if ( ! address ) throw Error ( "No address found" );
function sendTransaction () {
const tx = {
from: address ,
to: "0x..." , // any address
value: parseEther ( "0.0001" ),
};
const ethersProvider = new BrowserProvider ( walletProvider );
const signer = await ethersProvider . getSigner ();
const tx = await signer . sendTransaction ( tx );
console . log ( "transaction:" , tx );
}