Hackernoon logoHow To Create A Slick iOS Widget In JavaScript by@MartinMakarsky

How To Create A Slick iOS Widget In JavaScript

Martin makarsky Hacker Noon profile picture

@MartinMakarskyMartin makarsky


It’s not a long time ago when creating an iOS app or widget was solely available only for Objective-C or Swift developers with a solid Apple dev background (and of course, macOS device for development). These days, with a Scriptable app, it’s possible to create a native iOS widget even with basic JavaScript knowledge.

In this short tutorial, we’ll create an iOS home screen widget that will display scraped content directly on our iOS device home screen. For example purpose, we’ll scrape yahoo.finance losers page, we’ll get ticker symbol, name, and daily percentage change. Our script will also serialize these pieces of data into a JSON data source. This JSON file will be updated and published every hour by GitHub Actions. In the end, we use the Scriptable app for getting this JSON data and transform them into an iOS widget.

Of course, we could scrape URL directly using just JavaScript in our Scriptable script, however, we don’t need this data in real-time and I believe python and its packages are more suitable for this kind of task.

Scriptable what?

Scriptable is an app for iOS devices. In a nutshell, it allows you to write JavaScript code that will be under the hood translated into native iOS code. It provides you with a variety of nice APIs for creating an iOS widget user interface, networking, notifications, and many more. For skilled iOS developers, this might sound like magic (or it might remind you React Native, Cordova, or even PhoneGap). If you are wondering how it works under the hood I’d recommend this great podcast with the creator of Scriptable, Simon B. Støvring.


  1. Scrape the URL and create JSON with the scraped content
  2. Persist and serve data source JSON via GitHub pages
  3. Update JSON content every hour with GitHub action
  4. Get JSON content in Scriptable’s JavaScript
  5. Setup and present iOS widget

You’ll also need an iOS device with an installed Scriptable app, a GitHub account, and $0 for infrastructure.

1. Scrape the URL and create JSON with the scraped content

Create new GitHub repo and add a new python script (in my case


import requests
from bs4 import BeautifulSoup
import os
import json
import datetime

loosers_url = 'https://finance.yahoo.com/losers/'
loosers_response = requests.get(loosers_url)
loosers_page = BeautifulSoup(loosers_response.text, 'html.parser')
loosers_table = loosers_page.find('tbody')
looser_rows = loosers_table.find_all('tr')

result_json_content = {}
result_json_content['timestamp'] = datetime.datetime.now().strftime('%c')
result_json_content['loosers'] = []

for looser_row in looser_rows:
  cells = looser_row.find_all('td')
  ticker = cells[0].find('a').string
  name = cells[1].text
  change = cells[4].find('span').string
    'ticker': ticker,
    'name': name,
    'change': change

loosers_json_filename = 'docs/result.json'
if os.path.exists(loosers_json_filename):

with open(loosers_json_filename, 'a') as loosers_json_file:
  json.dump(result_json_content, loosers_json_file)

This python script gets the content of the URL using the requests package. With BeautifulSoup we’ll find data we are interested in (ticker symbol, name, and percentage). At the end of the script, we are using JSON and os packages for serializing and storing JSON on the

path. We'll later publish this docs directory to GitHub pages so our data source is available for our iOS widget.

Do not forget to add



This file is used by GitHub actions for installing dependencies.

2.Persist and serve data source JSON via GitHub Pages

Our JSON data source will be served by GitHub Pages — go to Settings of your repository and enable GitHub Pages for your

folder in your main branch. At his time, the content of the
directory does not exist yet. JSON content will be re-created periodically by the GitHub Action.

3. Update JSON content every hour with GitHub action

In the root of your 

create new

# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Python application

    branches: [ main ]
    branches: [ main ]
    - cron:  '0 13-23 * * 1-5'


    runs-on: ubuntu-latest

    - uses: actions/[email protected]
    - name: Set up Python 3.8
      uses: actions/[email protected]
        python-version: 3.8
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
    - name: Run script
      run: |
        python main.py
    - name: Deploy page
      run: |
        git config --local user.email "[email protected]"
        git config --local user.name "GitHub Action"
        git add docs/result.json -f
        git commit -m "Update docs/result.json" -a
        git push "https://makma:${{ secrets.GITHUB_PERSONAL_TOKEN }}@github.com/makma/scriptable-stocks.git" HEAD:main --follow-tags

Edit the last line of the script according to your repository name and GitHub handle.

This action will run at minute 0 past every hour from 13 through 23 on every day-of-week from Monday through Friday. If you want to change this behavior, just edit the cron expression. In addition, it also pushes serialized JSON into the

folder - this behavior is defined in the
Deploy page

4. Get JSON content in Scriptable's JavaScript

In the Scriptable app create a new script with the following code. This is basically the code of the widget on your iOS device. It renders a medium widget with the first seven losers.

// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-color: red; icon-glyph: magic;
const dataUrl = "https://makma.github.io/scriptable-stocks/result.json";

let widget = await createWidget();

async function createWidget() {
    const widget = new ListWidget();

    const data = await new Request(dataUrl).loadJSON();

    let titleRow = widget.addText(`Losers ${data.timestamp}`);
    titleRow.font = Font.boldSystemFont(15);
    titleRow.textColor = Color.white();

    for (i = 0; i < 7; i++) {
        const looser = data.loosers[i];
        let row = leftColumn.addText(`
        row.font = Font.semiboldSystemFont(14);

    let gradient = new LinearGradient()
    gradient.colors = [new Color("3a8cc1"), new Color("00A9D6")];
    gradient.locations =  [0, 1];
    widget.backgroundGradient = gradient
    return widget;

Change data URL to your JSON data source published on GitHub pages.

Protip: Use the Scriptable app directory in your iCloud drive. You can see all your scripts here. Moreover, you can write code directly in your favorite IDE on your PC or Mac.

5. Setup and present iOS widget

The last step is adding the widget to your screen. Add a new script to the Scriptable app and add a new Scriptable widget. Select Medium size and set your Script.


Your new widget should be displayed now.


You can find all the files and source code on GitHub.

Disclaimer: I’m not connected with the Scriptable app or Yahoo.


Join Hacker Noon

Create your free account to unlock your custom reading experience.