Skip to content

Build & publish a dApp

This is the full publishing path for a first Product app: start from a Product SDK frontend, build a static bundle, register a .dot name, and publish with the pad deploy CLI. When it works, the app is reachable as <name>.dot inside the Polkadot app and at https://<name>.dev-dot.li on the web gateway.

This is a devnet

The Polkadot Products Devnet is a public developer preview. Devnet tokens have no real value, and flows may change. Never paste a mnemonic or private key into a shared terminal, a config file you commit, or a support request.

How publishing works

An app is a static bundle. The pad CLI merkleizes your build directory into a content-addressed DAG-PB archive, uploads its blocks to the Bulletin Chain, then writes the resulting root CID as an ENS-style contenthash into the DotNS ContentResolver contract on Asset Hub. The web gateway resolves the name to that CID entirely client-side and renders the bundle.

flowchart TD
  A[Built static dist/] --> B[pad: merkleize to DAG-PB CAR]
  B --> C[Chunk ~2 MiB + skip unchanged blocks]
  C --> D[Bulletin: TransactionStorage.store_with_cid_config]
  D --> E[Store DAG-PB root node = content root CID]
  E --> F{DotNS on Asset Hub}
  F -->|not owned| G[register name]
  F -->|owned| H[skip]
  G --> I[setContenthash node = 0xe301 + CIDv1]
  H --> I
  I --> J[optional Publisher.publish label]
  J --> K[Live at name.dot and https://name.dev-dot.li]

Prerequisites

Install the SDK and the CLIs you will use:

npm i @parity/product-sdk
npm i -g @parity/polkadot-app-deploy   # deploy CLI (bin: pad)
npm i -g @parity/dotns-cli             # DotNS CLI (bin: dotns)
npm i -g @polkadot-community-foundation/cdm-cli               # contract manifest CLI (bin: cdm)

The publishing CLIs (pad and dotns) select a network with --env <network>. CDM uses -n/--name <network> instead. The concrete preset name for the public devnet is provided by the team operating the network — see Networks & endpoints.

You need storage authorization

The deploy account must own the .dot name and hold a live Bulletin storage authorization (TransactionStorage.Authorizations). The CLI never self-authorizes and fails fast if the authorization is missing or expired; the network operator grants quota. Fund the account from the faucet first.

1. Scaffold with the Product SDK

Start from a reference template rather than an empty directory. The playground template (playground-template.dev-dot.li, source playground-app-template) is a minimal React + Vite + TypeScript app wired to the Host API: it surfaces the app-scoped product account (SS58 and H160 addresses) and signs a message via @parity/product-sdk-signer. For a plain HTML/CSS/JS starting point, use dotli-starter, which detects the host container with @parity/product-sdk-host and submits extrinsics through the host provider.

Your app runs as a Product inside the Polkadot host (mobile, desktop, or the web gateway), which lends it a signer and routes all chain RPC. Reach the platform through @parity/product-sdkcreateApp(config) returns an app with wallet, chain, and cloud-storage APIs, and the SDK also exposes contract and identity modules. See Use platform services from the SDK.

2. Build the frontend

Produce a static build directory. With a Vite template:

npm install
npm run build   # emits dist/

The output (dist/) is what you publish. If your app is contract-backed, deploy and register its PolkaVM contracts first and record them in a cdm.json manifest with the cdm CLI — see Deploy & register contracts.

3. Register a .dot name

Names are .dot domains managed by DotNS. Check availability and register with the DotNS CLI:

dotns lookup <name>.dot --env <network>
dotns register <name>.dot --env <network>

Label eligibility depends on length and personhood tier — short or reserved names are gated behind proof of personhood. See Register a .dot name and the Naming architecture for the full rules.

Tip

pad will register the name for you during deploy if the signing account does not already own it, so this step is optional when you deploy with an account that will hold the name.

4. Publish with pad

Point pad at your build directory and the target name:

pad ./dist <name>.dot --env <network>

pad uploads the bundle to Bulletin (skipping unchanged blocks on repeat deploys), registers the name if needed, and writes the content hash on Asset Hub. Add --publish to also list the app in the on-chain Publisher registry so directory apps such as Browse can enumerate it:

pad ./dist <name>.dot --env <network> --publish

Once the transaction settles, the app is live at <name>.dot in the Polkadot app and at https://<name>.dev-dot.li on the web gateway. See List your app in Browse for discovery.

Reference apps to study

These are working, deployed examples (source under paritytech):

  • Simple Survey — storage-indexed app: survey JSON on Bulletin, an Asset Hub contract indexes response CIDs.
  • CDM Frontend and DotNS UI — reference tools for contracts and names.

Learn more