This guide will help you set up and customize the SvelteKit Web3 Starter template for your project.
- Node.js 20.18.0 or higher (see
.nvmrcfor exact version) - pnpm package manager (recommended) or npm
- A Reown Cloud project ID (free at cloud.reown.com)
-
Clone and install dependencies
git clone <your-repo-url> cd template pnpm install
Note: We recommend using pnpm for faster, more efficient package management. If you don't have pnpm installed, you can install it with
npm install -g pnpm. -
Set up environment variables
cp env.example .env
Edit
.envand add your Reown project ID:VITE_PROJECT_ID=your_project_id_here -
Start development server
pnpm run dev
-
Open your browser Navigate to http://localhost:5173
- Go to cloud.reown.com
- Sign up for a free account
- Create a new project
- Copy your project ID from the dashboard
- Add it to your
.envfile
-
Update contract addresses in
src/lib/config/contracts.ts:export const CONTRACT_ADDRESSES = { MY_CONTRACT: { [baseSepolia.id]: '0x...', // Your contract on Base Sepolia [base.id]: '0x...' // Your contract on Base Mainnet } };
-
Add your contract ABI to the same file or create a new file:
export const MY_CONTRACT_ABI = [ "function myFunction() external", "function myViewFunction() external view returns (uint256)", // ... your contract functions ];
-
Use in components:
<script> import { CONTRACT_ADDRESSES, MY_CONTRACT_ABI } from '$lib/config/contracts'; import ContractInteraction from '$lib/components/ContractInteraction.svelte'; </script> <ContractInteraction contractAddress={CONTRACT_ADDRESSES.MY_CONTRACT[84532]} // Base Sepolia abi={MY_CONTRACT_ABI} functionName="myFunction" onSuccess={(result) => console.log('Success!', result)} > Call My Function </ContractInteraction>
-
Import the network in
src/lib/config/appkit.ts:import { polygon, polygonMumbai } from '@reown/appkit/networks';
-
Add to networks array:
networks: [base, baseSepolia, polygon, polygonMumbai]
-
Update wallet store in
src/lib/stores/walletStore.ts:export const getSupportedChainIds = () => [base.id, baseSepolia.id, polygon.id, polygonMumbai.id]; export const getChainName = (chainId: number) => { switch (chainId) { case base.id: return 'Base'; case baseSepolia.id: return 'Base Sepolia'; case polygon.id: return 'Polygon'; case polygonMumbai.id: return 'Polygon Mumbai'; default: return 'Unknown'; } };
- Update theme colors in
src/lib/mint.css - Modify components in
src/lib/components/ - Change the homepage in
src/routes/+page.svelte - Update the navbar in
src/lib/components/Navbar.svelte
-
Create a new route in
src/routes/:<!-- src/routes/my-page/+page.svelte --> <script> import { account, isWalletConnected } from '$lib/stores/walletStore'; </script> <h1>My Custom Page</h1> {#if $isWalletConnected} <p>Welcome, {account.address}!</p> {:else} <p>Please connect your wallet to continue.</p> {/if}
-
Add navigation in
src/lib/components/Navbar.svelte:<a href="/my-page" class="text-surface-700 dark:text-surface-300 hover:text-surface-900 dark:hover:text-surface-100"> My Page </a>
Complete wallet connection component with network status and disconnect functionality.
<WalletStatus />Displays ETH balance with automatic updates.
<!-- ETH balance -->
<ETHBalance />Button that validates wallet connection and network.
<TransactionButton onClick={handleTransaction}>
Send Transaction
</TransactionButton>Handles contract function calls with error handling.
<ContractInteraction
contractAddress="0x..."
abi={contractABI}
functionName="transfer"
args={[toAddress, amount]}
value="0"
onSuccess={handleSuccess}
onError={handleError}
>
Transfer Tokens
</ContractInteraction>import {
account,
network,
isWalletConnected,
walletActions,
isChainSupported,
getChainName
} from '$lib/stores/walletStore';
// Check wallet state
$: console.log('Connected:', $isWalletConnected);
$: console.log('Address:', $account.address);
$: console.log('Network:', $network.chainId);
// Perform actions
walletActions.open(); // Open wallet modal
walletActions.switchNetwork(84532); // Switch to Base Sepolia
walletActions.disconnect(); // Disconnect wallet
// Check network support
if ($network.chainId && isChainSupported($network.chainId)) {
console.log('Supported network:', getChainName($network.chainId));
}import {
formatAddress,
formatTokenAmount,
getProvider,
getSigner,
isValidAddress,
getExplorerUrl
} from '$lib/utils/web3';
// Format addresses
const shortAddress = formatAddress('0x1234...5678');
// Format token amounts
const formatted = formatTokenAmount('1000000000000000000', 18);
// Get provider and signer
const provider = getProvider();
const signer = await getSigner();
// Validate addresses
const isValid = isValidAddress('0x...');
// Get explorer URLs
const txUrl = getExplorerUrl(84532, '0x...');- Push your code to GitHub
- Connect your repository to Vercel
- Add environment variables in Vercel dashboard
- Deploy!
- Push your code to GitHub
- Connect your repository to Netlify
- Add environment variables in Netlify dashboard
- Deploy!
This template works with any platform that supports SvelteKit. Just make sure to:
- Set your
VITE_PROJECT_IDenvironment variable - Build with
npm run build - Serve the
builddirectory
-
"VITE_PROJECT_ID is not set"
- Make sure you have a
.envfile with your project ID - Restart your development server after adding environment variables
- Make sure you have a
-
Wallet not connecting
- Check that your project ID is correct
- Make sure you're using a supported wallet (MetaMask, WalletConnect, etc.)
-
Network not supported
- The template supports Base Sepolia (84532) and Base Mainnet (8453)
- Add more networks in
src/lib/config/appkit.tsif needed
-
Build errors
- Run
pnpm run checkto see TypeScript errors - Make sure all imports are correct
- Check that all environment variables are set
- Run
- Check the SvelteKit documentation
- Read the Reown AppKit docs
- Look at the Ethers.js documentation
- Review the Skeleton UI docs
- Add your smart contracts and update the contract configuration
- Customize the UI to match your brand
- Add more pages and features
- Test on testnet before deploying to mainnet
- Deploy and share your dApp!
Happy building! 🚀