Skip to content

Latest commit

 

History

History
206 lines (139 loc) · 8.3 KB

File metadata and controls

206 lines (139 loc) · 8.3 KB

Deployment Guide

This guide covers deploying the frontend and parachain runtime.

Frontend Deployment

The frontend is a static Vite app that works on any hosting platform. It uses hash-based routing (HashRouter) and relative asset paths (base: "./") so it works correctly on IPFS gateways, GitHub Pages, and subdirectory deployments without configuration.

The app exposes the Substrate WebSocket endpoint on the home page. On localhost it defaults to the local dev URL; on hosted deployments it defaults to Polkadot Hub TestNet. You can also set a build-time default with VITE_WS_URL (see web/.env.example).

GitHub Pages

The simplest option for public demos.

Setup (one-time):

  1. Go to your repo Settings > Pages
  2. Under Source, select GitHub Actions

How it works:

The workflow at .github/workflows/deploy-github-pages.yml runs automatically on push to main/master. It builds the frontend and deploys to GitHub Pages.

Your site will be available at:

https://<username>.github.io/<repo-name>/

Manual trigger:

Go to Actions > Deploy to GitHub Pages > Run workflow to trigger a deploy without pushing code.

DotNS (IPFS + Polkadot naming)

Deploys the frontend to IPFS and registers a .dot domain that resolves to it via the Polkadot naming system.

How it works:

The workflow at .github/workflows/deploy-frontend.yml is manual on purpose. It:

  1. Builds the frontend
  2. Uploads to IPFS
  3. Registers/updates the DotNS domain via paritytech/dotns-sdk

The domain basename is entered when you dispatch the workflow. Domain registration is automatic (register-base: true).

Configuration:

  • Open Actions > Deploy Frontend to DotNS > Run workflow
  • Enter a unique DotNS basename (lowercase, 9+ letters followed by exactly 2 digits, e.g. my-cool-project42)
  • The workflow uses Alice's dev account by default, which works for free registration on Paseo testnet. To use your own account, set the DOTNS_MNEMONIC secret in your repo settings.

Local IPFS deployment:

You can also deploy to IPFS locally without CI:

# Install web3.storage CLI (one-time)
npm install -g @web3-storage/w3cli
w3 login your@email.com
w3 space create polkadot-stack-template

# Deploy
./scripts/deploy-frontend.sh

This builds the frontend, uploads to IPFS, and prints the gateway URL plus the DotNS follow-up steps.

Other platforms

Since the frontend is a static build, it works on any static hosting:

cd web && npm install && npm run build
# Output: web/dist/

Upload web/dist/ to Vercel, Netlify, Cloudflare Pages, S3, or any static file server.

Parachain Runtime

Local development

# Build and start with polkadot-omni-node
./scripts/start-dev.sh

This builds the runtime WASM, generates a chain spec, and starts the lightweight solo-node path. Endpoints:

  • Substrate RPC: ws://127.0.0.1:9944 by default

This solo-node mode is intentionally optimised for quick runtime and pallet iteration. Use the relay-backed scripts (./scripts/start-all.sh or ./scripts/start-local.sh) when you want the full Polkadot stack.

All local scripts also support STACK_PORT_OFFSET plus explicit STACK_SUBSTRATE_RPC_PORT and STACK_FRONTEND_PORT overrides. When you use those scripts, the frontend dev server, CLI defaults, and PAPI refresh all follow the active port settings automatically.

Local node flags

The local scripts currently start omni-node with the equivalent of:

polkadot-omni-node \
  --chain blockchain/chain_spec.json \
  --tmp \
  --alice \
  --force-authoring \
  --dev-block-time 3000 \
  --unsafe-force-node-key-generation \
  --rpc-cors all

