agentleFS
gear-foundationgear-foundation/vara-skills/skills/sails-frontend/SKILL.md

sails-frontend

Skill17 starsChanged 7 months agoMITView on GitHub

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.

  • Installs packages

We split this skill into the rules it gives an agent

39 rules. About 0 are common, 19 are distinctive, and 20 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈19

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 20

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    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 …

    line 10
  2. Very specific:

    Verify: one read query renders, one write action shows disabled/pending/success/error states

    line 29
  3. Very specific:

    When a Sails app needs a frontend — whether the project is brand-new or an existing repo without one — start with create-vara-app.

    line 36
  4. Distinctive:

    After the contract changes, re-run the scaffold from the project root:

    line 56
  5. Distinctive:

    After bootstrap, continue with the Standard Path below to customize screens, add queries, or wire advanced flows.

    line 64
  6. Very specific:

    Treat the program .idl as the frontend source of truth.

    line 68
  7. Very specific:

    Prefer useProgram with the generated Program class for typed service access.

    line 71
  8. Very specific:

    Use useProgramQuery for Sails queries and useProgramEvent only where live subscriptions are actually needed.

    line 72
  9. Very specific:

    Use usePrepareProgramTransaction to obtain gasLimit, extrinsic, or fee data before send when the UX needs validation or previews.

    line 73
  10. Very specific:

    Use useSendProgramTransaction for commands, await result.response, and surface pending, success, and failure states in the UI instead of …

    line 74
  11. Very specific:

    When the target frontend is a Next.js App Router project:

    line 80
  12. Very specific:

    If @gear-js/react-hooks or its wallet subdependencies cause persistent server-build failures after transpilePackages, fall back to a …

    line 83
  13. Very specific:

    Run next build before tsc --noEmit in App Router projects.

    line 86
  14. Very specific:

    When using sails-js for runtime IDL parsing (not the generated lib.ts client path), the Sails class requires an explicit parser instance …

    line 96
  15. Very specific:

    Before handoff, validate the installed sails-js API surface against the conventions in ../../references/sails-frontend-and-gear-js.md.

    line 100
  16. Distinctive:

    Before generating or editing a Vara frontend, resolve package versions from the target project and the current package metadata, not from …

    line 108
  17. Distinctive:

    Do not pin Gear/Vara frontend package versions from memory.

    line 116
  18. Distinctive:

    If the repo already has a lockfile, preserve it unless there is a clear compatibility issue.

    line 117
  19. Very specific:

    If starting a new frontend, first determine the current compatible package set, then write package.json.

    line 118
  20. Very specific:

    If using @gear-js/wallet-connect, also verify the required UI package set and required styles.

    line 119
  21. Distinctive:

    If the frontend uses packaged Gear wallet/UI components such as:

    line 124
  22. Distinctive:

    no Vara-compatible wallet extension is available

    line 141
  23. Distinctive:

    Do not collapse these states into a single generic “wallet not ready” message.

    line 145
  24. Distinctive:

    no wallet extension found

    line 149
  25. Distinctive:

    Do not hand off a Vara frontend until all of the following are true:

    line 161
  26. Distinctive:

    if packaged wallet/UI components are used, their styles are imported and the wallet UI is usable.

    line 165
  27. Very specific:

    if runtime IDL parsing is used, sails-js-parser is installed and parser initialization is present

    line 173
  28. Very specific:

    if using Next.js App Router, transpilePackages and 'use client' boundaries are confirmed

    line 174
  29. Distinctive:

    Every write action must expose at least:

    line 180
  30. Distinctive:

    Do not rely only on console logs or implicit alerts.

    line 186
  31. Distinctive:

    Before handoff, review the frontend specifically for:

    line 190
  32. Distinctive:

    Prefer generated clients and hooks over hand-built SCALE payloads for standard Sails apps.

    line 225
  33. Distinctive:

    Do not ship seed phrases, private keys, or test mnemonics in frontend code.

    line 226
  34. Very specific:

    Do not enable watch subscriptions everywhere by default.

    line 228
  35. Distinctive:

    Do not mix Sails IDL-driven calls with metadata-driven low-level calls unless the reason is named explicitly.

    line 229
  36. Distinctive:

    Do not decode arbitrary raw bytes with plain SCALE rules until you have named whether the source is a Sails interface path, a full-state …

    line 230
  37. Distinctive:

    Do not embed machine-specific absolute paths in generated configs, scripts, or documentation.

    line 231
  38. Very specific:

    When handing off to a frontend, confirm the IDL snapshot is available.

    line 232
  39. Very specific:

    Do not assume sendAndWait() exists on the sails-js transaction builder.

    line 233

≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Sails Frontend

Goal

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.

Inputs

  • 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.md

Minimal Path (simple apps)

For a straightforward app (counter, single-service CRUD) where the contract is already built:

  1. npx create-vara-app my-dapp --idl path/to/service.idl
  2. cd my-dapp && npm install && npm run dev
  3. Verify: one read query renders, one write action shows disabled/pending/success/error states
  4. Done — the scaffold handles providers, wallet, typed wrappers, and env validation

Skip the rest of this skill unless you need to customize screens, add Next.js support, wire vouchers, or handle advanced flows.

Bootstrap with create-vara-app

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:

  • Typed query/transaction wrappers from the IDL
  • Wallet integration (SubWallet, Polkadot.js, Talisman)
  • Live event subscriptions
  • Client-side input validation
  • Debug panel with runtime IDL explorer

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.

Standard Path

  1. Treat the program .idl as the frontend source of truth.
  2. Generate or refresh the typed client. If 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.
  3. Compose the React root around TanStack Query plus Gear providers: query client, API provider, account provider, and alert provider.
  4. Prefer useProgram with the generated Program class for typed service access.
  5. Use useProgramQuery for Sails queries and useProgramEvent only where live subscriptions are actually needed.
  6. Use usePrepareProgramTransaction to obtain gasLimit, extrinsic, or fee data before send when the UX needs validation or previews.
  7. Use useSendProgramTransaction for commands, await result.response, and surface pending, success, and failure states in the UI instead of relying only on extrinsic submission.
  8. Pass 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.
  9. Drop to low-level @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.

Next.js App Router Compatibility

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'.
  • If @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.
  • On the lower-level fallback path, add @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.
  • Run 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.

Repo Layout For Mixed Workspaces

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/.

sails-js-parser Initialization

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.

API Surface Validation

Before handoff, validate the installed sails-js API surface against the conventions in ../../references/sails-frontend-and-gear-js.md. Key points:

  • The transaction builder method is signAndSend(), not sendAndWait().
  • Function arguments are positional, not wrapped in objects.
  • Confirm program.<serviceName>.<functionName> exists on the generated client before wiring UI.

Dependency Freshness Policy

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:

  1. Existing repo lockfile and package.json
  2. Current peerDependencies of @gear-js/react-hooks and related packages
  3. Current published package versions if this is a new project

Rules:

  • Do not pin Gear/Vara frontend package versions from memory.
  • If the repo already has a lockfile, preserve it unless there is a clear compatibility issue.
  • If starting a new frontend, first determine the current compatible package set, then write package.json.
  • If using @gear-js/wallet-connect, also verify the required UI package set and required styles.
  • Name the resolved versions explicitly in the output.

Wallet UI Styling Rule

If the frontend uses packaged Gear wallet/UI components such as:

  • @gear-js/wallet-connect
  • @gear-js/ui
  • @gear-js/vara-ui

then import the required package styles at the app entrypoint before considering the wallet integration complete.

Minimum check:

  • wallet button renders correctly
  • modal is visually positioned and styled correctly
  • alert container is visible and not collapsed

Wallet Readiness Rule

