Skip to content

Arete documentation

Workflow

For the complete documentation index optimized for AI agents, see llms.txt or llms-full.txt. A markdown version of this page is available by appending .md to the URL or sending Accept: text/markdown.

For AI agents: the documentation index is at llms.txt (full corpus: llms-full.txt). A markdown source for this page is /building-stacks/workflow.md.

Most applications should begin with published Program SDKs and existing live views. Turn to custom authoring only when the catalog doesn’t offer the app-shaped view you need.

Search the registry and open the exact descriptor before starting custom work:

Terminal window
a4 explore catalog --query "<intent>" --json
a4 explore catalog program <slug> --json

If a published package already provides the required capabilities, install it instead. The advanced Rust path below assumes you have the exact local IDL for the program. Inspect that file with a4 idl summary, a4 idl search, and the IDL CLI reference before mapping it.

For an uncataloged or private program, supply the canonical IDL from the program’s own build or release artifacts, upstream repository, or published SDK package. An on-chain Anchor IDL is suitable only when the program intentionally publishes one and you verify its program address and provenance. If you cannot obtain a trustworthy IDL, ask the program owner rather than reconstructing one from explorer output.

This page documents the advanced Rust authoring path: define a live model, compile portable artifacts, deploy an exact StackManifest, and install the resulting SDK.

01

Write Rust

Define entities using #[arete] macro

→
02

Build Stack

Emit ProgramSpec, LiveSpec, and StackManifest

→
03

Deploy via CLI

Deploy the exact manifest with the CLI

→
04

Connect from App

Use generated SDK to stream


A stack definition is a Rust module that maps structure from the IDL into a rich, queryable state ready to consume in your application layer. Using Arete’s expressive DSL, you define entities, field mappings, aggregations, computed fields, relationships, and more — all in declarative Rust syntax.

use arete::{arete, Stream};
#[arete(idl = "my_program.json")]
pub mod ore_stack {
#[entity]
#[derive(Stream)]
pub struct OreRound {
#[map(RoundState::round_id, primary_key)]
pub round_id: u64,
#[map(RoundState::motherlode)]
pub motherlode: u64,
#[map(RoundState::difficulty)]
pub difficulty: u64,
}
}

The Rust code is purely declarative—you’re describing what data you want, not how to fetch it. Arete handles all the account parsing, event processing, and state management.

→ Stack Definitions — Learn the full DSL syntax


When you compile your Rust project, Arete macros transform the definition directly into three explicit, content-addressed artifact kinds:

  • ProgramSpec — endpoint-free program identity, public IDL, accounts, instructions, and PDAs.
  • LiveSpec — entity, mapping, handler, resolver, and view behavior over exact ProgramSpecs.
  • StackManifest — the client composition: aliased LiveSpecs, ProgramSpecs, and selected views. It contains no deployment URL.
Terminal window
cargo build

After building, you’ll find the generated specification in .arete/:

my-stack/
├── src/lib.rs
├── Cargo.toml
└── .arete/
├── ore.program-spec.json
├── OreStack.live-spec.json
└── OreStack.stack-manifest.json

The DSL can also generate only the program layer. An IDL-only module with no entities emits ProgramSpecs, a zero-live StackManifest, and a program-only spec() containing generated account readers:

#[arete(idl = ["my_program.json"])]
pub mod my_program {}
let spec = my_program::spec();

The program-only spec() is suitable for Server::builder().spec(spec) with Program Read HTTP routes and does not start projection work unless you enable a live runtime.

To combine independently built live packages, assign each LiveSpec a stable alias and optionally select an exact ordered view allowlist:

Terminal window
a4 stack compose --name my-app \
--live markets=./markets.live-spec.json \
--live positions=./positions.live-spec.json \
--artifact-dir . \
--selected-view markets=Market/list \
--selected-view positions=Position/state \
--output ./MyApp.stack-manifest.json

Omit --selected-view to expose every view from each supplied LiveSpec.


The Arete CLI (a4) handles hosted deployment. A single command submits one exact StackManifest. The control plane resolves its ProgramSpecs to immutable Program Releases, prepares each aliased LiveSpec, and creates deployment and endpoint bindings.

Terminal window
# Initialize project config (creates arete.toml)
a4 init
# Deploy your exact manifest
a4 up .arete/OreStack.stack-manifest.json

On success, you’ll receive a WebSocket URL:

✔ Stack pushed (v1)
✔ Build completed
🚀 Deployment and endpoint bindings are ready

→ CLI Reference — Full command documentation


Generate a typed SDK from the same manifest you reviewed and deployed:

Terminal window
a4 sdk create --manifest .arete/OreStack.stack-manifest.json --ts

This creates local source containing the selected stack definition, entities, views, and independent program SDKs. a4 sdk create does not publish an npm package or Rust crate; package publication is a separate operator action.

For composed manifests, each --live alias=path keeps its own live transport. Program Read bindings are selected per program, while chain and transaction transports are supplied independently. A client must not derive any of these endpoints from another. Import the generated source in your application:

Terminal window
npm install @usearete/react @usearete/sdk zod

@usearete/react installs zustand itself. Hosted browser connections require the publishable key shown below even for read-only use; a wallet is not required to view data.

import { AreteProvider, useArete } from "@usearete/react";
import { ORE_STREAM_STACK } from "./generated/ore-stack"; // Generated in Step 4
const publishableKey = import.meta.env.VITE_ARETE_PUBLISHABLE_KEY;
if (!publishableKey) throw new Error("VITE_ARETE_PUBLISHABLE_KEY is required");
// Wrap your app
<AreteProvider stack={ORE_STREAM_STACK} auth={{ publishableKey }}>
<App />
</AreteProvider>;
// In your component
const stack = useArete(ORE_STREAM_STACK);
const { data: rounds } = stack.views.OreRound.list.use();

Share the generated SDK with your team or publish it manually — anyone with the SDK can connect to the selected bindings when authorized. Hosted deployment does not prescribe a DNS provider; operators can hand returned endpoint bindings to their chosen DNS/CDN provider.

→ Your First Stack — Complete tutorial with working code


GoalPage
Understand the DSL in depthStack Definitions
Set up your development environmentInstallation
Build a complete exampleYour First Stack
Learn all available macrosMacro Reference
Master aggregation strategiesPopulation Strategies