| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Website: https://xnu.app/scriptwidget/
Create native widgets for iPhone, iPad, and Mac with JavaScript, JSX, and AI
English | 简体中文 | Español | 日本語 | 한국어 | Français | Deutsch | Português | Русский | العربية
✨ Build iPhone, iPad, and Mac widgets in ScriptWidget Studio—without writing Swift.
ScriptWidget is an open-source widget development platform for building native WidgetKit experiences with JavaScript and JSX-like syntax. Write once, preview on Mac, and run the same package on iPhone, iPad, and Mac—without requiring Swift for widget authoring.
It combines a JavaScriptCore runtime, native SwiftUI rendering, a desktop development environment, secure package sharing, AI-assisted generation, and a GitHub-backed community catalog.
| Feature | Description |
|---|---|
| 🖥️ Cross-Platform | One codebase for iOS and macOS widgets |
| 🎨 JSX Support | Declarative UI with JavaScript XML syntax |
| ⚡ Native Rendering | JSX elements are rendered as native SwiftUI views |
| 🔧 Versioned Runtime API | Storage, files, networking, device, location, health, system, and data sources |
| 📱 Interactive Widgets | Links, buttons, toggles, App Intents, Live Activities, and Control Widgets |
| 🎨 Custom Styling | Full control over appearance |
| 📦 Template Gallery | Pre-built templates to get started |
| 🌐 Community Gallery | Verified, one-click Widget and AI Skill installs |
| 🧰 ScriptWidget Studio | Build on Mac with CodeMirror, diagnostics, console, and multi-size preview |
| ✨ AI Generation | Generate, run, diagnose, and refine widgets with an OpenAI-compatible model |
| 🧠 Skills 1.0 | Import, author, export, and share focused AI instructions |
| 📦 Package 2.0 | Versioned widget.json, permissions, host allowlists, migration, and hardened imports |
| 🔌 Data Source Plugins | Declarative third-party API connectors with a Mac request lab |
Studio is the primary place to build widgets:
The first-launch guide can create a complete tutorial widget and walk a new user from editing through adding it to the desktop in about five minutes.
# Clone the repository
git clone https://github.com/everettjf/ScriptWidget.git
cd ScriptWidget# iOS app + widget + share extension
open iOS/ScriptWidget.xcodeproj
# macOS app + widget
open macOS/ScriptWidgetMac.xcodeprojScriptWidget/ ├── Shared/ │ └── ScriptWidgetRuntime/ # Core runtime: JavaScriptCore host, JSX→SwiftUI │ ├── AI/ # Provider settings, agent loop, evals, Skills │ ├── Common/ # Script storage, Package 2.0, cache & imports │ ├── Gallery/ # Verified GitHub catalog, cache & installer │ ├── Plugin/ # Declarative Data Source Plugin runtime │ ├── Widget/Runtime/ # JS engine setup, Babel transform, execution │ ├── Widget/API/ # JS APIs ($device, $file, $storage, ...) │ ├── Widget/Component/ # Element → SwiftUI view mapping │ └── Resource/ # Babel bundle + bundled example scripts ├── iOS/ │ ├── ScriptWidget/ # iOS app (editor, settings) │ ├── ScriptWidgetWidget/ # Widget, Live Activity, Control Widget │ └── ScriptWidgetShare/ # Share extension ├── macOS/ │ ├── ScriptWidgetMac/ # macOS app │ └── ScriptWidgetMacWidget/ # macOS widget ├── Editor/editorfe/ # Vite + CodeMirror 6 editor frontend ├── Gallery/ # Curated Widget & Skills Gallery index ├── Tests/ # Shared runtime, execution, cache & security tests ├── docs/ # User, API, package, Skills & release documentation ├── Resource/ # Marketing assets, screenshots └── README.md
A script's entry point is the $render(...) call, which takes a JSX tree built from runtime tags (vstack, hstack, zstack, text, image, gauge, chart, ...).
$render(
<vstack frame="max">
<text font="title">Hello, ScriptWidget! 👋</text>
</vstack>
);const result = await fetch("https://jsonplaceholder.typicode.com/todos/1");
const model = JSON.parse(result);
$render(
<vstack>
<text font="title">{model.title}</text>
</vstack>
);Package 2.0 widgets using network access must declare the network permission and matching hosts in widget.json.
const weather = await $dataSource.request(
"app.scriptwidget.datasource.open-meteo",
"forecast",
{ latitude: "37.7749", longitude: "-122.4194" }
);
$render(
<vstack frame="max" padding="16">
<text font="caption">San Francisco</text>
<text font="largeTitle">{weather.current.temperature_2m}°</text>
</vstack>
);The package must declare the plugin identifier, network permission, and the plugin host. Plugins are declarative HTTPS request mappings—not executable native extensions.
$storage.setString("greeting", "Hello ScriptWidget");
const greeting = $storage.getString("greeting");
$render(
<vstack frame="max" background="#0f172a">
<text font="caption" color="#94a3b8">Storage</text>
<text font="title3" color="#e2e8f0">{greeting}</text>
</vstack>
);# Clone and setup
git clone https://github.com/everettjf/ScriptWidget.git
cd ScriptWidget
# Open in Xcode (pick the platform you want)
open iOS/ScriptWidget.xcodeproj # iOS
open macOS/ScriptWidgetMac.xcodeproj # macOS
# Build and run (Cmd + R)The editor frontend (React + CodeMirror) lives in Editor/editorfe:
cd Editor/editorfe
npm install
npm start # dev server at http://localhost:3000
npm test
npm run build
npm run release # rebuild and copy StudioEditor.bundle into both appsRun the same repository gates used by CI:
./Scripts/release-readiness.sh
./Scripts/ipad-icloud-tests.shEach widget is stored under Scripts/<PackageName>/ and synced through iCloud/app-group storage. New projects use Package 2.0:
My Widget/
├── widget.json
├── main.jsx
├── lib/
│ └── format.js
└── image/
└── background.png
widget.json is the authoritative, versioned manifest. It declares the entry point, supported families, permissions, allowed network hosts, and Data Source Plugins. Legacy main.jsx/meta.json packages remain readable and migrate during supported import/export flows.
Start with the documentation hub or build your first widget in ScriptWidget Studio.
| API | Description |
|---|---|
| fetch() | HTTP requests (fetch/$fetch) |
| $storage | Persisted key/value store (string & JSON) |
| $file | Read/write files in the script package |
| $device | Device info (model, battery, screen, dark mode, …) |
| $location | Location & geocoding |
| $health | HealthKit data (steps, heart rate, …) |
| $system | System info (timezone, app version, …) |
| $import | Import another file from the package |
| $dataSource | Call a declared Data Source Plugin operation |
| $runtime | Runtime API version and enforced resource limits |
| console | Logging (console.log / console.error) |
The native JSX component switch is the runtime authority. Studio keeps static completion metadata in scriptWidgetAPI.js, checks it against the native switch, and generates the Runtime API reference from it.
Widget packages, Gallery content, Skills, and Data Source Plugins are treated as untrusted input:
See Package 2.0, modern WidgetKit features, Skills 1.0, Gallery, and Data Source Plugins for the complete contracts.
| Platform | Support | Notes |
|---|---|---|
| iOS | ✅ Full | iOS 16+ (iPhone, iPad) |
| macOS | ✅ Full | macOS 26+ (Mac) |
| watchOS | — | Not in the current roadmap |
| visionOS | — | Not in the current roadmap |
Contributions are welcome! Please read our Contributing Guide for details.
See the public roadmap, governance model, and Gallery submission guide. Every pull request runs the same release-readiness checks used locally.
The source code in this repository is released under the MIT License.
The ScriptWidget name, logos, screenshots, and App Store marketing materials are not licensed under the MIT License. All rights to those brand and marketing assets are reserved by their respective owners.
Built with:
Inspired by:
有问题?去 Issues 提问!
Made with ❤️ by Everett
Project Link: https://github.com/everettjf/ScriptWidget
| Back | FazBrowse Home | New Git URL |