For wallet-bound actions, distinguish at least these states in the UI:

  • wallets are still loading
  • no Vara-compatible wallet extension is available
  • wallet exists but no account is connected
  • account is connected and ready for signing

Do not collapse these states into a single generic “wallet not ready” message.

Disabled signed actions should expose a visible reason, such as:

  • wallets are still loading
  • no wallet extension found
  • connect a wallet first
  • program is not ready yet

Env Validation Rule

Validate required env values such as endpoint and program IDs before rendering feature screens.

Missing env values must fail visibly, not silently.

Definition of Done

Do not hand off a Vara frontend until all of the following are true:

  • dependency versions were resolved from the actual project/package metadata, not memory
  • app root includes QueryClientProvider, ApiProvider, AccountProvider, and AlertProvider
  • if packaged wallet/UI components are used, their styles are imported and the wallet UI is usable; otherwise, the custom wallet flow is visible and usable
  • at least one read query works
  • at least one signed transaction path is wired and shows disabled, pending, and success or error states in the UI
  • signed write actions are disabled when wallet/account prerequisites are missing
  • at least one invalid form path is handled without sending a transaction
  • affected queries refetch after successful mutations unless an explicit live-subscription strategy is used
  • build passes
  • installed sails-js API surface was validated: signAndSend method, positional arguments, and query builder pattern match the conventions in the reference doc
  • if runtime IDL parsing is used, sails-js-parser is installed and parser initialization is present
  • if using Next.js App Router, transpilePackages and 'use client' boundaries are confirmed
  • IDL snapshot is checked in or the generation command is documented
  • the final note includes exact run commands and required env vars

Transaction UX Rule

Every write action must expose at least:

  • disabled state when prerequisites are missing
  • pending state
  • success state
  • error state with a visible message

Do not rely only on console logs or implicit alerts.

Final Validation Pass

Before handoff, review the frontend specifically for:

  • provider setup
  • wallet connection assumptions
  • wallet readiness states
  • required CSS imports for packaged UI
  • transaction status rendering
  • disabled states for unauthenticated actions
  • query refetch after successful mutations
  • invalid form handling before send
  • env variable wiring
  • package version freshness

Route Here When

  • the builder asks for a React, Vite, or TypeScript dApp on Vara
  • the task is wallet connect, account selection, transaction signing, or voucher-aware sends
  • the task is wiring Sails queries, commands, events, and typed generated clients
  • the task needs program IDs, endpoint env vars, loading states, error states, or response handling in the UI
  • the task needs a justified low-level fallback with @gear-js/api

Required Output Shape

Name these decisions explicitly in the work product:

  • chosen frontend stack and package surface
  • .idl and generated client path
  • endpoint and program ID env contract
  • provider composition at app root
  • per-screen mapping of queries, commands, and events
  • signing, gas, voucher, and response-handling strategy
  • low-level escape hatches, if any
  • chosen integration path: hooks-based or lower-level fallback (if Next.js App Router)

Guardrails

  • Prefer generated clients and hooks over hand-built SCALE payloads for standard Sails apps.
  • Do not ship seed phrases, private keys, or test mnemonics in frontend code.
  • On manual transaction-builder or low-level Gear-JS paths, make the gas strategy explicit.
  • Do not enable watch subscriptions everywhere by default; only subscribe where the UX truly benefits.
  • Do not mix Sails IDL-driven calls with metadata-driven low-level calls unless the reason is named explicitly.
  • Do not decode arbitrary raw bytes with plain SCALE rules until you have named whether the source is a Sails interface path, a full-state metadata path, or a state-function path.
  • Do not embed machine-specific absolute paths in generated configs, scripts, or documentation. Use project-relative paths.
  • When handing off to a frontend, confirm the IDL snapshot is available. Cross-reference sails-idl-client for the canonical handoff pattern.
  • Do not assume sendAndWait() exists on the sails-js transaction builder; the correct method is signAndSend().

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.