skills/sails-frontend/SKILL.md
Use when a builder needs to build or extend a React or TypeScript frontend for a standard Gear/Vara Sails app, using Sails-JS, generated clients, React hooks, and low-level Gear-JS only where it adds value. Do not use for Rust-only contract work, raw gstd service design, or non-Vara frontends.
npx skillsauth add gear-foundation/vara-skills sails-frontendInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Keep frontend work on the typed Sails path first: generated lib.ts plus @gear-js/react-hooks, with @gear-js/api reserved for low-level fallback cases that the Sails stack does not cover cleanly.
assets/frontend-bootstrap-checklist.md../../references/sails-frontend-and-gear-js.md../../references/sails-idl-client-pipeline.md../../references/sails-cheatsheet.md../../references/sails-idl-v2-syntax.md — IDL v2 syntax for understanding generated client contracts../../references/sails-gtest-and-local-validation.md../../references/scale-binary-decoding-guide.md../../references/voucher-and-signless-flows.mdFor a straightforward app (counter, single-service CRUD) where the contract is already built:
npx create-vara-app my-dapp --idl path/to/service.idlcd my-dapp && npm install && npm run devSkip the rest of this skill unless you need to customize screens, add Next.js support, wire vouchers, or handle advanced flows.
When a Sails app needs a frontend — whether the project is brand-new or an existing repo without one — start with create-vara-app.
Prerequisite: the contract must be built first so the .idl file exists. If the .idl is not available yet, build the contract (cargo build) or use create-vara-app without --idl to scaffold with a demo contract.
npx create-vara-app my-dapp --idl path/to/service.idl
npm: https://www.npmjs.com/package/create-vara-app GitHub: https://github.com/gear-foundation/create-vara-app
This scaffolds a Vite + React + TypeScript frontend with:
Without --idl, scaffolds with a demo contract. With --idl, parses the service name and generates typed components automatically.
After the contract changes, re-run the scaffold from the project root:
npx tsx scripts/scaffold-client.ts
Detection: if the project has scripts/scaffold-client.ts, it was bootstrapped with create-vara-app. Use the scaffold script for regeneration. Otherwise use sails-cli.
After bootstrap, continue with the Standard Path below to customize screens, add queries, or wire advanced flows.
.idl as the frontend source of truth.scripts/scaffold-client.ts exists, run npx tsx scripts/scaffold-client.ts from the project root. Otherwise use sails-cli before wiring screens, hooks, or forms.useProgram with the generated Program class for typed service access.useProgramQuery for Sails queries and useProgramEvent only where live subscriptions are actually needed.usePrepareProgramTransaction to obtain gasLimit, extrinsic, or fee data before send when the UX needs validation or previews.useSendProgramTransaction for commands, await result.response, and surface pending, success, and failure states in the UI instead of relying only on extrinsic submission.voucherId only when the flow is intentionally voucher-backed or prepaid. Treat full gasless or signless UX as a separate product decision; use the dedicated EZ-transactions path when the product spec requires it.@gear-js/api only for dynamic multi-IDL control, metadata work, raw mailbox or voucher flows, or direct api.message.send, api.programState.read, and api.programState.readUsingWasm cases. On those paths, identify whether the bytes are IDL-driven, metadata-driven, or state.meta.wasm-driven before decoding.When the target frontend is a Next.js App Router project:
@gear-js/api, sails-js, and wallet subdependencies use browser globals and WASM that break in Server Components. Add them to transpilePackages in next.config.js and mark all Gear provider/hook files with 'use client'.@gear-js/react-hooks or its wallet subdependencies cause persistent server-build failures after transpilePackages, fall back to a lower-level sails-js + @gear-js/api integration path with runtime-only await import(...) boundaries in client components. If falling back, commit to the lower-level path for the entire project.@polkadot/util and @polkadot/util-crypto as explicit dependencies — they are no longer pulled in transitively without the hooks stack.next/font/google fetches fonts at build time and will fail in offline CI or proof-loop environments. Use next/font/local or system fonts instead.next build before tsc --noEmit in App Router projects; route types are generated during the build step.See ../../references/sails-frontend-and-gear-js.md for the full Next.js compatibility guide.
In monorepos with both a Rust Sails program and a web frontend, check for app/ directory collisions. The Rust program crate conventionally uses app/ and Next.js App Router also expects app/. Common resolution: keep the Rust app/ crate and place the frontend in frontend/ or web/.
When using sails-js for runtime IDL parsing (not the generated lib.ts client path), the Sails class requires an explicit parser instance from the separate sails-js-parser package. See ../../references/sails-frontend-and-gear-js.md for the initialization pattern.
Before handoff, validate the installed sails-js API surface against the conventions in ../../references/sails-frontend-and-gear-js.md. Key points:
signAndSend(), not sendAndWait().program.<serviceName>.<functionName> exists on the generated client before wiring UI.Before generating or editing a Vara frontend, resolve package versions from the target project and the current package metadata, not from memory.
Order of precedence:
package.jsonpeerDependencies of @gear-js/react-hooks and related packagesRules:
package.json.@gear-js/wallet-connect, also verify the required UI package set and required styles.If the frontend uses packaged Gear wallet/UI components such as:
@gear-js/wallet-connect@gear-js/ui@gear-js/vara-uithen import the required package styles at the app entrypoint before considering the wallet integration complete.
Minimum check:
For wallet-bound actions, distinguish at least these states in the UI:
Do not collapse these states into a single generic “wallet not ready” message.
Disabled signed actions should expose a visible reason, such as:
Validate required env values such as endpoint and program IDs before rendering feature screens.
Missing env values must fail visibly, not silently.
Do not hand off a Vara frontend until all of the following are true:
QueryClientProvider, ApiProvider, AccountProvider, and AlertProvidersails-js API surface was validated: signAndSend method, positional arguments, and query builder pattern match the conventions in the reference docsails-js-parser is installed and parser initialization is presenttranspilePackages and 'use client' boundaries are confirmedEvery write action must expose at least:
Do not rely only on console logs or implicit alerts.
Before handoff, review the frontend specifically for:
@gear-js/apiName these decisions explicitly in the work product:
.idl and generated client pathwatch subscriptions everywhere by default; only subscribe where the UX truly benefits.sails-idl-client for the canonical handoff pattern.sendAndWait() exists on the sails-js transaction builder; the correct method is signAndSend().development
Use when approved tasks require Rust code changes in a Sails ethexe workspace with the ethexe feature enabled. Do not use for standard Gear/Vara Sails apps without ethexe, or when the spec or architecture is still unsettled.
development
Use when a builder needs to design or review architecture for a Sails ethexe app with dual-transport, payable methods, Solidity interface generation, or Ethereum-style events. Do not use for standard Gear/Vara Sails apps without ethexe.
development
Use when a builder needs to design or debug calls from a standard Gear/Vara Sails program into runtime builtin actors such as BLS12-381, staking, proxy, or ETH bridge, including ActorId derivation, request encoding, reply decoding, and gas or ED budgeting. Do not use for regular program-to-program messaging, Vara.eth or ethexe-only work, non-Sails repositories, or runtime-maintenance tasks inside the Gear repo.
development
Use when a builder needs a read-side indexer and query API for a standard Gear/Vara Sails app using program events, IDL-driven decoding, projected read models, and optional on-chain query enrichment. Do not use for command-side backends, generic Node APIs, non-Sails repositories, Vara.eth or ethexe-first work.