Skip to main content Skills Marketplace Découvrez et explorez les compétences IA créées par la communauté.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Copier le promptAfficher les détails du prompt Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
npx skills add https://github.com/BEKO2210/Firstbrain --skill robius-app-architectureLa commande reste sur une seule ligne. Faites défiler horizontalement pour la vérifier avant de la copier.
Vous préférez une copie locale ? Téléchargez les fichiers actuellement disponibles dans SkillsMP.
Télécharger Zip Téléchargement... Métiers associés SOC
Basé sur la classification professionnelle SOC
name robius-app-architecture description | type skill created 2026-02-27T00:00:00.000Z domain software-development category architecture risk unknown source community tags ["skill","software-development","architecture","robius","app"]
Robius App Architecture Skill
Best practices for structuring Makepad applications based on the Robrix and Moly codebases - production applications built with Makepad and Robius framework.
Source codebases:
Robrix : Matrix chat client - complex sync/async with background subscriptions
Moly : AI chat application - cross-platform (native + WASM) with streaming APIs
When to Use
Use this skill when:
Building a Makepad application with async backend integration
Designing sync/async communication patterns in Makepad
Structuring a Robius-style application
Keywords: robrix, robius, makepad app structure, async makepad, tokio makepad
Production Patterns
For production-ready async patterns, see the _base/ directory:
Pattern Description 08-async-loading Async data loading with loading states 09-streaming-results Incremental results with SignalToUI 13-tokio-integration Full tokio runtime integration
Core Architecture Pattern
┌─────────────────────────────────────────────────────────────┐
│ UI Thread (Makepad) │
│ ┌─────────┐ ┌──────────┐ ┌──────────────────────┐ │
│ │ App │────▶│ WidgetRef │────▶│ Widget Tree (View) │ │
│ │ State │ │ ui │ │ Scope::with_data() │ │
│ └────┬────┘ └──────────┘ └──────────────────────┘ │
│ │ │
│ │ submit_async_request() │
│ ▼ │
│ ┌─────────────────┐ ┌─────────────────────────┐ │
│ │ REQUEST_SENDER │─────────▶│ Crossbeam SegQueue │ │
│ │ (MPSC Channel) │ │ (Lock-free Updates) │ │
│ └─────────────────┘ └─────────────────────────┘ │
└───────────────────────────────────┬─────────────────────────┘
│
SignalToUI::set_ui_signal()
│
┌───────────────────────────────────┴─────────────────────────┐
│ Tokio Runtime (Async) │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ worker_task (Request Handler) │ │
│ │ - Receives Request from UI │ │
│ │ - Spawns async tasks per request │ │
│ │ - Posts actions back via Cx::post_action() │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Per-Item Subscriber Tasks │ │
│ │ - Listens to external data stream │ │
│ │ - Sends Update via crossbeam channel │ │
│ │ - Calls SignalToUI::set_ui_signal() to wake UI │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
App Structure
Top-Level App Definition use makepad_widgets::*;
live_design! {
use link::theme::*;
use link::widgets::*;
App = {{App}} {
ui: <Root>{
main_window = <Window> {
window: {inner_size: vec2 (1280 , 800 ), title: "MyApp" },
body = {
}
}
}
}
}
app_main!(App);
#[derive(Live)]
pub struct App {
#[live] ui: WidgetRef,
#[rust] app_state: AppState,
}
impl LiveRegister for App {
fn live_register (cx: &mut Cx) {
makepad_widgets::live_design (cx);
crate::shared::live_design (cx);
crate::home::live_design (cx);
}
}
impl LiveHook for App {
fn after_new_from_doc (&mut self , cx: &mut Cx) {
}
}
AppMain Implementation impl AppMain for App {
fn handle_event (&mut self , cx: &mut Cx, event: &Event) {
self .match_event (cx, event);
let scope = &mut Scope::with_data (&mut self .app_state);
self .ui.handle_event (cx, event, scope);
}
}
Tokio Runtime Integration
Static Runtime Initialization use std::sync::Mutex;
use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
static TOKIO_RUNTIME: Mutex<Option <tokio::runtime::Runtime>> = Mutex::new (None );
static REQUEST_SENDER: Mutex<Option <UnboundedSender<AppRequest>>> = Mutex::new (None );
pub fn start_async_runtime () -> Result <tokio::runtime::Handle> {
let (request_sender, request_receiver) = tokio::sync::mpsc::unbounded_channel ();
let rt_handle = TOKIO_RUNTIME.lock ().unwrap ()
.get_or_insert_with (|| {
tokio::runtime::Runtime::new ()
.expect ("Failed to create Tokio runtime" )
})
.handle ()
.clone ();
*REQUEST_SENDER.lock ().unwrap () = Some (request_sender);
rt_handle.spawn (worker_task (request_receiver));
Ok (rt_handle)
}
Request Submission Pattern pub enum AppRequest {
FetchData { id: String },
SendMessage { content: String },
}
pub fn submit_async_request (req: AppRequest) {
if let Some (sender) = REQUEST_SENDER.lock ().unwrap ().as_ref () {
sender.send (req)
.expect ("BUG: worker task receiver has died!" );
}
}
Worker Task Pattern async fn worker_task (mut request_receiver: UnboundedReceiver<AppRequest>) -> Result <()> {
while let Some (request) = request_receiver.recv ().await {
match request {
AppRequest::FetchData { id } => {
let _task = tokio::spawn (async move {
let result = fetch_data (&id).await ;
Cx::post_action (DataFetchedAction { id, result });
});
}
AppRequest::SendMessage { content } => {
let _task = tokio::spawn (async move {
match send_message (&content).await {
Ok (()) => Cx::post_action (MessageSentAction::Success),
Err (e) => Cx::post_action (MessageSentAction::Failed (e)),
}
});
}
}
}
Ok (())
}
Lock-Free Update Queue Pattern For high-frequency updates from background tasks:
use crossbeam_queue::SegQueue;
use makepad_widgets::SignalToUI;
pub enum DataUpdate {
NewItem { item: Item },
ItemChanged { id: String , changes: Changes },
Status { message: String },
}
static PENDING_UPDATES: SegQueue<DataUpdate> = SegQueue::new ();
pub fn enqueue_update (update: DataUpdate) {
PENDING_UPDATES.push (update);
SignalToUI::set_ui_signal ();
}
impl Widget for MyWidget {
fn handle_event (&mut self , cx: &mut Cx, event: &Event, scope: &mut Scope) {
if let Event ::Signal = event {
while let Some (update) = PENDING_UPDATES.pop () {
match update {
DataUpdate::NewItem { item } => {
self .items.push (item);
self .redraw (cx);
}
}
}
}
}
}
Startup Sequence impl MatchEvent for App {
fn handle_startup (&mut self , cx: &mut Cx) {
let _ = tracing_subscriber::fmt::try_init ();
let _app_data_dir = crate::app_data_dir ();
if let Err (e) = persistence::load_window_state (
self .ui.window (ids!(main_window)), cx
) {
error!("Failed to load window state: {}" , e);
}
self .update_ui_visibility (cx);
let _rt_handle = crate::start_async_runtime ().unwrap ();
}
}
Shutdown Sequence impl AppMain for App {
fn handle_event (&mut self , cx: &mut Cx, event: &Event) {
if let Event ::Shutdown = event {
let window_ref = self .ui.window (ids!(main_window));
if let Err (e) = persistence::save_window_state (window_ref, cx) {
error!("Failed to save window state: {e}" );
}
if let Some (user_id) = current_user_id () {
if let Err (e) = persistence::save_app_state (
self .app_state.clone (), user_id
) {
error!("Failed to save app state: {e}" );
}
}
}
}
}
Best Practices
Separation of Concerns : Keep UI logic on the main thread, async operations in Tokio runtime
Request/Response Pattern : Use typed enums for requests and actions
Lock-Free Updates : Use crossbeam::SegQueue for high-frequency background updates
SignalToUI : Always call SignalToUI::set_ui_signal() after enqueueing updates
Cx::post_action() : Use for async task results that need action handling
Scope::with_data() : Pass shared state through widget tree
Module Registration Order : Register base widgets before dependent modules in live_register()
Reference Files
references/tokio-integration.md - Detailed Tokio runtime patterns (Robrix)
references/channel-patterns.md - Channel communication patterns (Robrix)
references/moly-async-patterns.md - Cross-platform async patterns (Moly)
PlatformSend trait for native/WASM compatibility
UiRunner for async defer operations
AbortOnDropHandle for task cancellation
ThreadToken for non-Send types on WASM
spawn() platform-agnostic function
Connections
Domain: [[Software Entwicklung]]
Kategorie: [[Software Architektur]]
Navigation: [[Skills Uebersicht]], [[Home]]