Skip to content

hyperware-ai/hypr-dao

Repository files navigation

Hyperware Skeleton App

A minimal, well-commented skeleton application for the Hyperware platform using the Hyperapp framework. This skeleton provides a starting point for building Hyperware applications with a React/TypeScript frontend and Rust backend.

Example prompt (works well with Codex):

Use `kit new myappname --template lock-and-bind --ui`, (replacing myappname with appropriate app name) to make a template in `/desired_folder`, which you will modify to build the following app:

Insert your app spec here, e.g.:
Todo List with P2P Sync.
A collaborative TODO list where items sync between nodes.

Write a spec, and then implement it step by step. Use the README.md given in lock-and-bind to find instructions on specific details.
At the end, I should be able to run `kit bs —hyperapp` and manually test that the app works.

The rest of this document is aimed at LLMs not humans.

Quick Start

Prerequisites

  • Hyperware development environment (kit command)
  • Rust toolchain
  • Node.js and npm

Building

Always build with

kit build --hyperapp

Project Structure

lock-and-bind/
├── Cargo.toml          # Workspace configuration
├── metadata.json       # App metadata
├── lock-and-bind/       # Main Rust process
│   ├── Cargo.toml      # Process dependencies
│   └── src/
│       ├── lib.rs      # Main app logic (well-commented)
│       └── icon        # App icon file
├── ui/                 # Frontend application
│   ├── package.json    # Node dependencies
│   ├── index.html      # Entry point (includes /our.js)
│   ├── vite.config.ts  # Build configuration
│   └── src/
│       ├── App.tsx     # Main React component
│       ├── store/      # Zustand state management
│       ├── types/      # TypeScript type definitions
│       └── utils/      # API utilities
├── api/                # Generated WIT files (after build)
└── pkg/                # The final build product, including manifest.json, scripts.json and built package output

Key Concepts

1. The Hyperprocess Macro

The #[hyperprocess] macro is the core of the Hyperapp framework. It provides:

  • Async/await support without tokio
  • Automatic WIT generation
  • State persistence
  • HTTP/WebSocket endpoint configuration

2. Required Patterns

HTTP Endpoints

ALL HTTP endpoints MUST be tagged with #[http]:

#[http]
async fn my_endpoint(&self) -> String {
    // Implementation
}

Remote Requests

All remote requests must use .expects_response(30), where the value 30 sets a 30‑second response timeout.

let req = Request::to(("friend.os", "some-hyperapp", "some-hyperapp", "publisher.os"))
    .expects_response(30)
    .blob(LazyLoadBlob {
        mime: None,
        bytes: message,
    })
    .body(body);

Frontend API Calls

Parameters must be sent as tuples for multi-parameter methods:

// Single parameter
{ "MethodName": value }

// Multiple parameters
{ "MethodName": [param1, param2] }

Frontend keys in snake_case

All keys in TypeScript need to stay in snake_case (node_id), camelCase (nodeId) will break the app!

export interface StatusSnapshot {
    node_id: string;
  }

The /our.js Script

MUST be included in index.html:

<script src="/our.js"></script>

3. State Persistence

Your app's state is automatically persisted based on the save_config option:

  • OnDiff: Save when state changes (strongly recommended)
  • Never: No automatic saves
  • EveryMessage: Save after each message (safest; slowest)
  • EveryNMessage(u64): Save every N messages received
  • EveryNSeconds(u64): Save every N seconds

Customization Guide

1. Modify App State

Edit AppState in lock-and-bind/src/lib.rs:

#[derive(Default, Serialize, Deserialize)]
pub struct AppState {
    // Add your fields here
    my_data: Vec<MyType>,
}

2. Add HTTP Endpoints

For UI interaction:

#[http]
async fn my_method(&mut self) -> Result<String, String> {
    // Parse request, update state, return response
}

3. Add Capabilities

Add system permissions in pkg/manifest.json:

"request_capabilities": [
    "homepage:homepage:sys",
    "http-server:distro:sys",
    "vfs:distro:sys"  // Add as needed
]

These are required to message other local processes. They can also be granted so other local processes can message us.

If sending messages between nodes, set:

"request_networking": true,

4. Update Frontend

  1. Add types in ui/src/types/lock-and-bind.ts
  2. Update store in ui/src/store/lock-and-bind.ts
  3. Modify UI in ui/src/App.tsx

Common Issues and Solutions

"Failed to deserialize HTTP request"

  • Check parameter format (tuple vs object)

"Node not connected"

  • Verify /our.js is included in index.html
  • Check that the app is running in Hyperware environment

WIT Generation Errors

  • Use simple types or return JSON strings
  • No HashMap (use Vec<(K,V)>)
  • No fixed arrays (use Vec)
  • Add #[derive(PartialEq)] to structs

Import Errors

  • Import the most important structs and functions from hyperware_process_lib, e.g. Request, LazyLoadBlob, ProcessId

manifest.json missing

  • Run kit b --hyperapp to generate it

Naming Restrictions

  • No struct/enum/interface name is allowed to contain digits or the substring "stream", because WIT doesn't allow it
  • No record/variant/enum name is allowed to end with Request, Response, RequestWrapper, ResponseWrapper, because TS caller utils are autogenerated with those suffixes

Instructions

Create an implementation plan

Carefully read the prompt; look carefully at instructions.md (if it exists) and in the example-apps directory. In particular, note the example applications example-apps/sign/, example-apps/id/, and example-apps/file-explorer. Note that file-explorer example contains an api folder, which is generated by the compiler, and not human or LLM written. sign and id demonstrate local messaging. file-explorer demonstrates VFS interactions.

Note in particular that bindings for the UI will be generated when the app is built with kit build --hyperapp. As such, first design and implement the backend; the interface will be generated from the backend; finally design and implement the frontend to consume the interface. Subsequent changes to the interface must follow this pattern as well: start in backend, generate interface, finish in frontend

Do NOT create the API. The API is machine generated. You create types that end up in the API by defining and using them in functions in the Rust backend "hyperapp"

Implement the plan

Look carefully at IMPLEMENTATION_PLAN.md and in the example-apps/ directory, if relevant.

Work from the existing template that exists at lock-and-bind/ and ui/.

Note in particular that bindings for the UI will be generated when the app is built with kit build --hyperapp. As such, first design and implement the backend; the interface will be generated from the backend; finally design and implement the frontend to consume the interface. Subsequent changes to the interface must follow this pattern as well: start in backend, generate interface, finish in frontend

Do NOT create the API. The API is machine generated. You create types that end up in the API by defining and using them in functions in the Rust backend "hyperapp"

Do not worry about serialization/deserialization when using send and send_rmp functions for p2p communication. Notice that this all happens within those functions: just take the rust types as args and return rust types as return values.

If you create a GUI for the app you MUST use target/ui/caller-utils.ts for HTTP requests to the backend. Do NOT edit this file: it is machine generated. Do NOT do fetch or other HTTP requests manually to the backend: use the functions in this machine generated interface.

About

hyperapp for locking and binding HYPR

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •