Create a Gora app
A Gora app starts as a local folder. You edit it locally, validate it locally, then deploy it to a Gora endpoint.Choose a starter template
For a pure off-chain app — code that reads request input and returns JSON — the simplest starting point is the generic template with--app-kind offchain-only. It scaffolds no contract or wallet component
(contracts: [] in the manifest):
The
offchain-callback starter emits a chain_callback.operation object with
structured target and params fields, and it includes a small callback
contract/program scaffold for the selected chain. Its operation_schema
declares allowed operation keys plus required and allowed target/params fields
for the starter callback.
Use the operation object for callback submitter routing; the flat target, method, and payload fields remain in the starter for compatibility with simple Dev Bridge flows.
Example:
gora config set api.token <string>) — it is your identity, and the first
token to claim an app id owns it. See
Connect to the testnet for how the token works.
Algorand is the live chain on the public testnet; Base and Solana callback
scaffolds work against a local devnet only. Endpoints and deployed contract
IDs are in Connect to the testnet.
Supported languages — pick based on what your app needs:
WASM is the default for the public testnet, and it is input-driven. A WASM
app reads request input (
gora::input_get), keeps durable state across requests
(gora::state_get / gora::state_put), can call an LLM (gora::llm), fetch
allowlisted HTTP (gora::http_get), and return variable-length output
(gora::set_output) — all deterministic and fuel-metered. gora init --language wasm scaffolds a capable starter (reads input, keeps a counter in state, echoes
it back), not an inert stub. JS, TS, and Python run unsandboxed, so they are
only available on a self-hosted node — not the WASM-only public testnet. The
full ABI, host functions, and build path are in the
WASM runtime reference.
Supported app kinds:
offchain-only— with the generic template, scaffolds no contract or wallet componentsmart-contract-nativeoffchain-program-walletai-agent-wallet
Generated files
A TypeScript app looks like this:Mobile UI
The mobile wallet renders app-specific UI as HTML only. Add aui section to gora.app.json:
gora deploy embeds the html_path file into the manifest as ui.html (up to 1 MiB), so the page ships with the app and the bridge can serve it for apps deployed from anywhere. You can also write ui.html inline yourself, or point ui.url at a page you host.
The WebView injects window.Gora so your HTML can ask native code for wallet context, read declared views, invoke the app, and open the native signer:
action() raises a native approval pop-up. On approve, the user’s wallet key
signs the request and the network cryptographically verifies the signature
before the action runs; your page gets the proof in a gora:actionComplete
event (declines arrive as gora:actionCancelled). The full API, event shapes,
and the signing protocol are in
Web UI and verified signing.
Keep private keys, seed phrases, RPC secrets, and algod tokens out of HTML. The HTML is a UI surface; native wallet code still owns signing.
Runtime contract
For JS, TS, and Python apps:request_id and input — no state, no
capabilities, no network. Everything your app needs must arrive in input;
everything it produces must go out in the result. If the result feeds
consensus, keep it deterministic: no clocks, no Math.random() — derive
randomness from the input (see how the
raffle drawer seeds an HMAC with the
round number and participant registry).
Example app (src/index.mjs):
gora::input_get, can persist
state with gora::state_get / gora::state_put, call an LLM with gora::llm,
fetch allowlisted HTTP with gora::http_get, and return variable-length output
with gora::set_output — exported memory, zero-arg entrypoint. See the
WASM runtime reference for the full ABI and the
build path.
Build
artifacts/program.wasm — the module must
export memory and the manifest entrypoint, and its sha256 is pinned into
the package (full ABI).
Validate
- manifest and policy JSON
- app id and package metadata
- artifact path and runtime kind
- allowed actions and chains
- linked contract metadata
- obvious secret-looking fields
Package
gora deploy uploads to Gora.
What not to put in an app
Do not put these in source, manifest, policy, fixtures, package metadata, or stdout:- private keys
- seed phrases
- deployer keys
- API tokens
- RPC secrets
- Algod tokens