What each flag is doing:

  • --chain blockchain/chain_spec.json: run this template's generated chain spec instead of omni-node's built-in dev chain
  • --tmp: use a temporary base path and delete chain data on shutdown
  • --alice: use Alice's dev keys for authoring and signing
  • --force-authoring: keep producing blocks even without peers
  • --dev-block-time 3000: use omni-node's solo dev sealing mode so blocks keep authoring without a relay chain
  • --unsafe-force-node-key-generation: allow omni-node to generate a temporary network key for this throwaway local authority
  • --rpc-cors all: keep browser-based local tooling working without extra CORS setup

When you might change these later:

  • Remove --tmp if you want local chain state to persist across restarts.
  • If you remove --tmp, also set an explicit --base-path so you control where chain data is stored.
  • If you remove --tmp, you should also stop relying on --unsafe-force-node-key-generation and generate a stable node key instead.
  • Replace --alice with another dev account or your own key setup if you do not want Alice authoring blocks.
  • Remove --force-authoring if you only want block production when the node is fully participating in a network.
  • Remove --dev-block-time only if you are switching to a relay-backed environment such as Zombienet.

This repo now generates a repo-specific chain ID instead of the generic custom default. That reduces accidental collisions with other local projects. If you move to a persistent base path later, it is still a good idea to keep the base path unique per project.

Zombienet (multi-node)

./scripts/start-local.sh

Use ./scripts/start-all.sh if you want the relay-backed network plus frontend startup in one command.

If you need a second relay-backed stack at the same time:

STACK_PORT_OFFSET=100 ./scripts/start-local.sh

IPFS content (Pinata)

Proposal descriptions and per-proposal photos are stored off-chain on IPFS via Pinata; only the CID is recorded on-chain.

Genesis fixtures are pinned by scripts/pin-genesis-content.mjs:

VITE_PINATA_API_KEY=... VITE_PINATA_SECRET_KEY=... \
  node scripts/pin-genesis-content.mjs

This pins each entry in blockchain/genesis-content/proposals.json, the per-slug images in blockchain/genesis-content/images/, and re-encrypts the residents' phone numbers in blockchain/genesis-content/homes.json with the dev committee public key. The output goes to blockchain/runtime/src/genesis_content.rs; commit the result. Pass --skip-ipfs to refresh phone ciphertexts only.

Frontend uploads (proposal images and rich descriptions) use the same Pinata account; set VITE_PINATA_API_KEY and VITE_PINATA_SECRET_KEY in web/.env (see web/.env.example). Without credentials the proposal form falls back to text-only.

CLI

Signer options

All write commands accept --signer (-s) which auto-detects the format:

--signer alice                              # dev account name
--signer "bottom drive obey lake ..."       # mnemonic phrase
--signer 0x5fb92d6e98884f76de468fa3f...     # raw secret seed

Default is alice if omitted.

Commands

# Chain info
cargo run -p stack-cli -- chain info
cargo run -p stack-cli -- chain blocks

# Membership
cargo run -p stack-cli -- membership apply --flat-number 305 --block-id 1 --signer //newuser
cargo run -p stack-cli -- membership approve <application-hash> --signer alice
cargo run -p stack-cli -- membership list-homes
cargo run -p stack-cli -- membership show-committee
cargo run -p stack-cli -- membership start-election --signer alice

# Governance
# create-proposal is an unsigned bare call (CheckCreateProposal extension);
# --signer only identifies the author. --cost is required unless --funding none.
cargo run -p stack-cli -- governance create-proposal --title "Install EV chargers" \
  --description-cid QmXyz... --deadline 1776902400000 \
  --funding reserve --cost 45000 --signer alice
cargo run -p stack-cli -- governance list-proposals
cargo run -p stack-cli -- governance get-tally <proposal-id>
cargo run -p stack-cli -- governance close-proposal <proposal-id> --signer alice

See cargo run -p stack-cli -- membership --help and governance --help for the full subcommand list (elections, comments, transfer, candidate Q&A, etc.).

Use --url to target a different endpoint:

cargo run -p stack-cli -- --url wss://your-node:9944 governance list-proposals