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 app, it’s possible to create a native iOS widget even with basic JavaScript knowledge. Scriptable 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 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. yahoo.finance 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? 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 . 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 with the creator of Scriptable, . Scriptable many more great podcast Simon B. Støvring Battleplan Scrape the URL and create JSON with the scraped content Persist and serve data source JSON via GitHub pages Update JSON content every hour with GitHub action Get JSON content in Scriptable’s JavaScript 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 ). main.py requests bs4 BeautifulSoup os json datetime loosers_url = loosers_response = requests.get(loosers_url) loosers_page = BeautifulSoup(loosers_response.text, ) loosers_table = loosers_page.find( ) looser_rows = loosers_table.find_all( ) result_json_content = {} result_json_content[ ] = datetime.datetime.now().strftime( ) result_json_content[ ] = [] looser_row looser_rows: cells = looser_row.find_all( ) ticker = cells[ ].find( ).string name = cells[ ].text change = cells[ ].find( ).string result_json_content[ ].append({ : ticker, : name, : change }) loosers_json_filename = os.path.exists(loosers_json_filename): os.remove(loosers_json_filename) open(loosers_json_filename, ) loosers_json_file: json.dump(result_json_content, loosers_json_file) import from import import import import 'https://finance.yahoo.com/losers/' 'html.parser' 'tbody' 'tr' 'timestamp' '%c' 'loosers' for in 'td' 0 'a' 1 4 'span' 'loosers' 'ticker' 'name' 'change' 'docs/result.json' if with 'a' as This python script gets the content of the URL using the package. With we’ll find data we are interested in (ticker symbol, name, and percentage). At the end of the script, we are using and 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. requests BeautifulSoup JSON os docs/result.json Do not forget to add . requirements.txt beautifulsoup4 requests==2.23.0 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 of your repository and enable 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. Settings GitHub Pages docs docs 3. Update JSON content every hour with GitHub action In the root of your create new . .github/workflows/ pythonapp.yml # 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 on: push: branches: [ main ] pull_request: branches: [ main ] schedule: - cron: '0 13-23 * * 1-5' jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up Python 3.8 uses: actions/setup-python@v1 with: 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 "action@github.com" 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:$ @github.com/makma/scriptable-stocks.git" HEAD:main --follow-tags {{ secrets.GITHUB_PERSONAL_TOKEN }} Edit the last line of the script according to your repository name and GitHub handle. This action will run . 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 step. at minute 0 past every hour from 13 through 23 on every day-of-week from Monday through Friday docs 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. dataUrl = ; widget = createWidget(); Script.setWidget(widget); widget.presentMedium(); Script.complete(); { widget = ListWidget(); data = Request(dataUrl).loadJSON(); titleRow = widget.addText( ); titleRow.font = Font.boldSystemFont( ); titleRow.textColor = Color.white(); widget.addSpacer( ); (i = ; i < ; i++) { looser = data.loosers[i]; row = leftColumn.addText( ); row.font = Font.semiboldSystemFont( ); } gradient = LinearGradient() gradient.colors = [ Color( ), Color( )]; gradient.locations = [ , ]; widget.backgroundGradient = gradient widget; } // Variables used by Scriptable. // These must be at the very top of the file. Do not edit. // icon-color: red; icon-glyph: magic; const "https://makma.github.io/scriptable-stocks/result.json" let await async ( ) function createWidget const new const await new let `Losers ` ${data.timestamp} 15 5 for 0 7 const let ` ` ${looser.ticker} ${looser.change} 14 let new new "3a8cc1" new "00A9D6" 0 1 return 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 and set your Script. Medium size 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.