Widget Examples

This script shows the Corona related numbers: https://gist.github.com/planecore/e7b4c1e5db2dd28b1a023860e831355e

The script was developed by @planecore.


This script shows a daily text snippet: https://gist.github.com/mattapperson/114e5267d5bc736fbe616b6205f3df92

Developed by @mattapperson.

1 Like

This script shows a random image: https://gist.github.com/jacopocolo/0e28c4af2e28c9de058480da0c5d4582

Developed by @jacopocolo.

1 Like

This script shows the XKCD comic of the day: https://gist.github.com/rudotriton/9d11ce1101ff1269f56844871b3fd536

Developed by @raigojerva.


This script shows a graph from Charty: https://gist.github.com/0507spc/85ac637e6f46c466c47332a55a6411f4

It depends on this shortcut: https://www.icloud.com/shortcuts/9a2c3dc4c8934db0a770a46eb18ff807

Developed by @cranies.


This script shows the menu in a company’s cantina: https://gist.github.com/Casperbart/d8850fcdb1d7549502ce68f65854f997

Developed by @cassebart.


@simonbs I’m trying to display this 800x800 image (exported by Charty):

I want it to fill the entire widget, but unfortunately this is what I get instead…

It does not seem to matter whether I set an imageSize (nor which width/height I use) or not.

What can be wrong here?

(I’m essentially using Steven Crane’s code, but with a different sized image - so my experiments are all on line 26 in his code)

Hi, it’s Steve here, it may be due to the widget export profile I have with Charty:

Try that and see if that helps (you may need to alter values to suit).

1 Like

Here is my Reddit code, it is not the cleanest, I copied / pasted / trial and error hacked until I got what I wanted. I have set the click to run script which then opens Reddit on that subreddit.

// Shows latest news from MacStories in a table.
// The table shows an image from the article, if available, and the title of the article.
let rReddit = "Scriptable"
let url = "https://www.reddit.com/r/" + rReddit + "/new.json?limit=6"
let req = new Request(url)
let json = await req.loadJSON()
let items = json.data.children
let appURL = "reddit:///r/" + rReddit

if (config.runsInWidget) {
  let widget = createWidget(items)
} else {

function createWidget(items) {
//   let item = items[0]
  let w = new ListWidget()
  w.backgroundColor = new Color("#47761E")

let header = w.addText("r/" + rReddit)
header.textColor = Color.black()


    for (item of items) {
      var myDate = new Date(item.data.created_utc * 1000)
      var myFormDate = addZero(myDate.getHours()) + ":" + addZero(myDate.getMinutes())
      let titleTxt = w.addText("• " + myFormDate + " - " + item.data.title)
        titleTxt.textColor = Color.white()
        titleTxt.textSize = 14
  var nowDate = new Date()
  var nowFormDate = addZero(nowDate.getHours()) + ":" + addZero(nowDate.getMinutes())
  let footer = w.addText("Last Updated: " + nowFormDate)
  footer.textColor = Color.black()
  return w

function addZero(i) {
  if (i < 10) {
    i = "0" + i;
  return i;

You’re so tempting me to try the iOS 14 beta… :slight_smile:


Thanks for posting that!

Will give that a try later today or this weekend (and probably start with the same widget size you use instead of a square one).

Using exactly your dimensions seems to work better!

Note: I intentionally made the background of the widget white to see what’s happening

@cranie Can you explain the dimensions? You use 1600x800 in Charty, but 300x1400 in Scriptable?

So excited for this!

1 Like

9 posts were split to a new topic: Radio Paradise Now Playing

I built a widget for informing about a storm nearby. It using some Polish SOAP service (http://burze.dzis.net), but should work for most of Europe (just replace coords). And… you need API key.

async function fetchData(position) {
  const DDtoDM = (coord) => {
    const coordInt = Math.floor(coord)
    return coordInt + (coord - coordInt) * 0.6;

  const KEY = 'KEY_KEY_KEY';
  const RADIUS = '12'; //km
  const stormURL = 'https://burze.dzis.net/soap.php';

  const requestXML = `
  <soapenv:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:soap='https://burze.dzis.net/soap.php'>
     <soap:szukaj_burzy soapenv:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
        <y xsi:type='xsd:string'>${DDtoDM(position.longitude).toFixed(2)}</y>
        <x xsi:type='xsd:string'>${DDtoDM(position.latitude).toFixed(2)}</x>
        <promien xsi:type='xsd:int'>${RADIUS}</promien>
        <klucz xsi:type='xsd:string'>${KEY}</klucz>


  const req = new Request(stormURL);
  req.method = 'POST';
  req.headers = {
    'Content-Type': 'text/xml',
    'SOAPAction': '\'https://burze.dzis.net/soap.php\''
  req.body = requestXML;
  const response = await req.loadString();


  const parser = new XMLParser(response);

  var processedItem = '';

  var returned = {
    liczba: -1,
    odleglosc: -1,
    kierunek: 'n/a',
    okres: '0',

  parser.didStartElement = (name) => {
    processedItem = name;

  parser.foundCharacters = (value) => {
    switch (processedItem) {
      case 'liczba':
        returned.liczba = parseInt(value, 10);
      case 'odleglosc':
        returned.odleglosc = parseInt(value, 10);
      case 'kierunek':
        returned.kierunek = value;
      case 'okres':
        returned.okres = parseInt(value, 10);

  parser.didEndElement = (name) => {
    processedItem = '';



  return returned;

function createWidget(position, data) {
  let addressString = position.name;
  let headlineString = "No storms";
  let detailsString = "—";

  if (data.odleglosc > 0) {
    headlineString = "Storm nearby!";
    detailsString = `${data.liczba} strikes from ${data.kierunek} in last ${data.okres} min. Closest in ${data.odleglosc} km.`;

  const w = new ListWidget();
  w.backgroundColor = new Color("#20504F");

  const headline = w.addText(headlineString);
  headline.textColor = new Color("#fff");

  const details = w.addText(detailsString);
  details.textColor = new Color("#fff");

  const address = w.addText(addressString);
  address.textColor = new Color("#fff");


  return w;

const run = async (getPosition, getData, onFinish) => {
  const position = await getPosition();
  const data = await getData(position);

  onFinish(position, data);

const getStaticPosition = () => {
  return {
    longitude: 51.00,
    latitude: 18.00,
    name: 'Home',

await run(
  (position, data) => Script.setWidget(createWidget(position, data)),

1 Like

I have created super simple scriptable widget which queries api for Brainkeeper app (personal assistant for foreign vocabulary) to get random word from my list of words I collected. Super cool to have always foreign words in my sight to remember words better. :slight_smile:
Thanks for this Scriptable!


what if i wanted to make a widget like the coronavirus one but with a gradient background? Sorry, I’m new to coding

Several of the other widgets in this thread have a gradient background. Try taking a look at those to see how they do it. You’ll want to keep an eye out for mentions of LinearGradient and widget.backgroundGradient.

1 Like

My new widget shuffles a random album of the “Top 500 albums of all time” (according to the Rolling Stone magazine) and shows the cover art. Upon tapping on the widget it opens the album either in Spotify or plays it on your Sonos system.

Gist and setup instructions:


I wrote about this one:

Based on Matt Silverback’s original code, I added AQI calculations and set the widget to present the background color based on the current air quality status.

code here: https://gist.github.com/jasonsnell/4b458e2775e11ff7dd8b21dd26aa504e