{"id":"8d25f25b-a11a-4d39-8927-d4de771c5a73","shortId":"upqLWJ","kind":"skill","title":"matlab-uihtml-app-builder","tagline":"Build interactive web applications using HTML/JavaScript interfaces with MATLAB computational backends via the uihtml component. Use when creating HTML-based MATLAB apps, JavaScript MATLAB interfaces, web UIs with MATLAB, interactive MATLAB GUIs, or when user mentions uihtml, HTM","description":"# MATLAB uihtml App Builder\n\nThis skill provides comprehensive guidelines for building interactive web applications that combine HTML/JavaScript interfaces with MATLAB computational backends using the uihtml component. This architecture leverages modern web UI capabilities while harnessing MATLAB's powerful calculation engine.\n\n## When to Use This Skill\n\n- Building interactive MATLAB apps with HTML/JavaScript interfaces\n- Creating web-based UIs for MATLAB applications\n- Developing modern, responsive MATLAB GUIs using web technologies\n- When user mentions: uihtml, HTML, JavaScript, web app, web interface, interactive GUI\n- Combining web UI design with MATLAB computational power\n- Creating calculator apps, data visualizers, or form-based MATLAB tools\n\n## Core Architecture\n\n### The Four Components\n\n1. **HTML Interface** - User interface with buttons, forms, displays\n2. **JavaScript Logic** - Event handling and UI interactions\n3. **MATLAB Backend** - Computational engine and data processing\n4. **uihtml Component** - Bridge between HTML and MATLAB\n\n### Communication Patterns\n\nThe uihtml component enables bidirectional communication between JavaScript and MATLAB through several mechanisms:\n\n#### Pattern 1: MATLAB → JavaScript (Data Property)\n\n**Use Case**: Sending data from MATLAB to update the HTML interface\n\n```matlab\n% MATLAB side\nh.Data = \"Hello World!\";\n```\n\n```javascript\n// JavaScript side\nhtmlComponent.addEventListener(\"DataChanged\", function(event) {\n    document.getElementById(\"display\").innerHTML = htmlComponent.Data;\n});\n```\n\n#### Pattern 2: JavaScript → MATLAB (Events)\n\n**Use Case**: Triggering MATLAB functions from user interactions\n\n```javascript\n// JavaScript side - send event to MATLAB\nhtmlComponent.sendEventToMATLAB(\"Calculate\", expression);\n```\n\n```matlab\n% MATLAB side - receive and handle event\nh.HTMLEventReceivedFcn = @handleEvent;\n\nfunction handleEvent(src, event)\n    eventName = event.HTMLEventName;\n    eventData = event.HTMLEventData;\n    % Process event...\nend\n```\n\n#### Pattern 3: MATLAB → JavaScript (Custom Events)\n\n**Use Case**: Sending computed results or status updates to JavaScript\n\n```matlab\n% MATLAB side - send custom event to JavaScript\nsendEventToHTMLSource(h, \"ResultChanged\", result);\n```\n\n```javascript\n// JavaScript side - listen for custom event\nhtmlComponent.addEventListener(\"ResultChanged\", function(event) {\n    document.getElementById(\"display\").textContent = event.Data;\n});\n```\n\n#### Pattern 4: Complex Data Transfer\n\n**Use Case**: Passing structured data between MATLAB and JavaScript\n\n```matlab\n% MATLAB side - struct data gets JSON encoded automatically\nitemData = struct(\"ItemName\",\"Apple\",\"Price\",2,\"Quantity\",10);\nh.Data = itemData;\n```\n\n```javascript\n// JavaScript side - access as object properties\nhtmlComponent.Data.ItemName  // \"Apple\"\nhtmlComponent.Data.Price     // 2\nhtmlComponent.Data.Quantity  // 10\n```\n\n## Critical Rules\n\n### Security Requirements\n\n- **ALWAYS** set `HTMLSource = 'trusted'` when using local HTML files:\n  ```matlab\n  h.HTMLSource = fullfile(pwd, 'myapp.html');\n  % This is treated as trusted automatically for local files\n  ```\n\n- **MUST** validate all input from JavaScript before processing in MATLAB\n- **NEVER** use `eval()` on user input without strict sanitization\n- **ALWAYS** restrict allowed characters in user input for expressions\n\n### Error Handling\n\n**ALWAYS wrap MATLAB event handlers in try-catch blocks:**\n\n```matlab\nfunction handleEvent(src, event)\n    eventName = event.HTMLEventName;\n    eventData = event.HTMLEventData;\n\n    try\n        % Process the event\n        result = processData(eventData);\n\n        % Send result back to JavaScript\n        sendEventToHTMLSource(src, 'ResultEvent', result);\n\n    catch ME\n        % Handle errors gracefully\n        fprintf('Error: %s\\n', ME.message);\n        sendEventToHTMLSource(src, 'ErrorEvent', ME.message);\n    end\nend\n```\n\n### Data Validation\n\n**ALWAYS validate user input before processing:**\n\n```matlab\nfunction result = validateExpression(expression)\n    allowedChars = '0123456789+-*/.() ';\n    if ~all(ismember(expression, allowedChars))\n        error('Invalid characters in expression');\n    end\n    % Additional validation...\n    result = true;\nend\n```\n\n### File Organization\n\n**Follow this directory structure:**\n\n```\nproject/\n├── app.m           # Main MATLAB function\n├── app.html        # HTML interface\n├── README.md       # Usage instructions\n└── examples/       # Additional examples (optional)\n```\n\n## Complete Examples\n\n### Example 1: Simple Calculator App\n\n**MATLAB Side (calculator.m):**\n\n```matlab\nfunction calculator()\n    % Create main figure\n    fig = uifigure('Name', 'Calculator', 'Position', [100 100 400 500]);\n\n    % Create HTML component\n    h = uihtml(fig, 'Position', [25 25 350 450]);\n    h.HTMLSource = fullfile(pwd, 'calculator.html');\n    h.HTMLEventReceivedFcn = @(src, event) handleEvent(src, event);\nend\n\nfunction handleEvent(src, event)\n    eventName = event.HTMLEventName;\n    eventData = event.HTMLEventData;\n\n    try\n        switch eventName\n            case 'Calculate'\n                % Validate input\n                expression = char(eventData);\n                allowedChars = '0123456789+-*/.() ';\n\n                if ~all(ismember(expression, allowedChars))\n                    error('Invalid characters in expression');\n                end\n\n                % Evaluate safely\n                result = eval(expression);\n\n                % Send result back\n                sendEventToHTMLSource(src, 'Result', num2str(result));\n\n            case 'Clear'\n                sendEventToHTMLSource(src, 'Result', '0');\n        end\n\n    catch ME\n        fprintf('Error: %s\\n', ME.message);\n        sendEventToHTMLSource(src, 'Error', 'Invalid expression');\n    end\nend\n```\n\n**HTML Side (calculator.html):**\n\n```html\n<!DOCTYPE html>\n<html>\n<head>\n    <style>\n        body {\n            font-family: Arial, sans-serif;\n            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n            margin: 0;\n            padding: 20px;\n        }\n\n        .calculator {\n            background: white;\n            border-radius: 10px;\n            padding: 20px;\n            box-shadow: 0 10px 30px rgba(0,0,0,0.3);\n        }\n\n        .display {\n            width: 100%;\n            height: 60px;\n            font-size: 24px;\n            text-align: right;\n            padding: 10px;\n            border: 2px solid #ccc;\n            border-radius: 5px;\n            margin-bottom: 10px;\n            background: #f9f9f9;\n        }\n\n        .buttons {\n            display: grid;\n            grid-template-columns: repeat(4, 1fr);\n            gap: 10px;\n        }\n\n        button {\n            padding: 20px;\n            font-size: 18px;\n            border: none;\n            border-radius: 5px;\n            cursor: pointer;\n            background: #667eea;\n            color: white;\n            transition: background 0.3s;\n        }\n\n        button:hover {\n            background: #764ba2;\n        }\n\n        .operator {\n            background: #ff6b6b;\n        }\n\n        .operator:hover {\n            background: #ee5a52;\n        }\n    </style>\n\n    <script type=\"text/javascript\">\n        let currentExpression = '';\n\n        function setup(htmlComponent) {\n            window.htmlComponent = htmlComponent;\n\n            // Listen for results from MATLAB\n            htmlComponent.addEventListener(\"Result\", function(event) {\n                document.getElementById(\"display\").value = event.Data;\n                currentExpression = event.Data;\n            });\n\n            htmlComponent.addEventListener(\"Error\", function(event) {\n                document.getElementById(\"display\").value = \"Error\";\n                currentExpression = '';\n            });\n        }\n\n        function appendToDisplay(value) {\n            currentExpression += value;\n            document.getElementById(\"display\").value = currentExpression;\n        }\n\n        function clearDisplay() {\n            currentExpression = '';\n            document.getElementById(\"display\").value = '0';\n            window.htmlComponent.sendEventToMATLAB(\"Clear\", \"\");\n        }\n\n        function calculate() {\n            if (currentExpression) {\n                window.htmlComponent.sendEventToMATLAB(\"Calculate\", currentExpression);\n            }\n        }\n    </script>\n</head>\n<body>\n    <div class=\"calculator\">\n        <input type=\"text\" id=\"display\" class=\"display\" value=\"0\" readonly>\n        <div class=\"buttons\">\n            <button onclick=\"appendToDisplay('7')\">7</button>\n            <button onclick=\"appendToDisplay('8')\">8</button>\n            <button onclick=\"appendToDisplay('9')\">9</button>\n            <button class=\"operator\" onclick=\"appendToDisplay('/')\">/</button>\n\n            <button onclick=\"appendToDisplay('4')\">4</button>\n            <button onclick=\"appendToDisplay('5')\">5</button>\n            <button onclick=\"appendToDisplay('6')\">6</button>\n            <button class=\"operator\" onclick=\"appendToDisplay('*')\">*</button>\n\n            <button onclick=\"appendToDisplay('1')\">1</button>\n            <button onclick=\"appendToDisplay('2')\">2</button>\n            <button onclick=\"appendToDisplay('3')\">3</button>\n            <button class=\"operator\" onclick=\"appendToDisplay('-')\">-</button>\n\n            <button onclick=\"appendToDisplay('0')\">0</button>\n            <button onclick=\"appendToDisplay('.')\">.</button>\n            <button onclick=\"calculate()\">=</button>\n            <button class=\"operator\" onclick=\"appendToDisplay('+')\">+</button>\n\n            <button style=\"grid-column: span 4; background: #ff6b6b;\" onclick=\"clearDisplay()\">Clear</button>\n        </div>\n    </div>\n</body>\n</html>\n```\n\n### Example 2: Data Visualization App\n\n**MATLAB Side (visualizer.m):**\n\n```matlab\nfunction visualizer()\n    fig = uifigure('Name', 'Data Visualizer', 'Position', [100 100 800 600]);\n\n    % Create HTML component for controls\n    h = uihtml(fig, 'Position', [25 400 750 175]);\n    h.HTMLSource = fullfile(pwd, 'controls.html');\n    h.HTMLEventReceivedFcn = @(src, event) handleEvent(src, event, fig);\n\n    % Create axes for plotting\n    ax = uiaxes(fig, 'Position', [25 25 750 350]);\n    xlabel(ax, 'X');\n    ylabel(ax, 'Y');\n    title(ax, 'Interactive Plot');\nend\n\nfunction handleEvent(src, event, fig)\n    eventName = event.HTMLEventName;\n    eventData = event.HTMLEventData;\n\n    try\n        switch eventName\n            case 'UpdatePlot'\n                % Parse parameters from JavaScript\n                params = eventData;\n                frequency = params.frequency;\n                amplitude = params.amplitude;\n                plotType = params.plotType;\n\n                % Generate data\n                x = linspace(0, 4*pi, 200);\n\n                switch plotType\n                    case 'sine'\n                        y = amplitude * sin(frequency * x);\n                    case 'cosine'\n                        y = amplitude * cos(frequency * x);\n                    case 'both'\n                        y = amplitude * sin(frequency * x);\n                        y2 = amplitude * cos(frequency * x);\n                end\n\n                % Find axes and plot\n                ax = findobj(fig, 'Type', 'axes');\n                cla(ax);\n\n                if strcmp(plotType, 'both')\n                    plot(ax, x, y, 'LineWidth', 2);\n                    hold(ax, 'on');\n                    plot(ax, x, y2, 'LineWidth', 2);\n                    hold(ax, 'off');\n                    legend(ax, 'Sine', 'Cosine');\n                else\n                    plot(ax, x, y, 'LineWidth', 2);\n                end\n\n                grid(ax, 'on');\n\n                % Send confirmation\n                sendEventToHTMLSource(src, 'PlotUpdated', 'Success');\n        end\n\n    catch ME\n        fprintf('Error: %s\\n', ME.message);\n        sendEventToHTMLSource(src, 'Error', ME.message);\n    end\nend\n```\n\n**HTML Side (controls.html):**\n\n```html\n<!DOCTYPE html>\n<html>\n<head>\n    <style>\n        body {\n            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n            background: linear-gradient(135deg, #2c3e50 0%, #34495e 100%);\n            color: white;\n            margin: 0;\n            padding: 20px;\n        }\n\n        .controls {\n            display: grid;\n            grid-template-columns: 1fr 1fr 1fr;\n            gap: 20px;\n        }\n\n        .control-group {\n            background: rgba(255,255,255,0.1);\n            padding: 15px;\n            border-radius: 8px;\n        }\n\n        label {\n            display: block;\n            margin-bottom: 5px;\n            font-weight: bold;\n        }\n\n        input[type=\"range\"] {\n            width: 100%;\n        }\n\n        select, button {\n            width: 100%;\n            padding: 8px;\n            border-radius: 5px;\n            border: none;\n            font-size: 14px;\n        }\n\n        button {\n            background: #3498db;\n            color: white;\n            cursor: pointer;\n            margin-top: 10px;\n            transition: background 0.3s;\n        }\n\n        button:hover {\n            background: #2980b9;\n        }\n    </style>\n\n    <script type=\"text/javascript\">\n        function setup(htmlComponent) {\n            window.htmlComponent = htmlComponent;\n\n            htmlComponent.addEventListener(\"PlotUpdated\", function(event) {\n                console.log(\"Plot updated successfully\");\n            });\n        }\n\n        function updatePlot() {\n            const frequency = parseFloat(document.getElementById(\"frequency\").value);\n            const amplitude = parseFloat(document.getElementById(\"amplitude\").value);\n            const plotType = document.getElementById(\"plotType\").value;\n\n            const params = {\n                frequency: frequency,\n                amplitude: amplitude,\n                plotType: plotType\n            };\n\n            window.htmlComponent.sendEventToMATLAB(\"UpdatePlot\", params);\n        }\n\n        function updateFreqLabel(value) {\n            document.getElementById(\"freqValue\").textContent = value;\n        }\n\n        function updateAmpLabel(value) {\n            document.getElementById(\"ampValue\").textContent = value;\n        }\n    </script>\n</head>\n<body>\n    <div class=\"controls\">\n        <div class=\"control-group\">\n            <label>Frequency: <span id=\"freqValue\">1</span></label>\n            <input type=\"range\" id=\"frequency\" min=\"0.1\" max=\"5\" step=\"0.1\" value=\"1\"\n                   oninput=\"updateFreqLabel(this.value)\">\n        </div>\n\n        <div class=\"control-group\">\n            <label>Amplitude: <span id=\"ampValue\">1</span></label>\n            <input type=\"range\" id=\"amplitude\" min=\"0.1\" max=\"5\" step=\"0.1\" value=\"1\"\n                   oninput=\"updateAmpLabel(this.value)\">\n        </div>\n\n        <div class=\"control-group\">\n            <label>Plot Type:</label>\n            <select id=\"plotType\">\n                <option value=\"sine\">Sine</option>\n                <option value=\"cosine\">Cosine</option>\n                <option value=\"both\">Both</option>\n            </select>\n        </div>\n    </div>\n\n    <button onclick=\"updatePlot()\">Update Plot</button>\n</body>\n</html>\n```\n\n### Example 3: Form Processing App\n\n**MATLAB Side (formProcessor.m):**\n\n```matlab\nfunction formProcessor()\n    fig = uifigure('Name', 'Form Processor', 'Position', [100 100 600 400]);\n\n    h = uihtml(fig, 'Position', [25 25 550 350]);\n    h.HTMLSource = fullfile(pwd, 'form.html');\n    h.HTMLEventReceivedFcn = @(src, event) handleEvent(src, event);\nend\n\nfunction handleEvent(src, event)\n    eventName = event.HTMLEventName;\n    eventData = event.HTMLEventData;\n\n    try\n        switch eventName\n            case 'SubmitForm'\n                % Extract form data\n                name = eventData.name;\n                email = eventData.email;\n                age = eventData.age;\n\n                % Validate data\n                if isempty(name) || isempty(email)\n                    error('Name and email are required');\n                end\n\n                if ~contains(email, '@')\n                    error('Invalid email address');\n                end\n\n                if age < 0 || age > 120\n                    error('Invalid age');\n                end\n\n                % Process data (example: save to file or database)\n                fprintf('Processing form:\\n');\n                fprintf('  Name: %s\\n', name);\n                fprintf('  Email: %s\\n', email);\n                fprintf('  Age: %d\\n', age);\n\n                % Send success message\n                result = struct('status', 'success', ...\n                               'message', 'Form submitted successfully!');\n                sendEventToHTMLSource(src, 'FormResult', result);\n\n            case 'ClearForm'\n                sendEventToHTMLSource(src, 'FormCleared', '');\n        end\n\n    catch ME\n        fprintf('Error: %s\\n', ME.message);\n        result = struct('status', 'error', 'message', ME.message);\n        sendEventToHTMLSource(src, 'FormResult', result);\n    end\nend\n```\n\n## Best Practices\n\n### UI Design Principles\n\n- **Use CSS Grid or Flexbox** for responsive layouts that adapt to different window sizes\n- **Implement hover effects** for better user experience and visual feedback\n- **Provide clear visual feedback** for user actions (button clicks, form submission, errors)\n- **Use semantic HTML elements** (button, input, form) for better accessibility\n- **Apply professional color schemes** using CSS gradients and modern design patterns\n\n### Performance Optimization\n\n- **Minimize data transfer** between HTML and MATLAB - send only necessary data\n- **Use appropriate data types** - numbers, strings, structs (converted to JSON)\n- **Implement loading indicators** for long MATLAB operations\n- **Cache results** when appropriate using persistent variables in MATLAB\n- **Batch multiple updates** instead of sending many small events\n\n### Error Handling Strategy\n\n**JavaScript Side:**\n```javascript\nhtmlComponent.addEventListener(\"Error\", function(event) {\n    // Display user-friendly error messages\n    alert(\"Error: \" + event.Data);\n});\n```\n\n**MATLAB Side:**\n```matlab\ntry\n    result = processInput(input);\n    sendEventToHTMLSource(src, 'Success', result);\ncatch ME\n    fprintf('Error: %s\\n', ME.message);\n    sendEventToHTMLSource(src, 'Error', 'Processing failed');\nend\n```\n\n### Testing Strategy\n\n1. **Unit Testing** - Test MATLAB functions independently\n   ```matlab\n   % Test individual processing functions\n   assert(validateExpression('2+2'), 'Validation should pass');\n   ```\n\n2. **Integration Testing** - Test HTML-MATLAB communication\n   ```matlab\n   % Test event handling with sample data\n   testEvent = struct('HTMLEventName', 'Calculate', 'HTMLEventData', '2+2');\n   handleEvent(h, testEvent);\n   ```\n\n3. **User Testing** - Test complete user workflows\n   - Try all button combinations\n   - Test edge cases and invalid inputs\n   - Verify visual feedback is clear\n\n4. **Error Testing** - Test error conditions\n   - Invalid input characters\n   - Empty input fields\n   - Network/timeout scenarios\n\n### Debugging Tips\n\n- **MATLAB Side**: Use `fprintf()` to log events and data\n  ```matlab\n  fprintf('Received event: %s with data: %s\\n', eventName, eventData);\n  ```\n\n- **JavaScript Side**: Use browser developer tools (F12) to debug\n  ```javascript\n  console.log(\"Sending to MATLAB:\", data);\n  ```\n\n- **Test each communication direction separately**\n  - First test MATLAB → JavaScript (Data property)\n  - Then test JavaScript → MATLAB (events)\n  - Finally test bidirectional flow\n\n- **Verify data types and formats**\n  ```matlab\n  fprintf('Data type: %s\\n', class(eventData));\n  fprintf('Data value: %s\\n', string(eventData));\n  ```\n\n## Common Patterns\n\n### Pattern 1: Calculator Pattern\n- JavaScript builds expression strings from button clicks\n- Send expression to MATLAB via `sendEventToMATLAB`\n- MATLAB safely evaluates with input validation\n- Results sent back via `sendEventToHTMLSource`\n- Display results in real-time\n\n### Pattern 2: Data Visualization Pattern\n- JavaScript handles user interaction (sliders, dropdowns)\n- Send parameters to MATLAB for computation\n- MATLAB processes data and updates plots\n- Can use uiaxes for MATLAB plots or send data for JavaScript plotting\n- Support real-time updates and animations\n\n### Pattern 3: Form Processing Pattern\n- JavaScript collects form data into structured object\n- Send entire form data as single event\n- MATLAB validates each field\n- Process data (save, compute, export)\n- Send confirmation or error messages back\n- Update UI based on results\n\n### Pattern 4: Real-time Monitoring Pattern\n- MATLAB continuously generates data (simulation, sensor reading)\n- Send updates via `sendEventToHTMLSource` at intervals\n- JavaScript updates display in real-time\n- Implement start/stop/pause controls\n- Use efficient data formats (arrays, structs)\n\n## Implementation Checklist\n\nBefore deploying a uihtml app, verify:\n\n- [ ] HTML file exists in correct location\n- [ ] `HTMLSource` property set to correct file path\n- [ ] `HTMLEventReceivedFcn` callback defined\n- [ ] JavaScript `setup(htmlComponent)` function implemented\n- [ ] Event listeners added for MATLAB→JS communication\n- [ ] Try-catch blocks wrap all MATLAB event handling\n- [ ] Input validation implemented for all user data\n- [ ] Error events sent back to JavaScript for user feedback\n- [ ] CSS styling applied for professional appearance\n- [ ] Responsive design tested at different window sizes\n- [ ] All user interactions provide visual feedback\n- [ ] Loading indicators shown for long operations\n- [ ] File organization follows project structure\n- [ ] Documentation (README) created with usage instructions\n\n## Troubleshooting\n\n**Issue**: HTML file not loading in uihtml component\n- **Solution**: Check file path is absolute or relative to current directory\n  ```matlab\n  h.HTMLSource = fullfile(pwd, 'app.html');  % Absolute path\n  ```\n\n**Issue**: Events not triggering MATLAB callback\n- **Solution**: Verify `HTMLEventReceivedFcn` is set before HTML loads\n- **Solution**: Check JavaScript is calling `sendEventToMATLAB` correctly\n\n**Issue**: Data not updating in JavaScript\n- **Solution**: Ensure `DataChanged` event listener is registered in `setup()`\n- **Solution**: Verify MATLAB is setting `h.Data` property, not sending event\n\n**Issue**: JavaScript errors in browser console\n- **Solution**: Open browser dev tools (F12) to see detailed error messages\n- **Solution**: Ensure `htmlComponent` is passed to `setup()` function\n- **Solution**: Check for typos in element IDs and function names\n\n**Issue**: MATLAB errors not displayed to user\n- **Solution**: Implement error event handling in both MATLAB and JavaScript\n- **Solution**: Use try-catch in MATLAB and send error messages via `sendEventToHTMLSource`\n\n**Issue**: Slow performance when sending data\n- **Solution**: Reduce frequency of updates (throttle events)\n- **Solution**: Send only changed data, not entire datasets\n- **Solution**: Use appropriate data types (numbers vs strings)\n\n**Issue**: Complex data structures not transferring correctly\n- **Solution**: Use MATLAB structs (automatically converted to JSON)\n- **Solution**: Avoid nested cell arrays; use struct arrays instead\n- **Solution**: Test data transfer with simple examples first\n\n**Issue**: Styling not appearing correctly\n- **Solution**: Verify CSS is in `<style>` block inside `<head>`\n- **Solution**: Check for CSS syntax errors\n- **Solution**: Use browser dev tools to inspect computed styles\n\n## Additional Resources\n\n- MATLAB Documentation: `doc uihtml`\n- HTML/CSS/JavaScript: MDN Web Docs\n- Event handling: `doc sendEventToHTMLSource`\n- Figure creation: `doc uifigure`\n- Debugging: Use browser Developer Tools (F12)","tags":["matlab","uihtml","app","builder","skills","agent-skill","agent-skills","agentic-ai","agents","claude","claude-api","claude-code"],"capabilities":["skill","source-matlab","skill-matlab-uihtml-app-builder","topic-agent-skill","topic-agent-skills","topic-agentic-ai","topic-agents","topic-claude","topic-claude-api","topic-claude-code","topic-claude-desktop","topic-claude-skills","topic-matlab","topic-matlab-skills"],"categories":["skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/matlab/skills/matlab-uihtml-app-builder","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add matlab/skills","source_repo":"https://github.com/matlab/skills","install_from":"skills.sh"}},"qualityScore":"0.482","qualityRationale":"deterministic score 0.48 from registry signals: · indexed on github topic:agent-skills · 65 github stars · SKILL.md body (23,727 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-22T00:55:57.753Z","embedding":null,"createdAt":"2026-04-18T22:14:25.979Z","updatedAt":"2026-04-22T00:55:57.753Z","lastSeenAt":"2026-04-22T00:55:57.753Z","tsv":"'+2':1194,1219 '0':619,648,748,950 '0123456789':485,589 '1':149,198,526,645,854,856,1179,1339 '10':347,362 '100':544,545,667,668,881,882 '120':952 '175':683 '2':158,232,345,360,646,651,801,810,824,1193,1198,1218,1373 '200':751 '25':555,556,680,703,704,889,890 '3':166,275,647,865,1223,1415 '350':557,706,892 '4':174,318,642,749,1245,1454 '400':546,681,884 '450':558 '5':643 '500':547 '550':891 '6':644 '600':670,883 '7':639 '750':682,705 '8':640 '800':669 '9':641 'absolut':1600,1611 'access':353,1074 'action':1059 'ad':1520 'adapt':1038 'addit':497,520 'address':946 'age':924,949,951,955,980,983 'alert':1150 'allow':411 'allowedchar':484,490,588,594 'alway':367,409,420,473 'amplitud':740,757,764,771,776,855 'anim':1413 'app':4,28,47,93,120,135,529,654,868,1495 'app.html':513,1610 'app.m':509 'appear':1555,1788 'appl':343,358 'appli':1075,1552 'applic':9,58,104 'appropri':1100,1119,1747 'architectur':72,145 'array':1487,1772,1775 'assert':1191 'automat':339,386,1764 'avoid':1769 'ax':699,708,711,714,785,791,797,803,806,812,815,820,827 'axe':696,782,789 'back':448,608,1363,1447,1544 'backend':16,66,168 'base':26,100,141,1450 'batch':1125 'best':1024 'better':1047,1073 'bidirect':188,1314 'block':429,1528 'bridg':177 'browser':1284,1663,1667 'build':6,55,90,1343 'builder':5,48 'button':155,1060,1069,1232,1347 'cach':1116 'calcul':83,134,252,528,535,542,582,1216,1340 'calculator.html':562,637 'calculator.m':532 'call':1631 'callback':1511,1618 'capabl':77 'case':204,237,281,323,581,614,730,754,761,768,915,999,1236 'catch':428,455,621,836,1005,1164,1527,1715 'cell':1771 'chang':1740 'char':586 'charact':412,493,597,1253 'check':1596,1628,1685 'checklist':1490 'cla':790 'class':1327 'clear':615,649,1054,1244 'clearform':1000 'click':1061,1348 'collect':1420 'color':1077 'combin':60,125,1233 'common':1336 'communic':182,189,1205,1298,1524 'complet':523,1227 'complex':319,1754 'compon':20,70,148,176,186,550,673,1594 'comprehens':52 'comput':15,65,131,169,283,1388,1440 'condit':1250 'confirm':830,1443 'consol':1664 'console.log':1291 'contain':941 'continu':1461 'control':675,1482 'controls.html':687,851 'convert':1106,1765 'core':144 'correct':1501,1507,1633,1759,1789 'cos':765,777 'cosin':762,817,860 'creat':23,97,133,536,548,671,695,1582 'critic':363 'css':1030,1080,1550,1792 'current':1604 'custom':278,294,307 'd':981 'data':136,172,201,206,320,326,335,471,652,664,745,919,927,958,1089,1098,1101,1212,1269,1276,1295,1305,1317,1323,1330,1374,1391,1403,1422,1429,1438,1463,1485,1540,1635,1729,1741,1748,1755,1779 'databas':964 'datachang':224,1642 'dataset':1744 'debug':1259,1289 'defin':1512 'deploy':1492 'design':128,1027,1084,1557 'detail':1673 'dev':1668 'develop':105,1285 'differ':1040,1560 'direct':1299 'directori':506,1605 'display':157,228,314,1144,1366,1475,1698 'document':1580 'document.getelementbyid':227,313 'dropdown':1382 'edg':1235 'effect':1045 'effici':1484 'element':1068,1689 'els':818 'email':922,932,936,942,945,975,978 'empti':1254 'enabl':187 'encod':338 'end':273,469,470,496,501,569,600,620,633,634,717,780,825,835,847,848,903,939,947,956,1004,1022,1023,1176 'engin':84,170 'ensur':1641,1677 'entir':1427,1743 'error':418,458,461,491,595,624,630,839,845,933,943,953,1008,1015,1064,1134,1141,1148,1151,1167,1173,1246,1249,1445,1541,1661,1674,1696,1703,1720 'errorev':467 'eval':402,604 'evalu':601,1357 'event':161,226,235,248,260,266,272,279,295,308,312,423,434,442,565,568,573,690,693,721,899,902,907,1133,1143,1208,1267,1273,1311,1432,1518,1532,1542,1614,1643,1658,1704,1736 'event.data':316,1152 'event.htmleventdata':270,438,577,726,911 'event.htmleventname':268,436,575,724,909 'eventdata':269,437,445,576,587,725,737,910,1280,1328,1335 'eventdata.age':925 'eventdata.email':923 'eventdata.name':921 'eventnam':267,435,574,580,723,729,908,914,1279 'exampl':519,521,524,525,650,864,959,1783 'exist':1499 'experi':1049 'export':1441 'express':253,417,483,489,495,585,593,599,605,632,1344,1350 'extract':917 'f12':1287,1670 'fail':1175 'feedback':1052,1056,1242,1549,1568 'field':1256,1436 'fig':539,553,661,678,694,701,722,787,875,887 'figur':538 'file':375,389,502,962,1498,1508,1575,1589,1597 'final':1312 'find':781 'findobj':786 'first':1301,1784 'flexbox':1033 'flow':1315 'follow':504,1577 'form':140,156,866,878,918,967,992,1062,1071,1416,1421,1428 'form-bas':139 'form.html':896 'format':1320,1486 'formclear':1003 'formprocessor':874 'formprocessor.m':871 'formresult':997,1020 'four':147 'fprintf':460,623,838,965,969,974,979,1007,1166,1264,1271,1322,1329 'frequenc':738,759,766,773,778,853,1732 'friend':1147 'fullfil':378,560,685,894,1608 'function':225,240,263,311,431,480,512,534,570,659,718,873,904,1142,1184,1190,1516,1683,1692 'generat':744,1462 'get':336 'grace':459 'gradient':1081 'grid':826,1031 'gui':38,109,124 'guidelin':53 'h':299,551,676,885,1221 'h.data':217,348,1654 'h.htmleventreceivedfcn':261,563,688,897 'h.htmlsource':377,559,684,893,1607 'handl':162,259,419,457,1135,1209,1378,1533,1705 'handleev':262,264,432,566,571,691,719,900,905,1220 'handler':424 'har':79 'hello':218 'hold':802,811 'hover':1044 'htm':44 'html':25,117,150,179,212,374,514,549,635,638,672,849,852,1067,1092,1203,1497,1588,1625 'html-base':24 'html-matlab':1202 'html/javascript':11,61,95 'htmlcompon':1515,1678 'htmlcomponent.addeventlistener':223,309,1140 'htmlcomponent.data':230 'htmlcomponent.data.itemname':357 'htmlcomponent.data.price':359 'htmlcomponent.data.quantity':361 'htmlcomponent.sendeventtomatlab':251 'htmleventdata':1217 'htmleventnam':1215 'htmleventreceivedfcn':1510,1621 'htmlsourc':369,1503 'id':1690 'implement':1043,1109,1480,1489,1517,1536,1702 'independ':1185 'indic':1111,1570 'individu':1188 'innerhtml':229 'input':393,405,415,476,584,1070,1159,1239,1252,1255,1359,1534 'instead':1128,1776 'instruct':518,1585 'integr':1199 'interact':7,36,56,91,123,165,243,715,1380,1565 'interfac':12,31,62,96,122,151,153,213,515 'interv':1472 'invalid':492,596,631,944,954,1238,1251 'isempti':929,931 'ismemb':488,592 'issu':1587,1613,1634,1659,1694,1724,1753,1785 'itemdata':340,349 'itemnam':342 'javascript':29,118,159,191,200,220,221,233,244,245,277,289,297,302,303,330,350,351,395,450,735,1137,1139,1281,1290,1304,1309,1342,1377,1405,1419,1473,1513,1546,1629,1639,1660,1710 'js':1523 'json':337,1108,1767 'layout':1036 'legend':814 'leverag':73 'linewidth':800,809,823 'linspac':747 'listen':305,1519,1644 'load':1110,1569,1591,1626 'local':373,388 'locat':1502 'log':1266 'logic':160 'long':1113,1573 'main':510,537 'mani':1131 'matlab':2,14,27,30,35,37,45,64,80,92,103,108,130,142,167,181,193,199,208,214,215,234,239,250,254,255,276,290,291,328,331,332,376,399,422,430,479,511,530,533,655,658,869,872,1094,1114,1124,1153,1155,1183,1186,1204,1206,1261,1270,1294,1303,1310,1321,1352,1355,1386,1389,1399,1433,1460,1522,1531,1606,1617,1651,1695,1708,1717,1762 'matlab-uihtml-app-build':1 'me.message':464,468,627,842,846,1011,1017,1170 'mechan':196 'mention':42,115 'messag':986,991,1016,1149,1446,1675,1721 'minim':1088 'modern':74,106,1083 'monitor':1458 'multipl':1126 'must':390 'myapp.html':380 'n':463,626,841,968,972,977,982,1010,1169,1278,1326,1333 'name':541,663,877,920,930,934,970,973,1693 'necessari':1097 'nest':1770 'network/timeout':1257 'never':400 'num2str':612 'number':1103,1750 'object':355,1425 'open':1666 'oper':1115,1574 'optim':1087 'option':522 'organ':503,1576 'param':736 'paramet':733,1384 'params.amplitude':741 'params.frequency':739 'params.plottype':743 'pars':732 'pass':324,1197,1680 'path':1509,1598,1612 'pattern':183,197,231,274,317,1085,1337,1338,1341,1372,1376,1414,1418,1453,1459 'perform':1086,1726 'persist':1121 'pi':750 'plot':698,716,784,796,805,819,857,863,1394,1400,1406 'plottyp':742,753,794 'plotupd':833 'posit':543,554,666,679,702,880,888 'power':82,132 'practic':1025 'price':344 'principl':1028 'process':173,271,397,440,478,867,957,966,1174,1189,1390,1417,1437 'processdata':444 'processinput':1158 'processor':879 'profession':1076,1554 'project':508,1578 'properti':202,356,1306,1504,1655 'provid':51,1053,1566 'pwd':379,561,686,895,1609 'quantiti':346 'read':1466 'readm':1581 'readme.md':516 'real':1370,1409,1456,1478 'real-tim':1369,1408,1455,1477 'receiv':257,1272 'reduc':1731 'regist':1646 'relat':1602 'requir':366,938 'respons':107,1035,1556 'restrict':410 'result':284,301,443,447,454,481,499,603,607,611,613,618,987,998,1012,1021,1117,1157,1163,1361,1367,1452 'resultchang':300,310 'resultev':453 'rule':364 'safe':602,1356 'sampl':1211 'sanit':408 'save':960,1439 'scenario':1258 'scheme':1078 'secur':365 'see':1672 'semant':1066 'send':205,247,282,293,446,606,829,984,1095,1130,1292,1349,1383,1402,1426,1442,1467,1657,1719,1728,1738 'sendeventtohtmlsourc':298,451,465,609,616,628,831,843,995,1001,1018,1160,1171,1365,1470,1723 'sendeventtomatlab':1354,1632 'sensor':1465 'sent':1362,1543 'separ':1300 'set':368,1505,1623,1653 'setup':1514,1648,1682 'sever':195 'shown':1571 'side':216,222,246,256,292,304,333,352,531,636,656,850,870,1138,1154,1262,1282 'simpl':527,1782 'simul':1464 'sin':758,772 'sine':755,816,859 'singl':1431 'size':1042,1562 'skill':50,89 'skill-matlab-uihtml-app-builder' 'slider':1381 'slow':1725 'small':1132 'solut':1595,1619,1627,1640,1649,1665,1676,1684,1701,1711,1730,1737,1745,1760,1768,1777,1790 'source-matlab' 'src':265,433,452,466,564,567,572,610,617,629,689,692,720,832,844,898,901,906,996,1002,1019,1161,1172 'start/stop/pause':1481 'status':286,989,1014 'strategi':1136,1178 'strcmp':793 'strict':407 'string':1104,1334,1345,1752 'struct':334,341,988,1013,1105,1214,1488,1763,1774 'structur':325,507,1424,1579,1756 'style':1551,1786 'submiss':1063 'submit':993 'submitform':916 'success':834,985,990,994,1162 'support':1407 'switch':579,728,752,913 'technolog':112 'test':1177,1181,1182,1187,1200,1201,1207,1225,1226,1234,1247,1248,1296,1302,1308,1313,1558,1778 'testev':1213,1222 'textcont':315 'throttl':1735 'time':1371,1410,1457,1479 'tip':1260 'titl':713 'tool':143,1286,1669 'topic-agent-skill' 'topic-agent-skills' 'topic-agentic-ai' 'topic-agents' 'topic-claude' 'topic-claude-api' 'topic-claude-code' 'topic-claude-desktop' 'topic-claude-skills' 'topic-matlab' 'topic-matlab-skills' 'transfer':321,1090,1758,1780 'treat':383 'tri':427,439,578,727,912,1156,1230,1526,1714 'trigger':238,1616 'troubleshoot':1586 'true':500 'trust':370,385 'try-catch':426,1525,1713 'type':788,858,1102,1318,1324,1749 'typo':1687 'ui':33,76,101,127,164,1026,1449 'uiax':700,1397 'uifigur':540,662,876 'uihtml':3,19,43,46,69,116,175,185,552,677,886,1494,1593 'unit':1180 'updat':210,287,862,1127,1393,1411,1448,1468,1474,1637,1734 'updateplot':731 'usag':517,1584 'use':10,21,67,87,110,203,236,280,322,372,401,1029,1065,1079,1099,1120,1263,1283,1396,1483,1712,1746,1761,1773 'user':41,114,152,242,404,414,475,1048,1058,1146,1224,1228,1379,1539,1548,1564,1700 'user-friend':1145 'valid':391,472,474,498,583,926,1195,1360,1434,1535 'validateexpress':482,1192 'valu':1331 'variabl':1122 'verifi':1240,1316,1496,1620,1650,1791 'via':17,1353,1364,1469,1722 'visual':137,653,660,665,1051,1055,1241,1375,1567 'visualizer.m':657 'vs':1751 'web':8,32,57,75,99,111,119,121,126 'web-bas':98 'window':1041,1561 'without':406 'workflow':1229 'world':219 'wrap':421,1529 'x':709,746,760,767,774,779,798,807,821 'xlabel':707 'y':712,756,763,770,799,822 'y2':775,808 'ylabel':710","prices":[{"id":"275868da-22df-463c-846b-42b37b5be28d","listingId":"8d25f25b-a11a-4d39-8927-d4de771c5a73","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"matlab","category":"skills","install_from":"skills.sh"},"createdAt":"2026-04-18T22:14:25.979Z"}],"sources":[{"listingId":"8d25f25b-a11a-4d39-8927-d4de771c5a73","source":"github","sourceId":"matlab/skills/matlab-uihtml-app-builder","sourceUrl":"https://github.com/matlab/skills/tree/main/skills/matlab-uihtml-app-builder","isPrimary":false,"firstSeenAt":"2026-04-18T22:14:25.979Z","lastSeenAt":"2026-04-22T00:55:57.753Z"}],"details":{"listingId":"8d25f25b-a11a-4d39-8927-d4de771c5a73","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"matlab","slug":"matlab-uihtml-app-builder","github":{"repo":"matlab/skills","stars":65,"topics":["agent-skill","agent-skills","agentic-ai","agents","claude","claude-api","claude-code","claude-desktop","claude-skills","matlab","matlab-skills"],"license":"other","html_url":"https://github.com/matlab/skills","pushed_at":"2026-03-20T00:56:44Z","description":"A collection of Agent Skills for MATLAB development. Skills are specialized instruction sets that extend a coding agent's capabilities for specific tasks, automatically activating when needed.","skill_md_sha":"df2ff28834346434269d617755539a8c159255f4","skill_md_path":"skills/matlab-uihtml-app-builder/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/matlab/skills/tree/main/skills/matlab-uihtml-app-builder"},"layout":"multi","source":"github","category":"skills","frontmatter":{"name":"matlab-uihtml-app-builder","license":"MathWorks BSD-3-Clause (see LICENSE)","description":"Build interactive web applications using HTML/JavaScript interfaces with MATLAB computational backends via the uihtml component. Use when creating HTML-based MATLAB apps, JavaScript MATLAB interfaces, web UIs with MATLAB, interactive MATLAB GUIs, or when user mentions uihtml, HTML, JavaScript, web apps, or web interfaces."},"skills_sh_url":"https://skills.sh/matlab/skills/matlab-uihtml-app-builder"},"updatedAt":"2026-04-22T00:55:57.753Z"}}