Three ready-to-render SemanticBundles live in
docs/demo/bundles. Each is generated from a real Foundry
fixture (contracts/fixtures), so what you see is exactly what the analyzer
produces from compiled ABIs - no hand-tuning.
| Demo | Fixture | Standards detected | Shows off |
|---|---|---|---|
erc20.bundle.json |
MockERC20 |
ERC-20 | Token transfer/approve UI + owner-gated mint |
vault.bundle.json |
MockVault |
ERC-20, ERC-4626 | Vault deposit/mint/withdraw/redeem with previews and share balances |
rwa.bundle.json |
MockRWA |
ERC-20, AccessControl, Pausable | Role manager, an emergency pause panel, and confirmation for critical ops |
Regenerate them after changing a fixture:
cd contracts/fixtures && forge build # produce artifacts
cd - && pnpm gen:abi # extract ABIs → contracts/fixtures/abi
pnpm build && pnpm gen:demos # rebuild the bundlesThe standalone template renders whatever bundle it finds - so a demo is just data.
pnpm build
cp docs/demo/bundles/vault.bundle.json apps/generated-app/public/bundle.json
pnpm --filter @semantic-dapp/generated-app devOpen the printed URL. Swap the copied file for erc20/rwa to see the others.
Without a public/bundle.json the template falls back to a committed demo token.
pnpm build
node packages/cli/dist/cli.js export \
--bundle docs/demo/bundles/rwa.bundle.json --out /tmp/rwa-app
cd /tmp/rwa-app && pnpm install && pnpm build
node <repo>/packages/cli/dist/cli.js serve --dir distexport scaffolds a standalone app with the bundle injected; build it, then
serve (or any static host) previews it. See export.md for the
full CLI reference, including building a bundle straight from an ABI file.
The bundles carry chainId 31337 and rpcUrl http://127.0.0.1:8545, matching the
Foundry deploy script. To make the write buttons real, start Anvil and deploy:
anvil # terminal 1
cd contracts/fixtures
forge script script/Deploy.s.sol \
--rpc-url http://127.0.0.1:8545 --broadcast # terminal 2The script prints the deployed MockERC20, MockVault and MockRWA addresses;
add the matching address to a bundle (or import the contract by address in the
studio) to read and write against the live deployment.
To let anyone try the write buttons without running Anvil, deploy the same fixtures to a public testnet (e.g. Sepolia or Base Sepolia). This needs a funded deployer key, so it is a manual step:
-
Fund a throwaway key with testnet ETH from a faucet (never use a key that holds real funds).
-
Deploy + verify (the deploy script already reads
PRIVATE_KEYand works against any RPC):cd contracts/fixtures export PRIVATE_KEY=0x<funded-testnet-key> export SEPOLIA_RPC_URL="https://sepolia.infura.io/v3/<key>" # or any RPC export ETHERSCAN_API_KEY="<key>" # for --verify forge script script/Deploy.s.sol \ --rpc-url "$SEPOLIA_RPC_URL" --broadcast \ --verify --etherscan-api-key "$ETHERSCAN_API_KEY"
Verifying the source means the Studio's By address import resolves the ABI automatically and shows a
verifiedprovenance badge. -
Point a demo at it - either import the printed address in the Studio (chain id
11155111for Sepolia), or bake it into a bundle for the standalone app by editingchainId/rpcUrl/addressin a copy of the relevantdocs/demo/bundles/*.json(or regenerate withgen:demosafter updating the generator's constants).
Because the address block explorer is known for these chains, transaction hashes
and addresses will link out automatically (see the known-chain registry in
@semantic-dapp/execution).
Reads on public RPCs can be rate-limited or CORS-blocked in the browser; a connected wallet on the same chain is used as a fallback transport, and an unreachable RPC now surfaces a recovery banner instead of silently-empty reads.