AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Openui Forge Rust

skill-othmanadi-openui-forge-openui-forge-rust · by OthmanAdi

OpenUI generative UI with Rust Axum backend. Async SSE streaming with reqwest and async-stream.

No reviews yet
0 installs
31 views
0.0% view→install

Install

$ agentstack add skill-othmanadi-openui-forge-openui-forge-rust

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-othmanadi-openui-forge-openui-forge-rust)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
3mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Openui Forge Rust? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

OpenUI Forge — Rust

Build generative UI apps with a React frontend + Rust Axum backend. Async SSE streaming to OpenAI-compatible NDJSON.

Activation Triggers

  • "openui rust", "openui axum", "openui rust backend"
  • "generative ui rust", "rust streaming ui backend"

Prerequisites

  • Node.js >= 22 (24 LTS recommended) + React >= 18.3.1 (19+ recommended) (frontend)
  • Rust >= 1.75 with Cargo (backend)
  • OPENAI_API_KEY environment variable set

Quick Start

  1. Create the React frontend and install OpenUI deps:
npm install @openuidev/react-ui @openuidev/react-headless @openuidev/react-lang lucide-react zod
  1. Generate the system prompt:
npx @openuidev/cli generate ./src/lib/library.ts --out backend/system-prompt.txt
  1. Create the Rust backend (see Full Code below)
  2. Run: cargo run on :3001, frontend on :3000

Full Code

Backend: backend/Cargo.toml

[package]
name = "openui-backend"
version = "0.1.0"
edition = "2021"

[dependencies]
axum = "0.8"
http = "1"
tokio = { version = "1", features = ["full"] }
reqwest = { version = "0.13", features = ["json", "stream"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
async-stream = "0.3"
futures = "0.3"
tower-http = { version = "0.6", features = ["cors"] }
dotenvy = "0.15"

Backend: backend/src/main.rs

use axum::{
    extract::{Json, State},
    response::sse::{Event, Sse},
    routing::post,
    Router,
};
use futures::stream::Stream;
use http::HeaderValue;
use reqwest::Client;
use serde::{Deserialize, Serialize};
use std::{convert::Infallible, fs, net::SocketAddr, sync::Arc};
use tower_http::cors::{Any, CorsLayer};

#[derive(Deserialize)]
struct ChatRequest {
    messages: Vec,
}

#[derive(Serialize, Deserialize, Clone)]
struct Message {
    role: String,
    content: String,
}

#[derive(Clone)]
struct AppState {
    system_prompt: String,
}

#[tokio::main]
async fn main() {
    dotenvy::dotenv().ok();
    let system_prompt = fs::read_to_string("system-prompt.txt")
        .expect("system-prompt.txt not found");
    let state = Arc::new(AppState { system_prompt });

    let cors = CorsLayer::new()
        .allow_origin("http://localhost:3000".parse::().unwrap())
        .allow_methods([http::Method::POST])
        .allow_headers(Any);

    let app = Router::new()
        .route("/api/chat", post(chat_handler))
        .layer(cors)
        .with_state(state);

    let addr = SocketAddr::from(([0, 0, 0, 0], 3001));
    println!("Rust backend listening on {addr}");
    let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

async fn chat_handler(
    State(state): State>,
    Json(req): Json,
) -> Sse>> {
    let mut messages = vec![Message { role: "system".into(), content: state.system_prompt.clone() }];
    messages.extend(req.messages);

    let api_key = std::env::var("OPENAI_API_KEY").expect("OPENAI_API_KEY not set");
    let client = Client::new();

    let stream = async_stream::stream! {
        let resp = client
            .post("https://api.openai.com/v1/chat/completions")
            .bearer_auth(&api_key)
            .json(&serde_json::json!({
                "model": std::env::var("OPENAI_MODEL").unwrap_or_else(|_| "gpt-5.5".into()),
                "stream": true,
                "messages": messages,
            }))
            .send()
            .await;

        if let Ok(resp) = resp {
            let mut bytes_stream = resp.bytes_stream();
            use futures::StreamExt;
            let mut buffer = String::new();
            while let Some(Ok(chunk)) = bytes_stream.next().await {
                buffer.push_str(&String::from_utf8_lossy(&chunk));
                while let Some(pos) = buffer.find("\n\n") {
                    let line = buffer[..pos].to_string();
                    buffer = buffer[pos + 2..].to_string();
                    if line.starts_with("data: ") {
                        yield Ok(Event::default().data(&line[6..]));
                    }
                }
            }
        }
    };

    Sse::new(stream)
}

Frontend: app/chat/page.tsx

"use client";
import { FullScreen } from "@openuidev/react-ui";
import { openuiChatLibrary } from "@openuidev/react-ui/genui-lib";
import {
  openAIAdapter,
  openAIMessageFormat,
} from "@openuidev/react-headless";

export default function ChatPage() {
  return (
    
  );
}

> The Rust backend re-emits SSE via Axum's Sse response (Axum wraps each Event::default().data(...) with the data: prefix). Pair it with openAIAdapter() on the frontend. openAIReadableStreamAdapter() is for NDJSON and will silently produce no output here.

System Prompt Generation

npx @openuidev/cli generate ./src/lib/library.ts --out backend/system-prompt.txt

Validation Checklist

  • [ ] system-prompt.txt exists in the Rust backend directory
  • [ ] OPENAI_API_KEY is set in environment or .env
  • [ ] CORS layer allows the frontend origin
  • [ ] SSE events forward OpenAI stream chunks correctly
  • [ ] Buffer parsing handles partial SSE lines across chunk boundaries
  • [ ] Frontend apiUrl points to http://localhost:3001/api/chat
  • [ ] Frontend uses streamProtocol={openAIAdapter()} and openAIMessageFormat
  • [ ] componentLibrary={openuiChatLibrary} prop passed to FullScreen
  • [ ] CSS import in root layout (@openuidev/react-ui/components.css)

Error Patterns

| Error | Cause | Fix | |-------|-------|-----| | system-prompt.txt not found | File missing | Run CLI generate command | | CORS blocked | Origin not in CorsLayer | Update .allow_origin() | | Partial SSE events | Chunk boundary splitting | Buffer and split on \n\n boundaries (handled in code) | | Compile error on http::HeaderValue | Missing http crate | Add http = "1" to Cargo.toml (already in the example) or import from axum::http | | static_mut_refs warning on static mut | Rust 2024 deprecates raw static mut access | Use OnceLock or carry state in State> (this example uses the latter) | | Connection reset | Tokio runtime panic | Check .await on all async calls, verify features = ["full"] |

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.