Casa Tookan's web build, devapp.casatookan.com, opens your app in a browser the way the phone's dApp browser does: same providers, same approval sheets, same CEID and Tookans — without a phone in the loop.
Developer tool — test wallets only<head>, serve your manifest with CORS, let devapp frame your page, and keep your session cookie when framed: your app then runs in devapp as it does in the phone.On a phone, Casa Tookan injects its providers — window.ethereum, the Bitcoin providers, window.unisat, window.webXCP, window.casaTookan — into your page's WebView. A browser cannot inject a script into a page of another origin, so devapp opens your app in an iframe, and a small script your page loads, the bridge, asks devapp for those providers over postMessage. Every call then goes through Casa Tookan's approval sheets, and signatures are made by its web signer.
The bridge sets window.casaTookan.isCasaTookan and window.ethereum.isCasaTookan as soon as it runs — over the window.ethereum a wallet extension such as MetaMask put in the frame. Calls made before the providers arrive wait for them.
Some extensions (MetaMask) lock window.ethereum in every frame: nobody can replace it, and it stays theirs. Casa Tookan announces itself through EIP-6963 with the rdns com.everdreamsoft.casatookan: pick that provider when it is announced, window.ethereum only otherwise.
Your page loads the bridge only when devapp frames it. In the phone, in a plain tab or framed by any other site, it loads nothing.
<head>Before your own scripts, so it runs before them. It loads casa-tookan-web.js from devapp only when devapp is the page framing yours.
<script>
(function () {
if (window.parent === window || window.ReactNativeWebView) return;
var o = (location.ancestorOrigins && location.ancestorOrigins[0]) || '';
if (!o && document.referrer) try { o = new URL(document.referrer).origin; } catch (e) {}
if (o === 'https://devapp.casatookan.com')
document.write('<script src="' + o + '/casa-tookan-web.js"><\/script>');
})();
</script>
A page with a strict Content-Security-Policy needs https://devapp.casatookan.com in script-src, and 'unsafe-eval' while devapp frames it./.well-known/wallet-app.json (or casatookan.json) from its own origin: serve it with Access-Control-Allow-Origin: * — it is public. Without it the browser blocks the read, Casa Tookan sees no declared capability and refuses casaTookan.ceid and tookans calls. A phone applies no CORS: this only shows on the web. Best: give every /.well-known/ answer that header, the 404s included, so devapp can tell a file you don't serve from a network failure (it assumes a missing file when the browser is online).Content-Security-Policy: frame-ancestors 'self' https://devapp.casatookan.com on your pages: devapp may frame them, other sites may not. A page sent with X-Frame-Options or a stricter frame-ancestors stays blank in devapp.SameSite=Lax cookie is not sent, and your server answers 401 right after a sign-in that worked. Over https, set it SameSite=None; Secure; Partitioned — partitioned, the cookie is kept per top-level site, so a session opened in devapp is not the one a player has elsewhere, and browsers that block third-party cookies still keep it.
POST whose Sec-Fetch-Site is neither same-origin nor none, or one that is not application/json (another site cannot send JSON without a CORS preflight you never grant).For Ethereum, keep listening for Casa Tookan's announcement — in devapp it arrives a few milliseconds after your scripts; in the phone it answers your request:
let casaEthereum = null;
window.addEventListener('eip6963:announceProvider', (e) => {
if (e.detail?.info?.rdns === 'com.everdreamsoft.casatookan') casaEthereum = e.detail.provider;
});
window.dispatchEvent(new Event('eip6963:requestProvider'));
const ethereum = () => casaEthereum ?? window.ethereum; // at the moment you call it
Then open devapp, create a test wallet, and type your app's URL in Browse. A page without the bridge shows a notice with the line to add.
Serve your app on http://localhost and open that URL in devapp: browsers treat localhost as a secure origin, so an https page may frame it, and your page loads the bridge from devapp like any other. Chrome may ask devapp for access to your local network the first time: accept it. On http://localhost, Chrome accepts Secure cookies too.
| Rule | Why |
|---|---|
| Trust devapp's origin only | The bridge evaluates the providers' code devapp sends: an origin you trust there can run code in your page. Never add localhost or a wildcard to the check in production. |
| Test wallets only | The web signer keeps its keys in the browser's storage, encrypted with a password, where an extension or a script on devapp's origin could reach them. Never type a recovery phrase that holds value; create a wallet for testing. |
| devapp is never framed | It is served with frame-ancestors 'none': no site can lay the wallet under a click. |
| Tokens, not pages | CEID tokens and Tookans receipts are signed by Casa Tookan: verify them on your server as in the phone. A page — or a fake devapp — cannot forge them. |
No in-app purchases of Tookans, no WalletConnect pairing by camera, no App Attest or Play Integrity: those are phone features. Back and forward follow what the bridge reports.