Please note that zkApp programmability is not yet available on Mina Mainnet, but zkApps can now be deployed to Berkeley Testnet.
How to Write a zkApp UI
Learn how to write an UI for your smart contract
To allow users to interact with your smart contract, you’ll typically want to build a website UI.
This UI can be written with any framework (e.g. React, Vue, Svelte, etc.) or plain HTML and JavaScript.
This page is a work in progress.
Adding your smart contract as a dependency of the UI
Setup
The index.ts
file is the entry point of your project. This file only imports all smart contract classes you want access to, and exports them. This pattern allows you to specify which smart contracts are available to import when consuming your project from npm within your UI.
import { YourSmartContract } from "./YourSmartContract.js";
export { YourSmartContract };
Local development
The npm link
command allows to use your smart contract within your UI project during local development without needing to publish it npm. This allows for rapid development.
- Using a command line, change into your smart contract project directory using
cd <your-project>
, typenpm link
, and hit enter. - Using a command line, change into your UI project directory using
cd <your-ui-project>
, typenpm link <your-package-name>
, and hit enter.your-package-name
is thename
property used within your smart contract'spackage.json
. - Import into your UI project like normal, using
import { YourSmartContract } from ‘your-package-name’;
.
Remember to run npm run build
in your smart contract directory after making any changes in order for changes to be reflected in the smart contract consumed by your UI project.
For additional details about npm link
, see the full npm reference docs.
Publish to npm for production
- Create an npm account: Create one here if you don't have one yet.
- Login: To sign in, enter
npm login
on the command line. You will be prompted to enter your username, password, and email address. - Publish: To publish your package, enter
npm publish
on the command line at the root of your smart contract project directory. If the package name already exists on npm, you will get an error. You can change the package name by changing the name property in yourpackage.json
.
You can check if a package name already exists on npm using the npm search
terminal command. To avoid naming collisions, npm allows to publish scoped packages:
@your-username/your-package-name
. For additional details about publishing packages including scoped packages, see the full npm reference docs.
Consuming your smart contract in your UI
Once you have published your smart contract to npm, you can easily add it to any UI framework of your choosing by importing the package.
- Install your smart contract package: To install your package, run the following npm command:
npm install your-package-name
from the root of your UI project directory. Or if you published a scoped npm package, runnpm install @your-username/your-project-name
. - Import your smart contract package into the UI using:
import { YourSmartContract } from ‘your-package-name’;
, whereYourSmartContract
is the named export that you chose in your smart contract.
For a more performant UI, you may want to render your UI before importing and loading your smart contract. This allows the SnarkyJS wasm workers to perform initialization without blocking the UI.
For example, if your UI is built using React, loading the smart contract in a useEffect
,
instead of a top level import, will give the UI time to render its components before
loading SnarkyJS.
Loading your contract with React
useEffect(() => {
(async () => {
const { YourSmartContract } = await import("your-package-name");
})();
}, []);
Loading your contract with Svelte
onMount(async () => {
const { YourSmartContract } = await import("your-package-name");
});
Loading your contract with Vue
onMounted(async () => {
const { YourSmartContract } = await import("your-package-name");
});
Enabling COOP and COEP headers
To load SnarkyJS code in your UI, you must set the COOP and COEP headers as described below. These enable SnarkyJS' use of SharedArrayBuffer, which SnarkyJS relies on to enable important WebAssembly features.
Cross-Origin-Opener-Policy
must be set tosame-origin
.Cross-Origin-Embedder-Policy
must be set torequire-corp
.
You can enable these headers a number of different ways. If you deploy your UI to a host such as Vercel or Cloudflare Pages, you can set these headers in a custom configuration file (see below). Otherwise, you can set these headers in the server framework of your choice (e.g. Express for JavaScript).
Vercel
If your app will be hosted on Vercel, you can set these headers via vercel.json
.
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Cross-Origin-Opener-Policy", "value": "same-origin" },
{ "key": "Cross-Origin-Embedder-Policy", "value": "require-corp" }
]
}
]
}
Cloudflare Pages
If your app will be hosted on Cloudflare Pages, you can set these headers via a _headers
file.
/*
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp