Getting Started for Developers
This path is for building a first Product on the Polkadot Products Devnet.
The basic loop is small: build a static web app, give it a .dot domain, publish
the bundle, and use the SDK when the app needs platform services.
The shape of a first app
flowchart LR
A[Build web app<br/>@parity/product-sdk] --> B[Produce static dist/]
B --> C[Register a .dot domain<br/>@polkadot-community-foundation/dotns-cli]
C --> D[Publish bundle to Bulletin<br/>+ bind name<br/>pad]
D --> E[Live at name.dot in the app<br/>and https://name.dev-dot.li]
A -. optional .-> F[Deploy contracts<br/>cdm]
F --> A
A Product is a static web app: HTML, CSS, and JavaScript. It runs inside a
host — the Polkadot app or the web gateway at
https://dev-dot.li — which provides the wallet, signing
prompts, storage, and chain access. Publishing means making the bundle available
on the Devnet and pointing a .dot domain at it.
Before you start
Every command below runs through the CLIs you install in step 1, so install those first. You also need one signing account — if you don't already have a key, mint a throwaway one (no seed to import, no password). That account has to be ready in three ways before any command touches the chain:
- Funded with native tokens on Asset Hub for fees — Faucet.
- Mapped to its EVM address, once:
dotns account map --env devnet. Every CLI here signs PolkaVM transactions on Asset Hub, and an unmapped account fails on the first one. - Authorized to write to Bulletin, so step 5 can upload your bundle — Get storage authorization.
The CLIs do not share a keystore: dotns keeps its own (step 4), and pad
takes --mnemonic on the command line. They can use the same account.
1. Install the tooling
Node.js 22 or newer
pad and cdm both require Node 22+. On Node 20 they fail at startup with
an unrelated-looking error (a module SyntaxError, or
Missing WebSocket class). Check with node --version before installing.
npm i -g @polkadot-community-foundation/dotns-cli # dotns
npm i -g @polkadot-community-foundation/polkadot-app-deploy # pad, pad-bootstrap
npm i -g @polkadot-community-foundation/cdm-cli # cdm
Install only what you need: pad publishes (and can register the name for
you), dotns manages names in depth, cdm is only for contracts. The first two
are large — expect a few minutes and roughly 1.5 GB across the global prefix and
the npm cache, with no progress output while npm works.
Installing on ARM64 (e.g. Termux / Android)
On some ARM64 platforms a transitive dependency (node-datachannel, used
for optional peer-to-peer CID verification) ships no prebuilt binary, and its
native build fails during npm i -g. Skip the build with --ignore-scripts:
Only the peer-to-peer verification path is unavailable in this mode; the CLI's gateway-based CID verification still works.
Your app code needs the SDK too — see Packages & tools for the full list:
2. Choose a network preset
Every CLI takes the network as a flag, and this Devnet is devnet:
--env devnet for pad and dotns, -n devnet for cdm.
Always pass the flag
The same binaries ship paseo and paseo-next presets pointing at other
networks, and the default is not devnet. Omit the flag and your app lands
on a different chain, where nothing on this Devnet can see it.
3. Build a web app with the Product SDK
The Product SDK (@parity/product-sdk) gives your app typed access to the host:
wallet, storage, chain calls, contracts, and identity.
import { createApp } from "@parity/product-sdk";
const app = await createApp({
name: "my-app",
cloudStorage: { environment: "devnet" }, // defaults to paseo
});
const result = await app.cloudStorage!.upload("hello world");
if (result.ok) console.log(result.value); // the CID
Run inside a host
The SDK expects the Polkadot app or the web gateway to provide the host
connection. Outside one, createApp() itself throws
Host storage unavailable. Start from the
dotli-starter template, and
use @parity/host-api-test-sdk for automated tests. See
Use platform services from the SDK.
Build your app to a static directory (the reference template uses vite build → dist/).
4. Set up an account and register a .dot domain
Your deploy account must own the .dot domain before you can publish to it.
This is a CLI signing key, separate from any account in the Polkadot app.
For a hackathon you do not need to import a seed phrase or set a keystore password. Mint a fresh account and hand its mnemonic to the CLIs through the environment:
# One fresh BIP-39 mnemonic, generated with the crypto that ships inside the CLIs
export MNEMONIC="$(NODE_PATH="$(npm root -g)/@polkadot-community-foundation/dotns-cli/node_modules" \
node -e 'const c=require("@polkadot/util-crypto");c.cryptoWaitReady().then(()=>console.log(c.mnemonicGenerate()))')"
export DOTNS_MNEMONIC="$MNEMONIC" # dotns signs with this — no `dotns auth set`, no password
dotns account address # the throwaway's address — fund THIS at the faucet
The same $MNEMONIC is what pad takes when it publishes (--mnemonic
"$MNEMONIC"), so one account both owns the name and deploys to it. It lives only
in this shell session: save the phrase if you want to keep the name, or discard
it and the account is genuinely throwaway.
Set a key, or you sign as a shared account
With neither DOTNS_MNEMONIC/DOTNS_KEY_URI set nor dotns auth set run,
dotns falls back to a shared public dev account anyone can control, and
a name registered to it is not yours — anyone can transfer it away.
dotns prints a warning on every command when it does.
Prefer to reuse an account across sessions?
Store a mnemonic or key-uri in the encrypted dotns keystore instead of
the environment:
dotns auth set # choose `mnemonic`, paste it, then set a password
dotns account address # confirm the active account
The keystore password is then needed by every later command — export
DOTNS_KEYSTORE_PASSWORD to avoid an interactive prompt. See
Register a .dot domain.
With $MNEMONIC exported, register your name:
Use a label whose stem is nine characters or longer; shorter ones are gated behind proof of personhood. Registration is a commit-reveal flow that takes a few minutes, so confirm it landed before moving on:
See Register a .dot domain for the full
rules.
5. Publish the bundle with pad
pad uploads your static build and points the .dot domain at it. It does not
read the dotns keystore — give it the signer that owns the name:
That account must own the name and hold a Bulletin storage authorization; a
successful run ends with Verified on-chain: and the published CID.
Your app is now reachable as my-cool-app.dot in the Polkadot app and at
https://my-cool-app.dev-dot.li on the gateway. To give it a name, description
and icon in the directory, add a product config — see
Add card metadata.
To also list it in Browse, add --publish. That step needs proof of personhood,
which today comes from the Polkadot app rather than the CLI; without it the
deploy still succeeds and the app simply is not listed. See
List your app in Browse.
6. Optional — deploy contracts with cdm
Smart contracts on this Devnet are PolkaVM contracts on Asset Hub. The Contract Dependency Manager builds, deploys, publishes metadata, and registers addresses so downstream apps can resolve contracts by name.
cdm needs a Rust toolchain that npm i -g does not install — run cdm setup
first. See Deploy & register contracts for
the full sequence.
Continue in the guides
This page is the quickstart; each step has a full guide with the rules and edge cases. Find them all under the Guides tab:
-
The full publishing path — bundle, name, deploy, and card metadata.
-
Account setup, name rules, and the commit-reveal flow in depth.
-
Build, deploy, and register PolkaVM contracts with
cdm. -
Use platform services from the SDK
Chains, storage, contracts, and identity from your app.
-
Get your Product into the in-app directory.
Try the reference apps
Working examples are the fastest way to see the shape of a Product — start with Playground or Simple Survey; the full list is in More resources. The dotli-starter template is a good skeleton to build from.
To test as an end user, install the app and fund an account — see Create an account & get funds.