+ {/* Header */}
+
+
+ {/* CUSTOMIZE: Token name */}
+ MyToken
+
+
+
+
+ {/* Main Content */}
+
+ {/* Token Info Card */}
+
+
Token Info
+ {/* CUSTOMIZE: Replace with actual token data from useToken hook */}
+
+
Name: MyToken
+
Symbol: MTK
+
Balance: --
+
+
+
+ {/* Transfer Card */}
+
+
Transfer
+ {/* CUSTOMIZE: Wire up transfer form with useToken hook */}
+
+
+
+
+ );
+}
+
+export default App;
diff --git a/templates/starters/op20-token/frontend/src/hooks/useToken.ts b/templates/starters/op20-token/frontend/src/hooks/useToken.ts
new file mode 100644
index 0000000..ff13476
--- /dev/null
+++ b/templates/starters/op20-token/frontend/src/hooks/useToken.ts
@@ -0,0 +1,122 @@
+// useToken — Hook for OP-20 token interactions
+// CUSTOMIZE: Replace CONTRACT_ADDRESS with your deployed contract address
+// CUSTOMIZE: Import your token's ABI
+//
+// This hook follows all OPNet frontend conventions:
+// - getContract from opnet package (NOT @btc-vision/transaction)
+// - signer: null, mldsaSigner: null (wallet handles signing)
+// - BigInt for all amounts
+// - Simulate before send
+
+import { useState, useEffect, useCallback } from 'react';
+// import { getContract, JSONRpcProvider } from 'opnet';
+// import { networks } from '@btc-vision/bitcoin';
+// import type { OP20Contract } from 'opnet';
+
+// CUSTOMIZE: Replace with your deployed contract address
+// const CONTRACT_ADDRESS = 'bcrt1p...your-contract-address';
+
+// CUSTOMIZE: Set your network
+// const NETWORK = networks.opnetTestnet;
+// const PROVIDER_URL = 'https://testnet.opnet.org';
+
+interface TokenMetadata {
+ name: string;
+ symbol: string;
+ decimals: number;
+ totalSupply: bigint;
+}
+
+interface UseTokenReturn {
+ metadata: TokenMetadata | null;
+ balance: bigint;
+ transfer: (to: string, amount: bigint) => Promise