Skip to content
Development
Skill

/makepad-2.0-splash

CRITICAL: Use for Makepad 2.0 Splash scripting language. Triggers on: splash language, makepad script, script_mod!, makepad scripting, splash 脚本, makepad 2.0 script, mod.state, on_render, script_eval, streaming evaluation, splash syntax, splash vm, let binding, splash functions,

From plugin
makepad-skills
74514 skills
Install
$ npx -y skills add ZhangHanDong/makepad-skills --skill makepad-2.0-splash --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/makepad-2.0-splash

Context preview

The summary Claude sees to decide when to auto-load this skill.

CRITICAL: Use for Makepad 2.0 Splash scripting language. Triggers on: splash language, makepad script, script_mod!, makepad scripting, splash 脚本, makepad 2.0 script, mod.state, on_render, script_eval, streaming evaluation, splash syntax, splash vm, let binding, splash functions,

SKILL.md

makepad-2.0-splash.SKILL.md
name: makepad-2.0-splash
description: |
  CRITICAL: Use for Makepad 2.0 Splash scripting language. Triggers on:
  splash language, makepad script, script_mod!, makepad scripting, splash 脚本,
  makepad 2.0 script, mod.state, on_render, script_eval, streaming evaluation,
  splash syntax, splash vm, let binding, splash functions, hot reload, live reload,
  ScriptModKey, script_mod_overrides, checkpoint, incremental parsing,
  canvas splash, POST splash, fn tick, on_audio, set_text, tab switching,
  音乐播放器, token monitor, driver script, audio API,
  热重载, 脚本引擎, 增量解析

Makepad 2.0 Splash Scripting Language

Splash is Makepad 2.0's core runtime UI scripting language, released February 12, 2026. It replaces the old compile-time `live_design!` macro system with a runtime `script_mod!` macro that enables hot reload, streaming evaluation, and AI-first code generation.

Core Concepts

Script Structure

Every Splash script starts with a `use` import and is embedded in Rust via the `script_mod!{}` macro:

use makepad_widgets::*;

app_main!(App);

script_mod! {
    use mod.prelude.widgets.*

    // let bindings, functions, state, and UI definitions go here

    startup() do #(App::script_component(vm)){
        ui: Root{
            main_window := Window{
                window.inner_size: vec2(800, 600)
                body +: {
                    // UI content
                }
            }
        }
    }
}

Syntax Rules

  • **No commas** between properties -- whitespace-delimited
  • **No semicolons** -- cleaner syntax optimized for LLM generation
  • **Property assignment**: `key: value`
  • **Dot-path shorthand**: `draw_bg.color: #f00` (equivalent to `draw_bg +: { color: #f00 }`)
  • **Merge operator**: `key +: { ... }` extends parent without replacing
  • **Named children**: `name := Widget{...}` (addressable, overridable per-instance)
  • **Let bindings**: `let MyTemplate = Widget{...}` (local scope, must be defined before use)
  • **Rust binding**: `#(Struct::register_widget(vm))` connects Splash to Rust structs
  • **Debug logging**: `~expression` logs value during evaluation

State Management

State is managed via the `mod.state` object and reactive `on_render` callbacks:

// Define state
let state = { counter: 0 }
mod.state = state

// Reactive rendering -- re-runs when .render() is called
main_view := View{
    on_render: ||{
        Label{ text: "Count: " + state.counter }
    }
}

Event Handling

Events are handled both inline in Splash and from Rust:

// Inline event handlers in Splash
add_button := Button{
    text: "Add"
    on_click: ||{
        add_todo(ui.todo_input.text(), "")
        ui.todo_input.set_text("")
    }
}

// TextInput return key
todo_input := TextInput{
    on_return: || ui.add_button.on_click()
}

// Startup event
on_startup: ||{
    ui.main_view.render()
}

From Rust, use `script_eval!` to execute Splash code:

impl MatchEvent for App {
    fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions) {
        if self.ui.button(cx, ids!(increment_button)).clicked(actions) {
            script_eval!(cx, {
                mod.state.counter += 1
                ui.main_view.render()
            });
        }
    }
}

Functions

fn tag_color(tag) {
    if tag == "dev" theme.color_highlight
    else if tag == "design" theme.color_selection_focus
    else theme.color_highlight
}

fn add_todo(text, tag) {
    todos.push({text: text, tag: tag, done: false})
    ui.todo_list.render()
}

Control Flow

// If/else
if todos.len() == 0
    EmptyState{}
else for i, todo in todos {
    TodoItem{ label.text: todo.text }
}

// For loops
for i, item in array {
    Label{ text: item.name }
}

// While
while condition { ... }

HTTP Requests

let req = net.HttpRequest{
    url: "https://api.example.com/data"
    method: net.HttpMethod.GET
    headers: {"User-Agent": "MakepadApp/1.0"}
}
net.http_request(req) do net.HttpEvents{
    on_response: |res| {
        let text = res.body.to_string()
        let json = res.body.parse_json()
    }
    on_error: |e| { /* handle error */ }
}

Streaming responses use `is_streaming: true` with `on_stream` and `on_complete` callbacks.

HTML Parsing

let doc = html_string.parse_html()
doc.query("p")              // all <p> elements
doc.query("#main")           // by id
doc.query("p.bold")          // by class
doc.query("div > p")         // direct children
doc.query("p[0]").text       // text content
doc.query("a@href")          // attribute value

Streaming Evaluation

Splash's parser supports checkpoint-based incremental parsing, designed for AI/LLM streaming code generation:

// Rust API for streaming evaluation
vm.eval_with_append_source(script_mod, &code, NIL.into())

This enables real-time UI updates as code is generated token-by-token, without requiring a complete script before evaluation.

Hot Reload & Script Mod Tracking

Splash scripts support hot reload via the `--hot` flag. The VM tracks each `script_mod!` block with a unique `ScriptModKey` (file, line, column):

// Internal: ScriptModKey uniquely identifies a script_mod! block
ScriptModKey { file: "src/app.rs", line: 5, col: 1 }

// Runtime substitution via overrides
ScriptCode::script_mod_overrides  // HashMap of ScriptModKey -> updated source

**How hot reload works:** 1. File watcher (`makepad_live_reload_core`) detects source file changes 2. `script_mod!` blocks are extracted from Rust source (handles raw strings, comments, char literals) 3. Rust placeholder counts (`#(...)`) are tracked -- adding/removing placeholders requires full rebuild 4. Validated script mods are applied via `script_mod_overrides` 5. IP-to-location mapping provides source maps for error reporting (fallback to nearest token for synthetic opcodes)

**ScriptSource variants:**

  • `ScriptSource::Mod` -- Standard module evaluation (startup)
  • `ScriptSource::Streaming` -- Incremental streaming
Read more
Ships withmakepad-skills

Skills for building cross-platform UI applications with Makepad 2.0.

Get the whole plugin

Other skills on makepad-skills.