<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title><![CDATA[Luke Zilioli]]></title>
        <description><![CDATA[Luke Zilioli's website]]></description>
        <link>https://www.lukezilioli.com/</link>
        <image>
            <url>https://www.lukezilioli.com/gui/im/icon.png</url>
            <title>Luke Zilioli</title>
            <link>https://www.lukezilioli.com/</link>
        </image>
        <generator>RSS for Node</generator>
        <lastBuildDate>Fri, 07 Nov 2025 17:04:30 GMT</lastBuildDate>
        <atom:link href="https://www.lukezilioli.com/blog/feed/" rel="self" type="application/rss+xml"/>
        <copyright><![CDATA[©2025 2∞&=> Luke Zilioli]]></copyright>
        <managingEditor><![CDATA[Luke Zilioli]]></managingEditor>
        <category><![CDATA[ai]]></category>
        <category><![CDATA[android]]></category>
        <category><![CDATA[app recommendation]]></category>
        <category><![CDATA[apple]]></category>
        <category><![CDATA[apple shortcuts]]></category>
        <category><![CDATA[apple wishlist]]></category>
        <category><![CDATA[archive]]></category>
        <category><![CDATA[building with ai]]></category>
        <category><![CDATA[comedy]]></category>
        <category><![CDATA[design]]></category>
        <category><![CDATA[detroit]]></category>
        <category><![CDATA[figma]]></category>
        <category><![CDATA[food]]></category>
        <category><![CDATA[git]]></category>
        <category><![CDATA[github]]></category>
        <category><![CDATA[hacking for change]]></category>
        <category><![CDATA[headlines and discoveries]]></category>
        <category><![CDATA[homepage]]></category>
        <category><![CDATA[i phone]]></category>
        <category><![CDATA[iOS]]></category>
        <category><![CDATA[javascript]]></category>
        <category><![CDATA[macOS]]></category>
        <category><![CDATA[now]]></category>
        <category><![CDATA[open source]]></category>
        <category><![CDATA[portfolio]]></category>
        <category><![CDATA[privacy]]></category>
        <category><![CDATA[smart home]]></category>
        <category><![CDATA[starbellysw]]></category>
        <category><![CDATA[svn]]></category>
        <category><![CDATA[tips and tricks]]></category>
        <category><![CDATA[travel]]></category>
        <category><![CDATA[typescript]]></category>
        <category><![CDATA[video games]]></category>
        <category><![CDATA[web dev]]></category>
        <item>
            <title><![CDATA[Apple Wishlist Website is Live]]></title>
            <description><![CDATA[<h1 id="table-of-contents"><a href="#table-of-contents">Table of Contents<i class="icon-link"></i></a></h1>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#how-we-got-here">How We Got Here</a></li>
<li><a href="#inside-the-new-wishlist">Inside the New Wishlist</a></li>
<li><a href="#whats-next">What&apos;s Next?</a></li>
<li><a href="#thanks-for-following-along">Thanks for following along</a></li>
</ul>
<h1 id="introduction"><a href="#introduction">Introduction<i class="icon-link"></i></a></h1>
<p>Today I&apos;m excited to share the <strong>final</strong> blog post on my Apple wishlist&#x2014;because it now has a permanent home! I&apos;ve launched a living, breathing site at <a href="https://apple.lukezilioli.com/wishlist/" target="_blank">https://apple.lukezilioli.com/wishlist/</a> that combines all of my past wishlist posts with a dynamic interface for new ideas and tips.</p>
<h1 id="how-we-got-here"><a href="#how-we-got-here">How We Got Here<i class="icon-link"></i></a></h1>
<p>Over the years, I&apos;ve tinkered with long form wish lists:</p>
<ul>
<li><a href="/blog/post/apple-2021-wishlist">My iOS 15 and macOS 12 Wish List</a></li>
<li><a href="/blog/post/top-ios-15-requests">Top iOS 15 Feature Wishlist</a></li>
<li><a href="/blog/post/ios-app-library-concept">iOS 17 App Library Concept</a></li>
</ul>
<p>Each of these posts captured ideas for iOS, iPadOS, macOS, watchOS and beyond. But maintaining separate blog posts was a pain&#x2014;updating them when Apple implemented features, keeping track of what I&apos;d already suggested, and organizing everything coherently. That&apos;s why I never made it an annual thing like I originally planned. Now they&apos;re all under one roof, categorized by platform and feature.</p>
<h1 id="inside-the-new-wishlist"><a href="#inside-the-new-wishlist">Inside the New Wishlist<i class="icon-link"></i></a></h1>
<p>On the new site you can:</p>
<ul>
<li>Browse requests by platform (iPhone, iPad, Mac, Watch, etc.)</li>
<li>Search or filter by keyword and status</li>
<li>Submit your own ideas for Apple to consider</li>
</ul>
<p>I&apos;ve replicated every suggestion from my old posts, and you&apos;ll notice some new surprises too. It&apos;s my one-stop hub for everything Apple-feature-related.</p>
<h1 id="whats-next"><a href="#whats-next">What&apos;s Next?<i class="icon-link"></i></a></h1>
<p>Now that the wishlist site is live, I&apos;ll continue adding new ideas  over time.</p>
<h1 id="thanks-for-following-along"><a href="#thanks-for-following-along">Thanks for following along<i class="icon-link"></i></a></h1>
<p>This is something I&apos;ve wanted to do for years, and I finally got around to it. Head over to <a href="https://apple.lukezilioli.com/wishlist/" target="_blank">https://apple.lukezilioli.com/wishlist/</a> and let me know which of my ideas you would love to see Apple work on.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/apple-wishlist-website</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/apple-wishlist-website</guid>
            <category><![CDATA[apple wishlist]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Wed, 25 Jun 2025 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Faking ChatGPT Function Calling]]></title>
            <description><![CDATA[<h1 id="table-of-contents"><a href="#table-of-contents">Table of Contents<i class="icon-link"></i></a></h1>
<ul>
<li><a href="#ai-function-calling-an-introduction">AI Function Calling: an Introduction</a><ul>
<li><a href="#what-is-function-calling">What is function calling?</a></li>
</ul>
</li>
<li><a href="#a-is-biggest-strength">AI&apos;s Biggest Strength</a></li>
<li><a href="#post-overview">Post Overview</a></li>
<li><a href="#the-approach">The Approach</a><ul>
<li><a href="#clever-prompting-and-system-message">Clever Prompting and System Message</a></li>
<li><a href="#my-approach-vs-function-calling-paradigm">My Approach vs. Function Calling Paradigm</a><ul>
<li><a href="#expanded-function-calling-example">Expanded Function Calling Example</a></li>
<li><a href="#sample-task-fetch-weather-conditions-and-notify-my-i-phone">Sample Task: Fetch Weather Conditions and Notify My iPhone</a></li>
</ul>
</li>
<li><a href="#pseudocode-for-the-runner">Pseudocode for the Runner</a><ul>
<li><a href="#pros-and-cons">Pros and Cons</a></li>
</ul>
</li>
<li><a href="#future-with-tool-calling">Future with Tool Calling</a></li>
</ul>
</li>
</ul>
<p>This post is from my drafts. I wrote the bulk of this post in <strong>June 2024</strong>, but am now getting around to publishing it.</p>
<h1 id="ai-function-calling-an-introduction"><a href="#ai-function-calling-an-introduction">AI Function Calling: an Introduction<i class="icon-link"></i></a></h1>
<p>OpenAI made a significant leap in AI capabilities when they <a href="https://openai.com/index/function-calling-and-other-api-updates/#:~:text=GPT%2D3.5%20Turbo%20*%20API%20Platform.%20*%202023" target="_blank">introduced function calling</a>  on June 13, 2023.</p>
<p>I can&apos;t pinpoint my <strong>first</strong> exposure to AI function calling, but it was either: <a href="https://github.com/Significant-Gravitas/AutoGPT" target="_blank">AutoGPT</a>, which I discovered &amp; played with as soon as I saw <a href="https://news.ycombinator.com/item?id=35413054" target="_blank">this post on hackernews</a> in April 2023, or TypingMind, which added <a href="https://docs.typingmind.com/changelog/typingmind/the-first-version-of-plugins-has-been-released!" target="_blank">official support for plugins</a> (which uses function calling) on June 26, 2023. TypingMind had unofficial support for plugins before that, and I suspect I first saw it while poking around TypingMind settings.</p>
<h2 id="what-is-function-calling"><a href="#what-is-function-calling">What is function calling?<i class="icon-link"></i></a></h2>
<p>Function calling allows developers to connect AI models like GPT directly with tools and APIs through a clearly defined JSON schema. Refer to <a href="https://platform.openai.com/docs/guides/function-calling" target="_blank">OpenAI&apos;s function calling docs</a> for a deeper understanding. In short, its like teaching an AI to know when to fetch data or perform an action, and letting the AI tell the developer&apos;s code to perform the action and with what parameters.</p>
<p>What this means in layman&apos;s terms is that developers can now define tasks&#x2014;like fetching weather data or sending an email&#x2014;and have the AI determine when to call those tasks and how to do it smartly. Instead of having the AI just give you information, it can now take action on your behalf.</p>
<p>Function calling opens the door for AI models to interface hands-on with external systems by understanding input as actions. For instance, an AI could automatically convert, &#x201C;Email Luke to see if he wants to get coffee next Friday&#x201D; into an actionable function call like <code>send_email(to: string, body: string)</code>. Similarly, a question like &#x201C;What&#x2019;s the weather like in Boston?&#x201D; becomes <code>get_current_weather(location: string, unit: &apos;celsius&apos; | &apos;fahrenheit&apos;)</code>.</p>
<h1 id="ais-biggest-strength"><a href="#ais-biggest-strength">AI&apos;s Biggest Strength<i class="icon-link"></i></a></h1>
<p>Function calling is the <strong>perfect</strong> use for AI. Remember that GPT stands for &quot;generative predictive text&quot; and LLM stands for &quot;large language model&quot;. The key is in the names: AI is good at <strong>language</strong>!</p>
<p>Function calling... that is&#x2013;taking natural language input like &quot;find my favorite contacts and send them an email inviting them over for dinner Friday night&quot; and converting it into a series of steps that a machine can take to achieve this goal&#x2013;leans heavily on AI&apos;s greatest strength&#x2013;taking natural language and &quot;understanding&quot; how to translate it into a machine-readable language.</p>
<h1 id="post-overview"><a href="#post-overview">Post Overview<i class="icon-link"></i></a></h1>
<p>Once I became privy to function calling in early 2023, I baked support for it into my Shortcuts Toolbox Project by adding a new <code>/ai/perform/?task=</code> endpoint.</p>
<p>Because OpenAI hadn&apos;t yet added function calling to their API, I had to get clever and achieve the same thing with some clever system prompting.</p>
<p>Now in June 2024, I am rewriting that code to integrate the function calling API. I figured I&apos;d write a post explaining my previous approach before I delete that code forever.</p>
<h1 id="the-approach"><a href="#the-approach">The Approach<i class="icon-link"></i></a></h1>
<p>My approach was inspired by <a href="https://www.typingmind.com" target="_blank">TypingMind</a>. In the early days of TypingMind, you could see the full system prompt, and while inspecting it, I noticed that it contained instructions saying something like &quot;if you want to use the search tool, respond with json: <code>{search: string}</code> containing your query&quot;. A lightbulb immediately went off in my head. This was brilliant!</p>
<h2 id="clever-prompting-and-system-message"><a href="#clever-prompting-and-system-message">Clever Prompting and System Message<i class="icon-link"></i></a></h2>
<p>The system message I crafted for Shortcuts Toolbox:</p>
<pre><code>The<span class="hljs-built_in"> user </span>will tell you what goal they wish <span class="hljs-keyword">to</span> achieve, <span class="hljs-keyword">and</span> optionally, the context <span class="hljs-keyword">in</span> which you are <span class="hljs-keyword">to</span> respond.
Pay special attention <span class="hljs-keyword">to</span> the context when constructing the plan, <span class="hljs-keyword">and</span> make sure that the final output will adhere
<span class="hljs-keyword">to</span> the desired context. E.g. <span class="hljs-keyword">if</span> the<span class="hljs-built_in"> user </span>asks <span class="hljs-keyword">for</span> an html webpage, <span class="hljs-keyword">and</span> you ask GPT <span class="hljs-keyword">for</span> it, make sure <span class="hljs-keyword">to</span> tell GPT
that it should respond with html, <span class="hljs-keyword">and</span> <span class="hljs-literal">nothing</span> extra. Sometimes the context will mention an existing<span class="hljs-built_in"> User </span>Tool.
<span class="hljs-keyword">If</span> this is the case, you should use that<span class="hljs-built_in"> tool </span><span class="hljs-keyword">and</span> send it what would otherwise be your final output.
<span class="hljs-keyword">If</span> the response is unspecified, use your best judgement. A text response is usually most appropriate.

<span class="hljs-keyword">If</span> the<span class="hljs-built_in"> user </span>asks you <span class="hljs-keyword">to</span> access their data, <span class="hljs-keyword">do</span> <span class="hljs-keyword">not</span> hallucinate <span class="hljs-keyword">or</span> make up data.
<span class="hljs-keyword">If</span> you are unable <span class="hljs-keyword">to</span> fetch the data using the tools, state as such <span class="hljs-keyword">in</span> your response.
<span class="hljs-keyword">If</span> you defer <span class="hljs-keyword">to</span> GPT, relay the message <span class="hljs-keyword">to</span> <span class="hljs-keyword">not</span> halluicate <span class="hljs-keyword">or</span> make up data <span class="hljs-keyword">to</span> GPT so that
it can provide a more appropriate response.

YOUR JOB
Return a list of steps that can be run, <span class="hljs-keyword">in</span> sequence <span class="hljs-keyword">to</span> piece together the available
tools <span class="hljs-keyword">to</span> accomplish the user<span class="hljs-string">&apos;s goal.

At the bottom of this message is a list of User Tools that are available to you.
Your response (the steps) will be passed to a runner that executes the tools in
sequence and with the inputs that you specify.
The runner&apos;</span>s code is below. Follow the RunnerSpecification format <span class="hljs-keyword">in</span> your response.

STICK <span class="hljs-keyword">TO</span> THIS SPEC:

<span class="hljs-variable">${runnerContents}</span>

Special Tools:
HANDLEBARS_RENDERER
Description:
This is a special<span class="hljs-built_in"> tool </span>that we ALWAYS <span class="hljs-builtin-name">run</span> when processing the input <span class="hljs-keyword">and</span> output properties.
Rules:
1. This does <span class="hljs-keyword">not</span> exist as its own tool, it is automatically applied <span class="hljs-keyword">to</span> all inputs <span class="hljs-keyword">and</span> outputs, refer <span class="hljs-keyword">to</span> the processInput implementation <span class="hljs-keyword">for</span> a deep understanding of how the input <span class="hljs-keyword">and</span> output properties are processed
2. When processing the input <span class="hljs-keyword">for</span> a tool, <span class="hljs-keyword">or</span> the output <span class="hljs-keyword">for</span> the spec, its value may be a string <span class="hljs-keyword">or</span> an object. <span class="hljs-keyword">For</span> an object, we will recursively render each string as a handlebars template.
3. <span class="hljs-keyword">In</span> a lot of cases, <span class="hljs-keyword">if</span> a shortcut returns JSON, <span class="hljs-keyword">and</span> the<span class="hljs-built_in"> user </span>wants you <span class="hljs-keyword">to</span> use GPT <span class="hljs-keyword">to</span> summarize the results, you <span class="hljs-keyword">do</span> <span class="hljs-keyword">not</span> need <span class="hljs-keyword">to</span> map the response before passing it <span class="hljs-keyword">to</span> GPT, you can simply pass along the json response <span class="hljs-keyword">from</span> the previous <span class="hljs-keyword">step</span>.
4. <span class="hljs-keyword">If</span> you need <span class="hljs-keyword">to</span> combine JSON <span class="hljs-keyword">from</span> two actions, <span class="hljs-keyword">or</span> pass a response as json, you can <span class="hljs-keyword">do</span> so using a handlebars template.
   e.g. <span class="hljs-keyword">step</span> 1: fetchWeather step2: fetchCalendar output: \`&amp;#123;<span class="hljs-string">&quot;weather&quot;</span>: {{{json fetchWeather}}}, <span class="hljs-string">&quot;calendar&quot;</span>: {{{json fetchCalendar}}}&amp;#125;\`
5. Generally, use {{{data}}} instead of two {{data}}. We want double quotes as double quotes, <span class="hljs-keyword">not</span> &amp;quot; etc.
6. <span class="hljs-keyword">If</span> a<span class="hljs-built_in"> tool </span>outputs JSON <span class="hljs-keyword">and</span> you want <span class="hljs-keyword">to</span> pass it as input <span class="hljs-keyword">or</span> output, you MUST <span class="hljs-keyword">do</span> so via the handlebars json helper e.g.: {{{json fetchWeather}}}
ALWAYS REMEMBER THE ABOVE RULE
<span class="hljs-keyword">If</span> your goal is <span class="hljs-keyword">to</span> send a notification <span class="hljs-keyword">and</span> return the response:
INCORRECT APPROACH, <span class="hljs-keyword">DO</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">DO</span> THIS
  <span class="hljs-keyword">step</span> 1: sendNotification
  output: <span class="hljs-string">&apos;{{sendNotification}}&apos;</span>
CORRECT APPROACH
  <span class="hljs-keyword">step</span> 1: sendNotification
  output: {{{json sendNotification}}}
Input:
This<span class="hljs-built_in"> tool </span>will always render a steps input as a handlebars template.
The context <span class="hljs-keyword">for</span> the template will be {[stepID]: &lt;output <span class="hljs-keyword">from</span> <span class="hljs-keyword">step</span> with id stepID&gt;}.
Handlebars helpers:
  There is only a single handlebars helper. You can use <span class="hljs-keyword">if</span>, etc. but you can compare using eq. etc. handlebars only lets you check <span class="hljs-keyword">for</span> truthiness.
  - \`json\` - which render data directly as json <span class="hljs-keyword">in</span> the results
    Example usage: {{{json weatherConditions}}} <span class="hljs-keyword">or</span> {{#each weatherConditions.daily}}{{{json this}}}{{/each}}
Output:
The resulting rendered template&#x2013;either a string <span class="hljs-keyword">or</span> a JSON object
The runner will attempt <span class="hljs-keyword">to</span> parse the results as JSON, <span class="hljs-keyword">and</span> <span class="hljs-keyword">if</span> successful, will pass the resulting object, instead of a string, <span class="hljs-keyword">to</span> the <span class="hljs-keyword">step</span><span class="hljs-string">&apos;s input.
---
ASK_GPT
Description:
Another special tool that queries GPT with the given prompt.
Input:
  object of format { system: string, user: string, jsonMode?: boolean }
  // jsonmode defaults to false, USE THIS IF YOU WANT JSON FROM GPT
Output: The AI assistant&apos;</span>s response
---<span class="hljs-built_in">
User </span>Tools:
<span class="hljs-variable">${toolSummary}</span>

Tips <span class="hljs-keyword">and</span> Tricks:
The<span class="hljs-built_in"> tool </span>summary is passed along when running ASK_GPT. <span class="hljs-keyword">If</span> you need it <span class="hljs-keyword">to</span> configure inputs <span class="hljs-keyword">for</span><span class="hljs-built_in"> tool </span><span class="hljs-keyword">for</span> you, use JSON mode <span class="hljs-keyword">and</span> reference the<span class="hljs-built_in"> tool </span>by name.
e.g. <span class="hljs-keyword">if</span> you need it <span class="hljs-keyword">to</span> configure a notification <span class="hljs-keyword">for</span> you, tell GPT <span class="hljs-keyword">to</span> configure a notification <span class="hljs-keyword">for</span> &lt;notification<span class="hljs-built_in"> tool </span>name&gt; about: blah</code></pre><p>This guidance ensures the AI grasps user goals in context, converting them into actionable plans.</p>
<p>Note that for the <code>${runnerContents}</code>, I inserted the contents of the typescript file that I created which runs the spec that the AI returns. This file contains the explicit type definitions and code for the runner, and gives GPT an intimate understanding of what my code will do with its output.</p>
<h2 id="my-approach-vs-function-calling-paradigm"><a href="#my-approach-vs-function-calling-paradigm">My Approach vs. Function Calling Paradigm<i class="icon-link"></i></a></h2>
<p>What&apos;s interesting is how my solution deviates from the function calling approach:</p>
<ul>
<li><strong>Function Calling API</strong>: You make an API call to trigger a function call, execute it, make another call to GPT, and iterate until the AI determines it&apos;s done.</li>
<li><strong>My Method</strong>: The entire plan is laid out up front, then each step is executed in sequence. This ensures everything stays on track and everything&apos;s tight from the start, allowing fluid task handling and adaptability.</li>
</ul>
<h3 id="expanded-function-calling-example"><a href="#expanded-function-calling-example">Expanded Function Calling Example<i class="icon-link"></i></a></h3>
<h3 id="sample-task-fetch-weather-conditions-and-notify-my-iphone"><a href="#sample-task-fetch-weather-conditions-and-notify-my-iphone">Sample Task: Fetch Weather Conditions and Notify My iPhone<i class="icon-link"></i></a></h3>
<p>Let&apos;s dive into a detailed look at how everything functions together with this expanded example:</p>
<p><strong>Goal</strong>: Get the current weather and alert the iPhone.</p>
<p><strong>Tool Descriptions:</strong></p>
<ul>
<li><strong>FetchWeather</strong>: Retrieves weather data for a designated locale.</li>
<li><strong>SendNotification</strong>: Alerts a selected device, such as an iPhone.</li>
</ul>
<p>After passing the above to GPT with the system prompt, it might come up with the following plan:</p>
<ul>
<li><strong>Plan</strong>:<ol>
<li>Use <strong>FetchWeather</strong> to grab the latest weather conditions.</li>
<li>Use <strong>SendNotification</strong> to ping the iPhone with a weather update.</li>
</ol>
</li>
</ul>
<p><strong>Plan as JSON:</strong></p>
<pre><code class="language-json">{
  <span class="hljs-attr">&quot;goal&quot;</span>: <span class="hljs-string">&quot;Fetch Weather Conditions and Notify My iPhone&quot;</span>,
  <span class="hljs-attr">&quot;steps&quot;</span>: [
    {
      <span class="hljs-attr">&quot;id&quot;</span>: <span class="hljs-string">&quot;step1&quot;</span>,
      <span class="hljs-attr">&quot;tool&quot;</span>: <span class="hljs-string">&quot;FetchWeather&quot;</span>,
      <span class="hljs-attr">&quot;input&quot;</span>: {
        <span class="hljs-attr">&quot;location&quot;</span>: <span class="hljs-string">&quot;New York&quot;</span>
      }
    },
    {
      <span class="hljs-attr">&quot;id&quot;</span>: <span class="hljs-string">&quot;step2&quot;</span>,
      <span class="hljs-attr">&quot;tool&quot;</span>: <span class="hljs-string">&quot;SendNotification&quot;</span>,
      <span class="hljs-attr">&quot;input&quot;</span>: {
        <span class="hljs-attr">&quot;device&quot;</span>: <span class="hljs-string">&quot;iPhone&quot;</span>,
        <span class="hljs-attr">&quot;message&quot;</span>: <span class="hljs-string">&quot;The current weather in New York is {{step1.weatherDescription}} with a temperature of {{step1.temperature}}.&quot;</span>
      }
    }
  ],
  <span class="hljs-attr">&quot;output&quot;</span>: <span class="hljs-string">&quot;{{step2}}&quot;</span>
}</code></pre>
<h2 id="pseudocode-for-the-runner"><a href="#pseudocode-for-the-runner">Pseudocode for the Runner<i class="icon-link"></i></a></h2>
<p>Here&apos;s a simplified version of the pseudocode for driving this method, connecting planned steps with execution:</p>
<pre><code class="language-pseudocode"><span class="hljs-keyword">function</span> runner(spec) {
    initialize context = {};
    <span class="hljs-keyword">for</span> each step <span class="hljs-keyword">in</span> spec.steps <span class="hljs-keyword">do</span> {
        process<span class="hljs-constructor">InputForStep()</span>;
        <span class="hljs-keyword">if</span> step.tool is &apos;ASK_GPT&apos; <span class="hljs-keyword">then</span> {
            response = query<span class="hljs-constructor">GPT(<span class="hljs-params">step</span>.<span class="hljs-params">processedInput</span>)</span>;
            context<span class="hljs-literal">[<span class="hljs-identifier">step</span>.<span class="hljs-identifier">id</span>]</span> = response;
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-comment">// Mock tool execution without a formal API call</span>
            context<span class="hljs-literal">[<span class="hljs-identifier">step</span>.<span class="hljs-identifier">id</span>]</span> = execute<span class="hljs-constructor">Tool(<span class="hljs-params">step</span>.<span class="hljs-params">tool</span>, <span class="hljs-params">step</span>.<span class="hljs-params">processedInput</span>)</span>;
        }
    }
    return process<span class="hljs-constructor">Output(<span class="hljs-params">spec</span>.<span class="hljs-params">output</span>, <span class="hljs-params">context</span>)</span>;
}</code></pre>
<h3 id="pros-and-cons"><a href="#pros-and-cons">Pros and Cons<i class="icon-link"></i></a></h3>
<p><strong>Pro</strong>: Fewer calls to ChatGPT = lower costs. My approach uses a single call to Chat GPT to create the plan and then executes that plan. The plan can make additional calls to GPT, but for most requests will only do so once or twice. These calls are not used to revise the plan, just to get a response for a given step.</p>
<p><strong>Con</strong>: The plan isn&apos;t always good. With my approach, the AI has one chance to come up with a plan, and no opportunity to modify that plan once it is set in motion. Sometimes it gets it wrong, and the whole task fails.</p>
<p><strong>Con:</strong> Verbose system prompts. As you can see in the system message, I had to do a lot of coaching to get this right. Since GPT&apos;s official function calling support means the model was explicitly trained to understand functions, your system prompt can be much cleaner if you use the official API.</p>
<p><strong>Con:</strong> Sometimes, but not every time, Open AI keeps flagging my prompts</p>
<p><strong>Task:</strong>
Build a pretty, responsive webpage containing...
my tasks from things on a chartjs scatter plot plotted by impact vs effort you will need to determine impact and effort yyourself before plotting please list tasks under the chart
Don&apos;t forget to use tools to fetch the relevant data</p>
<p><strong>Context:</strong> stylized html webpage</p>
<p><strong>Response:</strong></p>
<pre><code><span class="hljs-string">BadRequestError:</span> <span class="hljs-number">400</span> Invalid <span class="hljs-string">prompt:</span> your prompt was flagged <span class="hljs-keyword">as</span> potentially violating our usage policy. Please <span class="hljs-keyword">try</span> again with a different <span class="hljs-string">prompt:</span> <span class="hljs-string">https:</span><span class="hljs-comment">//platform.openai.com/docs/guides/reasoning#advice-on-prompting</span></code></pre><h2 id="future-with-tool-calling"><a href="#future-with-tool-calling">Future with Tool Calling<i class="icon-link"></i></a></h2>
<p>Though this method relied on clever system prompting, <a href="https://openai.com/index/function-calling-and-other-api-updates/#:~:text=GPT%2D3.5%20Turbo%20*%20API%20Platform.%20*%202023" target="_blank">function calling</a> is the future of AI agent software.</p>
<p>I&apos;m eager to transition and grow alongside these emerging possibilities.</p>
<hr>
<p>Thanks for reading! Hopefully you learned something new about building software with AI.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/emulating-tool-calling</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/emulating-tool-calling</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[building with ai]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Fri, 28 Feb 2025 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[TripCase Data Export Utility]]></title>
            <description><![CDATA[<p><strong>Update 2025-04</strong>: TripCase now has their own data exporter. You can log in to your account and export your data from your profile page.</p>
<hr>
<p><strong>Note to Redditors:</strong> After I posted this on /r/travel, the moderators banned me. I haven&apos;t been able to respond to comments, or make posts in that subreddit.</p>
<p>Please open a Github Issue <a href="https://github.com/lzilioli/tripcase/issues" target="_blank">here</a> if you are having issues. I am happy to help you resolve it.</p>
<hr>
<p>TripCase, the trip tracking app that I have been using for over 10 years announced that they are shutting down on 2025-04-01.</p>
<p>Per chance, just a couple of months ago, I spent the time to figure out how to export my data from TripCase data so that I could import it into <a href="https://flighty.com" target="_blank">Flighty</a>.</p>
<p>Because of the shutdown, I decided to share this code (even though it&apos;s quick and dirty) on GitHub for others to use.</p>
<p>Find my <a href="https://github.com/lzilioli/tripcase?tab=readme-ov-file#lzilioli-changes-2025" target="_blank">TripCase repo here</a>. This code pulls all data from TrioCase and writes flights to an ics file, and other data to a json file for safe keeping.</p>
<p>Hopefully this helps some folks out there! Please do not feel obligated, but if you wish to show support, you can <a href="https://buymeacoffee.com/lzilioli" target="_blank">buy me a Coffee</a>.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/tripcase-data-exporter</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/tripcase-data-exporter</guid>
            <category><![CDATA[open source]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Thu, 13 Feb 2025 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[iPhone 16 Camera Button Tip]]></title>
            <description><![CDATA[<h2 id="update-2024-11-11"><a href="#update-2024-11-11">Update 2024-11-11<i class="icon-link"></i></a></h2>
<p>With iOS 18.2 beta 3, Apple introduced a new setting. In Settings &gt; Display &amp; Brightness &gt; Camera Control &gt; Require Screen On. If you disable this setting, the camera control will behave consistently regardless of if your screen is locked or not.</p>
<p>I&apos;ve changed my settings to single click, and let&apos;s hope I can update my muscle memory.</p>
<p><img src="/images/camera-control-new-setting.jpeg" alt></p>
<h3 id="you-should-switch-your-iphone-16-camera-control-to-launch-the-camera-with-a-double-click"><a href="#you-should-switch-your-iphone-16-camera-control-to-launch-the-camera-with-a-double-click">You Should Switch Your iPhone 16 Camera Control to Launch the Camera With a Double Click<i class="icon-link"></i></a></h3>
<p>Hey there, iPhone 16 users! Today, I&apos;ve got a tip that&#x2019;s going to save you a lot of frustration. So, you got your shiny new iPhone 16 and started playing around with that fancy new Camera Control button, right? But here&#x2019;s something I&#x2019;ve noticed after some hands-on experience &#x2013; you might want to consider changing the button&#x2019;s setting to launch the camera from a single click to a double click setting.</p>
<h4 id="why-the-default-single-click-setting-is-a-mess"><a href="#why-the-default-single-click-setting-is-a-mess">Why the Default Single-Click Setting is a Mess<i class="icon-link"></i></a></h4>
<p>Alright, here&#x2019;s the deal. When your iPhone 16&apos;s screen is locked or dimmed (requires a tap or a raise to wake), the Camera Control button behaves inconsistently compared to when the screen is awake. Let me break it down:</p>
<ul>
<li><strong>Locked/Dimmed Screen:</strong> The first click wakes the phone, and the second click actually launches the camera. So yeah, you end up needing to chick twice, despite the setting being &quot;Single Click&quot;</li>
<li><strong>Awake Screen:</strong> Only one click is needed to launch the camera, and a second click takes a picture.</li>
</ul>
<p>Imagine thinking you&#x2019;re about to capture a quick moment, but you end up just waking the phone. By the time you realize you need a second click&#x2026; the moment&#x2019;s gone. Brutal, right?</p>
<h4 id="why-double-click-setting-is-the-way-to-go"><a href="#why-double-click-setting-is-the-way-to-go">Why Double Click Setting is the Way to Go<i class="icon-link"></i></a></h4>
<p>Switching to a double click setting creates much-needed predictability. Whether your screen is awake or asleep, you&#x2019;ll always perform the same action&#x2014;a double click&#x2014;to launch the camera. No surprises, no missed moments.</p>
<p>You know, I can&apos;t help but think about how the Apple under Steve Jobs would have meticulously thought through this kind of user experience nuance. It disappointing to see such an oversight in UX from a brand I look up to, as a UI engineer myself. But hey, improvements can still be made (though after everyone builds up their muscle memory is too late)! In the meantime...</p>
<p>Here&apos;s how to make the switch:</p>
<ol>
<li><strong>Open Settings:</strong> Dive into the Settings app on your iPhone.</li>
<li><strong>Navigate to Camera Settings:</strong> Scroll and find the Camera section.</li>
<li><strong>Change Button Behavior:</strong> Find the Camera Control Button settings and switch from Single Click to Double Click.</li>
<li><strong>Test It Out:</strong> Lock your phone and give it a whirl. Enjoy that sweet, sweet consistency.</li>
</ol>
<p>By doing this, you&#x2019;re set for a more predictable and reliable photography experience with the iPhone 16. </p>
<p>Happy snapping! &#x1F4F8;</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/iphone-16-camera-button-tip</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/iphone-16-camera-button-tip</guid>
            <category><![CDATA[i phone]]></category>
            <category><![CDATA[tips and tricks]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Wed, 25 Sep 2024 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Headlines & Discoveries for May 1, 2023]]></title>
            <description><![CDATA[<hr>
<p><a href="https://9to5mac.com/2023/05/01/apple-card-savings-account-deposits/" target="_blank">Apple&#x2019;s high-yield savings account reportedly drew $1 billion in deposits in just four days</a></p>
<p><em>Luke&apos;s take:</em> Apple doing big numbers, as always. I&#x2019;m one of them.</p>
<hr>
<p><a href="https://vercel.com/blog/vercel-storage#vercel-postgres-complex-data-made-easy" target="_blank">Introducing storage on Vercel &#x2013; Vercel</a></p>
<p><em>Luke&apos;s take:</em> This is like the total opposite of &quot;separation of concerns&quot;. But I&apos;m not mad at it. Seems like it might be a quick way to spin up an app.</p>
<hr>
<p><a href="https://9to5mac.com/2023/05/02/wheres-my-uber-eats-dynamic-island/" target="_blank">Uber Eats delivering order tracking on iPhone with Live Activities and Dynamic Island</a></p>
<p><em>Luke&apos;s take:</em> I&apos;m a huge fan of dynamic island. I use it for flights, sports, maps, music, shortcuts. It&apos;s great! I love seeing it come to more and more third party applications.</p>
<hr>
<p><a href="https://sixcolors.com/link/2023/05/apple-google-propose-unwanted-tracking-standard/" target="_blank">Apple, Google propose &#x2018;unwanted tracking&#x2019; standard &#x21A6;</a></p>
<p><em>Luke&apos;s take:</em> This is cool. Tile was never gonna step up and address this problem on its own.</p>
<hr>
<p><a href="https://tidbits.com/2023/05/02/did-you-know-that-the-option-key/" target="_blank">Did You Know That the Option Key&#x2026;</a></p>
<p><em>Luke&apos;s take:</em> This is a good thing for Mac users to browse through the option key is an unsung hero on Mac.</p>
<hr>
<p><a href="https://appleinsider.com/articles/23/05/02/the-godfather-of-ai-quit-google-to-call-for-global-regulations" target="_blank">Google&apos;s &apos;Godfather of AI&apos; is afraid of the dangers that AI poses to humanity</a></p>
<p><em>Luke&apos;s take:</em> More AI headlines. Where is it headed?</p>
<hr>
<p><a href="https://9to5mac.com/2023/05/02/apple-bank/" target="_blank">Apple Bank: Ten years on, the idea seems a lot less out-there</a></p>
<p><em>Luke&apos;s take:</em> As a big Apple fan, I love thinking about possibilities like this. Anticompetitive nightmares aside.</p>
<hr>
<p><a href="https://github.com/farizrahman4u/loopgpt" target="_blank">farizrahman4u/loopgpt: Modular Auto-GPT Framework</a></p>
<p><em>Luke&apos;s take:</em> Looks to be a bit more user friendly than autogpt. Might be worth playing with.</p>
<hr>
<p><a href="https://urbit.org/" target="_blank">Urbit</a></p>
<p><em>Luke&apos;s take:</em> Nobody said Web 2.0 NEEDED to be centralized, but aws and other companies popularized that paradigm. I love to see projects that attempt to shift that status quo.</p>
<hr>
<p><a href="https://9to5mac.com/2023/05/09/final-cut-pro-logic-ipad-subscription-price/" target="_blank">Let&#x2019;s talk about subscription pricing for Logic and Final Cut Pro for iPad</a></p>
<p><em>Luke&apos;s take:</em> The subscription pricing model here is a shame.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/headlines-&amp;-discoveries-2023-05-01</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/headlines-&amp;-discoveries-2023-05-01</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[headlines and discoveries]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Mon, 01 May 2023 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Headlines & Discoveries for Apr 26, 2023]]></title>
            <description><![CDATA[<p>Welcome to my first installment of Headlines &amp; Discoveries.</p>
<p>This Week, I dive into the rapid rise of AI in various industries and the potential for user fatigue. How will the music industry and AI advancements change the human aspect of music creation? As AI becomes more prevalent, what does that mean for equality of access? I ponder the implications of Apple shutting down online services for older software, and I put AutoGPT to the test. Join me as we explore these captivating stories and more.</p>
<hr>
<p><a href="https://appleinsider.com/articles/23/04/12/the-music-industry-wants-apple-music-spotify-to-block-ai-music-training" target="_blank">The music industry wants Apple Music &amp; Spotify to block AI music training</a></p>
<p><em>Luke&apos;s take:</em> AI Drake briefly topped the charts. Will companies like UMG circumvent artists altogether, or work to preserve the human aspect of music? So far UMG is taking Artist&apos;s side, but will that only last until they get ahold of their own AI Drake?</p>
<hr>
<p><a href="https://9to5mac.com/2023/04/24/snapchat-my-ai-pinned-to-feed-update/" target="_blank">Snapchat users are furious over recent My AI update, flooding the App Store with 1-star reviews</a></p>
<p><em>Luke&apos;s take:</em> AI is everywhere. Users will quickly grow accustomed to it.</p>
<hr>
<p><a href="https://appleinsider.com/articles/23/04/13/mac-survey-says-80-of-developers-have-or-will-integrate-chatgpt" target="_blank">Survey says 80% of Mac developers will integrate ChatGPT soon</a></p>
<p><em>Luke&apos;s take:</em> More proof of the impending AI Fatigue</p>
<p>The ubiquity of generative text AI is going to come very fast, so unless software companies find novel and truly valuable ways to integrate it with their products, it may not be a strong product selling point due to AI fatigue</p>
<hr>
<p><a href="https://www.reddit.com/r/AutoGPT/" target="_blank">AutoGPT: Automating GPT Model for Natural Language Generation</a></p>
<p><em>Luke&apos;s take:</em> I played with this for a few days. It&apos;s definitely got a ton of potential. In its current state it&apos;s more of a proof of concept. Lots of the YouTube videos are click bait and don&apos;t actually achieve anything. (See below)</p>
<hr>
<p><a href="https://youtube.com/watch?v=JWELpf_5JvU&amp;feature=share" target="_blank">AutoGPT just OBLITERATED all Traders</a></p>
<p><em>Luke&apos;s take:</em> My ass! Total click bait! At the end his AutoGPT is stuck in a loop doing nothing of value. Good tutorial to get up and running, though. Props to the YouTuber.</p>
<hr>
<p><a href="https://githubnext.com/" target="_blank">GitHub Next</a></p>
<p><em>Luke&apos;s take:</em> All the hating on AI I&apos;ve been doing in this post, it&apos;s very useful in my day to day as well. I can&apos;t deny that. I&apos;m excited for these features from GitHub.</p>
<hr>
<p><a href="https://techcrunch.com/2023/04/25/a-developer-exploited-an-api-flaw-to-provide-free-access-to-gpt-4/?guccounter=2" target="_blank">A developer exploited an API flaw to provide free access to GPT-4 | TechCrunch</a></p>
<p><em>Luke&apos;s take:</em> The importance of universal access to AI cannot be emphasized enough. gpt-4 is an excellent AI model that everyone should have access to at minimal cost. Those without access will be less efficient than those with, making it an equality issue.</p>
<hr>
<p><a href="https://9to5mac.com/2023/04/04/apple-shut-down-services-older-devices/" target="_blank">Apple to shut down its online services for some older software</a></p>
<p><em>Luke&apos;s take:</em> This sucks! First they killed 32 bit apps, now they&apos;re killing the server that provides old iPhones access to them. I hope you have your old games on an old iOS device, they won&apos;t be accessible soon. Maybe worth money one day. Apple is making the early days of the App Store that made the iPhone so dear to many a thing of the past.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/headlines-&amp;-discoveries-2023-04-26</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/headlines-&amp;-discoveries-2023-04-26</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[headlines and discoveries]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Wed, 26 Apr 2023 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Streamlining Shortcut Sharing and Distribution with Git and Shortcuts]]></title>
            <description><![CDATA[<p>As a developer and enthusiast of Apple Shortcuts, I&apos;m always looking for ways to enhance the sharing and collaboration experience of complex shortcuts. Thus, I&apos;m excited to introduce my submissions for the <a href="https://www.macstories.net/stories/enter-your-shortcuts-in-the-2023-automation-april-shortcuts-contest/" target="_blank">MacStories Automation April 2023 contest</a> &#x2013; <strong>SC Pshr &#x2B06;&#xFE0F; (Shortcut Pusher)</strong> and <strong>SC Pllr &#x2B07;&#xFE0F; (Shortcut Puller)</strong>. The complete solution is published on my <a href="https://github.com/lzilioli/iOS-Util-Shortcuts.git" target="_blank">iOS Util Shortcuts</a> repository on GitHub.</p>
<p>My approach involves incorporating Git repositories to streamline the sharing and distribution process of shortcuts and their dependencies. This simplifies the process and makes it more efficient for both developers and users alike.</p>
<p>Sharing a complex shortcut often requires other subsidiary shortcuts to provide functionality building blocks. This reliance on dependencies can make sharing updates quite cumbersome, as clicking multiple iCloud links becomes necessary to install the updated shortcut and its dependencies.</p>
<p>This is where my <strong>SC Pllr &#x2B07;&#xFE0F; (Shortcut Puller)</strong> solution comes in, offering a seamless and accessible solution to this problem. Upon running the shortcut, it quickly prompts for a Git repository URL and installs all the shortcuts present within the repository.</p>
<p>To make this process possible, I utilized a shortcuts technique for extracting shortcuts as JSON and XML, generously shared by <a href="https://club.macstories.net/posts/parsing-shortcuts-as-xml-or-json-and-extracting-comments-from-them" target="_blank">Federico from MacStories</a>. This allows for more straightforward PR reviews and collaboration by allowing users to store shortcuts in repositories. I also used the excellent <a href="https://apps.apple.com/us/app/working-copy-git-client/id896694807" target="_blank">Working Copy</a> app, a Git client designed for iOS devices.</p>
<p>Please feel free to navigate my <a href="https://github.com/lzilioli/iOS-Util-Shortcuts.git" target="_blank">GitHub repository</a>, download the shortcuts by installing and running the <a href="https://github.com/lzilioli/iOS-Util-Shortcuts/blob/main/SC%20Pllr%20%E2%AC%87%EF%B8%8F.shortcut?raw=true" target="_blank">SC Pllr &#x2B07;&#xFE0F;</a> shortcut, and check out the <a href="https://github.com/lzilioli/iOS-Util-Shortcuts#readme" target="_blank">README</a> in the repository for a comprehensive overview of the shortcuts and their functionalities.</p>
<p>By adopting these iOS Util Shortcuts, we can revolutionize the way we develop, share, and work collaboratively on Apple Shortcuts &#x2013; taking automation capabilities to new heights. I hope that my solution inspires you and future developers to reimagine how creative automations are shared.</p>
<p>Enjoy your shortcutting!</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/sc-pshr-pllr</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/sc-pshr-pllr</guid>
            <category><![CDATA[apple shortcuts]]></category>
            <category><![CDATA[git]]></category>
            <category><![CDATA[github]]></category>
            <category><![CDATA[iOS]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Fri, 21 Apr 2023 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Hey Siri, Red Light, Green Light]]></title>
            <description><![CDATA[<p>The following is a guest post from one of my best friends, Jordan Webb. Over the weekend, I helped him make a shortcut that he can run with Siri that lets him, with the help of his smart home, play Red Green Light with his daughter.</p>
<p>This idea was <strong>TOO</strong> cute not to share, so I asked Jordan if we would be willing to write a guest post about it. Read it below.</p>
<h1 id="red-light-green-light"><a href="#red-light-green-light">Red Light, Green Light<i class="icon-link"></i></a></h1>
<p>I&#x2019;m pretty new to both programming, and parenting. Although I don&#x2019;t have any life hacks to make potty training a breeze, I do have one that can turn your HomeKit enabled smart bulbs into a fun game of &#x201C;Red Light Green Light&#x201D; for you and your littles to enjoy. </p>
<p>All you need is an iOS device with the HomeKit and Shortcuts apps. You&#x2019;ll also need a HomeKit compatible color changing-bulb. I&#x2019;m using Phillips Hues and the MSL450 <a href="https://www.meross.com/mTerminal/smart-light/smart-led-lamp/119" target="_blank">from Meross</a>, but any compatible color-changing bulb will work fine. </p>
<p><img src="/images/red-light-green-light/Rl_gl_1.jpeg" alt></p>
<p>Next, setup 2 scenes in HomeKit. The first scene will change your light bulbs red. Simply select the desired bulbs, set their desired brightness and save. Do the same thing for the color green. </p>
<p><img src="/images/red-light-green-light/Rl_gl_2.jpeg" alt></p>
<p>Next, add <a href="https://www.icloud.com/shortcuts/7dcd2c97991d49828a70f5ca3b652e4a" target="_blank">this shortcut</a> to your Shortcuts app and click the 3 dots on the upper right hand corner of the tile to get into the settings. Once insIde you&#x2018;ll need to change a few things to ensure your shortcut functions properly. See where Siri says &#x201C;Red light&#x201D;? Well right under that your HomeKit app will need to run the scene that turns your lights red. Lock that setting in and then do the same for your scene that turns your lights green after Siri says &#x201C;Green light.&#x201D; You can modify Siri&#x2019;s speaking prompts by selecting the text you&#x2019;d like to change. I&#x2019;d recommend some kind of sign off so that everyone knows the game has ended and the lights are going back to normal. </p>
<p><img src="/images/red-light-green-light/Rl_gl_3.png" alt></p>
<p>Download the Shortcut: <a href="https://www.icloud.com/shortcuts/7dcd2c97991d49828a70f5ca3b652e4a" target="_blank">Red Light Green Light Game</a></p>
<p><img src="/images/red-light-green-light/Rl_gl_4.png" alt="Rl_gl_4"></p>
<p>And that&#x2019;s it! Have fun playing along with your littles!</p>
<p>Keep following for more ways to integrate iOS into your home address.</p>
<p>Jordan Webb
Husband/Father Correspondent</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/red-light-green-light</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/red-light-green-light</guid>
            <category><![CDATA[apple shortcuts]]></category>
            <category><![CDATA[iOS]]></category>
            <category><![CDATA[smart home]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Tue, 31 Jan 2023 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[iOS 17 App Library Concept]]></title>
            <description><![CDATA[<h1 id="app-library"><a href="#app-library">App Library<i class="icon-link"></i></a></h1>
<blockquote>
<p><strong>Update 2025:</strong> This concept is now part of my live wishlist at <a href="https://apple.lukezilioli.com/wishlist/" target="_blank">apple.lukezilioli.com/wishlist</a>. Check out my blog post about <a href="/blog/post/apple-wishlist-website">Apple Wishlist Website is Live</a> for more details and all my latest Apple requests.</p>
</blockquote>
<p>iOS 14 introduced the App Library, a new page on the far right side of the iPhone Home Screen. If you are like the vast majority of my friends and family, you have no idea what the App Library is.</p>
<p>From <a href="https://support.apple.com/en-us/HT211345" target="_blank">Apple&apos;s support page</a> on App Library:</p>
<blockquote>
<p>From your Home Screen, swipe left until you see the App Library. Your apps are automatically sorted into categories. For example, you might see your social media apps under a Social category. The apps that you use most frequently will automatically reorder based on your usage. When you install new apps, they&apos;ll be added to your App Library</p>
</blockquote>
<p><img src="/images/app-library.png" alt></p>
<p>I have some ideas for how Apple could improve upon it in iOS 17, discussed below.</p>
<h1 id="app-library-ios-17-concept"><a href="#app-library-ios-17-concept">App Library iOS 17 Concept<i class="icon-link"></i></a></h1>
<p>First, a video.</p>
<iframe style="display: block; margin: 0 auto;" width="560" height="315" src="//www.youtube-nocookie.com/embed/LYguV13YGRM" frameborder="0" allowfullscreen></iframe>

<p>This new concept for App Library migrates existing Home Screen folders over to Custom Groups in the App Library, so you will already have some custom App Groups as soon as you upgrade from iOS 16. Home Screen folders are still a thing, but now they are placed on the Home Screen as App Library Widgets, rather than the traditional Home Screen folders we are used to.</p>
<p>This iOS 17 prototype also introduces a new small Home Screen widget size. Perfect for Shortcuts, Photos, Home, or App Library widgets,.</p>
<p>All in all, this App Library redesign is intended to make it easier for users to manage the apps that are installed on their iPhone.</p>
<p>You can play with the Figma prototype below.</p>
<iframe style="margin: 0 auto; display: block; border: 1px solid rgba(0, 0, 0, 0.1); height: 90vh; width: auto;" src="https://www.figma.com/embed?embed_host=share&amp;url=https%3A%2F%2Fwww.figma.com%2Fproto%2FJaGbjdohLzeW5UeRyRTn5d%2FLuke&apos;s-iOS-17-Mockups%3Fpage-id%3D8%253A891%26node-id%3D75%253A11600%26viewport%3D1412%252C5603%252C0.38%26scaling%3Dscale-down%26starting-point-node-id%3D75%253A11600" allowfullscreen></iframe>]]></description>
            <link>https://www.lukezilioli.com/blog/post/ios-app-library-concept</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/ios-app-library-concept</guid>
            <category><![CDATA[apple]]></category>
            <category><![CDATA[apple wishlist]]></category>
            <category><![CDATA[design]]></category>
            <category><![CDATA[figma]]></category>
            <category><![CDATA[iOS]]></category>
            <category><![CDATA[portfolio]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Thu, 22 Dec 2022 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Functional Shortcuts and Pagination Shortcut]]></title>
            <description><![CDATA[<h1 id="introduction"><a href="#introduction">Introduction<i class="icon-link"></i></a></h1>
<p>When I explain iOS Shortcuts to people, I tell them that simple Shortcuts are straightforward, but the Shortcuts App is an interface for coding via drag-and-drop. Like any programming language, the Shortcuts App provides constructs for while loops, if statements, text parsing, etc.. Similar to code, Shortcuts can grow in complexity <strong>fast</strong>.</p>
<p>One of the coolest features of Shortcuts is that they can take input and return output. If you&apos;ve run a Shortcut from the Share Sheet, you&apos;ve passed input (the thing you were sharing) into a Shortcut. A lesser known feature of Shortcuts is that, using the &quot;Run Shortcut&quot; action, you can run one Shortcut from another. &quot;Run Shortcut&quot; accepts input which it passes to the Shortcut you are running, and it returns the output from the Shortcut that you run. You can do anything you want with the output. This should sound familiar to anybody with coding experience. In the context I am describing, Shortcuts are essentially... functions.</p>
<p>As you develop your own Shortcut library, making a folder full of functional Shortcuts is a good idea. It will save you time in the future by encapsulating functionality that you can re-use in your other Shortcuts&#x2013;akin to functions in a codebase. If you&apos;ve found yourself duplicating actions from Shortcut #1 into Shortcut #2, you probably could have broken those actions out into a functional Shortcut, Shortcut #3 that Shortcut #1 and #2 both utilize via the &quot;Run Shortcut&quot; action.</p>
<p><strong>Sidebar:</strong> Calling one Shortcut from another is great for your own Shortcuts library. This practice breaks down if you want to publish your Shortcuts for others to use&#x2013;you need to instruct people to install <strong>all</strong> required Shortcuts and their dependencies. There are utilities (such as <a href="https://adamtow.github.io/actioncuts/" target="_blank">ActionCuts</a>), which embed one Shortcut into another on your behalf, but they are outside the scope of this blog post.</p>
<h1 id="paginator"><a href="#paginator">Paginator<i class="icon-link"></i></a></h1>
<p>The purpose of this post is to share a specific &quot;Function Shortcut&quot; I have created which I use in my other Shortcuts.</p>
<h2 id="whats-it-do"><a href="#whats-it-do">What&apos;s it do?<i class="icon-link"></i></a></h2>
<p>With the iOS 14 redesign, Apple changed the way lists are presented to users when using the &quot;choose from list&quot; Shortcut action. If you are presenting the user with lots of choices, the list is slow and choppy to scroll.</p>
<p>I fixed this by chunking the list into pages of 7 items each, and prompting the user with 7 items plus a next and a back button for navigating between pages.</p>
<p>Download it <a href="https://www.icloud.com/shortcuts/2427f4d2850a4bb9a769cf44edb64ca9" target="_blank">here</a>.</p>
<ul>
<li><strong>Input</strong>: List of items</li>
<li><strong>Output</strong>: A single item which the user selected from the list</li>
</ul>
<p><strong>Note:</strong> If this is your first shortcut, you might run into issues installing &quot;Untrusted Shortcuts&quot;. I provide instructions for that <a href="/blog/post/my-first-untrusted-shortcuts">here</a>.</p>
<h1 id="usage-example"><a href="#usage-example">Usage Example<i class="icon-link"></i></a></h1>
<p>I created a sample Shortcut called Shortcut Picker which fetches all of your Shortcuts, has you choose one with the Paginator, and runs the selected shortcut (with no input). It is a quick illustration of how to leverage the Paginator Shortcut from another one of your Shortcuts.</p>
<p>Download it <a href="https://www.icloud.com/shortcuts/e0600f3ded804154854049798722ca41" target="_blank">here</a>.</p>
<p>
    <iframe width="560" height="315" src="//www.youtube.com/embed/Kld8CMWVzR4" frameborder="0" allowfullscreen></iframe>
</p>]]></description>
            <link>https://www.lukezilioli.com/blog/post/pagination-shortcut</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/pagination-shortcut</guid>
            <category><![CDATA[apple shortcuts]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Wed, 09 Mar 2022 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Top iOS 15 Feature Wishlist]]></title>
            <description><![CDATA[<h1 id="table-of-contents"><a href="#table-of-contents">Table of Contents<i class="icon-link"></i></a></h1>
<ul>
<li><a href="#overview">Overview</a></li>
<li><a href="#additional-privacy-enhancements">Additional Privacy Enhancements</a></li>
<li><a href="#home-screen">Home Screen</a></li>
<li><a href="#app-library">App Library</a></li>
<li><a href="#contexts-automated-context-switching">Contexts &amp; Automated Context Switching</a></li>
<li><a href="#u-1-enabled-room-level-automations">U1-Enabled Room-Level Automations</a></li>
<li><a href="#shortcuts">Shortcuts</a></li>
<li><a href="#misc">Misc.</a></li>
</ul>
<h1 id="overview"><a href="#overview">Overview<i class="icon-link"></i></a></h1>
<blockquote>
<p><strong>Update 2025:</strong> This wishlist is now outdated! I&apos;ve created a live, continuously updated version at <a href="https://apple.lukezilioli.com/wishlist/" target="_blank">apple.lukezilioli.com/wishlist</a>. Check out my blog post about <a href="/blog/post/apple-wishlist-website">Apple Wishlist Website is Live</a> for more details.</p>
</blockquote>
<p>Last year, <a href="/blog/post/apple-2021-wishlist">I shared a huge wishlist for iOS 15 and macOS 12</a>. I&apos;m holding out hope for many of those features to be announced at next week&apos;s WWDC.</p>
<p>We have had a whole year to play with iOS 14. In that time, Apple has released the HomePod Mini, AirTag, among other products. What&apos;s that mean? My wishlist has grown.</p>
<p>The purpose of this post is to share my top new wishlist entries since last year&apos;s post.</p>
<h1 id="additional-privacy-enhancements"><a href="#additional-privacy-enhancements">Additional Privacy Enhancements<i class="icon-link"></i></a></h1>
<p>Last year, Apple did a lot to enhance user privacy in iOS. Despite <a href="https://www.cnet.com/news/facebook-vs-apple-heres-what-you-need-to-know-about-their-privacy-feud/" target="_blank">Facebook pouting about it all year</a>, Apple&apos;s new anti-tracking features were very well received.</p>
<p>Last year, Apple introduced fine-grained control of access to user photos. I wrote up an overview of that feature <a href="/blog/post/ios-14-privacy#all-vs-selected-photos">here</a>. <strong>Apple desperately needs to do the same thing for contacts!</strong> Some apps refuse to function if you don&apos;t grant contact access, which is all or none in iOS 14. Social media websites like <a href="https://www.huffpost.com/entry/facebook-phonebook-contacts_n_924543" target="_blank">Facebook</a> and <a href="https://www.vox.com/recode/22278601/clubhouse-invite-privacy-contacts-app" target="_blank">Clubhouse</a> upload and store your entire address book to their servers the moment you grant this access, and there is nothing you can do about it.</p>
<p>Granting an app access to your contacts grants access to all of your contact data. <a href="https://appleinsider.com/articles/19/06/06/apple-to-block-third-party-access-to-notes-field-in-contacts-with-ios-13" target="_blank">As of iOS 13, this excludes notes data</a>, but Facebook likely has your neighbor&apos;s garage code if you stored it in the notes field and granted them contact access prior to iOS 13. Yeah, you read that right, any personal information your friends and family had stored in the notes field for their version of your contact <em>very likely</em> lives on Facebook&apos;s servers and has been sold and distributed to countless third parties. Companies can cross-reference your contact across all of their users who uploaded a version of it, aggregate a list of all of of your possible nicknames, addresses, etc. based on those contact fields, and use that data to strengthen their profile of you. It&apos;s fun to think about, really. &#x1F643;</p>
<p>In my opinion, this is a privacy nightmare of unconscionable proportion. Apple needs to fix this by introducing fine-grained address-book privacy controls that function analogously to iOS 14&apos;s Photos access settings. They also need to <strong>strongly discourage</strong> users from granting unfettered contact access to third party apps, since this is leaking <em>other people</em>&apos;s data to them.</p>
<h1 id="home-screen"><a href="#home-screen">Home Screen<i class="icon-link"></i></a></h1>
<p>I love the new Home Screen Pages feature. The ability to hide and show pages is great, and super helpful when it comes to keeping a tidy home screen.</p>
<p><img src="/images/iOS-14-edit-pages.PNG" alt></p>
<p>I want a few enhancements here:</p>
<ul>
<li>We should be able to pinch to zoom out from the home screen into the grid view of Pages. It is absurd that we can only access this feature while in &quot;Jiggle Mode&quot;.</li>
<li>We should be able to give each home screen a name such as &quot;Work&quot;, &quot;Smart Home&quot;, &quot;Games&quot;, etc.<ul>
<li>We should be able to hide and show home screens via Shortcuts actions</li>
</ul>
</li>
<li>We should be able to drag to reorder pages in this &quot;Edit Pages&quot; view. We are up to iOS 14 and we still have no easy way to reorder our home screen pages. Come on, yo.</li>
<li>We should be able to give each Apple Watch Face a custom name. This would make Shortcuts automation for Watch Faces way more straightforward.</li>
</ul>
<h1 id="app-library"><a href="#app-library">App Library<i class="icon-link"></i></a></h1>
<p>The new App Library feature is nice, but could be made more useful:</p>
<ul>
<li>There should be an entry in App Library labeled &quot;Not in Home Screen&quot; so that I can easily see all of the apps that only exist within my App Library.</li>
<li>Merge home screen folders with App Library<ul>
<li>We should be able to add my existing home screen folders to the App Library</li>
<li>Conversely, I want an App Library Folder widget that we can place anywhere on our Home Screen, which can be configured to display any category from App Library, including our own folders.</li>
</ul>
</li>
</ul>
<h1 id="contexts--automated-context-switching"><a href="#contexts--automated-context-switching">Contexts &amp; Automated Context Switching<i class="icon-link"></i></a></h1>
<p>In my last wish list post, I mentioned:</p>
<blockquote>
<p>Switch up which app pages are active based on location, time, or via a Shortcut</p>
</blockquote>
<p>Allow me to elaborate.</p>
<p>Today, I have a few different watch faces with different complications depending on what I am doing. When home, I like having HomeKit scenes, Music Control, etc. at my fingertips, but when out and about, I want quick access to shazam, maps, etc. When working, I want slack, jira, mail, and other work-related complications.</p>
<p>I am able to create personal automations based on time of day, location, presence in the car, etc. to automatically switch my watch face. The ability to rename watch faces would greatly improve this process. But I want to introduce the concept of  &quot;contexts&quot;, which expands the idea of automated context switching far beyond watch faces.</p>
<p>Similar to the watch faces I mention above, I have Home Screens that are only relevant to me based on what I&apos;m doing.</p>
<ol>
<li>Home<ul>
<li>Apple Remote App</li>
<li>Home App</li>
<li>Philips Hue</li>
<li>App Store</li>
<li>Music Widgets and Shortcuts for my Home AirPlay environment</li>
</ul>
</li>
<li>Work<ul>
<li>Slack</li>
<li>BitBucket</li>
<li>Jira</li>
<li>Work Notes Widget</li>
<li>Work-specific calendar Widget</li>
</ul>
</li>
<li>Out and About<ul>
<li>Find My</li>
<li>Maps</li>
<li>Music</li>
<li>FourSquare</li>
<li>Shortcut to open the Gate in my Apartment</li>
<li>Activity Widget</li>
<li>Workout</li>
<li>Slopes</li>
</ul>
</li>
</ol>
<p>In addition, I have HomeKit scenes and shortcuts that are only relevant to me based on time of day or location. These exist on different Home Screens for quick access. Today, I swipe between Home Screens to get to the page that&apos;s relevant to me. It isn&apos;t worth the effort required to manually edit pages and hide and show them as I go about my day. This means that many times during my work day, I swipe past multiple irrelevant Home Screens when trying to view my Work home screen.</p>
<p>Zooming out and revisiting the Edit Pages View:</p>
<p><img src="/images/iOS-14-edit-pages.PNG" alt></p>
<p>I think this view can be enhanced to support a proper concept of &quot;Contexts&quot;:</p>
<ul>
<li>Pinch anywhere on Home Screen to activate this view outside of &quot;Jiggle Mode&quot;</li>
<li>Add a tab switcher that allows us to switch between active sets of pages (contexts)</li>
<li>Each context should have its own name and set of visible pages</li>
<li>Ability to associate a particular watch face with each context</li>
<li>Ability to automatically switch your phone&apos;s active context via a Shortcut Action</li>
</ul>
<h1 id="u1-enabled-room-level-automations"><a href="#u1-enabled-room-level-automations">U1-Enabled Room-Level Automations<i class="icon-link"></i></a></h1>
<p><a href="https://youtu.be/TckA5BZO_7g" target="_blank">AirTags precision finding is cool as hell</a>, and super accurate. It would be great if I could place AirTag in various rooms of my house, and create personal or home automations that trigger as my iPhone or Apple Watch enter and exit various rooms (this feature should also work with the HomePod Mini, no need for AirTag).</p>
<p>Music should follow me as I move around the house, cuz why not?</p>
<h1 id="shortcuts"><a href="#shortcuts">Shortcuts<i class="icon-link"></i></a></h1>
<ul>
<li>With iOS 13, Apple introduced <a href="https://developer.apple.com/videos/play/wwdc2019/213/" target="_blank">Parameters for Shortcuts</a>, and strictly type their outputs. This greatly enhanced the utility of app-provided shortcut actions. We should be able to create our own Shortcuts that are parameterized in the same way, for reuse in other Shortcuts.<ul>
<li>This would allow us to create utility Shortcuts that are specifically designed for invocation from other Shortcuts</li>
<li>When sharing a Shortcut, all required utility Shortcuts should be automatically bundled with the shared Shortcut.<ul>
<li>This will make life easier for maintainers of public Shortcuts.</li>
</ul>
</li>
</ul>
</li>
<li>HomeKit automation needs a complete overhaul. Setting up scenes and automations requires far too many taps. I should be able to list all accessories by type from a single action, iterate over that list, and perform an action against each Repeat Item in the list.</li>
<li>Shortcuts should have their own persistent data store. <a href="https://datajar.app/" target="_blank">DataJar</a> is a great application, but iCloud syncing across devices is not the most reliable. This should be an OS-level feature.</li>
<li>There is currently no way to append a photo to note via a Shortcut. This is an oversight and should be fixed. Shortcut support was added to Notes in a dot release, and has yet to be fully fleshed out by the Shortcuts team.</li>
<li>Permission for a Shortcut to access more of iCloud Drive. We should be able to perform path-based scripting like we can with the Dropbox integration. iCloud Drive is not a competitive product without this feature.</li>
</ul>
<h1 id="misc"><a href="#misc">Misc.<i class="icon-link"></i></a></h1>
<ul>
<li>We should be able to mark episodes as unwatched in TV app... like seriously...</li>
<li>When tapping a color with Apple Pencil, switch back to pen tool if the eraser is currently active</li>
<li>Delete activity awards</li>
<li>Quickly toggle AirPods mute with gesture</li>
<li>AirPods Max microphone should work over the wire</li>
<li>AirPods spatial audio with Apple TV</li>
<li>AirPods Pro as hearing aids (<a href="https://appleinsider.com/articles/21/05/19/airpods-pro-could-act-as-hearing-aids-for-those-with-minimal-hearing-loss-study-claims?utm_medium=rss" target="_blank">we&apos;re getting closer!</a>)</li>
<li>Bring back cover flow in the Music app! PLEASE!</li>
<li>Toothbrushing detection for Apple Watch</li>
<li>Restore ability to customize tab bar in music app.... Apple Music has too prominent of a placement</li>
<li>Home-wide timers for HomePod. All HomePods should know the answer to questions about timers. It&apos;s super frustrating knowing that you set a timer, but the HomePod with the timer running refuses to respond.<ul>
<li>If I set a laundry timer in the basement, it should also go off upstairs, otherwise I don&apos;t hear it.</li>
</ul>
</li>
</ul>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/top-ios-15-requests</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/top-ios-15-requests</guid>
            <category><![CDATA[apple]]></category>
            <category><![CDATA[apple wishlist]]></category>
            <category><![CDATA[iOS]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Thu, 03 Jun 2021 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Note Taker Update - iOS 14 Bug]]></title>
            <description><![CDATA[<p>In August, <a href="/blog/post/note-taker">I shared my Note Taker shortcut</a>, which I use to quickly capture my thoughts into Apple&apos;s notes app. This was before the release of iOS 14. After iOS 14 was released, I started realizing that some of my <code>#thoughts</code> notes were missing when Note Taker was asking me where I wanted to put the thought.</p>
<p>After some investigating, I determined this is actually a bug in the Shortcuts app on iOS 14. The &quot;Find Notes&quot; action is completely unreliable when searching for hashtags, that is, anything starting with a <code>#</code>. I created a <a href="https://www.icloud.com/shortcuts/d3f589ef8ad146f1ad94302d91c91592" target="_blank">simple shortcut that illustrates the bug</a> and reported it to Apple, so hopefully they resolve it sometime soon.</p>
<p>Unfortunately, the best workaround for now, is to just not use hashtags. I updated Note Taker to work with the <code>shortcuts-thoughts</code> tag instead of <code>#thoughts</code>. You can download the updated shortcut <a href="https://routinehub.co/shortcut/8062/" target="_blank">here</a>.</p>
<p>If you have been using this shortcut, be sure and change any of the <code>#thoughts</code> tags in your notes over to <code>shortcuts-tag-thoughts</code> in order for the notes to be found.</p>
<p>In the future, if I update this Shortcut, it will prompt you to install the update using UpdateKit. If you don&apos;t have the UpdateKit Shortcut installed, it will skip this step. You can download UpdateKit and learn more about it <a href="https://www.mikebeas.com/shortcuts/updatekit" target="_blank">here</a>.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/note-taker-update</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/note-taker-update</guid>
            <category><![CDATA[apple shortcuts]]></category>
            <category><![CDATA[iOS]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Tue, 12 Jan 2021 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[TypeScript Advanced Usage – Template Types]]></title>
            <description><![CDATA[<h1 id="table-of-contents"><a href="#table-of-contents">Table of Contents<i class="icon-link"></i></a></h1>
<ul>
<li><a href="#introduction">Introduction</a><ul>
<li><a href="#audience">Audience</a></li>
<li><a href="#overview">Overview</a></li>
</ul>
</li>
<li><a href="#example">Example</a></li>
<li><a href="#same-example-in-type-script">Same Example, in TypeScript</a></li>
<li><a href="#diving-deeper">Diving Deeper</a><ul>
<li><a href="#avoid-any-like-the-plag-ahem-coronavirus">Avoid <code>any</code> Like the Plag... <em>ahem</em> Coronavirus</a></li>
<li><a href="#why-any">Why <code>any</code>?</a></li>
<li><a href="#with-any-type-safety-is-lost">With <code>any</code>, Type Safety is Lost</a></li>
<li><a href="#improvement-1-still-using-any">Improvement #1 (Still using <code>any</code>)</a></li>
<li><a href="#improvement-2-using-unknown-in-place-of-any">Improvement #2 (Using <code>unknown</code> in place of <code>any</code>)</a></li>
<li><a href="#issues-with-unknown-and-casting">Issues with <code>unknown</code> and Casting</a><ul>
<li><a href="#properly-casting">Properly Casting</a></li>
<li><a href="#hastily-casting">Hastily Casting</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#template-types">Template Types</a><ul>
<li><a href="#avoiding-any-and-casting-with-template-types">Avoiding <code>any</code> and <code>casting</code> with Template Types</a></li>
<li><a href="#query-example-in-type-script-using-template-types">Query Example, in TypeScript Using Template Types</a></li>
<li><a href="#now-lets-type-the-variables-argument">Now let&apos;s type the variables argument...</a></li>
<li><a href="#what-the-hell-is-up-with-the-t-and-u">What the Hell is up With the <code>T</code> and <code>U</code>?</a></li>
</ul>
</li>
<li><a href="#unnecessary-examples">Unnecessary Examples</a><ul>
<li><a href="#normalizing-a-crappy-database-query-method">Normalizing a Crappy database.query Method</a><ul>
<li><a href="#same-example-with-normalized-return-type">Same Example, With Normalized Return Type</a></li>
<li><a href="#same-example-taken-to-an-unnecessary-level-of-detail">Same Example, Taken to an Unnecessary Level of Detail</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#conclusion">Conclusion</a></li>
</ul>
<h1 id="introduction"><a href="#introduction">Introduction<i class="icon-link"></i></a></h1>
<h2 id="audience"><a href="#audience">Audience<i class="icon-link"></i></a></h2>
<p>This is a technical post intended for software developers. If you don&apos;t code, you can skip it. If you are new to TypeScript, this post may be dense for you, but you may find value in reading it.</p>
<h2 id="overview"><a href="#overview">Overview<i class="icon-link"></i></a></h2>
<p>TypeScript is powerful and expressive. Typically we are able to reference the types we are using in our classes and functions directly. Sometimes we want to write a generic function that can work with multiple types, without losing type safety. This post helps explain how to do that.</p>
<p>This post starts with a vanilla JavaScript example and slowly builds it up to a full-fledged utility method that leverages type safety insofar as possible. Along the way, we spend a lot of time exploring alternative implementations to the example code, and caveats we may run into with those implementations.</p>
<p>It&apos;s not until the later half of the post that I even mention template types, but try to bear with me until I get there&#x2013;a lot of the background leading up to it will help provide necessary context toward describing their usefulness.</p>
<h1 id="example"><a href="#example">Example<i class="icon-link"></i></a></h1>
<p>TypeScript is great, even in simple use cases. Lets start with a code snippet in plain-old JavaScript.</p>
<pre><code class="language-js"><span class="hljs-keyword">function</span> <span class="hljs-title">databaseQueryWrapper</span>(variables) {
    <span class="hljs-keyword">return</span> <span class="hljs-type">database.query(variables)</span>;
}</code></pre>
<p>Simple enough, right? This function takes an argument: query variables, and returns the results of querying the database with those variables. But what is variables? What <code>variables</code> do I need to pass to the <code>query</code> method? This is something we can&apos;t answer without more context.</p>
<p>This is where TypeScript can help.</p>
<h1 id="same-example-in-typescript"><a href="#same-example-in-typescript">Same Example, in TypeScript<i class="icon-link"></i></a></h1>
<pre><code class="language-ts"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">databaseQueryWrapper</span><span class="hljs-params">(variables: QueryVariables)</span>: any </span>{
    <span class="hljs-keyword">return</span> database.query(variables);
}</code></pre>
<p>This is an improvement. By reading the same code, we can now infer: pass in <code>QueryVariables</code>, get back <em>anything</em>. When starting out with TypeScript, this change alone enhances your codebase with type safety. But let&apos;s go deeper.</p>
<h1 id="diving-deeper"><a href="#diving-deeper">Diving Deeper<i class="icon-link"></i></a></h1>
<p>The above example is overly simplistic for illustration purposes. Let&apos;s talk about what it&apos;s doing. The method queries the database, which is a low level operation. In any language, when you query a database, you pass in a query and get back a list of... &lt;the thing that you queried for&gt;. In the example above, we typed the return to <code>any</code>, which is less than ideal.</p>
<h2 id="avoid-any-like-the-plag-ahem-coronavirus"><a href="#avoid-any-like-the-plag-ahem-coronavirus">Avoid any Like the Plag... ahem Coronavirus<i class="icon-link"></i></a></h2>
<p>I am about to spend a loooong time convincing you that <code>any</code>, used in the above examples is dangerous and ought to be avoided.</p>
<h2 id="why-any"><a href="#why-any">Why any?<i class="icon-link"></i></a></h2>
<p>Typing the method&apos;s return value to <code>any</code>, (equivalent to bypassing TypeScript entirely), while problematic, has a single benefit: we can proceed with writing typed code where we consume <code>databaseQueryWrapper</code>. See:</p>
<pre><code class="language-ts">// query the database <span class="hljs-keyword">for</span> a list <span class="hljs-keyword">of</span> contacts
<span class="hljs-keyword">const</span> variables: <span class="hljs-type">QueryVariables</span> = <span class="hljs-meta">{...}</span>;
<span class="hljs-keyword">const</span> queryResults: <span class="hljs-type">Contact</span>[] = databaseQueryWrapper(variables);</code></pre>
<p>If you don&apos;t explicitly use they type <code>any</code> in your code, any time you are working with vanilla (non TypeScript) JavaScript, all function arguments and return values are assumed to be <code>any</code>. The caveats I discuss below are worth understanding because as you convert your codebase over to stronger typings, you will run into issues of this nature.</p>
<p>We will explore our options for typing the return value to something other than <code>any</code> later in this post.</p>
<h2 id="with-any-type-safety-is-lost"><a href="#with-any-type-safety-is-lost">With any, Type Safety is Lost<i class="icon-link"></i></a></h2>
<p>TypeScript will allow us to assign the <code>any</code> type returned from <code>databaseQueryWrapper</code> to the <code>Contact[]</code> type in the above example. But consider the following issue one could inadvertently introduce during development:</p>
<pre><code class="language-ts"><span class="hljs-comment">// oops, we forgot the `[]` in our queryResults type</span>
const queryResults: Contact = databaseQueryWrapper(<span class="hljs-keyword">variables</span>);</code></pre>
<p>TypeScript is happy, but if we try to work with the <code>queryResults: Contact</code> variable from the above example:</p>
<pre><code class="language-ts">console.<span class="hljs-built_in">log</span>(queryResults.address);
<span class="hljs-comment">// undefined</span>
console.<span class="hljs-built_in">log</span>(queryResults.address.city)
<span class="hljs-comment">// throws Cannot read property address of undefined</span></code></pre>
<p>The first line of code logs <code>undefined</code> because we are referencing <code>queryResults.address</code> when we should be referencing <code>queryResults[&lt;array index&gt;].address</code>. The second line throws an error because we (both the developer, and TypeScript) think we are accessing the <code>city</code> property on the <code>address</code> object of a <code>Contact</code>, but in reality we are attempting to reference the <code>city</code> property of what the previous line of code already let us know... is <code>undefined</code>.</p>
<h2 id="improvement-1-still-using-any"><a href="#improvement-1-still-using-any">Improvement #1 (Still using any)<i class="icon-link"></i></a></h2>
<p>If we know <code>database.query</code> will always return an array, we can make an enhancement and return <code>any[]</code> instead of <code>any</code> to improve type safety:</p>
<pre><code class="language-ts"><span class="hljs-keyword">function</span> <span class="hljs-title">databaseQueryWrapper</span>(variables: QueryVariables): any[] {
    <span class="hljs-keyword">return</span> <span class="hljs-type">database.query(variables)</span>;
}</code></pre>
<p>If we try to use it, we get an error before the code even compiles:</p>
<pre><code class="language-ts">const queryResults: Contact = databaseQueryWrapper(<span class="hljs-keyword">variables</span>);</code></pre>
<blockquote>
<p>Type &apos;Contact[]&apos; is not assignable to type &apos;Contact&apos;.</p>
</blockquote>
<p>That&apos;s whats up. While this is progress, it <strong>still</strong> requires us to use <code>any</code>. <code>any</code> is evil. So we are clear: If you eliminate no other TypeScript error from your codebase, eliminate this one:</p>
<blockquote>
<p>Type declaration of &apos;any&apos; loses type-safety. Consider replacing it with a more precise type. (no-any)tslint(1).</p>
</blockquote>
<h2 id="improvement-2-using-unknown-in-place-of-any"><a href="#improvement-2-using-unknown-in-place-of-any">Improvement #2 (Using unknown in place of any)<i class="icon-link"></i></a></h2>
<p>How do we get rid of that <code>any</code>? Let&apos;s try typing the return to <code>unknown[]</code>:</p>
<pre><code class="language-ts"><span class="hljs-keyword">function</span> <span class="hljs-title">databaseQueryWrapper</span>(variables: QueryVariables): unknown[] {
    <span class="hljs-keyword">return</span> <span class="hljs-type">database.query(variables)</span>;
}</code></pre>
<p>...but when we try to use it:</p>
<pre><code class="language-ts">const queryResults: Contact[] = databaseQueryWrapper(<span class="hljs-keyword">variables</span>);</code></pre>
<blockquote>
<p>Type &apos;unknown[]&apos; is not assignable to type &apos;Contact[]&apos;.
Type &apos;unknown&apos; is not assignable to type &apos;Contact&apos;.ts(2322)</p>
</blockquote>
<p>To bypass this, we have to cast it:</p>
<pre><code class="language-ts">const queryResults: Contact[] = databaseQueryWrapper(<span class="hljs-keyword">variables</span>) as <span class="hljs-comment">Contact[]</span>;</code></pre>
<h2 id="issues-with-unknown-and-casting"><a href="#issues-with-unknown-and-casting">Issues with unknown and Casting<i class="icon-link"></i></a></h2>
<p>We got that <code>any</code> out of the way, but can we do better? This solution requires us to cast the return value of <code>databaseQueryWrapper</code> <em>everywhere that it is used</em>, fuck that. Casting is <em>sometimes</em> necessary, but designing an API that requires it is a terrible starting point. What if you work with &quot;cast happy&quot; TypeScript developers? You know the type, their attitude is usually: &quot;Oh? It won&apos;t compile? That&apos;s alright, just cast a return value here... a variable over there... and boom... ok TypeScript is happy.&quot; How do you prevent people like this from shooting themselves in the foot?</p>
<p>Revisiting the example mistake from above, which now throws a type error:</p>
<pre><code class="language-ts"><span class="hljs-comment">// oops, we forgot the `[]` in our queryResults type</span>
const queryResults: Contact = databaseQueryWrapper(<span class="hljs-keyword">variables</span>);</code></pre>
<blockquote>
<p>Type &apos;Contact[]&apos; is not assignable to type &apos;Contact&apos;.</p>
</blockquote>
<p>There are two ways someone might try to fix it.</p>
<h3 id="properly-casting"><a href="#properly-casting">Properly Casting<i class="icon-link"></i></a></h3>
<p>If you recognize your mistake, you&apos;ll fix the variable typing to include <code>[]</code>:</p>
<pre><code class="language-ts">const queryResults: Contact[] = databaseQueryWrapper(<span class="hljs-keyword">variables</span>);</code></pre>
<p>Which will give the following type error:</p>
<blockquote>
<p>Type &apos;unknown[]&apos; is not assignable to type &apos;Contact[]&apos;.
Type &apos;unknown&apos; is not assignable to type &apos;Contact&apos;.ts(2322)</p>
</blockquote>
<p>Which you will (correctly) fix with:</p>
<pre><code class="language-ts">const queryResults: Contact[] = databaseQueryWrapper(<span class="hljs-keyword">variables</span>) as <span class="hljs-comment">Contact[]</span>;</code></pre>
<h3 id="hastily-casting"><a href="#hastily-casting">Hastily Casting<i class="icon-link"></i></a></h3>
<p>If you don&apos;t recognize the mistake, and you&apos;re feelin&apos; a lil cast happy, you&apos;ll trust your <code>queryResults</code> variable&apos;s typing and cast the function return as your first fix:</p>
<pre><code class="language-ts">const queryResults: Contact = databaseQueryWrapper(<span class="hljs-keyword">variables</span>) as <span class="hljs-comment">Contact</span>;</code></pre>
<p><strong>Fortunately</strong>, TypeScript <em>will</em> throw an error in this case.</p>
<blockquote>
<p>Conversion of type &apos;unknown[]&apos; to type &apos;Contact&apos; may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to &apos;unknown&apos; first.ts(2352)</p>
</blockquote>
<p>This is progress. The last time we had this bug we didn&apos;t find out about it until runtime&#x2013;now TypeScript is catching it for us at compile time. If you scrutinize the message, it helpfully says <code>&apos;unknown[]&apos; to type &apos;Contact&apos;</code>, which <em>should</em> tip you off that your variable, which is typed to <code>Contact</code> should actually be typed to <code>Contact[]</code>. But who reads error messages amirite? (I do, and you should) <strong>Unfortunately</strong>, the second half of this error message is actively unhelpful. TypeScript <strong><em>encourages</em></strong> the cast happy approach when it advises &quot;convert the expression to &apos;unknown&apos; first&quot;. Someone following TypeScript&apos;s recommendation would be inclined to fix the errors thusly:</p>
<pre><code class="language-ts">const queryResults: Contact = database<span class="hljs-constructor">QueryWrapper(<span class="hljs-params">variables</span>)</span> <span class="hljs-keyword">as</span>  unknown <span class="hljs-keyword">as</span> Contact;</code></pre>
<p>TypeScript is happy, but we have introduced the same bug we had from when our return was typed to <code>any</code>:</p>
<pre><code class="language-ts">console.<span class="hljs-built_in">log</span>(queryResults.address);
<span class="hljs-comment">// undefined</span>
console.<span class="hljs-built_in">log</span>(queryResults.address.city)
<span class="hljs-comment">// throws Cannot read property address of undefined</span></code></pre>
<p>The takeaway? Casting introduces bugs in the same class as bugs you had when your codebase was full of <code>any</code> types. Be smart about when you use it, if at all, and definitely don&apos;t require it when designing your API.</p>
<hr>
<h1 id="template-types"><a href="#template-types">Template Types<i class="icon-link"></i></a></h1>
<h2 id="avoiding-any-and-casting-with-template-types"><a href="#avoiding-any-and-casting-with-template-types">Avoiding any and casting with Template Types<i class="icon-link"></i></a></h2>
<p>Can we stop here? Should we even worry about the &quot;cast happy&quot; developer who might shoot themselves in the foot while consuming our API? Probably not, who do we think we are, God? If &quot;cast happiness&quot; is a consistent issue with any one person on the team, let them know like &quot;hey, types are cool, honor them and stop casting shit left and right&quot;. Don&apos;t waste your own time writing code to protect people from themselves.</p>
<p>But, I will continue for two reasons:</p>
<ol>
<li>On our bad days, we are all that &quot;cast happy&quot; developer. As engineers we are placed under deadlines and pressure all the time. All engineers are gonna cut corners&#x2013;it comes with the territory. Good engineers cut the right corners at the right time (and document the fact that they cut the corner, why they cut the corner, and the potential impact of their decision to cut the corner, but I digress)</li>
<li>I haven&apos;t even mentioned template types yet in this incredibly long winded and verbose TypeScript example. I can&apos;t end the blog post before I discuss template types. And this is still a useful illustration for doing that.</li>
</ol>
<hr>
<p>Are we convinced template types might be useful yet? Cool. Let&apos;s use them.</p>
<h2 id="query-example-in-typescript-using-template-types"><a href="#query-example-in-typescript-using-template-types">Query Example, in TypeScript Using Template Types<i class="icon-link"></i></a></h2>
<pre><code class="language-ts">function databaseQueryWrapper&lt;T&gt;(<span class="hljs-keyword">variables</span>: QueryVariables): T <span class="hljs-comment">{</span>
    return <span class="hljs-comment">database.query(variables)</span>;
}

const queryResults: Contact[] = databaseQueryWrapper&lt;Contact&gt;(<span class="hljs-keyword">variables</span>);</code></pre>
<p>While the consuming code is slightly less intuitive, and requires a shallow understanding of template types, it eliminates casting, removes the <code>any</code> keyword, and is less error prone. This is great.</p>
<h2 id="now-lets-type-the-variables-argument"><a href="#now-lets-type-the-variables-argument">Now let&apos;s type the variables argument...<i class="icon-link"></i></a></h2>
<p>Up until now, we have used a vague <code>QueryVariables</code> type for the <code>variables</code> argument for purposes of simplicity. But in practice, what <em>is</em> variables going to be? This example was inspired by a wrapper that I wrote for <a href="https://github.com/apollographql/apollo-client" target="_blank">apollo-client</a> which we use to query our GraphQl API at my job. In my case, the variables that we use to query for an entity depends on the entity that we are querying for, so what we are able to pass to the query method needs to change based on what we are expecting to get back. Just like we used template types to allow the consumer of <code>databaseQueryWrapper</code> to specify its own return type, we can use template types to allow the consumer to specify the type for the parameters it wants to pass to the method:</p>
<pre><code class="language-ts">function databaseQueryWrapper&lt;T, U&gt;(<span class="hljs-keyword">variables</span>: T): U <span class="hljs-comment">{</span>
    return <span class="hljs-comment">database.query(variables)</span>;
}

const <span class="hljs-keyword">variables</span>: ContactQueryParams <span class="hljs-comment">= {}</span>;
const queryResults: Contact[] = databaseQueryWrapper&lt;ContactQueryParams, Contact&gt;(<span class="hljs-keyword">variables</span>);</code></pre>
<p>Now we are really flying. We have implemented a great low level helper that helps us query our database. We can define some helpers for our consumers to use:</p>
<pre><code class="language-ts">export <span class="hljs-keyword">function</span> <span class="hljs-title">queryForContacts</span>(variables: ContactQueryParams): Contact[] {
  <span class="hljs-keyword">return</span> <span class="hljs-type">databaseQueryWrapper&lt;ContactQueryParams,</span> Contact&gt;(variables);
}

export <span class="hljs-keyword">function</span> <span class="hljs-title">queryForEvents</span>(variables: EventsQueryParams): Event[] {
  <span class="hljs-keyword">return</span> <span class="hljs-type">databaseQueryWrapper&lt;EventsQueryParams,</span> Event&gt;(variables);
}</code></pre>
<h2 id="what-the-hell-is-up-with-the-t-and-u"><a href="#what-the-hell-is-up-with-the-t-and-u">What the Hell is up With the T and U?<i class="icon-link"></i></a></h2>
<p>I was trained in C++, which has the same exact concept of template types as TypeScript. To my knowledge, convention has always used letters of the alphabet, starting with T (I assume for &quot;Template&quot;) when naming template types.</p>
<p>What most examples on the internet never tell you, is that <code>T</code> and <code>U</code> are just variables, and can be named <em>anything</em>. Readers of these internet tutorials would be better served if descriptive names for <code>T</code> and <code>U</code> were used. You are advised to never name variables stuff like <code>a</code> and <code>b</code>, so why doesn&apos;t the same thing apply to template variable names? I think everyone is afraid the programming gods will strike them down if they break convention here, but imma do it anyway:</p>
<pre><code class="language-ts"><span class="hljs-keyword">function</span> <span class="hljs-title">databaseQueryWrapper&lt;TypeForQueryVariables,</span> TypeForQueryResults&gt;(variables: TypeForQueryVariables): TypeForQueryResults {
    <span class="hljs-keyword">return</span> <span class="hljs-type">database.query(variables)</span>;
}</code></pre>
<p>This example removes the ambiguity from <code>T</code> and <code>U</code> and captures some of the original developer&apos;s intent when creating the templatized method to begin with.</p>
<p>At the risk of talking out of my ass: Once you are so far off the deep end that you are finding value in using template types within your functions or class implementation, you won&apos;t be bothered by the fact that your templatized types have super abstract names like <code>T</code> and <code>U</code>. You&apos;re already thinking so far in the abstract it will be the least of your concerns. I would venture to say that most examples don&apos;t bother giving <code>T</code> and <code>U</code> more meaningful names because once this whole concept clicks for you, <code>T</code> and <code>U</code> will prove to me more than sufficient descriptors.</p>
<hr>
<h1 id="unnecessary-examples"><a href="#unnecessary-examples">Unnecessary Examples<i class="icon-link"></i></a></h1>
<p>If I hadn&apos;t already convinced you of the value in avoiding casting and unknown types as reason enough to dive into template types, let me give you two more concrete and less contrived examples of when you may need them.</p>
<h2 id="normalizing-a-crappy-databasequery-method"><a href="#normalizing-a-crappy-databasequery-method">Normalizing a Crappy database.query Method<i class="icon-link"></i></a></h2>
<p>What if the <code>database.query</code> method is inconsistent and returns a <em>single object</em> if the query only returned a single entity, but an <em>array of objects</em> if the query matched multiple entities? This is a low-level oddity that you might want to smooth over within <code>databaseQueryWrapper</code> so that future consumers wouldn&apos;t need to check if the item(s) returned from <code>databaseQueryWrapper</code> is an array or not.</p>
<p>Let&apos;s fix it:</p>
<h3 id="same-example-with-normalized-return-type"><a href="#same-example-with-normalized-return-type">Same Example, With Normalized Return Type<i class="icon-link"></i></a></h3>
<pre><code class="language-ts"><span class="hljs-keyword">function</span> <span class="hljs-title">databaseQueryWrapper&lt;T,</span> U&gt;(variables: T): U[] {
    const results: U | U[] = database.query(variables);
    <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">Array</span>.isArray(results)) {
        results = [results];
    }
    <span class="hljs-keyword">return</span> results;
}</code></pre>
<p>Cool, you just saved the rest of your team from having to accidentally discover that your third-party database package sucks ass.</p>
<h3 id="same-example-taken-to-an-unnecessary-level-of-detail"><a href="#same-example-taken-to-an-unnecessary-level-of-detail">Same Example, Taken to an Unnecessary Level of Detail<i class="icon-link"></i></a></h3>
<p>What if your <code>database.query</code> method might throw an error if the database is not initialized or properly authenticated, but returns an object <em>containing</em> an error if the query was malformed? Thats inconsistent (in this example, this particular inconsistency might be okay)! Maybe your database package doesn&apos;t return the number of entities that match your query, but you want to encapsulate that and return a count along side your results? tl;dr, what if you want to normalize your return value to the following:</p>
<pre><code class="language-json">{
  success: <span class="hljs-built_in">boolean</span>;
  <span class="hljs-keyword">error</span>?: <span class="hljs-built_in">string</span>;
  results: Contact[];
  <span class="hljs-built_in">count</span>: <span class="hljs-built_in">number</span>;
}</code></pre>
<p>This is something you would want to encapsulate within the <code>databaseQueryWrapper</code> method, and template types can help:</p>
<pre><code class="language-ts"><span class="hljs-keyword">interface</span> DatabaseQueryResults&lt;T&gt; {
  success: <span class="hljs-built_in">boolean</span>;
  error?: <span class="hljs-built_in">string</span>;
  results: T[];
  count: <span class="hljs-built_in">number</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">databaseQueryWrapper</span>&lt;<span class="hljs-title">T</span>, <span class="hljs-title">U</span>&gt;(<span class="hljs-params">variables: T</span>): <span class="hljs-title">DatabaseQueryResults</span>&lt;<span class="hljs-title">U</span>&gt; </span>{
    <span class="hljs-keyword">let</span> success: <span class="hljs-built_in">boolean</span> = <span class="hljs-literal">true</span>;
    <span class="hljs-keyword">let</span> results: U | U[] = [];
    <span class="hljs-keyword">let</span> error: <span class="hljs-built_in">string</span> = <span class="hljs-string">&apos;&apos;</span>;
    <span class="hljs-keyword">try</span> {
        results = database.query(variables);
    } <span class="hljs-keyword">catch</span>(e) {
        <span class="hljs-comment">// don&apos;t follow my lead here, I am swallowing the error&apos;s</span>
        <span class="hljs-comment">// stack in this example... don&apos;t be like me</span>
        error = e.message;
        success = <span class="hljs-literal">false</span>;
    }
    <span class="hljs-keyword">const</span> results: U | U[] = database.query(variables);
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">Array</span>.isArray(results)) {
        results = [results];
    }

    <span class="hljs-keyword">return</span> {
        success,
        results,
        count: results.length,
        error,
    }
}</code></pre>
<h1 id="conclusion"><a href="#conclusion">Conclusion<i class="icon-link"></i></a></h1>
<p>Thats it! I hope you found value in this post. Thanks for reading it.</p>
<p><a href="https://codeburst.io/five-tips-i-wish-i-knew-when-i-started-with-typescript-c9e8609029db" target="_blank">Click for an article</a> that I stumbled on while researching this post. It&apos;s a great read and full of TypeScript tips.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/typescript-template-types</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/typescript-template-types</guid>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[web dev]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Thu, 07 Jan 2021 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Privacy Enhancements in iOS 14]]></title>
            <description><![CDATA[<p><strong>If you read nothing else, read this paragraph.</strong> Now that iOS 14 has released, I <strong>strongly</strong> recommend that you go to <code>Settings &gt; General &gt; Reset</code> and tap on &quot;Reset Location &amp; Privacy&quot;. This will clear out your Privacy settings, requiring every application to prompt you the next time it needs access to your photos, location, or any other sensitive data. New to iOS 14, you can turn off &quot;Precise Location&quot; for apps that don&apos;t need it. When apps like Instagram request photos access, you can grant access to &quot;Selected Photos&quot; instead of your entire library.</p>
<p>In this post, I&apos;ll provide a quick overview of iOS 14&apos;s new privacy controls. iOS 14 introduces fine-grained settings to give you tighter control over your privacy. Without a doubt, Apple is doing something right; the <a href="https://9to5mac.com/2020/07/03/permission-for-tracking/" target="_blank">advertising industry is pissed off at them</a> because of these changes.</p>
<p>There are two new privacy settings that I want to highlight in this post:</p>
<ol>
<li>Precise/imprecise location setting</li>
<li>Ability to grant applications access to &quot;Selected Photos&quot;. (Pre iOS 14, photos access was all or none)</li>
</ol>
<h1 id="precise-location-setting"><a href="#precise-location-setting">Precise Location Setting<i class="icon-link"></i></a></h1>
<p>Before iOS 14, you had 3 options when granting an application access to your location: &quot;allow once&quot;, &quot;always allow&quot;, or &quot;allow while using the app&quot;. These are useful settings that provided a necessary level of privacy controls, but in 2020, when advertisers are running amok with our data, we need more. With iOS 14, Apple came thru.</p>
<p>Apps like Snapchat (which request location access for purposes of users sharing their location on a map) can use that precise location data however they see fit; they could learn that you visit Target every Friday and start showing you Target ads on Thursday evenings. Nefarious developers with access to your location could glean your home address, your work address, and your frequently visited locations just from having access to your location.</p>
<p>I have heard tales of companies with internal dashboards that show where all of their app&apos;s users are at on a map at any given time. In the age of ubiquitous technology, lots of <a href="https://digitalcommons.law.yale.edu/cgi/viewcontent.cgi?article=1098&amp;context=yjolt" target="_blank">&quot;creepy&quot; practices are emerging</a>. By default, companies should NOT be trusted with your data. Engineers are asked to implement solutions that violate user&apos;s best interest on the daily. Many comply.</p>
<p>In iOS 14, Apple has taken steps to mitigate developers&apos; access to your precise location. The new location prompt on iOS 14 allows you to toggle whether the app can see your precise location. There are <strong>very</strong> few applications that <em>need</em> access to your precise location. Other than navigation apps, the majority of apps should be able to function just fine without precise location access.</p>
<h1 id="all-vs-selected-photos"><a href="#all-vs-selected-photos">All vs. Selected Photos<i class="icon-link"></i></a></h1>
<p>In iOS 13, Instagram has access to your full photo library. Swiping left from the camera illustrates this&#x2013;you are presented with a list of ALL of your photos thru the Instagram interface.</p>
<p>No way in hell do I trust Instagram (owned by Facebook) with unfettered access to my photos. For all I know, they could be uploading my entire photo library to their server, running image processing on them, and using what they learned to serve targeted ads to me on Facebook. Photos that I have <strong>never</strong> posted to Instagram could have been used for nefarious purposes by the company. For all we know, we are unwittingly feeding a facial recognition database&#x2013;simply by granting an application access to our photos. We have no control of what an application does with our photos after we grant access&#x2013;and this is an issue.</p>
<p>In iOS 14, Apple has mitigated this. When an application requests access to your photos, you are presented with a new option: &quot;Selected Photos&quot;. Tapping this option presents you with your photo library, and allows you to select specific photos that the  app will have access to. As far as that application is concerned, your photo library contains the photos you have selected, nothing more. If you use the &quot;Selected Photos&quot; permission level, it&apos;s impossible for a developer to see photos that you don&apos;t explicitly select when granting access.</p>
<h1 id="significant-locations"><a href="#significant-locations">Significant Locations<i class="icon-link"></i></a></h1>
<p>Significant Locations isn&apos;t a new feature to iOS 14, but now is as good a time as any to educate people about the feature&apos;s existence.</p>
<p>By default, iOS is tracks your location to a surprising level of detail. Take a look at <code>Settings &gt; Privacy &gt; Location Services &gt; System Services</code>, scroll down and tap on &quot;Significant Locations&quot;. You&apos;ll see a detailed log and map of the places you frequent, along with timestamps of when you visited those locations.</p>
<p>This can be startling the first time you see it. Your iPhone is collecting A LOT of your location history. If you&apos;d like, you can disable this feature within the &quot;Significant Locations&quot; setting screen. I keep the feature enabled. The Significant Locations feature is what enables the iPhone to predict where I may want to drive when I get in the car, and suggest directions to those locations when pertinent. These locations are stored  on my device, and are locked behind FaceID. I trust Apple to not use my location history for nefarious purposes.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/ios-14-privacy</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/ios-14-privacy</guid>
            <category><![CDATA[iOS]]></category>
            <category><![CDATA[tips and tricks]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Wed, 16 Sep 2020 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Small Business Directory]]></title>
            <description><![CDATA[<p>The unjust killing of George Floyd, Breonna Taylor, Elijah McClain, and countless others has revived nation-wide protests and with them, the conversation about the plethora of problems that white people in America create for Black people.</p>
<p>I&apos;ve noticed a pattern among online activists: people are creating directories containing small and/or black-owned businesses that need our support. Some have likened these directories to a modern-day <a href="https://www.smithsonianmag.com/smithsonian-institution/history-green-book-african-american-travelers-180958506/" target="_blank">green book</a>. In a lot of cases, people are taking the quick &amp; dirty approach: creating a google spreadsheet or document, and sharing a view-only link. In other cases, people like my good friend Kristle (<a href="https://www.instagram.com/kristhecreative/?hl=en" target="_blank">@kristhecreative</a> on Instagram) are manually maintaining PDFs and publishing updates on a semi-regular basis. This is a time-consuming, repetitive, and arduous process.</p>
<p>Any time I observe time consuming or repetitive processes, my mind goes straight to automation. Computers are great at performing repetitive tasks.</p>
<p>I asked myself: what if someone could create a Google Spreadsheet and, with the press of a button, convert the spreadsheet into a website? In theory, it was a simple thing to create, so I set out to create it. This is an example of where I feel my software skills can be applied toward the greater good&#x2013;and I can have my own positive impact on the movement.</p>
<p>I know myself. I need a tangible deliverable and deadline if I&apos;m going to get something done. To that end, I reached out to Kristle and asked her if I could work with her to convert her Small Business Directory PDF into a website. I explained how this could save her time and enable her to focus on the content of the directory rather than the presentation. She was into it.</p>
<p>We did it. Check out Kristle&apos;s Small Business Directory <a href="https://shopsmall.kriscreates.com" target="_blank">here</a>. Big ups to Kristle for the excellent design and the Small Business Directory she&apos;s been maintaining manually for most of the year. Shoutout to <a href="https://twitter.com/migreva" target="_blank">@migreva</a> for chipping in on some of the code. This project would have taken me significantly longer to complete without his help.</p>
<p>Now that I have reached my first goal: to prove out the idea and leverage it to make a single business listings website, I am setting my sights higher. My friend Precious lives in D.C. and maintains a spreadsheet containing black-owned businesses in her area. I am going to work to open source the code that I wrote for Kristle&apos;s <a href="https://shopsmall.kriscreates.com" target="_blank">Small Business Directory</a> so that I can reuse it for Precious&apos;s website. Look out for a future post once that&apos;s complete. At that point, I plan to provide step-by-step instructions for <em>anyone</em> to create their own business directory in a few easy steps.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/small-business-directory</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/small-business-directory</guid>
            <category><![CDATA[hacking for change]]></category>
            <category><![CDATA[portfolio]]></category>
            <category><![CDATA[web dev]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Mon, 14 Sep 2020 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Note Taker Shortcut]]></title>
            <description><![CDATA[<p><strong>Update 2021-01-12:</strong> Updated shortcut link and post text to fix iOS 14 issue with hashtags. See my <a href="/blog/post/note-taker-update">post about the bug</a> for more info.</p>
<p>I created a shortcut that I wanna share with y&apos;all. I think of new ideas at the most random times. An idea might be something I want to incorporate into an existing project, a new project, a topic I want to research, or anything in-between. Before this shortcut, I would file away new ideas by saying &quot;hey Siri, note to self <idea>&quot;.</idea></p>
<p>The problem with this was that each new idea ended up in its own note. Then, at some point in the future, I have to comb through my notes and figure out what to do with each of them. This is an unnecessary step that builds up a backlog of ideas. It would be preferred if I took the time up-front to add the idea to its pertinent note. The problem: half the time, by the time I finish hunting down which note I want to put the idea into, I forgot the idea I wanted to capture. I&apos;ve lost many good ideas because I forgot them before writing them down.</p>
<blockquote>
<p>That mean I forgot better shit than you ever thought of</p>
</blockquote>
<p>To help remedy this, I created a shortcut, Note Taker. When you run it, you will be prompted for text. After you enter the idea, it will let you pick from any note with a <code>shortcuts-tag-thoughts</code> tag and add the idea to the end of that note.</p>
<p>Download Note Taker <a href="https://routinehub.co/shortcut/8062/" target="_blank">here</a>.</p>
<p>If this is your first shortcut, you might run into issues installing &quot;Untrusted Shortcuts&quot;. I provide instructions for that <a href="/blog/post/my-first-untrusted-shortcuts">here</a>.</p>
<p>After you install it, you can run it from the Share Sheet or the Shortcuts app to take a new note. It will create a &quot;My Thoughts&quot; note for you on the first run, and you can add the <code>shortcuts-tag-thoughts</code> tag to any other notes into which you might want to file an idea. You can also select &quot;Note Taker&quot; from the share sheet to capture anything the phone lets you share into a note.</p>
<h1 id="advanced-usage"><a href="#advanced-usage">Advanced Usage<i class="icon-link"></i></a></h1>
<p>As explained above and by default, Note Taker searches for notes that contain the text <code>shortcuts-tag-thoughts</code>. But you might want to create a customized version that searches a different tag. I do exactly that for work so that I can capture notes for things I need to bring up in a 1:1 or upcoming meeting. Download my <code>shortcuts-work-note</code> version of this note <a href="https://routinehub.co/shortcut/8197" target="_blank">here</a>. <strong>Note:</strong> You will need to install the Note Taker shortcut for the customized <code>shortcuts-work-note</code> version to work.</p>
<p>For more documentation for this shortcut, check out the <a href="https://routinehub.co/shortcut/8062/" target="_blank">RoutineHub listing</a>.</p>
<p><img src="/images/shortcuts/note-taker-advanced.jpg" alt></p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/note-taker</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/note-taker</guid>
            <category><![CDATA[apple shortcuts]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Mon, 24 Aug 2020 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Mind Node]]></title>
            <description><![CDATA[<p>I have <strong>a lot</strong> of ideas. I&apos;m in the habit of writing them down, but organizing, revisiting, and evolving them can be an arduous process. I get frustrated by using list apps like Reminders when planning out a coding project, a comedy set, a vacation, an event, a life plan; anything that requires up-front thought or organization of interconnected items.</p>
<p>This is where the concept of &quot;Mind Mapping&quot; comes in. Mind Mapping is a popular concept among productivity enthusiasts. You can find countless videos and articles online about Mind Mapping, I won&apos;t repeat their content in this post. Take a look at the photo at the top of this post for an example mind map. You get the idea.</p>
<p>After I discovered the concept of Mind Mapping, I set out to find the best Mind Mapping app for iPhone, iPad and macOS.</p>
<p>IMO, Good Mind Mapping software must do a few things:</p>
<ol>
<li>Work on macOS, iOS, and iPadOS&#x2013;syncing your documents across devices with ease</li>
<li>It should support the same features on iOS and iPadOS as it does on Mac. It shouldn&apos;t be dumbed down for mobile devices.</li>
<li>Support exporting your Mind Map as outlines</li>
<li>Support drag and drop, and split screen on iPad for importing and exporting content to and from the app</li>
<li>Make it super easy to move items on the map from one place to another via drag and drop</li>
<li>Allow you to create weak connections between nodes, so that you can indicate a relationship between items on different branches of the tree</li>
<li>Provide a high-level expand and collapsible outline view of your mind map</li>
<li>Provide task support&#x2013;where you can treat select items in the mind map as a task to complete</li>
<li>Integrate with the Shortcuts app for maximum automation</li>
<li>Support tagging of individual items</li>
</ol>
<p>Mind Node checks all of these boxes. <a href="https://mindnode.com" target="_blank">Visit their website</a> to download the app today. <a href="https://mindnode.com/post/mindnode-7.1" target="_blank">Here&apos;s</a> a blog post of theirs that highlights some of its more advanced features.</p>
<p>It costs money, but it&apos;s worth it if you have ideas to organize. Unfortunately, they are moving to a paid subscription, but they have proven to be capable developers who frequently update the app. Apple leaves them with very little choice (find my rant on that <a href="/blog/post/subscription-based-apps">here</a>).</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/mind-node</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/mind-node</guid>
            <category><![CDATA[app recommendation]]></category>
            <category><![CDATA[iOS]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Mon, 17 Aug 2020 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[My Rant on Subscription Based Apps]]></title>
            <description><![CDATA[<blockquote>
<p><strong>Update 2025:</strong> My thoughts on App Store policies are now part of my live wishlist at <a href="https://apple.lukezilioli.com/wishlist/" target="_blank">apple.lukezilioli.com/wishlist</a>. Check out my blog post about <a href="/blog/post/apple-wishlist-website">Apple Wishlist Website is Live</a> for more details and all my latest Apple requests.</p>
</blockquote>
<p>Have y&apos;all noticed the upward trend of subscription-based apps? They&apos;re <strong>EVERYWHERE</strong>. We have Apple to thank for that. While I think Apple does a lot of good, this is one place they have prioritized profits and have failed both developers and consumers alike in the process.</p>
<p>The US Government spent a day probing Apple and other tech companies about monopolistic practices a couple of weeks ago. I was disappointed to see the issue of subscription-based apps not get addressed. This is an area of the App Store where I genuinely feel Apple has misused its power. The government should put regulations in place to right this wrong. Get this&#x2013;Apple loves subscriptions sooo much, they offer developers a 50% discount on the fee they take from subscriptions when compared to apps. Apple takes a 30% cut of App Sales, but only a 15% cut of subscription fees for year-long subscriptions. If making one model of app pricing financially superior to another isn&apos;t considered monopolistic and anti-competitive behavior, I don&apos;t know what is.</p>
<p>Before the App Store, the upgrade pricing model for software was straightforward. You&apos;d buy an app for a set amount of money, and you knew you could use that app until it is no longer compatible with your operating system. Think of Microsoft Office back in the day: you could buy the disc and not have to buy another copy until you upgraded your computer or you <strong>needed</strong> a feature that was only available in a new version (lookin&apos; at you, .docx files). This pricing model is great! As users, we get to decide if we want to continue using the old version of the app we already paid for, or if we want to pay to buy the new version of the app with the new features. Developers can invest time into creating a new version of their software knowing that they can sell that new version to users once they release it. Everybody wins.</p>
<p>No such thing exists on Apple&apos;s App Store, despite the fact that <a href="https://www.macworld.com/article/3196016/app-store-upgrades-it-s-not-that-apple-can-t-do-it-but-they-won-t-do-it.html" target="_blank">developers</a> have been requesting, and <a href="https://www.macobserver.com/tmo/article/app-store-upgrades-masquerade-as-app-store-bundles" target="_blank">finding clever ways</a> of offering paid upgrades to their apps for YEARS. Savvy developers have found ways around this by creating new App Store listings for new versions of their apps, but that comes with drawbacks. Namely that they lose their app store rankings and reviews from old versions. Other developers have offered one time unlocks of available features, and lock down new features behind another one-time fee in the future. In my opinion, the <a href="https://workingcopyapp.com" target="_blank">Working Copy</a> app for iOS has one of the most fair pricing models around. I commend the developer for not succumbing to Apple&apos;s subscription model.</p>
<p>For some apps like Netflix, or others with ongoing server costs, a subscription-based model makes a lot of sense. Its great that the option is available&#x2013;I am not advocating for subscription-based-pricing to be removed. However, apps within Apple&apos;s ecosystem with no server backing and no ongoing costs have been moving to a subscription-based model. Apps that should theoretically work forever if the user never updated their software again are starting to get locked behind paid subscriptions. Mind Node (a favorite app of mine that I have been using for years) is the <a href="https://mindnode.com/post/mindnode-7--visual-tags-and-business-model-changes" target="_blank">latest such app</a>. Look at the backflips they have to do in that blog post to convince us that subscriptions are worthwhile. We all know they aren&apos;t ideal.</p>
<p>Subscriptions have other issues, none of which are consumer-friendly. Developers can sell their app based on promises of future features. Users might sign up for a subscription on good faith that developers will deliver the promised features. That day could never come. Worse: Apple&apos;s policies don&apos;t make it easy to get a refund for a subscription to an app that is updated to no longer function as promised. Users might pay for an app only to find that its next major release is something they want nothing to do with. Fantastical is one such app. They radically reinvented the app and its interface as part of their shift to subscription pricing... and it is <strong>not</strong> an improvement. Lots of people jumped ship from Fantastical as a result, myself included. Look at their <a href="https://apps.apple.com/us/app/fantastical-calendar-tasks/id718043190" target="_blank">recent App Store reviews</a>. A PR nightmare.</p>
<p>Take the time to read the <a href="https://www.2doapp.com/update-roadmap/" target="_blank">&quot;Roadmap&quot;</a> blog post from one of my favorite task management apps, 2Do (I&apos;ve been using 2Do since &apos;09). This is a developer who feels it is unfair to charge a subscription for a simple to do list, but feels Apple has given him few alternatives if he wants to make a living off of his software. He rightly understands that users are less inclined to sign up for a subscription for a task manager than they are to shell out 4 or 5 dollars every few years for the latest and greatest version of that same app. Compounding the 2Do app&apos;s problems, iOS 13 abandoned the CalDav syncing API the app was relying on to integrate with the iOS Reminders. As a result, the application has been stuck in a limbo for a year as he assesses the best path forward. Apple shouldn&apos;t be allowed to play with people&apos;s livelihood in this way.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/subscription-based-apps</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/subscription-based-apps</guid>
            <category><![CDATA[apple]]></category>
            <category><![CDATA[apple wishlist]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Mon, 10 Aug 2020 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Bridging Plex to Shortcuts with nodejs and Pushcut]]></title>
            <description><![CDATA[<p>I have been relying on <a href="https://www.pushcut.io" target="_blank">Pushcut</a> for many of my smart home automation needs. Pushcut is hard to describe, so I&apos;ll list a few things it has enabled me to do:</p>
<ul>
<li>My work meetings get announced out loud from my desk speakers 5 minutes before they start and again when they begin</li>
<li>When I get out of bed, Siri reads my schedule for the day, including any reminders I have set for myself</li>
<li>When I walk in the door, Siri greets me with &quot;what up doe&quot;</li>
<li>If it gets too cold in my apartment, the AC turns off (even tho its a dumb AC that plugs into the wall)</li>
</ul>
<p>The latest thing I have used Pushcut for is to send notifications to my phone and iPad when I start watching something thru Plex. The notification comes with a few different options that let me dim the lights or activate other Home scenes, depending on what I&apos;m feelin&apos; at the time.</p>
<p>I have a few goals:</p>
<ol>
<li>I want to get different notifications depending on which room I was watching TV in.</li>
<li>I want different notifications for if I play or pause a show. </li>
<li>I don&apos;t want a notification <em>every</em> time I play or pause, that&apos;s too noisy.</li>
</ol>
<p>To give myself maximum customization options, and meet these goals, I wrote a little <a href="https://github.com/lzilioli/plex-to-pushcut" target="_blank">node app</a>.</p>
<p>It receives Plex webhooks and maps them to Pushcut endpoints. It can send notifications, or for more advanced users, forward the webhook payload to a Shortcut running on a Pushcut automation server. Check out the repo, <code>plex-to-pushcut</code> on my <a href="https://github.com/lzilioli/plex-to-pushcut" target="_blank">GitHub</a>.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/plex-to-pushcut</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/plex-to-pushcut</guid>
            <category><![CDATA[apple shortcuts]]></category>
            <category><![CDATA[open source]]></category>
            <category><![CDATA[smart home]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Mon, 03 Aug 2020 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[How to Install Your First Untrusted Shortcut on iOS]]></title>
            <description><![CDATA[<h1 id="purpose"><a href="#purpose">Purpose<i class="icon-link"></i></a></h1>
<p>If you&apos;re trying to install a shortcut and running into problems with the &quot;Allow Untrusted Shortcuts&quot; setting, you&apos;re in the right place.</p>
<h1 id="overview"><a href="#overview">Overview<i class="icon-link"></i></a></h1>
<p>A few years ago, Apple added the Shortcuts app to the iPhone and iPad. Shortcuts is a super powerful app. It lets you automate repetitive tasks. Its like coding but you don&apos;t type out the code, you drag and drop it into place. It&apos;s fun.</p>
<p>Most people won&apos;t ever create their own Shortcut. Thats okay! Apple enables shortcut authors to share them with others. Thanks to this, everybody can take advantage of Shortcuts&apos; power.</p>
<p>The only problem? Apple makes it difficult to install your first &quot;Untrusted&quot; shortcut. Not only do they make you turn on a setting, they disable that setting for no apparent reason.</p>
<p>When you try to add a Shortcut to your iPhone that wasn&apos;t from the Shortcut gallery, you&apos;ll see the following error message:</p>
<blockquote>
<p><strong>Shortcut can&apos;t be opened.</strong>
This shortcut cannot be opened because your Shortcuts security settings don&apos;t allow untrusted shortcuts.</p>
</blockquote>
<p>If you&apos;re lucky, you might have found the the &quot;Allow Trusted Shortcuts&quot; setting. If this is your first shortcut, the setting will be completely disabled. You won&apos;t be able to turn it on, even if you wanted to. Its inexplicable why Apple made it this way, it really <strong>is</strong> dumb as hell, but I explain how to fix it in this post.</p>
<h1 id="disclaimer"><a href="#disclaimer">Disclaimer<i class="icon-link"></i></a></h1>
<p>While it ought to be easier to flip the switch, <strong>the setting itself exists for good reason</strong>. I would be remiss if I didn&apos;t explain the reason for the setting&apos;s existence before providing instructions on how to disable it.</p>
<p>Shortcuts, like apps, are powerful. If you don&apos;t understand what a shortcut you installed does, you could be giving your personal data to the shortcut author without knowing it. Don&apos;t get scammed.</p>
<p>Apple has done a solid job of making sure that, even if you don&apos;t read and understand the whole shortcut, you&apos;ll know and can control what data it has access to.</p>
<p>Like the first time you run an app and get prompted to let it access your location, the first time you run a shortcut you will be prompted for EVERYTHING it tries to access. <strong>Take care to read these prompts, and say no if you don&apos;t understand what or why you are being asked for something.</strong> Don&apos;t worry, the nightmare scenario of a shortcut stealing your nudes and uploading them to a private server is unlikely, just <strong>read the prompts</strong> and  don&apos;t grant the same shortcut access to your photos AND to some random server you don&apos;t trust.</p>
<p>At any time, you can access the shortcut&apos;s details to view and manage a list of everything it has requested access to.</p>
<p>Who knows&#x2013;maybe Apple made it unnecessarily difficult to enable this setting so that people like me would write disclaimers like this before explaining how to enable the &quot;Allow Untrusted Shortcuts&quot; setting. OK... on to the instructions.</p>
<h1 id="instructions"><a href="#instructions">Instructions<i class="icon-link"></i></a></h1>
<p><strong>Please take the time to understand why this setting exists before blindly enabled it. I explain it <a href="#disclaimer">above</a>. You&apos;ve been warned.</strong></p>
<p>All you gotta do is enable the &quot;Allow Untrusted Shortcuts&quot; setting in <code>Settings &gt; Shortcuts</code>.</p>
<h1 id="if-the-setting-is-disabled"><a href="#if-the-setting-is-disabled">If the Setting is Disabled<i class="icon-link"></i></a></h1>
<p>To enable the &quot;untrusted&quot; shortcuts switch when its totally disabled, you need to first install and run at least one shortcut from the gallery.</p>
<p><strong>Note:</strong> A video of this process can be found at the end of this post.</p>
<p><strong>Note:</strong> If you are running iOS 14 instead of 12 or 13, you can skip steps 2-5 and instead run one of the &quot;Starter Shortcuts&quot; from the shortcuts tab. That alone should enable the &quot;Allow Untrusted Shortcuts&quot; switch in settings.</p>
<ol>
<li>Launch the Shortcuts app</li>
<li>Tap &quot;Gallery&quot; on the bottom navigation bar</li>
<li>Install <em>any</em> shortcut from the gallery (<a href="/blog/post/apple-features-daily-standup">I have one in there!</a>)</li>
<li>Switch to the &quot;My Shortcuts&quot; tab in the navigation bar</li>
<li>Run the shortcut you just installed</li>
<li>Launch the Settings App</li>
<li>Scroll down to the &quot;Shortcuts&quot; section and tap on it</li>
<li>The &quot;Allow Untrusted Shortcuts&quot; setting should no longer be greyed out.</li>
<li>Turn it on</li>
</ol>
<p>You should be able to install the untrusted shortcut this time around. Go back and click the link to install the shortcut.</p>
<p>Here&apos;s the viddy:</p>
<iframe width="375" height="667" src="https://www.youtube.com/embed/EmLJSmTT-RY" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>]]></description>
            <link>https://www.lukezilioli.com/blog/post/my-first-untrusted-shortcuts</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/my-first-untrusted-shortcuts</guid>
            <category><![CDATA[apple shortcuts]]></category>
            <category><![CDATA[iOS]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Sat, 25 Jul 2020 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Daily Standup Featured by Apple]]></title>
            <description><![CDATA[<p>Like a lot of software teams, we have daily stand up meetings at my job. For a while, we were doing these over chat, where we would type up our status as opposed to delivering it verbally over video.</p>
<p>It&apos;s a repetitive task when you keep an updated todo list. Stand up is just regurgitating:</p>
<ol>
<li>The tasks you completed yesterday</li>
<li>The tasks you intend on completing today</li>
<li>The blockers&#x2013;those tasks you can&apos;t get done because someone who isn&apos;t you has to do something first, and</li>
<li>Your schedule for the day so people know to get at you when you&apos;re free.</li>
</ol>
<p>Daily stand ups are super useful, but I&apos;m not about to sit down every morning and re-type my to-do list for my team. That&apos;s not a good use of my time. You already know where this is going... When we were doing chat stand ups, I wrote a <a href="https://routinehub.co/shortcut/1495" target="_blank">shortcut</a> to do it for me, and published it to RoutineHub in case anybody else wanted to use it. It saved me a bunch of time. It stores the previous day&apos;s standup to iCloud drive, and uses that as the starting point for &quot;Yesterday&apos;s&quot; tasks. It also integrates with your &quot;Work&quot; Reminders list and pre-populates with pertinent tasks.</p>
<p><img class="callout" src="/images/shortcuts/im-featured.jpeg" title="Daily" standup in the shortcuts gallery> That&apos;s cool and all, but the reason for this post is because I just stumbled across a &quot;Daily Standup&quot; shortcut in Apple&apos;s Shortcuts gallery&#x2013;its looks to be a stripped down version of the shortcut I posted to RoutineHub&#x2013;the structure and variable names are similar. It even uses the same icon.</p>
<p><img src="/images/shortcuts/lz-vs-apple.jpeg" alt>
<strong>Above:</strong> My shortcut on the right, Apple&apos;s on the left. My version is a little smarter about preceding <code>-</code> characters for each line item. Apple removed that logic, and puts a <code>-</code> in front of each line without exception.</p>
<p>To be clear, I think this is dope. I shared the shortcut in the spirit of helping people save time, and I am happy to see Apple pick it up and elevate it to a level I couldn&apos;t on my own. A little credit wouldn&apos;t hurt tho...</p>
<p><img src="/images/shortcuts/im-featured-fixed.jpeg" alt></p>
<p>There... I fixed it &#x1F602;.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/apple-features-daily-standup</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/apple-features-daily-standup</guid>
            <category><![CDATA[apple shortcuts]]></category>
            <category><![CDATA[portfolio]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Sat, 25 Jul 2020 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[My First Website]]></title>
            <description><![CDATA[<p>Like a lot of people my age, I went through a Pok&#xE9;mon phase. Arguably,  it&apos;s not over. Just last year, I caught all 150 from the Nintendo Switch remake of Red/Blue: Pok&#xE9;mon Let&apos;s go Eevee.</p>
<p>Rewind to the Windows 98 days, child Luke built a Pok&#xE9;mon site using Microsoft Publisher. All I did was compile lots of links and pictures of Pok&#xE9;mon from all over the internet, and with my Dad&apos;s help, got it hosted.</p>
<p>One of my biggest regrets in life is not putting Google Ads on this site. Over the years it has accumulated millions of hits from Pok&#xE9;mon fans everywhere.</p>
<p>I recently moved the site from its original domain to host it under lukezilioli.com, so that it can live for eternity. </p>
<p>Find it <a href="https://pokemon.lukezilioli.com" target="_blank">here</a>.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/pokemon</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/pokemon</guid>
            <category><![CDATA[web dev]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Mon, 06 Jul 2020 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[My iOS 15 and macOS 12 Wish List]]></title>
            <description><![CDATA[<h1 id="lukes-apple-wishlist"><a href="#lukes-apple-wishlist">Luke&apos;s Apple Wishlist<i class="icon-link"></i></a></h1>
<blockquote>
<p><strong>Update 2025:</strong> This wishlist is now outdated! I&apos;ve created a live, continuously updated version at <a href="https://apple.lukezilioli.com/wishlist/" target="_blank">apple.lukezilioli.com/wishlist</a>. Check out my blog post about <a href="/blog/post/apple-wishlist-website">Apple Wishlist Website is Live</a> for more details.</p>
</blockquote>
<p>I am a heavy user of my iPhone, iPad, MacBook, all of that. I push &apos;em to their limits. As such, I find myself wishing Apple would add a lot of new features.</p>
<p>For the last few years, I&apos;ve kept a running list in my Notes app of things I wanna see Apple add. This year I&apos;m publishing that list. I&apos;ve updated it by moving stuff added this year in iOS 14 into the &quot;Completed&quot; section. That&apos;s why the list is called iOS 15 and macOS 12 Wish List&#x2013;this stuff&apos;s gonna have to wait &apos;till next year.</p>
<p>This list is only gonna grow once I get my hands on this year&apos;s betas. I&apos;m not sure if imma update this post as I think of new ideas, or do another post with new ideas.</p>
<p>If you&apos;re interested in seeing everything Apple <em>did</em> announce this year, there&apos;s a <a href="/blog/post/apple-wwdc-2020">post for that</a>.</p>
<h1 id="table-of-contents"><a href="#table-of-contents">Table of Contents<i class="icon-link"></i></a></h1>
<ul>
<li><a href="#lukes-apple-wishlist">Luke&apos;s Apple Wishlist</a></li>
<li><a href="#platforms">Platforms</a><ul>
<li><a href="#i-phone">iPhone</a></li>
<li><a href="#i-pad">iPad</a></li>
<li><a href="#i-phone-i-pad">iPhone &amp; iPad</a></li>
<li><a href="#mac-os">macOS</a></li>
<li><a href="#apple-tv">AppleTV</a></li>
<li><a href="#apple-watch">Apple Watch</a></li>
<li><a href="#air-pods">AirPods</a></li>
<li><a href="#continuity">Continuity</a></li>
<li><a href="#apps-services">Apps &amp; Services</a><ul>
<li><a href="#files-app">Files App</a></li>
<li><a href="#apple-card">Apple Card</a></li>
<li><a href="#shortcuts">Shortcuts</a></li>
<li><a href="#music">Music</a></li>
<li><a href="#tv">TV</a></li>
<li><a href="#home">Home</a></li>
<li><a href="#notes">Notes</a></li>
<li><a href="#voice-memos">Voice Memos</a></li>
<li><a href="#reminders">Reminders</a></li>
<li><a href="#settings">Settings</a></li>
<li><a href="#app-store">App Store</a></li>
<li><a href="#calendar">Calendar</a></li>
<li><a href="#mail">Mail</a></li>
<li><a href="#i-message">iMessage</a></li>
<li><a href="#photos">Photos</a></li>
</ul>
</li>
<li><a href="#misc">Misc.</a></li>
</ul>
</li>
<li><a href="#completed">Completed</a><ul>
<li><a href="#i-os-14">iOS 14</a></li>
<li><a href="#i-os-13-and-earlier">iOS 13 and Earlier</a></li>
</ul>
</li>
</ul>
<h1 id="platforms"><a href="#platforms">Platforms<i class="icon-link"></i></a></h1>
<h2 id="iphone"><a href="#iphone">iPhone<i class="icon-link"></i></a></h2>
<ul>
<li><input disabled type="checkbox"> The current audio player in Messages and Files is trash</li>
<li><input disabled type="checkbox"> Paste button on keyboard</li>
<li><input disabled type="checkbox"> More icons in dock</li>
<li><input disabled type="checkbox"> Split View</li>
<li><input disabled type="checkbox"> Apple Pencil support</li>
</ul>
<h2 id="ipad"><a href="#ipad">iPad<i class="icon-link"></i></a></h2>
<ul>
<li><input disabled type="checkbox"> HDMI display mode for iPad Pro to be used as as external monitor for any device&#x2013;this would be so dope for playing Switch or PlayStation with friends on the go.</li>
</ul>
<h2 id="iphone--ipad"><a href="#iphone--ipad">iPhone &amp; iPad<i class="icon-link"></i></a></h2>
<ul>
<li><input disabled type="checkbox"> Ability for Apple to update native apps separate from OS so that they can release new features quicker</li>
<li><input disabled type="checkbox"> iPhone app storage under app details in Settings</li>
<li><input disabled type="checkbox"> Switch up which app pages are active based on location, time, or via a Shortcut</li>
<li><input disabled type="checkbox"> Screen sharing with FaceTime</li>
<li><input disabled type="checkbox"> Shared video watching with FaceTime</li>
<li><input disabled type="checkbox"> Find My optional in Family Sharing</li>
<li><input disabled type="checkbox"> Temporarily disable night shift while videos play</li>
<li><input disabled type="checkbox"> Change default apps<ul>
<li><input disabled type="checkbox"> Maps</li>
<li><input disabled type="checkbox"> Calendar</li>
<li><input disabled type="checkbox"> Text Editor</li>
<li><input checked disabled type="checkbox"> Browser</li>
<li><input checked disabled type="checkbox"> Mail</li>
</ul>
</li>
</ul>
<h2 id="macos"><a href="#macos">macOS<i class="icon-link"></i></a></h2>
<ul>
<li><input disabled type="checkbox"> View Live Photos in Finder&#x2013;Its inexcusable that the only way to view Live Photos is from inside of an app</li>
<li><input disabled type="checkbox"> show menubar in fullscreen apps</li>
<li><input disabled type="checkbox"> Bring back Spaces &amp; Expos&#xE9;&#x2013;Mission Control is insultingly dumbed down from what we had back in the Leopard days</li>
<li><input disabled type="checkbox"> 4x4 and more advanced full screen window support</li>
<li><input disabled type="checkbox"> TouchID finger identification when you rest a finger on the TouchId sensor in System Preferences</li>
<li><input disabled type="checkbox"> FaceID on Mac</li>
<li><input disabled type="checkbox"> Grouped notifications on MacOS</li>
<li><input disabled type="checkbox"> Magic Keyboard/Trackpad/Mouse should switch between devices with ease the same way AirPods do</li>
</ul>
<h2 id="appletv"><a href="#appletv">AppleTV<i class="icon-link"></i></a></h2>
<ul>
<li><input disabled type="checkbox"> I want to be able to plug another HDMI device into my AppleTV and picture in picture my PlayStation</li>
</ul>
<h2 id="apple-watch"><a href="#apple-watch">Apple Watch<i class="icon-link"></i></a></h2>
<ul>
<li><input disabled type="checkbox"> Change watch face based on time of day or location</li>
<li><input disabled type="checkbox"> Raise To Siri is unusable... fix it</li>
<li><input disabled type="checkbox"> Third party watch faces</li>
</ul>
<h2 id="airpods"><a href="#airpods">AirPods<i class="icon-link"></i></a></h2>
<ul>
<li><input disabled type="checkbox"> Volume control without using Siri, touching phone, or watch</li>
</ul>
<h2 id="continuity"><a href="#continuity">Continuity<i class="icon-link"></i></a></h2>
<ul>
<li><input disabled type="checkbox"> Optional phrase to specify which device should respond to a Hey Siri request&#x2013;&quot;hey Siri on Watch&quot;</li>
<li><input disabled type="checkbox"> Reminders for &quot;on my Mac&quot; or &quot;on my iPad&quot; to be reminded of a thing when you pick up a different device</li>
<li><input disabled type="checkbox"> When placing/making a phone calls, offer button to pause anything thats playing on other devices</li>
</ul>
<h2 id="apps--services"><a href="#apps--services">Apps &amp; Services<i class="icon-link"></i></a></h2>
<h3 id="files-app"><a href="#files-app">Files App<i class="icon-link"></i></a></h3>
<ul>
<li><input disabled type="checkbox"> Cleaner &quot;Open In...&quot; experience</li>
</ul>
<h3 id="apple-card"><a href="#apple-card">Apple Card<i class="icon-link"></i></a></h3>
<ul>
<li><input disabled type="checkbox"> Change Apple Card bill cycle date</li>
<li><input disabled type="checkbox"> Syncing with Quicken and Mint&#x2013;csv export ain&apos;t it</li>
</ul>
<h3 id="shortcuts"><a href="#shortcuts">Shortcuts<i class="icon-link"></i></a></h3>
<ul>
<li><input disabled type="checkbox"> Control orientation lock</li>
<li><input disabled type="checkbox"> Control all settings with shortcuts. Such as keyboard click, etc.</li>
<li><input disabled type="checkbox"> Allow user-created Shortcuts to parameterize inputs just like app Shortcuts can</li>
<li><input disabled type="checkbox"> Shortcut bundles that embed referenced Shortcuts so that we can share complex Shortcuts that call one another without requiring users to install multiple Shortcuts</li>
<li><input disabled type="checkbox"> Multiple speaker destinations from AirPlay action</li>
<li><input disabled type="checkbox"> Handoff between all AirPlay 2 devices&#x2013;this is restricted to HomePods and AppleTV&#x2019;s</li>
<li><input disabled type="checkbox"> Wait fractions of seconds in the Shortcuts wait action</li>
<li><input disabled type="checkbox"> Music action to fetch a list of all of the user&apos;s Music playlists</li>
<li><input disabled type="checkbox"> OCR from a Shortcuts action</li>
<li><input disabled type="checkbox"> NFC from a Shortcuts action</li>
<li><input disabled type="checkbox"> NFC invoked Shortcuts should receive encoded tag data as input</li>
<li><input disabled type="checkbox"> Native support for prettier menus in Shortcuts</li>
<li><input disabled type="checkbox"> Message to existing threads via Shortcut</li>
<li><input disabled type="checkbox"> Collapsible control flow in Shortcuts</li>
<li><input disabled type="checkbox"> Switch blocks in Shortcuts that behave like Menus but switch on a variable</li>
<li><input disabled type="checkbox"> Persistent Shortcut data&#x2013;like DataJar</li>
<li><input disabled type="checkbox"> Delete Shortcut permissions for apps whose actions are no longer in use within the Shortcut</li>
<li><input disabled type="checkbox"> Multi-window support for Shortcuts app</li>
<li><input disabled type="checkbox"> Unlock device rotation via Shortcut</li>
<li><input disabled type="checkbox"> While loop</li>
<li><input disabled type="checkbox"> Shortcut version history</li>
<li><input disabled type="checkbox"> Play ambient sounds via Shortcut</li>
<li><input disabled type="checkbox"> Contextual shortcuts. When I launch an app let me prompt at the top of the ui without disrupting the user.</li>
<li><input disabled type="checkbox"> Full access to iCloud Drive from Shortcuts, including the ability to list and iterate over files</li>
<li><input disabled type="checkbox"> Functions/subroutines</li>
<li><input disabled type="checkbox"> Read and modify file tags</li>
<li><input disabled type="checkbox"> Query Notes by folder</li>
<li><input disabled type="checkbox"> Run Shortcuts on an interval&#x2013;shoutout to <a href="https://apps.apple.com/us/app/pushcut-shortcuts-automation/id1450936447" target="_blank">Pushcut</a> for enabling this today</li>
<li><input disabled type="checkbox"> User-defined smart folders</li>
</ul>
<h3 id="music"><a href="#music">Music<i class="icon-link"></i></a></h3>
<ul>
<li><input disabled type="checkbox"> UI for rating single song sucks</li>
<li><input disabled type="checkbox"> Spotify like cross platform music control</li>
<li><input disabled type="checkbox"> Offer to resume Music after a meeting ends</li>
<li><input disabled type="checkbox"> Sync ALL Smart Playlists with macOS&#x2013;smart playlists that reference other smart playlists do not sync today<ul>
<li><input disabled type="checkbox"> ability to modify Smart Playlists on iOS</li>
</ul>
</li>
<li><input disabled type="checkbox"> Drag and drop and multi-select in Music app</li>
</ul>
<h3 id="tv"><a href="#tv">TV<i class="icon-link"></i></a></h3>
<ul>
<li><input disabled type="checkbox"> Keep AppleTV paired with AirPlay2 device after sleep/wake</li>
<li><input disabled type="checkbox"> allow Plex to surface user&apos;s own content in TV app</li>
<li><input disabled type="checkbox"> Sling and Philo in TV app</li>
<li><input disabled type="checkbox"> Netflix in TV app</li>
<li><input disabled type="checkbox"> Season 2 of Defending Jacob</li>
</ul>
<h3 id="home"><a href="#home">Home<i class="icon-link"></i></a></h3>
<ul>
<li><input disabled type="checkbox"> Home app wallpaper sync across devices</li>
<li><input disabled type="checkbox"> Device-specific permissions in the Home app</li>
</ul>
<h3 id="notes"><a href="#notes">Notes<i class="icon-link"></i></a></h3>
<ul>
<li><input disabled type="checkbox"> Ability to put lock notes that contain pdf and audio file attachments</li>
<li><input disabled type="checkbox"> User-defined smart folders synced with macOS</li>
</ul>
<h3 id="voice-memos"><a href="#voice-memos">Voice Memos<i class="icon-link"></i></a></h3>
<ul>
<li><input disabled type="checkbox"> Convert my voice memo to text</li>
</ul>
<h3 id="reminders"><a href="#reminders">Reminders<i class="icon-link"></i></a></h3>
<ul>
<li><input disabled type="checkbox"> <strong>Save any notification as a Reminder</strong></li>
<li><input disabled type="checkbox"> Calendar view in reminders app so you can drag to change the due date of a reminder</li>
<li><input disabled type="checkbox"> User-defined smart lists synced with macOS</li>
</ul>
<h3 id="settings"><a href="#settings">Settings<i class="icon-link"></i></a></h3>
<ul>
<li><input checked disabled type="checkbox"> Sound profiles&#x2013;home, work, switch based on location&#x2013;I guess we can do this with Shortcuts at this point, but an optimized UI would be nice</li>
<li><input disabled type="checkbox"> WiFi network preferred order</li>
</ul>
<h3 id="app-store"><a href="#app-store">App Store<i class="icon-link"></i></a></h3>
<ul>
<li><input disabled type="checkbox"> Why is it so hard to see the price of purchased apps...?</li>
<li><input disabled type="checkbox"> Specify what device to download an app to</li>
<li><input disabled type="checkbox"> Wish List</li>
</ul>
<h3 id="calendar"><a href="#calendar">Calendar<i class="icon-link"></i></a></h3>
<ul>
<li><input disabled type="checkbox"> easy alarm setting like Calvetica used to have</li>
<li><input disabled type="checkbox"> Copy and paste events</li>
<li><input disabled type="checkbox"> Improved drag and drop support (drag to change calendar)</li>
</ul>
<h3 id="mail"><a href="#mail">Mail<i class="icon-link"></i></a></h3>
<ul>
<li><input disabled type="checkbox"> Sync macOS user-defined smart folders with iOS<ul>
<li><input disabled type="checkbox"> ability to change smart folders on iOS</li>
</ul>
</li>
<li><input disabled type="checkbox"> Gmail-like message snoozing</li>
</ul>
<h3 id="imessage"><a href="#imessage">iMessage<i class="icon-link"></i></a></h3>
<ul>
<li><input disabled type="checkbox"> Mark as unread</li>
<li><input disabled type="checkbox"> Schedule messages</li>
<li><input disabled type="checkbox"> Arrow key support when choosing who to send a message to</li>
<li><input disabled type="checkbox"> Bubble unreads to the top</li>
</ul>
<h3 id="photos"><a href="#photos">Photos<i class="icon-link"></i></a></h3>
<ul>
<li><input disabled type="checkbox"> Sync smart albums from macOS to iOS<ul>
<li><input disabled type="checkbox"> Ability to modify smart albums on iOS</li>
</ul>
</li>
<li><input disabled type="checkbox"> Hide hidden photos album behind FaceID/TouchID</li>
<li><input disabled type="checkbox"> I want a single Photos Library with a subset synced to iCloud&#x2013;when I export a photo from the Photos app, it should keep the live, burst, and other Apple-specific features&#x2013;the fact that it doesn&apos;t forces me to keep paying for iCloud storage to preserve my memories. It is monopolistic of Apple to force me to pay for iCloud storage in order to to enjoy my photographs.</li>
</ul>
<h2 id="misc"><a href="#misc">Misc.<i class="icon-link"></i></a></h2>
<ul>
<li><input disabled type="checkbox"> A true 1Password competitor</li>
<li><input disabled type="checkbox"> <a href="https://www.sublimetext.com#multiple-selections" target="_blank">Sublime Text&apos;s multiple selections feature</a> system-wide</li>
<li><input disabled type="checkbox"> Ask Siri to complete multiple commands at once</li>
<li><input disabled type="checkbox"> Dark and light shading of alarms based on a.m. or p.m. in Clock app</li>
<li><input disabled type="checkbox"> Improved PDF annotation in iBooks</li>
<li><input disabled type="checkbox"> Contact photo in contact list of Contacts app</li>
</ul>
<h1 id="completed"><a href="#completed">Completed<i class="icon-link"></i></a></h1>
<h2 id="ios-14"><a href="#ios-14">iOS 14<i class="icon-link"></i></a></h2>
<ul>
<li><input checked disabled type="checkbox"> Home screen widgets</li>
<li><input checked disabled type="checkbox"> Privacy considerations around apps reading the clipboard</li>
<li><input checked disabled type="checkbox"> Folders in the Shortcuts app</li>
<li><input checked disabled type="checkbox"> Less-intrusive Siri and background requests</li>
<li><input checked disabled type="checkbox"> Turn off lights/tv when I fall asleep</li>
<li><input checked disabled type="checkbox"> Threaded conversations in iMessage</li>
<li><input checked disabled type="checkbox"> Mentions in iMessage</li>
<li><input checked disabled type="checkbox"> iMessage group photos</li>
<li><input checked disabled type="checkbox"> Allow users to backup and restore Shortcuts from files&#x2013;not just iCloud links (this worked in iOS 12, but not 13. They are adding it back in 14)</li>
</ul>
<h2 id="ios-13-and-earlier"><a href="#ios-13-and-earlier">iOS 13 and Earlier<i class="icon-link"></i></a></h2>
<ul>
<li><input checked disabled type="checkbox"> iCloud Keychain password management on iOS</li>
<li><input checked disabled type="checkbox"> Access macOS shared files from iOS</li>
<li><input checked disabled type="checkbox"> Night Shift on macOS</li>
<li><input checked disabled type="checkbox"> Native screen sharing support with Mac on iPad (SideCar)</li>
<li><input checked disabled type="checkbox"> Dark mode on iOS</li>
<li><input checked disabled type="checkbox"> Multiple windows of the <strong>same</strong> app open side by side</li>
<li><input checked disabled type="checkbox"> Multiple timers on HomePod</li>
<li><input checked disabled type="checkbox"> Amazon prime in TV app</li>
<li><input checked disabled type="checkbox"> Now playing across all devices in a single interface</li>
<li><input checked disabled type="checkbox"> Better ui for notification settings</li>
<li><input checked disabled type="checkbox"> Color coded Reminders lists</li>
<li><input checked disabled type="checkbox"> Don&#x2019;t pause music while dictating or talking to Siri through headphones, bluetooth speaker or AirPlay</li>
<li><input checked disabled type="checkbox"> Allow third-party provided Shortcuts take input/receive output</li>
<li><input checked disabled type="checkbox"> Send an email to all members of a contact group</li>
<li><input checked disabled type="checkbox"> True file downloads in Safari on iOS</li>
<li><input checked disabled type="checkbox"> Maps for icloud.com</li>
<li><input checked disabled type="checkbox"> Jump to album, artist, from song in Music app</li>
<li><input checked disabled type="checkbox"> WiFi and Bluetooth settings in control center</li>
<li><input checked disabled type="checkbox"> Quicker event entry in Calendar app</li>
<li><input checked disabled type="checkbox"> Home automation integration, start playing when I get home</li>
<li><input checked disabled type="checkbox"> Annotate PDFs from Files or iBooks</li>
<li><input checked disabled type="checkbox"> Open whole folder from Files app in another App</li>
<li><input checked disabled type="checkbox"> iMessage<ul>
<li><input checked disabled type="checkbox"> TimeStamps</li>
<li><input checked disabled type="checkbox"> Quick Reply</li>
<li><input checked disabled type="checkbox"> Proper Color button when messaging from API</li>
<li><input checked disabled type="checkbox"> Avatars</li>
<li><input checked disabled type="checkbox"> Extract 2 factor auth codes from sms</li>
</ul>
</li>
</ul>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/apple-2021-wishlist</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/apple-2021-wishlist</guid>
            <category><![CDATA[apple]]></category>
            <category><![CDATA[apple wishlist]]></category>
            <category><![CDATA[iOS]]></category>
            <category><![CDATA[macOS]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Mon, 29 Jun 2020 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Apple WWDC 2020 - iOS 14 & Big Sur]]></title>
            <description><![CDATA[<h1 id="table-of-contents"><a href="#table-of-contents">Table of Contents<i class="icon-link"></i></a></h1>
<ul>
<li><a href="#black-lives-matter">Black Lives Matter</a></li>
<li><a href="#announcements">Announcements</a><ul>
<li><a href="#misc">Misc.</a></li>
</ul>
</li>
<li><a href="#voice-memos">Voice Memos</a></li>
<li><a href="#apple-music">Apple Music</a></li>
<li><a href="#notes-reminders">Notes &amp; Reminders</a><ul>
<li><a href="#home-screen-app-library">Home Screen &amp; App Library</a></li>
<li><a href="#home-screen-widgets">Home Screen Widgets</a></li>
<li><a href="#siri-changes">Siri changes</a></li>
<li><a href="#translation">Translation</a></li>
<li><a href="#messages">Messages</a></li>
<li><a href="#maps">Maps</a></li>
<li><a href="#car-play">CarPlay</a></li>
<li><a href="#car-key">CarKey</a></li>
<li><a href="#app-clips">App Clips</a></li>
<li><a href="#i-pad-os-14">iPadOS 14</a></li>
<li><a href="#apple-pencil">Apple Pencil</a><ul>
<li><a href="#scribble">Scribble</a></li>
</ul>
</li>
<li><a href="#air-pods">AirPods</a></li>
<li><a href="#watch-os-7">watchOS 7</a><ul>
<li><a href="#sleep-tracking">Sleep Tracking</a></li>
</ul>
</li>
<li><a href="#privacy">Privacy</a></li>
<li><a href="#home">Home</a></li>
<li><a href="#apple-tv">AppleTV</a></li>
<li><a href="#safari">Safari</a></li>
<li><a href="#mac-os-big-sur">MacOS Big Sur</a></li>
<li><a href="#transition-to-arm">Transition to ARM</a><ul>
<li><a href="#how-does-this-benefit-users">How does this benefit users?</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#device-compatibility">Device Compatibility</a></li>
<li><a href="#updates">Updates</a><ul>
<li><a href="#control-center">Control Center</a></li>
<li><a href="#shortcuts">Shortcuts</a></li>
</ul>
</li>
</ul>
<h1 id="black-lives-matter"><a href="#black-lives-matter">Black Lives Matter<i class="icon-link"></i></a></h1>
<p>Apple covered this topic at the forefront of the event, and for good reason. I gotta say it here as well. <strong>Black Lives Matter! &#x1F5E3;</strong></p>
<p>If you&apos;re white, you probably <strong>believe</strong> that you <strong>embody</strong> the idea of Black Lives Matter. Thats a <em>start</em>.</p>
<p>I&apos;d put money that <strong>unconsciously</strong>, you still contribute to making a Black person have a shitty day somewhere in America. In part, The Black Lives Matter movement is about making those <strong>unconscious</strong> acts of racism <strong>conscious</strong> (to you). Only then (and after we <a href="https://youtu.be/8ebWFnGWOaA" target="_blank">abolish the police</a>, and reform our justice system) can <strong>everyone</strong> walk around our society as comfortable as you always have. If you&apos;re white, shut the hell up, let go of your ego, listen to Black people (by reading what they have written, not by asking the nearest Black person to speak for all of Black America), challenge yourself and other whites around you to embrace Black perspectives, and have a nice day.</p>
<h1 id="announcements"><a href="#announcements">Announcements<i class="icon-link"></i></a></h1>
<p>Apple announced <em>a lot</em> on Monday, in their first ever streaming-only <a href="https://www.apple.com/apple-events/june-2020/" target="_blank">WWDC keynote</a>, a brand new format brought to you by the coronavirus.</p>
<p>Below you&apos;ll find an outline of a lot of the stuff that Apple announced related to iOS 14, iPadOS 14, tvOS 14, watchOS 7, AirPods, macOS Big Sur, and the transition from Intel chips to Apple&apos;s own ARM-based silicon. Apple has <a href="https://www.apple.com/ios/ios-14-preview/features/" target="_blank">their own version of this list</a>. I guarantee you that I missed some things, more details will emerge, and features will be added and dropped before these updates are available in the Fall.</p>
<p>My thoughts are included below <em>in itallics</em>. I try to link out to relevant articles or discussions where applicable.</p>
<p>Curious to see what features I want to see Apple to introduce, but that didn&apos;t make the cut this year? Check out my <a href="/blog/post/apple-2021-wishlist">Apple Wishlist</a>.</p>
<h2 id="misc"><a href="#misc">Misc.<i class="icon-link"></i></a></h2>
<ul>
<li>Third-party apps can tap into the <a href="https://www.theverge.com/2020/6/22/21299712/apple-find-my-iphone-network-third-party-devices-support-location-tracking" target="_blank">Find My app interface</a><ul>
<li><em>Apple is smart to do this before announcing their own trackers. This will lull complaints of anti-trust behaviors coming from companies like Tile.</em></li>
<li><em>I wonder if this extends to the Find My offline finding ability</em> update: <a href="https://www.theverge.com/2020/6/22/21299712/apple-find-my-iphone-network-third-party-devices-support-location-tracking" target="_blank">it does</a></li>
</ul>
</li>
<li>Severe weather tracking and real-time precipitation in Weather app<ul>
<li><em>Likely from their Dark Sky purchase</em></li>
</ul>
</li>
<li>Search is revamped<ul>
<li>On iPad, it doesn&apos;t take over the full screen. Like spotlight on Mac</li>
<li>&quot;Universal search&quot; &#x2013; intended to be the starting point for all searches<ul>
<li><em>I thought this was always their goal with search on iOS but arite...</em></li>
</ul>
</li>
</ul>
</li>
<li>Phone calls don&apos;t take over the full screen anymore</li>
<li>Picture-in-picture on iPhone<ul>
<li>If you leave the app while watching a video, you get a video window floating above everything else. Works like picture-in-picture on iPad today.</li>
<li><em>I really want to see a full-out split view feature on iPhone. Looks like we will have to wait another year.</em></li>
</ul>
</li>
<li><a href="https://appleinsider.com/articles/20/06/22/homepod-to-support-third-party-music-streaming-services" target="_blank">HomePod works with Spotify and other music services</a></li>
<li>Set default email and browser apps</li>
<li>Redesigned photo and video picker</li>
<li>One for developers, they will be able to <a href="https://9to5mac.com/2020/06/22/apple-wwdc-dev-tools-challenge-app-guidelines/" target="_blank">formally challenge their app store rejections</a></li>
<li>If the developer enables it, family sharing groups can share app subscriptions</li>
<li><a href="https://appleinsider.com/articles/20/06/22/facetime-eye-contact-correction-feature-to-launch-with-ios-14" target="_blank">FaceTime eye correction</a>. When you look at the screen, it&apos;ll make it look like you are looking at the camera.<ul>
<li><em>This was from the iOS 13 beta, but got dropped</em></li>
</ul>
</li>
<li><a href="https://9to5mac.com/2020/06/22/ios-14-apple-emoji-search/" target="_blank">Emoji search in the keyboard</a><ul>
<li><em>So you can type words while you avoid typing words to send an emoji</em></li>
</ul>
</li>
<li>Revamped Podcasts app with curated suggestions</li>
<li><a href="https://appleinsider.com/articles/20/06/23/control-iphone-with-new-back-tap-ios-14-accessibility-feature" target="_blank">Back Tap accessibility setting</a>&#x2013;you can trigger an action (any shortcut!) by double tapping the back of your iPhone or iPad</li>
<li>All iPhone models now feature quick toggles to change video resolution and frame rate in Video mode.</li>
<li>A new option allows you to capture burst photos by pressing the Volume Up button, and QuickTake video can be captured on supported devices using the Volume Down button.</li>
<li>A new option in Settings lets you capture mirrored selfies, which reflect the front camera preview.</li>
<li>The Files app supports external drives using APFS encryption. Simply enter the password to access the content of the drive.</li>
<li>Contacts autofill in third party apps<ul>
<li><em>should reduce the number of times you have to give an app contact access just to pick a single contact</em></li>
</ul>
</li>
<li>Time Machine now supports APFS drives</li>
<li><a href="https://twitter.com/simonbs/status/1275188237158490112?s=21" target="_blank">Long press back button to view navigation stack</a></li>
<li><a href="https://twitter.com/simonbs/status/1276875469707784192?s=21" target="_blank">In app intent handling</a><ul>
<li>Android has <em>always</em> had this feature. Recent additions to iOS have made it painfully necessary. What this means is that your apps won&apos;t have to jump around between different apps to get things done as much. This was extra painful for Shortcuts.</li>
</ul>
</li>
</ul>
<h1 id="voice-memos"><a href="#voice-memos">Voice Memos<i class="icon-link"></i></a></h1>
<ul>
<li>Mark some voice memos as favorites</li>
<li>Enhanced recording setting</li>
<li>Folders and smart folders</li>
</ul>
<h1 id="apple-music"><a href="#apple-music">Apple Music<i class="icon-link"></i></a></h1>
<ul>
<li>Listen now tab</li>
<li>Endless Autoplay when Apple Music reaches the end of a playlist</li>
<li>Overhauled sidebar on iPad</li>
<li>New search experience</li>
<li>Multi-window support for Music on iPad</li>
</ul>
<h1 id="notes--reminders"><a href="#notes--reminders">Notes &amp; Reminders<i class="icon-link"></i></a></h1>
<p><a href="https://www.macstories.net/stories/everything-changing-in-apple-notes-and-reminders-in-ios-and-ipados-14/" target="_blank">Good overview</a>.</p>
<ul>
<li>No more texture in Notes</li>
<li>Better scan quality</li>
<li>Collapse pinned notes</li>
<li>Redesigned actions menu in Notes</li>
<li>&quot;Send a Copy&quot; action in Notes that exports your notes to other apps, in other formats</li>
<li>Touch and hold Aa button to quickly change section styling</li>
<li>Assign Reminders to other people</li>
<li>New date picker for Calendars and Reminders<ul>
<li><img src="https://2672686a4cf38e8c2458-2712e00ea34e3076747650c92426bbb5.ssl.cf1.rackcdn.com/212FC761-14F3-47E5-901A-ADC06F1B438A-1593016248157.png" alt></li>
</ul>
</li>
</ul>
<h2 id="home-screen--app-library"><a href="#home-screen--app-library">Home Screen &amp; App Library<i class="icon-link"></i></a></h2>
<ul>
<li>You can hide entire pages of the home screen... cuz Apple knows none of us ever touch page 2, 3, 4...</li>
<li>The last page becomes &quot;App Library&quot;<ul>
<li>Broken down by category automatically</li>
<li>Has &quot;Suggestions&quot; section with most relevant apps</li>
<li>Can launch top 3 apps from each category or tap to view all apps in the category</li>
<li><em>I would like the ability to organize what categories appear in App Library, and which app falls into which category. It seems like Apple could let us put our own folders into this section, rather than using Apple&apos;s pre-determined categories.</em></li>
</ul>
</li>
<li>Settings for if new app downloads show up on an app page, or in the App Library</li>
</ul>
<p><img src="/images/wwdc-2020/app-library.jpg" alt></p>
<h2 id="home-screen-widgets"><a href="#home-screen-widgets">Home Screen Widgets<i class="icon-link"></i></a></h2>
<ul>
<li>You can drag widgets out of today view onto the home screen</li>
<li>Widgets live along-side app icons on your home screen.<ul>
<li><em>We been waiting on this for a minuteeeee</em></li>
</ul>
</li>
<li>&#x202A;Widgets come in different sizes. Some are 2x2 app icons big, some are 2x4, 4x4, etc.</li>
<li>Special widget called &quot;Smart stack&quot;<ul>
<li>You can swipe between widgets at will, the OS will sort them based on what it thinks you might care about at that moment</li>
<li><em>This seems like the siri watch face, but on the iPhone home screen</em></li>
</ul>
</li>
<li>In wiggle mode, you can also add widgets, and browse all available widgets for a given app by pressing a <code>+</code> button in the top-left corner of the screen.</li>
<li><em>I would like to be able to put a watch face on my iPhone home screen as a widget</em></li>
</ul>
<p><img src="/images/wwdc-2020/widgets.jpg" alt></p>
<h2 id="siri-changes"><a href="#siri-changes">Siri changes<i class="icon-link"></i></a></h2>
<ul>
<li>No longer takes over the whole screen!<ul>
<li>Great for if you wanna reference something on the screen while using Siri, to tell Siri to dial a non-clickable phone number or something like that.</li>
</ul>
</li>
<li>If you ask for stuff like Weather, it shows up at the top of the screen, like a notification.</li>
<li>&#x202A;You can ask Siri to send audio messages&#x202C;</li>
<li>&#x202A;Voice dictation is run on the device instead of in the cloud. No internet connection required&#x202C;.</li>
<li>&quot;Siri is getting smarter every day&quot;<ul>
<li>20x more facts than 3 years ago</li>
<li>Can answer stuff like &quot;how do hybrid cars work&quot;<ul>
<li><em>I&apos;ll believe it when I see it. Siri was better at complex queries when she dropped in 2010 or whenever it was.</em></li>
</ul>
</li>
</ul>
</li>
</ul>
<p><img src="/images/wwdc-2020/siri.jpg" alt></p>
<h2 id="translation"><a href="#translation">Translation<i class="icon-link"></i></a></h2>
<ul>
<li>&#x202A;New app called &quot;Translate&quot;<ul>
<li><a href="https://9to5mac.com/2020/06/22/hands-on-with-the-new-built-in-translate-app-on-ios-14/" target="_blank">9to5mac hands on</a></li>
</ul>
</li>
<li>Help facilitate conversation across languages</li>
<li>Works offline</li>
<li>Can translate text and voice conversations between 11 languages</li>
<li><a href="https://9to5mac.com/2020/06/22/hands-on-with-the-new-built-in-translate-app-on-ios-14/" target="_blank">9to5mac hands-on</a></li>
</ul>
<h2 id="messages"><a href="#messages">Messages<i class="icon-link"></i></a></h2>
<ul>
<li>You can pin conversations to the top of the list so you don&apos;t miss messages from people you care about&#x202C;</li>
<li>Memoji updates<ul>
<li>Memoji have face masks now... very necessary...<ul>
<li><em>People are gonna use this more than they use masks in real life</em></li>
</ul>
</li>
<li>20 new Memoji hair styles</li>
</ul>
</li>
<li>&#x202A;You can mention people in messages... just type their name<ul>
<li>Setting for group conversation to <strong>only be notified when mentioned</strong></li>
</ul>
</li>
<li>You can reply to a specific message, and view replies in the conversation, or in their own thread.<ul>
<li><em>I want to see this in action. Slack does a <strong>terrible</strong> job at this and I&apos;m looking forward to seeing how Apple handles it.</em></li>
</ul>
</li>
<li>New display at top of group<ul>
<li>Custom group photo</li>
<li>Latest person to send a message has biggest picture</li>
</ul>
</li>
</ul>
<h2 id="maps"><a href="#maps">Maps<i class="icon-link"></i></a></h2>
<ul>
<li>Will <a href="https://appleinsider.com/articles/20/06/22/apple-maps-will-help-drivers-avoid-speed-and-traffic-cameras-in-ios-14" target="_blank">warn you about speed traps and traffic cameras</a>.</li>
<li>Apple has finished rolling out the new maps designs from last year to all of the U.S.<ul>
<li>More countries coming this year</li>
</ul>
</li>
<li>&quot;The worlds most trusted brands&quot; can create guides of places to check out<ul>
<li><em>They need to make this a feature that <strong>any</strong> user can create, share and <strong>monetize</strong>. This is another place Apple could have a direct impact on diversity. Are Black-owned and hole-in-the wall spots gonna be featured in these places from &quot;trusted brands&quot;? No need for Apple to be a gatekeeper of this feature when user reviews could do the job.</em></li>
<li><strong>Update:</strong> it seems like it <em>will</em> be possible for users to make and share their own guides, but it will likely be difficult to get them the same level of exposure as guides from &quot;trusted brands&quot;</li>
</ul>
</li>
<li>Cycling directions, will tell you what your route will be like<ul>
<li>Includes cycling paths (duh)</li>
<li>Elevation</li>
<li>Quiet or busy roads</li>
<li>If you will need to carry your bike up stairs<ul>
<li>Can choose to avoid stairs</li>
</ul>
</li>
<li>NY, LA, SF, cities in China<ul>
<li><em>They won&apos;t have Detroit for <strong>years</strong> &#x1F644;</em></li>
</ul>
</li>
</ul>
</li>
<li>Directions to electric charging vehicle stations, with knowledge of what stations work for what brands of cars</li>
<li>Congestion-based navigation. Tells you if it&apos;s too busy to go somewhere. Limited to very few cities.</li>
</ul>
<h2 id="carplay"><a href="#carplay">CarPlay<i class="icon-link"></i></a></h2>
<ul>
<li>Wallpapers in CarPlay</li>
<li>New app categories (parking, car charging, food ordering)</li>
</ul>
<h2 id="carkey"><a href="#carkey">CarKey<i class="icon-link"></i></a></h2>
<ul>
<li>Lets you unlock and start your car with your phone.<ul>
<li><em>This shit sweet but first car w it is BMW so it&apos;ll be FOREVER until its a regular degular feature. I still dont have CarPlay in my car... This is the worst part about CarPlay.&#x202C;</em></li>
<li>Apple has worked with an open industry-wide committee to support this in all cars, so support for this should be coming to new cars soon.<ul>
<li><em>The question is, are asshole car manufacturers gonna up-charge for access to the feature?</em></li>
</ul>
</li>
</ul>
</li>
<li>You can text a key to someone with rules about how fast they can drive, when they can use the car, etc.<ul>
<li><em>If you spend thousands more for a car that supports this, you can save hundreds on physical copies of your car key.</em></li>
<li><em>I want to see this supported at the OS level for smart locks in the Home app too... why is it limited to cars?</em></li>
</ul>
</li>
<li>Coming to iOS 13.6 sooner than later</li>
</ul>
<h2 id="app-clips"><a href="#app-clips">App Clips<i class="icon-link"></i></a></h2>
<ul>
<li>Sometimes you want to interact with a part of a service without downloading the full app.</li>
<li>Apple gives lots of examples in the keynote, some:<ul>
<li>Paying for parking - Hold your phone up to the meter and a ParkYourCityNameHere screen pops up for you to pay for parking. No more downloading app for a one-off trip to some random city.</li>
<li>Shared scooters - You hold your phone up and can Apple Pay to use the scooter. No account or app download required.</li>
<li>Paying at a coffee shop</li>
<li>Buying something from an Etsy link that a friend texted you</li>
<li>Ordering food from a nearby restaurant (directly from the Maps app)</li>
<li>That one friend who insists on using Venmo instead of Apple Pay</li>
</ul>
</li>
<li>Never need to use credit card numbers, because they work with Apple Pay</li>
<li>Can use Sign in With Apple</li>
<li>Won&apos;t clutter your home screen but you can still access recent App Clips</li>
<li>&#x202A;Businesses can stick these tags on the register, integrate Apple Pay, or people can quickly get info about an app.</li>
<li>Yelp can make App Clips for businesses, so individual businesses will be able to take advantage of App Clips without being developers themselves.&#x202C;</li>
</ul>
<h2 id="ipados-14"><a href="#ipados-14">iPadOS 14<i class="icon-link"></i></a></h2>
<ul>
<li>A lil history lesson: iPad apps started as iPhone apps on larger screens. People started making apps designed specifically for the iPad that were optimized for the larger screen.</li>
<li>Now, people are making iPad apps more rich and powerful.<ul>
<li><em>Basically, what Apple is saying here, without saying it is that iPad apps are catching up to Mac apps in power and quality.</em></li>
</ul>
</li>
<li>&#x202A;Photos, Notes, Files, Music, and Calendar apps  all getting a new sidebar<ul>
<li><em>The 12.9&quot; iPad Pro has had a 3rd sidebar panel for some-time, but it seems they are making it standard &amp; improved for all iPads with iPad OS 14.</em></li>
</ul>
</li>
<li>Filter and sort photos</li>
<li>Add caption to photos to add context</li>
<li>Redesigned image picker</li>
<li>A lot of apps are adding toolbars at the top of the window, letting you control sort order, etc.<ul>
<li><em>The Mac been had a lot of these features, but this is all great to see on iPad. Trackpad support makes these features feel necessary, so I am glad to see Apple adding them. This is only gonna increase how much I use my iPad.&#x202C;</em></li>
</ul>
</li>
</ul>
<h2 id="apple-pencil"><a href="#apple-pencil">Apple Pencil<i class="icon-link"></i></a></h2>
<ul>
<li>You can edit handwriting like text, with cursor, easily add more space between sections, etc.</li>
<li>Shapes will sharpen their lines if you pause at the end of drawing them so you can draw straight lines, round circles, etc.</li>
<li>Double-tap to select a word or drawing... easily change color or move it around the document</li>
<li>Handwritten phone numbers can be acted on&#x2013;place a call or whatever</li>
<li>Copy handwriting into another app and it will paste as typed text</li>
</ul>
<h3 id="scribble"><a href="#scribble">Scribble<i class="icon-link"></i></a></h3>
<ul>
<li>Whenever a cursor is active, you can write text <strong>anywhere</strong> on the screen and it will convert to typed text. Fuck a keyboard!</li>
<li>You can jump between languages</li>
<li>Tap and hold to add space between handwritten text</li>
</ul>
<h2 id="airpods"><a href="#airpods">AirPods<i class="icon-link"></i></a></h2>
<p><a href="https://appleinsider.com/articles/20/06/25/how-airpods-airpods-pro-get-even-better-with-ios-14" target="_blank">This article</a> has a great overview.</p>
<ul>
<li>Auto-switch between devices.. if you are paired with your iPhone then start a zoom call on your Mac, your AirPods will switch over.<ul>
<li><em>This is gonna save me <strong>so</strong> much frustration. It&apos;s shit like this that drives people to update all of their devices to the latest version ASAP.</em></li>
</ul>
</li>
<li>Spatial audio, 3D audio but for AirPods Pro... makes you feel like you&apos;re in a movie theater.<ul>
<li>&#x202A;They talking about how they solve that technically... they use motion data from your head combined with your device to keep the audio scene centered relative to your device&apos;s screen, even as you are moving around in physical space. Sounds crazy as shit.</li>
<li><em>Clearly this is gonna be super useful for their AR goggles...</em></li>
<li><em>I hope this works with the PS5&apos;s 3D audio feature</em></li>
</ul>
</li>
<li><a href="https://9to5mac.com/2020/06/23/ios-14-airpods-optimized-charging/" target="_blank">Optimized battery charging</a></li>
<li>Charge alerts if you should top off the battery before a meeting</li>
<li>Developers can get motion data from AirPods Pro to know how you are moving your head in space<ul>
<li><em>this is another precursor to the Goggles</em></li>
</ul>
</li>
</ul>
<h2 id="watchos-7"><a href="#watchos-7">watchOS 7<i class="icon-link"></i></a></h2>
<ul>
<li>You can now have multiple complications for a single app on the same watch face, so one app can expose multiple features on your watch face.<ul>
<li><em>Clever developers were working around this by letting you customize how each type of complication slot behaved, but it is great to see Apple adding a standard, OS-level way to do this. I&apos;m sure it will save lots of developer&apos;s time.</em></li>
</ul>
</li>
<li><a href="https://appleinsider.com/articles/20/06/24/all-the-new-faces-and-complications-coming-as-part-of-watchos-7" target="_blank">All the new faces and complications</a></li>
<li>&#x202A;New faces, one with a <a href="https://en.m.wikipedia.org/wiki/Tachymeter_(watch)" target="_blank">tachyometer</a> (a tool for measuring speed based on travel time, or distance based on speed)&#x202C;</li>
<li>Share watch faces<ul>
<li><a href="https://9to5mac.com/2020/06/24/watchos-7-apple-watch-face-sharing/" target="_blank">overview</a></li>
</ul>
</li>
<li>&#x202A;You can share a watch face with friends... this is lowkey a genius way to drive app downloads&#x202C;<ul>
<li>&#x202A;If I share a face with you and you don&apos;t have the apps, it&apos;ll prompt you to download them.</li>
<li><em>The Shortcuts app already does that but everyday users don&apos;t use Shortcuts. Watch faces is a feature with much more broad appeal.</em></li>
</ul>
</li>
<li>Redesigned interface for configuring watch faces</li>
<li>A new dance workout type<ul>
<li>&#x202A;People will say &quot;they shOulDa bEeN haD tHis&quot; but they had to solve for different types of dance styles to ensure they all get tracked properly</li>
<li>&#x202A;Apple prolly had people dancing in a lab for DAYS...</li>
<li><em>This is where Apple can put their money where their mouth is on the Black Lives Matter front. What all types of dance are supported? They make it sound like a wide range but I&apos;d be curious to see a breakdown of what dancers they measured when building the feature&#x202C;. It would not be a good feeling to try out this new feature only to discover that Apple failed to incorporate the ability to track your favorite method of dance.</em></li>
</ul>
</li>
<li>Activity app improvements<ul>
<li>Overview page, more intelligently curated</li>
<li>Renamed to &quot;Fitness&quot;</li>
</ul>
</li>
<li>Removed force touch on the watch<ul>
<li>You have to <a href="https://9to5mac.com/2020/06/23/list-view-grid-view-watch-os-7/" target="_blank">go into settings</a> to toggle between grid and list view for apps</li>
</ul>
</li>
<li><a href="https://twitter.com/mattbirchler/status/1275413795012317184" target="_blank">Faster animations</a></li>
<li>Notification on your iPhone when your watch battery is low</li>
<li>Announce messages with siri<ul>
<li><em>I don&apos;t know if this is like out loud or if this means when the watch is paired with AirPods, it will announce messages</em></li>
</ul>
</li>
</ul>
<h3 id="sleep-tracking"><a href="#sleep-tracking">Sleep Tracking<i class="icon-link"></i></a></h3>
<ul>
<li><em>This another big one. I been waiting on this for forever.</em></li>
<li>Phone has a &quot;wind down&quot; mode that dims the screen, sets alarm, and lets you specify shortcuts to quickly kick off. If you have hue lights, easy way to dim shortcuts, etc.<ul>
<li><em>This ties in with the mood-based lighting feature.</em></li>
<li><em>I am curious how this relates to Bed Time mode (a feature I find to be confusing.)</em></li>
</ul>
</li>
<li>&#x202A;Watch will remind you to charge when you get home and after you wake up so you will have charge for the day and for sleeping.<ul>
<li><em>Or they could just improve the watch&apos;s battery life. The cynic in me knows this is a way for them to get people to own two watches&#x202C;.</em></li>
</ul>
</li>
<li>&#x202A;Watch OS 7 detect hand watching and times how long you watch, it gives a countdown.<ul>
<li><em>They should do this for teeth brushing.</em></li>
</ul>
</li>
</ul>
<h2 id="privacy"><a href="#privacy">Privacy<i class="icon-link"></i></a></h2>
<ul>
<li>&#x202A;New location sharing option to share <strong>approximate</strong> instead of <strong>precise</strong> location with apps<ul>
<li>Approximate location is within 10 miles of your actual location</li>
<li><em>This is a great idea</em></li>
</ul>
</li>
<li>Mic and Camera have a recording indicator in the status bar, so you always know if either are in use.</li>
<li>App Store policy requires apps to ask you for a system-level permission before allowing them to track you with third parties.<ul>
<li><em>I assume the OS will block third party tracking if the user says no to these prompts</em></li>
</ul>
</li>
<li>&#x202A;Introducing a &quot;nutrition labels&quot;-like card in App Store listings for developers to disclose their privacy practices&#x2013;before you download an app.</li>
<li>New ability to convert existing accounts within apps to &quot;Sign in With Apple&quot; accounts<ul>
<li>They said that when Kayak added &quot;Sign in With Apple&quot;, it quickly became their most used login method.<ul>
<li><em>This makes sense to me. Its a <strong>much better</strong> option than Login With Facebook, and I think most people understand this.</em></li>
</ul>
</li>
</ul>
</li>
<li><a href="https://appleinsider.com/articles/20/06/22/safari-now-blocks-google-analytics-on-sites-new-privacy-report-feature-shows" target="_blank">Safari now blocks Google Analytics</a>.<ul>
<li><em>Good for Apple. I encourage and instruct people to do this on <a href="https://www.lukezilioli.com/privacy#on-the-whole-internet">this website&apos;s privacy page</a></em>.</li>
</ul>
</li>
<li><a href="https://appleinsider.com/articles/20/06/24/apple-fine-tunes-photos-privacy-in-ios-14-to-tailor-access-to-specific-images" target="_blank">New Privacy settings for Photo Library</a> access&#x2013;you can give apps like Instagram access to only specific photos instead of the full library</li>
<li>Sends a notification when apps read the clipboard<ul>
<li>provides API for developers to figure out what is on the clipboard before accessing the full contents, <a href="https://9to5mac.com/2020/06/24/ios-14-clipboard-notifications/" target="_blank">this will cut down on how much you see the notification</a></li>
<li><em>this is great, apps have had unfettered access to the clipboard without user knowledge for too long</em></li>
<li>Thanks to this feature, people who installed the beta have already <a href="https://appleinsider.com/articles/20/06/25/new-ios-14-feature-prompts-tiktok-to-end-clipboard-snooping" target="_blank">caught TikTok sniffing user&apos;s clipboard</a>, even when running in the background</li>
</ul>
</li>
<li>Microphone and screen recording indicator in the status bar</li>
<li>Apps have to ask <a href="https://appleinsider.com/articles/20/06/24/apple-makes-idfa-opt-in-on-app-by-app-basis-in-ios-14" target="_blank">permission to track you</a></li>
</ul>
<h2 id="home"><a href="#home">Home<i class="icon-link"></i></a></h2>
<ul>
<li>New standard making it easier for device manufacturers to make new devices and device types for the Home app</li>
<li>Automations will be suggested when you add new devices</li>
<li>New widget at top of Home app with contextually relevant device controls available&#x2013;a quick visual status indicator</li>
<li>&#x202A;Adaptive lighting: hue has had this forever, but you can make your lights switch from cool to warm based on time of day, simulate sunset and sunrise, among other things.<ul>
<li><em>I am excited for the ability to integrate this with HomeKit Automations</em></li>
</ul>
</li>
<li>&#x202A;Activity zones&#x2013;lets you draw areas to be alerted about activity... so you can ignore cars on the street, but catch people on your walkway.</li>
<li>Face recognition for HomeKit camera&#x202C;</li>
<li>HomePod can announce whose at the door if it recognizes them</li>
<li><em>This <strong>sounds</strong> creepy, but it all happens locally within your HomeKit system, unlike Amazon&apos;s Ring doorbell, <a href="https://www.washingtonpost.com/technology/2019/11/19/police-can-keep-ring-camera-video-forever-share-with-whomever-theyd-like-company-tells-senator/" target="_blank">which freely shares footage with Police</a>. For the love of all that is holy, don&apos;t buy a Ring</em></li>
<li>Pull up HomeKit camera video at any time with Siri on iOS or tvOS device</li>
<li>AppleTV will automatically pop up a video window when someone rings the doorbell</li>
</ul>
<h2 id="appletv"><a href="#appletv">AppleTV<i class="icon-link"></i></a></h2>
<ul>
<li>New Home app</li>
<li>New Home controls on AppleTV sidebar</li>
<li>&#x202A;Picture in picture system wide. You can watch one thing on AppleTV and AirPlay another thing to another window... this is dope&#x202C;</li>
<li>You can use a workout app while watching a TV show in the corner</li>
<li>Multi-user support for Apple Arcade<ul>
<li><em>This is okay, but I wanted a more rich user profile feature. Why can&apos;t we have different app layouts for different users? Why doesnt the iPad support multiple user accounts yet?</em></li>
</ul>
</li>
<li><em>I fasho be wanting to watch two things at once, or watch some shit while I&apos;m playing some shit&#x202C;, so this is great.</em></li>
<li>New AppleTV+ series: Foundation (based on the Isaac Asimov book series) (<a href="https://youtu.be/xgbPSA94Rqg" target="_blank">watch the trailer</a>)</li>
<li>Audio sharing so that multiple people can listen with AirPods</li>
</ul>
<h2 id="safari"><a href="#safari">Safari<i class="icon-link"></i></a></h2>
<p><em>It seems a lot of these features are Mac specific. Its not clear yet.</em></p>
<ul>
<li>50% faster than Chrome</li>
<li>More rich Safari extensions<ul>
<li>Support for web extensions api<ul>
<li>Chrome supports this&#x2013;so extensions should be able to be translated across browsers a lot easier.</li>
</ul>
</li>
<li>Privacy controls for extensions&#x2013;you control which sites each extension can see.<ul>
<li>You can give an extension access to a site for the hour, the day, or forever.</li>
</ul>
</li>
</ul>
</li>
<li>Redesigned tabs<ul>
<li>Icons in tabs<ul>
<li><em>I thought this already existed</em></li>
</ul>
</li>
<li>Tabs will now scale themselves like Chrome tabs do&#x2013;this is way better. You can see more tabs in the tab bar.<ul>
<li><em>This was long overdue.</em></li>
</ul>
</li>
</ul>
</li>
<li>Monitors saved passwords and notifies you if they were in a data breach<ul>
<li><em>1Password already does this, I wanted Apple to make a full-blown password manager</em></li>
</ul>
</li>
<li>Native web page translation&#x202C;</li>
<li>&#x202A;Safari will report the trackers that it blocks&#x202C;</li>
<li>Customizable start page<ul>
<li>Custom wallpaper&#x2013;drag and drop an image onto the start page to set a new background</li>
</ul>
</li>
<li>Can now stream <a href="https://9to5mac.com/2020/06/29/safari-can-now-stream-4k-hdr-and-dolby-vision-content-on-netflix-with-macos-big-sur/" target="_blank">4K HDR videos in Safari</a></li>
</ul>
<h2 id="macos-big-sur"><a href="#macos-big-sur">MacOS Big Sur<i class="icon-link"></i></a></h2>
<blockquote>
<p>We love the Mac, its the tool we use to make all of the products that we put out into the world.</p>
</blockquote>
<ul>
<li>They didn&apos;t stress this on stage, but the X (10) in macOS X is no more. MacOS is moving on to version 11.0.</li>
<li>Major visual refresh. Everything is refined<ul>
<li><em>looks more iOS like</em></li>
</ul>
</li>
<li>Apps have their own &quot;Key color&quot; that is used on sidebar icons, list highlights, etc.<ul>
<li><em>This seems to usurp the system-level highlight color they introduced with the last MacOS release.</em></li>
</ul>
</li>
<li>New suite of sounds</li>
<li>&#x202A;Menu bar drop downs like the Sound menu is a lot more helpful, new designs and better affordances</li>
<li><a href="https://9to5mac.com/2020/06/25/first-look-at-new-control-center-and-widgets-on-macos-big-sur/" target="_blank">Control Center on Mac</a>.<ul>
<li>You can drag stuff out of control center straight into the menu bar, and vice-versa</li>
</ul>
</li>
<li>Redesigned Notification Center, grouped with widgets, <em>no more tabs</em></li>
<li>iOS widgets supported on the Mac<ul>
<li><em>I assume that this is thanks to Catalyst&#x2013;developers can likely add widgets to macOS super easily if they have one in their iOS app today</em></li>
</ul>
</li>
<li>Messages on Mac works like iOS messages, complete with the new groups features, pinned conversations, better search, an app menu, etc.</li>
<li>All new version of Maps<ul>
<li>Favorites and lists from iOS will show up in Maps on Mac</li>
<li>Ability to see friend&apos;s ETA progress</li>
<li>All iOS maps features</li>
</ul>
</li>
<li>Catalyst<ul>
<li>Lets developers bring their iPad apps over to the Mac with minimal effort</li>
<li>Lots of enhancements to Catalyst that developers can take advantage of</li>
<li>Maps and Messages are now Catalyst apps</li>
</ul>
</li>
<li><a href="https://osxdaily.com/2020/06/22/macos-big-sur-screenshots-features/" target="_blank">osxdaily post with lots of screenshots</a></li>
</ul>
<h2 id="transition-to-arm"><a href="#transition-to-arm">Transition to ARM<i class="icon-link"></i></a></h2>
<ul>
<li>After the Mac demo, they revealed the whole thing was run on an ARM-based Mac.</li>
<li>Theres a few components to this, and a lot to be said on this topic, in particular related to app compatibility<ul>
<li><a href="https://tidbits.com/2020/06/22/macs-make-the-move-to-arm-with-apple-silicon/" target="_blank">Here&apos;s a good overview by tidbits.com</a></li>
</ul>
</li>
<li>They rewrote their redesigned Mac apps for their custom chips, but they are backwards compatible with Intel chips</li>
<li>You can still run windows within parallels and other virtualization</li>
<li>Developers can make their iOS apps available for download on the Mac, <a href="https://appleinsider.com/articles/20/06/22/beyond-rosetta-2-for-intel-apps-apple-silicon-macs-will-run-iphone-ipad-apps-natively" target="_blank">running natively</a>, if they choose to</li>
<li>First ARM Mac shipping to consumers by the end of this year</li>
<li><a href="https://www.theverge.com/2020/6/24/21302213/apple-silicon-mac-arm-windows-support-boot-camp" target="_blank">BootCamp is dead</a>. Seems like virtualization is the wave</li>
<li><a href="https://tidbits.com/2020/06/25/troubleshooting-startups-will-work-differently-in-apple-silicon-macs/" target="_blank">New system recovery method</a></li>
</ul>
<h3 id="how-does-this-benefit-users"><a href="#how-does-this-benefit-users">How does this benefit users?<i class="icon-link"></i></a></h3>
<p>In theory, new ARM-based Macs running Apple chips can take advantage of Apple&apos;s full-stack approach to designing their devices. My hope is that Apple can deliver two things to consumers with this transition:</p>
<ol>
<li>Better battery life</li>
<li>Faster year-over-year speed improvements.</li>
</ol>
<p>The iPhone has been outpacing the Mac in speed and efficiency gains for years, and the theory is that the transition to Apple&apos;s own chips can help the Mac play catch up.</p>
<h1 id="device-compatibility"><a href="#device-compatibility">Device Compatibility<i class="icon-link"></i></a></h1>
<p>Check out <a href="https://www.theverge.com/2020/6/22/21299686/apple-ios-14-ipados-macos-big-sur-watchos-7-compatibility-update-new-software-wwdc-2020" target="_blank">The Verge&apos;s article on this</a>.</p>
<h1 id="updates"><a href="#updates">Updates<i class="icon-link"></i></a></h1>
<p>I will update this secton as details of new features emerge in the coming days.</p>
<ul>
<li><a href="https://twitter.com/stroughtonsmith/status/1275270084961894406?s=21" target="_blank">System wide color picker</a></li>
<li><a href="https://twitter.com/firt/status/1275453911042633728?s=21" target="_blank">Home screen web apps</a></li>
<li>FaceTime can detect when someone is using sign language and auto-focus them just like it does for speech</li>
<li><a href="https://appleinsider.com/articles/20/06/24/new-safari-api-enables-face-id-and-touch-id-authentication-for-websites" target="_blank">Login to websites with FaceId and TouchID</a></li>
<li><a href="https://appleinsider.com/articles/20/06/24/apple-revamps-game-center-controller-support-in-ios-14-tvos-14-macos-big-sur" target="_blank">GameCanter app is coming back</a></li>
<li><a href="https://appleinsider.com/articles/20/06/24/apple-introduces-hand-body-pose-detection-to-vision-framework-for-developers" target="_blank">Hand and body pose detection to vision framework</a><ul>
<li><em>Another one that will be useful for the AR goggles</em></li>
<li><em>I remember doing this with the Kinect back in college, its taken this long for this technology to jump to the phone. Kinda crazy to think about.</em></li>
</ul>
</li>
<li><a href="https://appleinsider.com/articles/20/06/23/sound-recognition-in-ios-14-alerts-deaf-iphone-users-to-fire-alarms" target="_blank">Sound recognition</a>&#x2013;if you are hard of hearing you can have your phone notify you of common sounds such as doorbells, etc.</li>
<li><strong>Headphone accommodations</strong><ul>
<li><em>My interpretation of this is that Apple is strategically turning the AirPods into (relatively affordable) hearing aids</em></li>
<li><em>This is a big deal.</em><ul>
<li>From Apple&apos;s website: &quot;This new accessibility feature is designed to amplify soft sounds and adjust certain frequencies for an individual&#x2019;s hearing, to help music, movies, phone calls, and podcasts sound more crisp and clear. <strong>Headphone Accommodations also supports Transparency mode on AirPods Pro, making quiet voices more audible and tuning the sounds of your environment to your hearing needs.</strong>&quot;</li>
</ul>
</li>
</ul>
</li>
<li>New status alerts when headphones and other devices connect-looks like the apple pencil charge notifications</li>
<li>You can enable/disable specific screensaver categories on AppleTV</li>
<li>The <a href="https://developer.apple.com/wwdc20/10668" target="_blank">Nearby Interaction Framework</a> will help developers make apps that let your phone know where it is relative to other phones.</li>
<li><a href="https://appleinsider.com/articles/20/06/26/apples-arkit-4-anchors-3d-reality-into-real-world-maps-locations" target="_blank">ARKit lets developers anchor things at specific locations in the real world</a></li>
<li><a href="https://9to5mac.com/2020/06/26/ios-14-apple-news-links/" target="_blank">Apple News can auto-redirect web links into the News app</a></li>
<li><a href="https://9to5mac.com/2020/06/25/ipados-14-game-controller-framework-expands-with-keyboard-mouse-and-trackpad-support/" target="_blank">Improved game controller support</a>&#x2013;including support for the DualShock 4 Light Bar</li>
<li>Low Power Mode on iPad</li>
<li><a href="https://twitter.com/simonbs/status/1276776233347551233?s=21" target="_blank">iPhone will notify you when your Watch is fully charged</a></li>
</ul>
<h2 id="control-center"><a href="#control-center">Control Center<i class="icon-link"></i></a></h2>
<ul>
<li>Announce messages with Siri in control center</li>
<li>Hearing toggle in control center</li>
<li>HomeKit devices and scenes inline in Control Center</li>
</ul>
<h2 id="shortcuts"><a href="#shortcuts">Shortcuts<i class="icon-link"></i></a></h2>
<p>I am a huge fan of the Shortcuts app. It got no mention on stage, which makes sense since it got a lot of love last year and the year before that. It turns out Shortcuts is getting some updates <a href="https://9to5mac.com/2020/06/23/ios-14-shortcuts-gains-new-automation-triggers-apple-watch-app-folders-more/" target="_blank">after all</a>.</p>
<p><img src="https://9to5mac.com/wp-content/uploads/sites/6/2020/06/Screen-Shot-2020-06-23-at-14.52.32-PM.png" alt></p>
<ul>
<li>Shortcuts folders</li>
<li>More automatic automation options for personal automations</li>
<li>Shortcuts can run locally on Watch&#x2013;no iPhone required</li>
<li><a href="https://twitter.com/simonbs/status/1276831098710999041?s=21" target="_blank">Can import .shortcut files again</a></li>
<li><a href="https://twitter.com/simonbs/status/1275181371678490624?s=21" target="_blank">Copy and paste actions</a></li>
</ul>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/apple-wwdc-2020</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/apple-wwdc-2020</guid>
            <category><![CDATA[apple]]></category>
            <category><![CDATA[iOS]]></category>
            <category><![CDATA[macOS]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Tue, 23 Jun 2020 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[lukezilioli.com Website Redesign - Tech Post]]></title>
            <description><![CDATA[<p>Hello everybody! It&apos;s been forever since I updated the code that drives this site. (Just under eight years). But I have been doing stuff! I wanna show you my redesigned website. For the non-technical version of this post, read <a href="/blog/post/welcome-2">A Long Overdue Update</a></p>
<p>The old lukezilioli.com was written in PHP, the new one is written in NodeJS (with a super light-weight front-end). There&apos;s lots of cool technical stuff going on behind the scenes. Some of it has been open sourced.</p>
<p>I&apos;ve got the new site set up so that I can edit blog posts in markdown on my iPad, commit and push the changes to a git repository, and have them published to this site automatically.</p>
<h1 id="open-source"><a href="#open-source">Open Source<i class="icon-link"></i></a></h1>
<p>While architecting this blog, I kept open source in mind. It is not open-sourced yet, but I have defined a standard format for a blog repository (written in markdown, of course), and created <code>@lzilioli/blog-parser</code>, a module that I am using internally to turn my blog into structured data for rendering this website. Eventually I will open source this module.</p>
<p> I also created <a href="/blog/post/md-macros">md-macros</a>, which I use to parse my blog&apos;s markdown, and embed rich markup and data into my blog posts.</p>
<h1 id="shoutouts"><a href="#shoutouts">Shoutouts<i class="icon-link"></i></a></h1>
<p>I wanted to include a shoutouts section with this post, like I did <a href="/blog/post/welcome#shoutouts">with the launch of the last redesign</a>.</p>
<h2 id="newcomers"><a href="#newcomers">Newcomers<i class="icon-link"></i></a></h2>
<h3 id="rss-feed"><a href="#rss-feed">RSS Feed<i class="icon-link"></i></a></h3>
<p>I love RSS. <a href="https://www.lukezilioli.com/blog?id=23">I was sad when Google Reader died</a>. I have long since switched over to <a href="https://feedly.com/i/welcome" target="_blank">feedly</a>, a more than sufficient replacement. Since I am such a fan of RSS, I created an RSS feed for the site. Subscribe <a href="https://lukezilioli.com/blog/feed/" target="_blank">here</a>. Like most node-based web services that provide an RSS feed, I am using an <a href="https://www.npmjs.com/package/rss" target="_blank">npm package, rss</a>.</p>
<h3 id="navigatorshare-api"><a href="#navigatorshare-api">navigator.share api<i class="icon-link"></i></a></h3>
<p>At the bottom of every post, if your browser supports it, you can find a &quot;Share&quot; button, which will pop up your browser&apos;s native share sheet. If you are on an iOS device or using Safari on your Mac, sharing posts from this site is extra easy.</p>
<h3 id="clipboardjs"><a href="#clipboardjs">ClipboardJS<i class="icon-link"></i></a></h3>
<p>I am no longer using ZeroClipboard. (Flash is sooo 2013.) This redesigned website uses <a href="https://clipboardjs.com/" target="_blank">ClipboardJS</a> to provide the same functionality. ClipboardJS doesn&apos;t need flash and instead relies on browser standards.</p>
<pre><code class="language-txt">Try <span class="hljs-keyword">it</span>! Click <span class="hljs-keyword">on</span> <span class="hljs-keyword">the</span> <span class="hljs-keyword">copy</span> icon <span class="hljs-keyword">on</span> <span class="hljs-keyword">the</span> right <span class="hljs-keyword">to</span>
<span class="hljs-keyword">copy</span> this block <span class="hljs-keyword">of</span> <span class="hljs-built_in">text</span> <span class="hljs-keyword">to</span> your clipboard.</code></pre>
<p>Now paste it here:</p>
<p><input type="text" style="border: 1px solid; width: 100%; padding: 10px; border-radius: 5px;"></p>

<h3 id="dark-mode"><a href="#dark-mode">Dark Mode<i class="icon-link"></i></a></h3>
<p>If you are using MacOS or iOS latest versions, you will notice this site will match your system-level light or dark preference. Switch to light or dark mode and watch the page update!</p>
<h3 id="visited-link-styling"><a href="#visited-link-styling">:visited link styling<i class="icon-link"></i></a></h3>
<p>My old website displayed circular read/unread indicators beside the post titles. This is impossible using the <code>:visited</code> pseudo element styling, so the old website was tracking post read/unread status in the browser&apos;s <code>localStorage</code>. At the time, I wanted to learn how to work with <code>localStorage</code>, and that feature was the perfect place to do it. As part of simplifying the codebase for this redesign, I ripped out <code>localStorage</code> usage in favor of <code>:visited</code> pseudo-element styling.</p>
<h3 id="nodejs--heroku"><a href="#nodejs--heroku">Nodejs + heroku<i class="icon-link"></i></a></h3>
<p>Most would say this simple blog could be published as a static site. I didn&apos;t want to do that for a few reasons. First, as part of migrating from the old design to the new design, I implemented some better practices. (Working on an SEO optimization team at RetailMeNot rubbed off of me). On my old site, blog post urls were formed as follows: <code>/blog?id=&lt;post-id&gt;</code>. Here they live at <code>/blog/post/&lt;post-slug&gt;</code>, which makes the urls more human readable, follows RESTful principles, and is better practice all around. However, you can still visit the old urls, and get 301 redirected to their new URLs. That small bit of redirect logic mapping post ids to post slugs was much easier to put on a node server than in a static front-end app.</p>
<p>Also, I&apos;m a front-end engineer, so this was the perfect excuse to play with supporting and building node app in a production environment.</p>
<h3 id="bitbucket-pipelines"><a href="#bitbucket-pipelines">bitbucket pipelines<i class="icon-link"></i></a></h3>
<p>I&apos;m using bitbucket pipelines to build the site and push it out whenever I push code to the repo. Its mad easy, and it took me 10 minutes to integrate with heroku. Everything is so standardzed these days, I love it.</p>
<h3 id="2023-update"><a href="#2023-update">2023 Update<i class="icon-link"></i></a></h3>
<ul>
<li>Heroku raised prices, so I switched to render.com</li>
<li>As part of this process, I replaced BitBucket &amp; pipelines with GitHub &amp; actions</li>
</ul>
<h3 id="typescript"><a href="#typescript">TypeScript<i class="icon-link"></i></a></h3>
<p>JavaScript has come a long way, but it remains error prone and untyped. Thankfully, theres <a href="https://www.typescriptlang.org" target="_blank">TypeScript</a>. I don&apos;t write JavaScript anymore, everything I do is TypeScript. If you haven&apos;t made the switch, do so. I can&apos;t believe I could ever write functioning applications using vanilla JS.</p>
<h3 id="webpack"><a href="#webpack">Webpack<i class="icon-link"></i></a></h3>
<p>I don&apos;t even know how I would compile a front-end (or node back-end) without <a href="https://webpack.js.org/" target="_blank">webpack</a>. It has become my go to TypeScript bundler, is highly extensible, and gets better with every update.</p>
<h3 id="gulp"><a href="#gulp">Gulp<i class="icon-link"></i></a></h3>
<p>Out with the old and in with the new (less old?). Over the years, I have used Grunt as my task runner. I used it for a long time. Longer than most. I&apos;d even created a <a href="https://github.com/lzilioli/shared-grunt-config" target="_blank">shared-grunt-config</a> package that encapsulated all of my favorite grunt plugins and standardized my JavaScript development workflow across multiple repos.</p>
<p>With this website overhaul, I jumped ship from Grunt over to <a href="https://gulpjs.com/" target="_blank">gulp</a>, since its better supported and been updated to play nicely with newer versions of node. I ditched <code>shared-grunt-config</code> in favor of Github&apos;s <a href="https://help.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-template-repository" target="_blank">template repo feature</a>. I created <a href="https://github.com/lzilioli/lz-ts-template" target="_blank">lz-ts-template</a> which will be the basis for my future JavaScript projects.</p>
<p>I <em>have</em> used <code>npm scripts</code>, which is everybody&apos;s favorite way to manage their scripts these days, but I still prefer the power and abstractions provided by a JavaScript task runner.</p>
<h3 id="open-graph-tags"><a href="#open-graph-tags">Open Graph Tags<i class="icon-link"></i></a></h3>
<p>When you share a link to a post using iMessage or another modern messaging app, you will get rich inline previews of what is on the page. This improves everyone&apos;s life, and it means if you share a link to my blog with a friend, they are more likely to know what you sent them, even if they don&apos;t bother to click the link.</p>
<h3 id="handlebars"><a href="#handlebars">Handlebars<i class="icon-link"></i></a></h3>
<p>I have a few rules when it comes to selecting a template library:</p>
<ol>
<li>Must be able to render client, or server-side in JavaScript</li>
<li>Must encourage minimal logic in templates (but support <code>if</code>/<code>else</code>/<code>for</code>)</li>
<li>Read like html insofar as possible</li>
</ol>
<p><a href="https://handlebarsjs.com" target="_blank">Handlebars</a> checks these boxes, and I have used it in many projects both personal and professional, making it the obvious candidate for this site.</p>
<h2 id="updates"><a href="#updates">Updates<i class="icon-link"></i></a></h2>
<p>A lot changes in the web development community, and as such, some of the tools that I was excited about back when I first created this site in 2012 have fallen by the wayside.</p>
<h3 id="twitter-bootstrap"><a href="#twitter-bootstrap">Twitter Bootstrap<i class="icon-link"></i></a></h3>
<p><a href="https://twitter.github.com/bootstrap/" target="_blank">Twitter Bootstrap</a> had its time, but I have stopped using it. These days, I write my own custom styles for stuff.</p>
<h2 id="old-timers"><a href="#old-timers">Old-Timers<i class="icon-link"></i></a></h2>
<h3 id="sass"><a href="#sass">Sass<i class="icon-link"></i></a></h3>
<p>I still love <a href="https://sass-lang.com/" target="_blank">Sass</a>. Lucky for me, so does the web community. There are some great people behind the project, and it now has a c++ implementation (Libsass) which is much faster and more reliable.</p>
<h3 id="jquery"><a href="#jquery">jquery<i class="icon-link"></i></a></h3>
<p>I&apos;m still using jQuery. Its great in my opinion. This site is super lightweight on the front-end, so jQuery is the perfect candidate.</p>
<p>Even for more complex applications, I am a big fan of event delegation combined with stateless functions and centralized state management (shoutout to redux). But I work on an Angular app as my day job, and as an engineer I try and remain framework agnostic. Finding, fixing, and folding code patterns onto themselves is what I&apos;m good at.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/welcome-2-tech</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/welcome-2-tech</guid>
            <category><![CDATA[portfolio]]></category>
            <category><![CDATA[web dev]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Sat, 20 Jun 2020 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[A Long Overdue Update]]></title>
            <description><![CDATA[<p>Hello everybody! Its been forever since I last posted something. (Just under eight years). But I have been doing stuff! First, I wanna show you my redesigned website. Welcome! For a technical deep dive on the new site, read <a href="/blog/post/welcome-2-tech">the tech post</a>.</p>
<p>I have backfilled the contents of this site to capture some of the milestones I&apos;ve hit over the last seven years, both personal and technical. Stay tuned for more posts.</p>
<h1 id="why-now"><a href="#why-now">Why Now?<i class="icon-link"></i></a></h1>
<p>Anyone who knows me knows I am an avid Apple user. I have been known to live-tweet their product and software announcements for my friends.</p>
<p>For years, I have kept my own personal &quot;Apple Wishlist&quot;, a list of things I&apos;d like to see them support in future versions of their whateverOS. This year, I want to start capturing those thoughts on my website. I also want to start writing tips and tricks to help people get the most out of their MacOS and iOS devices.</p>
<p>In April, I set the goal of relaunching my website by June 20th. I wanted to get it done by the time iOS 14 is announced so that I have a place to put my thoughts about the release. I&apos;ve hit that goal, so stay tuned for Apple-related content in the coming weeks as I process what they announce at this year&apos;s WWDC.</p>
<p>Last time I launched this website, I wrote 2 posts in the following months, and didn&apos;t touch it again until today. Back then, I had to manually upload the posts to my website after I finished writing them. Today, that process is automated. Since its easy to write and publish posts, and I can do it all from my iPad, I should be posting regularly. We gon see...</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/welcome-2</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/welcome-2</guid>
            <category><![CDATA[portfolio]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Sat, 20 Jun 2020 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[md-macros]]></title>
            <description><![CDATA[<p>Markdown is great for its simplicity and easy-to-read syntax. Sometimes you want to embed rich markup or components <em>inside</em> of a markdown document. How do you do this without writing ugly html along side your content?</p>
<p>Enter <a href="https://github.com/lzilioli/md-macros" target="_blank">md-macros</a>, an npm package that I created and use myself on this blog. It allows me to link from one post to another with <code>\\[[macro:postLink slug=&quot;welcome-2&quot;]]</code>(<strong>update 2023-12:</strong> I now support wiki-style backlinks popularized by second brain apps like Obsidian), or embed a youtube video with <code>\\[[macro:youtubeEmbed url=&quot;&lt;youtube video url&gt;&quot;]]</code>. This enables me to keep my markdown documents clean and free of html.</p>
<p>Each macro maps to a simple JavaScript function, making this a highly extensible library. I use it in other projects to embed a table of contents inside of the README.</p>
<p>Check out the code <a href="https://github.com/lzilioli/md-macros" target="_blank">on my github</a>, or use it in one of your projects by installing the <a href="https://github.com/lzilioli/md-macros/packages/220235" target="_blank">npm package</a>.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/md-macros</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/md-macros</guid>
            <category><![CDATA[open source]]></category>
            <category><![CDATA[portfolio]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Mon, 18 May 2020 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Starbelly Software Website Redesign]]></title>
            <description><![CDATA[<p>I finally relaunched the <a href="//www.starbellysw.com">Starbelly Software website</a> to reflect the fact that the apps are no longer being sold or maintained, and I&apos;ve pivoted to web development. I faithfully maintain the Starbelly Software LLC., so it was only right the website be modernized. I coded up the redesign years ago and I&apos;m just now getting around to launching it.</p>
<p>For posterity, I kept the old site hanging around <a href="/labs/starbellysw.com-legacy">here</a>. I&apos;d made it with a drag and drop website making app on my first MacBook, way back before I even knew how to code a website.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/starbelly-relaunch</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/starbelly-relaunch</guid>
            <category><![CDATA[portfolio]]></category>
            <category><![CDATA[starbellysw]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Sun, 15 Mar 2020 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Prism.fm]]></title>
            <description><![CDATA[<p>After a hiatus, I am back in the working world. I recently started a job at Prism.fm as their Lead Software Engineer.</p>
<h1 id="what-is-prism"><a href="#what-is-prism">What is Prism?<i class="icon-link"></i></a></h1>
<p>Prism is an Austin-based start-up that was co-founded by my homie <a href="http://www.adriantavares.com" target="_blank">Adrian</a>. To steal a blurb from their website: &quot;Prism is revolutionizing how live music events are managed.&quot;</p>
<p>In short, it&apos;s a software solution for venues and promoters to streamline their concert-planning workflow. As a software engineer who deeply loves music, Prism couldn&apos;t be a better fit for me.</p>
<h1 id="on-my-joining"><a href="#on-my-joining">On My Joining<i class="icon-link"></i></a></h1>
<p>I worked with Adrian at Zappos back in 2012. He and I <a href="/blog/post/zappos-recruiting">built their internship website</a> as a pet-project at the end of the summer. Working with him was great&#x2013;an experience that stuck with me through 4+ years at RetailMeNot.</p>
<p>As Adrian&apos;s friend, I&apos;ve watched Prism.fm evolve over the years. He and I have shared many late night working sessions with me hacking on a personal project or some task for RetailMeNot, and him working his ass off to build Prism. On occasion, I&apos;ve given him random advice related to his responsibilities as a CTO at Prism. I&apos;m hype to be able to play a direct role in its future evolution.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/prism.fm</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/prism.fm</guid>
            <category><![CDATA[portfolio]]></category>
            <category><![CDATA[web dev]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Thu, 01 Nov 2018 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Withings Sleep + Homekit Integration]]></title>
            <description><![CDATA[<p><strong>Update July 2020:</strong> I am using <a href="https://www.pushcut.io" target="_blank">Pushcut</a> with an iPod Touch as a server, and have stopped using this package. I&apos;ve simplified my setup and have IFTTT forwarding the Withings Sleep webhook straight to Pushcut.</p>
<p>I got the <a href="https://www.withings.com/eu/en/sleep-analyzer" target="_blank">Withings Sleep Mat</a> as a gift. While the sleep tracking and health app integrations are cool, what <strong>I</strong> find exciting is that it can sense when I get in and out of bed. This gives me lots of new automation ideas to implement in my smart home. I was mad excited to start playing with this aspect of the sleep mat, but once I got everything set up, I was disappointed to learn that the Withings Sleep Mat doesn&apos;t integrate with HomeKit, only IFTTT, leaving Apple users out to dry.</p>
<p>I couldn&apos;t have this. My house needs to know when I get in or out of the bed, and a Shortcut should be able to determine if I am in bed or not&#x2013;if the sleep mat doesn&apos;t enable that, its only realizing half of its purpose.</p>
<p>After brainstorming, I figured I can use the same contact sensor approach that I use to <a href="/blog/post/plex-bridge-homebridge">bridge plex to HomeKit</a>, with the help of <a href="https://github.com/benzman81/homebridge-http-webhooks" target="_blank"><code>homebridge-http-webhooks</code></a>. Except this time, the incoming webhook will be coming from IFTTT, which the sleep sensor <strong>does</strong> support.</p>
<p>I adapted the code I use to receive Plex webhooks and forward it to <code>hemebridge-http-webhooks</code>, and repurposed it for receiving webhooks from IFTTT and sending them along to HomeBridge. Find it <a href="https://github.com/lzilioli/nokia-sleep-homebridge" target="_blank">here</a>.</p>
<p>Note the code integrates with <a href="https://ngrok.com" target="_blank">ngrok</a>. The node server runs on your local network, while IFTTT is a hosted service, so ngrok is used to set up a persistent hostname for handling the incoming requests. This requires a paid ngrok account.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/withings-sleep-homebridge</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/withings-sleep-homebridge</guid>
            <category><![CDATA[open source]]></category>
            <category><![CDATA[smart home]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Wed, 22 Aug 2018 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[See Ya, RetailMeNot]]></title>
            <description><![CDATA[<p>After 4+ years, I have parted ways with RetailMeNot. It&apos;s bittersweet. I liked my team and learned a lot while working on a codebase I was proud of, but I&apos;d stayed for 4+ years. The day I realized I had worked there longer than I had done any one other thing in my life was the day I realized it was time for a change.</p>
<p>I learned a lot and wanna shout out to everyone I worked with over the years. I hope to work with some of y&apos;all again.</p>
<h1 id="so-whats-the-next-move"><a href="#so-whats-the-next-move">So... whats the next move?<i class="icon-link"></i></a></h1>
<p>As I mentioned in <a href="/blog/post/stand-up-comedy">my stand-up comedy post</a>, I&apos;ve started doing stand-up. My only plan right now is to focus on honing that craft. Catch me grindin&apos; at open mics in the coming months...</p>
<p>Besides that... I don&apos;t have a solid plan. I hope to return to Detroit, where the majority of my family and friends live. At the end of the day, I hope to find a decent living situation, and enough work/life balance to focus on comedy or other passions on an ongoing basis.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/cya-retailmenot</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/cya-retailmenot</guid>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Mon, 01 Jan 2018 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Bridging Plex to Homekit]]></title>
            <description><![CDATA[<p><strong>Update July 2020:</strong> Its been a minute since I&apos;ve used this package myself. I have been using <a href="https://www.npmjs.com/package/homebridge-plex-sensors" target="_blank">homebridge-plex-sensors</a>, which integrates with homebridge and receives Plex webhooks directly. I have also written a new plugin: <a href="/blog/post/plex-to-pushcut">plex-to-pushcut</a>, which integrates with <a href="https://www.pushcut.io" target="_blank">Pushcut</a>, one of my favorite apps for home automation.</p>
<h1 id="goal"><a href="#goal">Goal<i class="icon-link"></i></a></h1>
<p>I wanted to set it up so that when I play a movie or TV show, my lights dim, and when I pause, they brighten. I&apos;d like to be able to set different scenes to activate depending on if I start watching in the bedroom vs the living room.</p>
<h1 id="alternatives"><a href="#alternatives">Alternatives<i class="icon-link"></i></a></h1>
<p>IFTTT is too dumb to support this, because there needs to be logic around what to do depending on which webhook event was fired.</p>
<h1 id="solution"><a href="#solution">Solution<i class="icon-link"></i></a></h1>
<p>I wrote a small <a href="https://github.com/lzilioli/plex-bridge-homebridge-http-webhooks" target="_blank">node app</a> for this. It receives incoming webhooks from Plex. For play/pause/start events, it forwards the webhook to <a href="https://github.com/benzman81/homebridge-http-webhooks" target="_blank"><code>homebridge-http-webhooks</code></a>, which maps to a contact sensor in my HomeKit setup.</p>
<p>With a contact sensor whose state maps to the playing status of Plex, I can use Apple&apos;s Home app to set up automations for different HomeKit scenes based on changes to the contact sensor state.</p>
<p>Check out the package <a href="https://github.com/lzilioli/plex-bridge-homebridge-http-webhooks" target="_blank">on my GitHub</a> for details.</p>
<p>I adapted the code from an example app published by the Plex developers. I don&apos;t expect this to be universally useful, but the more tech savvy smart home user could use or adapt the code for their needs. For this reason, I figured there&apos;s no harm in open sourcing it.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/plex-bridge-homebridge</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/plex-bridge-homebridge</guid>
            <category><![CDATA[open source]]></category>
            <category><![CDATA[smart home]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Fri, 17 Mar 2017 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[F*ck You, Pay Memes]]></title>
            <description><![CDATA[<p>I made a twitter bot: <a href="https://twitter.com/fuckyoupaymemes" target="_blank">@fuckyoupaymemes</a>.</p>
<p>Why?</p>
<p>It does&apos;t sit well with me when I watch a term that Black people originated enter the collective consciousness and get used by your every day run-of-the-mill white person. The term &quot;on fleek&quot; is the latest example of this. Many <a href="https://www.vox.com/culture/2017/3/28/14777408/on-fleek-kayla-lewis-ihop-dennys-vine-twitter-cultural-appropriation" target="_blank">others</a> <a href="https://medium.com/@TheReclaimed/the-sad-backstory-of-on-fleek-and-how-to-overcome-cultural-theft-f307b177f48c" target="_blank">have</a> <a href="https://www.huffingtonpost.ca/2018/12/30/2018-slang-words-appropriation_a_23629985/" target="_blank">covered</a> <a href="https://brokeassstuart.com/2017/06/02/how-appropriating-slang-can-be-problematic-yaaaasss-queen-even-for-you/" target="_blank">this</a> topic.</p>
<p>I wanted to find a way to apply my software skills to this problem. The popularization of &quot;on fleek&quot; is a great opportunity for this. Peaches, the term&apos;s originator, has an active GoFundMe campaign to raise money for having originated the term.</p>
<p>You might ask, &quot;why does Peaches deserve money? Memes get created every day&quot;. I think anyone would agree with the sentiment that for <em>any</em> meme, the creator deserves credit and proper compensation when profits are involved. In the absence of universal justice for meme originators, you might ask what makes Peaches&apos; case unique enough that I am blogging about it&#x2013;America&apos;s ongoing crimes against Black people is your answer.</p>
<p>What some fail to recognize is that there are white-owned brands using the term &quot;on fleek&quot; in their advertising. Thanks to Peaches, these brands are able to gain access to a demographic that is otherwise inaccessible to them&#x2013;there is value in that. White-owned brands should not be furthering their economic advantages over Peaches without elevating her along with them&#x2013;to not do so is classical white people bullshit if you ask me.</p>
<p>There are people profiting off &quot;on fleek&quot; today who would look down on someone like Peaches if they encountered her in their everyday lives. <strong>THAT</strong> doesn&apos;t sit well with me. This is what people refer to when they speak of cultural appropriation&#x2013;how many people throwing around &quot;on fleek&quot; knowing good and god damn well it&apos;s a term they would <strong>never</strong> embrace on their own, if the rest of the hive mind weren&apos;t too?</p>
<p>Enter <a href="https://twitter.com/fuckyoupaymemes" target="_blank">@fuckyoupaymemes</a>, a twitter bot I created that subscribes to all tweets across twitter, and when it finds one that contains the term &quot;on fleek&quot;, it responds with one of a few random messages asking the user to contribute to Peaches&apos; GoFundMe.</p>
<p>The code is sitting on my desktop, and I&apos;ve got the bot running locally on my MacBook. I&apos;ll keep it up and running for the next few weeks while &quot;on fleek&quot; is dominating the hive mind. If it gets a massive response, I might spend time open sourcing the code and getting the bot hosted long term&#x2013;no promises on that. The search term (in this case, &quot;on fleek&quot;) and the canned responses are both configurable, meaning that this code could easily be adapted for the next meme.</p>
<p>Consider this my part in trying to get Peaches paid and raise awareness on the fact that even the seemingly innocuous spreading of memes can harm marginalized groups and further reinforce a wealth disparity in this country which white people reap by capitalizing on the labor (both physical and intellectual) of Black people without proper compensation.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/fuck-you-pay-memes</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/fuck-you-pay-memes</guid>
            <category><![CDATA[hacking for change]]></category>
            <category><![CDATA[portfolio]]></category>
            <category><![CDATA[web dev]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Sat, 11 Mar 2017 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Stand Up Comedy]]></title>
            <description><![CDATA[<p>I&apos;ve always wanted to do stand-up. I own tons of books, and DVDs about it. People have always told me they thought I was funny, and I enjoy making people laugh. Most importantly, I have important things to say from up here on my high horse, and stand-up is a great medium for that.</p>
<p>To that end, I&apos;ve started doing stand-up. My first time was earlier this year at an open mic night here in Austin.</p>
<p>My second time doing stand-up was today. I&apos;m home for Christmas, and my friends encouraged me to do an open mic, so I did. I got a lot of laughs, prolly cuz I had friends there. I don&apos;t care the reason, all I know is that it went way better than my first time.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/stand-up-comedy</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/stand-up-comedy</guid>
            <category><![CDATA[comedy]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Thu, 22 Dec 2016 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[I Went to Italy and Germany]]></title>
            <description><![CDATA[<p>I recently returned from a trip to Germany and Italy. I spent a week with a German friend of mine, who I&apos;ve known since High School. It&apos;s always good to spend some quality time catching up with him.</p>
<p><img class="callout" src="/images/Italy-food-3.jpg" title="Some" bomb ass bolognese sauce> After that, I went to a few different cities in Italy, piggybacking off of the trip that my aunt had planned. I got to spend two weeks with my aunt, uncle and cousins. It was hype as hell.</p>
<p>The whole purpose of this post is to show off the delicious food from the trip.</p>
<p><img src="/images/Italy-food-1.jpg" alt>
<img src="/images/Italy-food-2.jpg" alt>
<img src="/images/Italy-food-4.JPG" alt>
<img src="/images/Italy-food-5.JPG" alt>
<img src="/images/Italy-food-7.JPG" alt>
<img src="/images/Italy-food-8.JPG" alt>
<img src="/images/Italy-food-9.JPG" alt></p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/italy</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/italy</guid>
            <category><![CDATA[food]]></category>
            <category><![CDATA[travel]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Sun, 24 Jul 2016 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Mixin' It Up With FlightJS - Cross Post from RetailMeNot Blog]]></title>
            <description><![CDATA[<p>I recently did a blog post on RetailMeNot&apos;s blog. Re-printed below for posterity.</p>
<hr>
<h1 id="mixin-it-up-with-flightjs"><a href="#mixin-it-up-with-flightjs">Mixin&#x2019; It Up With FlightJS<i class="icon-link"></i></a></h1>
<p>As <a href="http://www.retailmenot.com/corp/eng/" target="_blank">RetailMeNot</a> started to develop more rich interactions for our site, we found ourselves needing to include the same functionality and patterns in different components or objects without duplicating the code, lest we end up in the <a href="https://speakerdeck.com/anguscroll/how-we-learned-to-stop-worrying-and-love-javascript?slide=18" target="_blank">wild west of inheritance</a>. Enter Twitter&#x2019;s <a href="http://flightjs.github.io" target="_blank">FlightJS</a> framework.</p>
<p>FlightJS is something that we already make use of a great deal at RetailMeNot. One of the key features of FlightJS is the <a href="https://github.com/flightjs/flight/blob/v1.2.0/lib/component.js#L106" target="_blank">.mixin()</a> pattern. Using mixin() enables us to associate a piece of functionality with any component, without having to worry about how said functionality fits into some class hierarchy.</p>
<h1 id="guidelines"><a href="#guidelines">Guidelines<i class="icon-link"></i></a></h1>
<p>At RetailMeNot, we&#x2019;ve been using FlightJS since February 2014, and what we consider &quot;best practices&quot; has been continually evolving as the framework &#x2014; and our understanding of it has matured. We currently use the following set of guidelines while working on FlightJS code:</p>
<ul>
<li>Separate your concerns into single-purposed functions. This helps with unit testing and AB testing, as it becomes easy to override small bits of functionality. Such concerns may include: dom updating, analytics, ajax requests, internal state management</li>
<li>Keep functions small, if you find yourself writing a function that&#x2019;s more than 9&#x2013;10 lines of code, you&#x2019;re probably doing too much.</li>
<li>Look for opportunities to mix functionality into a component. Use component.mixin, and the advice API. This helps with not forking huge js files, and with identifying common functionality between components.</li>
<li>Look for repeated code, I guarantee there is almost always a way to not repeat it.</li>
<li>Avoid calling one function from another when possible, instead use event communication (internal or external), and the advice API.</li>
</ul>
<h1 id="missteps"><a href="#missteps">Missteps<i class="icon-link"></i></a></h1>
<p>When we first moved from FlightJS, we blindly ported most of our JS code into flight components. In hindsight this was probably unnecessary, given that <a href="http://www.retailmenot.com/corp/eng/posts/2014/08/28/how-flight-plays-well-with-non-flight-js/" target="_blank">Flight plays well with non-Flight JS</a>. This was a mistake that we are still paying for.</p>
<p>The beauty of FlightJS is that it encourages and enforces separation of concerns using a combination of functional mixins and aspect oriented programming paradigms. Unfortunately, the library doesn&#x2019;t stop you from putting too much code in any single file/function.</p>
<p>Our older JS code tended towards putting too much functionality in our functions, which our FlightJS components inherited when we ported over to FlightJS. Because of this, we started out of the gate with FlightJS by breaking many of the above guidelines. This made it difficult to leverage other aspects of the library, such as the advice API or component.mixin. As a result, our initially ported code is no easier to maintain then if we had never started using FlightJS.</p>
<p>We are refactoring our older FlightJS components to make them better-aligned with our guidelines. This will ensure the maintainability and testability of our components moving forward.</p>
<h1 id="lack-of-componentmixin-prior-to-flightjs-120"><a href="#lack-of-componentmixin-prior-to-flightjs-120">Lack of component.mixin prior to FlightJS 1.2.0<i class="icon-link"></i></a></h1>
<p>Before upgrading to FlightJS version 1.2.0, which added <a href="https://github.com/flightjs/flight/blob/v1.2.0/lib/component.js#L106" target="_blank">component.mixin()</a>, we had to include all of a component&#x2019;s desired functionality when we returned the result of calling component(). But what if we needed a component that is in all ways identical to the original component, except that it fires different analytics upon the user taking some action? Well, prior to the flight 1.2 upgrade, we were forced to split the bulk of out component&#x2019;s implementation into a mixin of it&#x2019;s own, for later inclusion in a particular component. This limitation combined with the fact that our functions were not small and single-purposed, forced us into some strange paradigms. Let&#x2019;s examine them:</p>
<p>Code for one of our components might typically look something like this:</p>
<p><strong>component.js</strong></p>
<pre><code class="language-javascript">define([
    <span class="hljs-string">&apos;flight/lib/component&apos;</span>
], <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(
    component
)</span></span>{
    <span class="hljs-keyword">return</span> component( componentCode );
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">componentCode</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Define default attributes for the component</span>
        <span class="hljs-keyword">this</span>.attributes({ <span class="hljs-comment">/*...*/</span> });
        <span class="hljs-comment">// Once the user has successfully completed an action, update the DOM accordingly</span>
        <span class="hljs-keyword">this</span>.updateDomOnSuccess = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> </span>{ <span class="hljs-comment">/*...*/</span> };
        <span class="hljs-comment">// Fire analytics indicating that the user has successfully completed an action</span>
        <span class="hljs-keyword">this</span>.doSuccessAnalytics = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> </span>{ <span class="hljs-comment">/*...*/</span> };
        <span class="hljs-comment">// Set up listeners to make the component do things</span>
        <span class="hljs-keyword">this</span>.after( <span class="hljs-string">&apos;initialize&apos;</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> </span>{ <span class="hljs-comment">/*...*/</span> });
    }
});</code></pre>
<p>But what if we want to start using this component in two different places on the site, and in one context we want to run a different doSuccessAnalytics() function?</p>
<p>Prior to the FlightJS 1.2 upgrade, we would do it this way:</p>
<h1 id="the-override-functions-in-the-attachto-approach"><a href="#the-override-functions-in-the-attachto-approach">The &quot;Override Functions in the attachTo&quot; Approach<i class="icon-link"></i></a></h1>
<p><strong>component.js, with abstracted analytics</strong></p>
<pre><code class="language-javascript">define([
    <span class="hljs-string">&apos;flight/lib/component&apos;</span>
], <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(
    component
)</span></span>{
    <span class="hljs-keyword">return</span> component( componentCode );
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">componentCode</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Define default attributes for the component</span>
        <span class="hljs-keyword">this</span>.attributes({
            <span class="hljs-comment">// default analytics implementation for component</span>
            successAnalyticsImplementation**:** <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> </span>{ <span class="hljs-comment">/*...*/</span> }
        });
        <span class="hljs-comment">// Once the user has successfully completed an action, update the DOM accordingly</span>
        <span class="hljs-keyword">this</span>.updateDomOnSuccess = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> </span>{ <span class="hljs-comment">/*...*/</span> };
        <span class="hljs-comment">// Fire analytics indicating that the user has successfully completed an action</span>
        <span class="hljs-keyword">this</span>.doSuccessAnalytics = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> </span>{
            <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.attr.successAnalyticsImplementation){
                <span class="hljs-keyword">this</span>.attr.successAnalyticsImplementation();
            }
        };
        <span class="hljs-comment">// Set up listeners to make the component do things</span>
        <span class="hljs-keyword">this</span>.after( <span class="hljs-string">&apos;initialize&apos;</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> </span>{ <span class="hljs-comment">/*...*/</span> });
    }
});</code></pre>
<p>With the above set of changes, we now have the ability to override the analytics function by passing a different implementation in via the .attachTo call for our component&#x2019;s different context. But is this much better? All we have done is push concern of analytics for a component up to the page level, where these components are being attached. This introduces the potential issue of failing to fire analytics when we add our components to new pages (by omitting an analytics implementation).</p>
<p>To rectify the aforementioned issue, we shifted to the following pattern:</p>
<h1 id="the-move-the-bulk-of-your-components-implementation-into-a-mixin-approach"><a href="#the-move-the-bulk-of-your-components-implementation-into-a-mixin-approach">The &quot;Move the Bulk of your Component&#x2019;s Implementation Into a Mixin&quot; Approach<i class="icon-link"></i></a></h1>
<p><strong>mixins/with-component-core.js</strong></p>
<pre><code class="language-javascript">define([
    <span class="hljs-string">&apos;flight/lib/component&apos;</span>
], <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(
    component
)</span></span>{
    <span class="hljs-keyword">return</span> componentCode;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">componentCode</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Define default attributes for the component</span>
        <span class="hljs-keyword">this</span>.attributes({ <span class="hljs-comment">/*...*/</span> });
        <span class="hljs-comment">// Once the user has successfully completed an action, update the DOM accordingly</span>
        <span class="hljs-keyword">this</span>.updateDomOnSuccess = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> </span>{ <span class="hljs-comment">/*...*/</span> };
        <span class="hljs-comment">// Fire analytics indicating that the user has successfully completed an action</span>
        <span class="hljs-keyword">this</span>.doSuccessAnalytics = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> </span>{
            <span class="hljs-comment">// default analytics implementation for component</span>
        };
        <span class="hljs-comment">// Set up listeners to make the component do things</span>
        <span class="hljs-keyword">this</span>.after( <span class="hljs-string">&apos;initialize&apos;</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> </span>{ <span class="hljs-comment">/*...*/</span> });
    }
});</code></pre>
<p>This pulls the bulk our components implementation into a mixin, to be shared between different implementations of the component as follows:</p>
<p><strong>component.js</strong></p>
<pre><code class="language-javascript">define([
    &apos;mixins/with-component-core&apos;
    &apos;flight/lib/component&apos;
], function(
    <span class="hljs-name">componentCore</span>
    component
){
    return component( <span class="hljs-name">componentCore</span> )<span class="hljs-comment">;</span>
})<span class="hljs-comment">;</span></code></pre>
<p><strong>tests/component.js &#x2014; with variation in analytics</strong></p>
<pre><code class="language-javascript">define([
    <span class="hljs-string">&apos;mixins/with-component-core&apos;</span>
    <span class="hljs-string">&apos;flight/lib/component&apos;</span>
], <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(
    componentCore
    component
)</span></span>{
    <span class="hljs-keyword">return</span> component( componentCore, withVariationInAnalytics );
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">withVariationInAnalytics</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Fire analytics indicating that the user has successfully completed an action</span>
        <span class="hljs-keyword">this</span>.doSuccessAnalytics = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> </span>{
            <span class="hljs-comment">// overriding analytics implementation for our test</span>
        }
    };
});</code></pre>
<p>Following this approach, we can now provide a default analytics implementation, override it at the component level, and not have to worry about remembering to include it when we add the component to a new context. However, we were forced to move the majority of our component&#x2019;s implementation into a mixin, one that can essentially stand alone as a component, which totally defeats the purpose of the mixin pattern.</p>
<p>Enter FlightJS 1.2, which introduced <a href="https://github.com/flightjs/flight/blob/v1.2.0/lib/component.js#L106" target="_blank">component.mixin()</a>. We can now solve this problem as follows:</p>
<h1 id="the-flight-12s-componentmixin-function-is-the-answer-to-all-of-our-problems-approach"><a href="#the-flight-12s-componentmixin-function-is-the-answer-to-all-of-our-problems-approach">The &quot;Flight 1.2&#x2019;s component.mixin Function is the Answer to All of Our Problems&quot; Approach<i class="icon-link"></i></a></h1>
<p><strong>component.js</strong></p>
<pre><code class="language-javascript">define([
    <span class="hljs-string">&apos;flight/lib/component&apos;</span>
], <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(
    component
)</span></span>{
    <span class="hljs-keyword">return</span> component( componentCode );
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">componentCode</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Define default attributes for the component</span>
        <span class="hljs-keyword">this</span>.attributes({ <span class="hljs-comment">/*...*/</span> });
        <span class="hljs-comment">// Once the user has successfully completed an action, update the DOM accordingly</span>
        <span class="hljs-keyword">this</span>.updateDomOnSuccess = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> </span>{ <span class="hljs-comment">/*...*/</span> };
        <span class="hljs-comment">// Fire analytics indicating that the user has successfully completed an action</span>
        <span class="hljs-keyword">this</span>.doSuccessAnalytics = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> </span>{
            <span class="hljs-comment">// default analytics implementation for component</span>
        };
        <span class="hljs-comment">// Set up listeners to make the component do things</span>
        <span class="hljs-keyword">this</span>.after( <span class="hljs-string">&apos;initialize&apos;</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> </span>{ <span class="hljs-comment">/*...*/</span> });
    }
});</code></pre>
<p><strong>tests/component.js &#x2014; with variation in analytics</strong></p>
<pre><code class="language-javascript">define([
    <span class="hljs-string">&apos;component&apos;</span> <span class="hljs-comment">// path to component.js</span>
], <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(
    originalComponent
)</span></span>{
    <span class="hljs-keyword">return</span> originalComponent.mixin( analyticsOverride );
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">analyticsOverride</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Fire analytics indicating that the user has successfully completed an action</span>
        <span class="hljs-keyword">this</span>.doSuccessAnalytics = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// overriding analytics implementation for our test</span>
        }
    };
});</code></pre>
<p>This new pattern solves the aforementioned issues, and comes with the following benefits:</p>
<ul>
<li>We can implement the component as it is intended to behave in the majority of cases.</li>
<li>We can provide variations of the existing component without having to touch our original component.</li>
<li>As a bonus, it is much more semantically clear as to what we are trying to achieve for the purpose of our test.</li>
</ul>
<p>By following the guidelines above, and leveraging the power of FlightJS and its component.mixin() function, it becomes easy to write testable client-side JavaScript that encapsulates functionality in a clear, concise manner. As a result the reading, reasoning about, and extending the code becomes much more straight-forward because our component definitions are more expressive and easy to follow. We hope you find the mixin() pattern as valuable as we do.</p>
<p>Originally published at <a href="http://www.retailmenot.com/corp/eng/posts/2014/11/18/mixin-it-up-with-flightjs/" target="_blank">www.retailmenot.com</a> on November 18, 2014. Now available at <a href="https://engineering.ziffmedia.com/mixin-it-up-with-flightjs-7070d075729" target="_blank">engineering.ziffmedia.com</a>. Forever available on <a href="/blog/post/mix-it-up-flightjs">Luke&apos;s Blog</a></p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/mix-it-up-flightjs</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/mix-it-up-flightjs</guid>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Mon, 17 Nov 2014 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[scriptdown - Markdown for TV or Movie Scripts]]></title>
            <description><![CDATA[<p><strong>Update 2015:</strong> I have discovered <a href="https://fountain.io" target="_blank">fountain</a>, an evolved implementation of this same idea.</p>
<p>As stated in my <a href="/blog/post/since-graduation#writing-a-tv-show">Since Graduation</a> post, I have been working on a TV show script. I&apos;ve been playing with different software for writing scripts. I&apos;ve tried Apple&apos;s Pages (with my own custom template), a trial of <a href="https://www.finaldraft.com" target="_blank">Final Draft</a> (which I decided not to pay for), among other things. As a coder who is accustomed to working with plain text, none of these solutions are ideal for me.</p>
<p>One night, I thought: what if I could write my TV scripts in plain text just as I do my blog posts? So I created <a href="https://github.com/lzilioli/scriptdown" target="_blank">scriptdown</a>. Inspired by <a href="https://daringfireball.net/projects/markdown/" target="_blank">Markdown</a>. For me, this is the optimal way to write TV scripts. I can track them in a git repository and treat them like code. The coder in me loves it.</p>
<p>This project was also a quick way to play with Python. I won&apos;t update or enhance this script beyond my own needs, but it was a fun little project to throw together.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/scriptdown</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/scriptdown</guid>
            <category><![CDATA[open source]]></category>
            <category><![CDATA[portfolio]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Wed, 28 May 2014 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[RetailMeNot]]></title>
            <description><![CDATA[<p>At the time of my <a href="/blog/post/since-graduation">Graduation and Beyond post</a>, I was hunting for a job. Not long after making that post, I officially accepted an offer for a position as a UI Engineer at RetailMeNot in Austin, TX.</p>
<p>I have since paused my TV writing ambitions, packed up my apartment in Ann Arbor, moved to Austin, and began working at RetailMeNot.</p>
<p>I&apos;ve learned A LOT. The UI team is led by <a href="https://craveytrain.com/" target="_blank">Mike Cravey</a>, he&apos;s a great leader and has helped me grow and begin to realize my potential as a software engineer.</p>
<p>I won&apos;t go into too much detail about what I&apos;ve worked on in my short time here, but some highlights:</p>
<ul>
<li>Lots of front-end components and improvements.</li>
<li>I&apos;ve refactored numerous components for reuse across different contexts.</li>
<li>I built an admin tool for our marketing team to generate the html for their weekly emails. This saved them hours each week by automating a previously manual process.</li>
<li>I worked with two other engineers, a project manager, and a designer to redesign our mobile website</li>
<li>RetailMeNot relies on being at the top of Google&apos;s search results. Thus our pages need to be fast and highly ranked. I have worked on performance improvements to the end of speeding up the webpage and boosting SEO.</li>
<li>I&apos;ve implemented lots of AB tests that we have run on the website to help us optimize our user&apos;s experience and reduce their bounce rate back to Google search.</li>
</ul>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/retailmenot</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/retailmenot</guid>
            <category><![CDATA[portfolio]]></category>
            <category><![CDATA[web dev]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Wed, 01 Jan 2014 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[A Big Win for The Coalition For Tuition Equality]]></title>
            <description><![CDATA[<p>Back in <a href="https://www.lukezilioli.com/blog/?id=13" title="Previous blog post">October</a> I wrote about a website I made for the Coalition For Tuition Equality, <a href="https://www.lukezilioli.com/labs/mdibt/" title="My Dream Is Bigger Than">My Dream Is Bigger Than</a> (pictured above).</p>
<p>Since the site went live, a lot has happened. We had the protest on October 25, and the CTE has remained hard at work on this issue.</p>
<p>I just wanted to give them a quick shout-out. Today, everyone involved in this effort is celebrating a <a href="http://annarbor.com/news/university-of-michigan-governing-board-passes-tuition-equality-for-military-unauthorized-immigrants/" target="_blank">big win</a>. The University of Michigan Regents voted on the issue, approving a change to Michigan&apos;s residency guidelines.</p>
<blockquote>
<p>The approval means affected students pay $27,250 less in tuition. In the fall Michigan residents will pay $13,142 a year, while non-residents will pay $40,392. Under current tuition levels, the difference amounts to $109,000 over the course of four years.</p>
</blockquote>
<p>Many people fought long and hard for this, and <a href="http://www.fokus.org" target="_blank">FOKUS&apos;</a> My Dream Is Bigger Than campaign was just the beginning.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/a-big-win-for-the-coalition-for-tuition-equality</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/a-big-win-for-the-coalition-for-tuition-equality</guid>
            <category><![CDATA[web dev]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Fri, 19 Jul 2013 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[PSA: W3Schools]]></title>
            <description><![CDATA[<p>I want to share with you something that I was lucky enough to find very early while learning web development.</p>
<h1 id="audience"><a href="#audience">Audience<i class="icon-link"></i></a></h1>
<p>The intended audience for this post is web developers, as the information is only useful to them, but anyone who reads it might learn something.</p>
<h1 id="background"><a href="#background">Background<i class="icon-link"></i></a></h1>
<p>As most people know, I have been very interested in web development, which I have been learning and working on for quite some time. When I started learning, like most people, Google was my best friend. Anything I needed to know about web development, I would search on Google. Anyone who started learning web development this way should recognize the name <a href="https://www.w3schools.com/" target="_blank">w3schools</a>, which is commonly ranked very high in Google&apos;s results. Fortunately, I also am a big fan of StackOverflow, and frequently ask questions and search for answers on there as well. Fortunately, one day early in my learning days, I stumbled across <a href="https://stackoverflow.com/questions/1946426/html-5-is-it-br-br-or-br#comment5178414_1946426" target="_blank">this comment on StackOverflow</a>, which is in response to a question that referenced <a href="https://www.w3schools.com/" target="_blank">w3schools</a>.</p>
<blockquote>
<p>w3schools is a terrible reference. Please avoid it, and don&apos;t trust information they publish.</p>
</blockquote>
<p>and the next comment:</p>
<blockquote>
<p>check out: <a href="http://w3fools.com/" target="_blank">w3fools.com</a> for evidence of w3schools poor quality</p>
</blockquote>
<p>I suggest that you read w3fools, not only to see the argument against w3schools, but also because you will learn a lot of small nuances about web development in doing so.</p>
<h1 id="conclusion"><a href="#conclusion">Conclusion<i class="icon-link"></i></a></h1>
<p>Because it can sometimes provide incorrect information, and typically when I end up on the site, its for information I don&apos;t know, I wanted to avoid the site altogether. As suggested at the bottom of w3fools <a href="http://w3fools.com/#road-ahead" target="_blank">here</a>, I blocked it from my Google results.</p>
<p>After educating myself on this matter, I turned to <a href="https://meta.stackoverflow.com/questions/87678/discouraging-w3schools-as-a-resource" target="_blank">this StackOverflow question</a> which helped shape my ultimate opinion. Read through the question and answers yourself, but my takeaway can be best summed up with the following excerpt from <a href="https://meta.stackoverflow.com/a/87680" target="_blank">this</a> answer:</p>
<blockquote>
<p>In short, we should be thinking for ourselves when deciding what specific page is a good reference, not relying on a blanket statement made by a 3rd party.</p>
</blockquote>
<p>Which is really just a good rule to follow in life.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/psa-w3schools</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/psa-w3schools</guid>
            <category><![CDATA[web dev]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Tue, 19 Mar 2013 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Goodbye Google Reader]]></title>
            <description><![CDATA[<p>Google announced on Wednesday that as part of its annual <a href="https://googleblog.blogspot.com/2013/03/a-second-spring-of-cleaning.html" target="_blank">spring cleaning</a> initiative it will be <a href="https://googlereader.blogspot.com/2013/03/powering-down-google-reader.html" target="_blank">shutting down Google Reader</a>. This saddens me, because now I have no idea how I will get my daily dose of news. My go-to Google Reader client on the Mac, iPhone, and iPad is <a href="https://reederapp.com/" target="_blank">Reeder</a>. I love Reeder for its simple, intuitive and functional interface. Fortunately, following the announcement, the devs of Reeder tweeted the following. So it looks like I don&apos;t have to worry.</p>
<blockquote class="twitter-tweet"><p>Don&apos;t worry, Reeder won&apos;t die with Google Reader.</p>&#x2014; Reeder (@reederapp) <a href="https://twitter.com/reederapp/status/311995748482945025" target="_blank">March 14, 2013</a></blockquote>

<p>The real purpose of this post, however, is to inform people what Google Reader <s>is</s> was, because a surprising number of people I have talked to have told me they had no idea.</p>
<p>Google Reader is an <a href="http://en.wikipedia.org/wiki/RSS" target="_blank">RSS</a> client, so in order to understand what Google Reader is, you must first understand what RSS is. RSS stands for &quot;Rich Site Summary&quot;, or &quot;Really Simple Syndication&quot;. Most news sites or blogs publish what is called an RSS feed. This feed is a file that can be accessed over the internet that represents a list of all of the content that has been published to the site. For example, Twitter publishes RSS feeds for each of its user&apos;s tweets. An RSS reader could subscribe to this feed, and use it to display a user&apos;s recent tweets to a subscriber of the feed.</p>
<p>Google Reader had the added bonus of living &apos;in the cloud&apos;, which means it could act as a central hub for my client, &quot;Reeder&quot;. This enabled my read and starred status of articles to keep in sync across all three of my devices, so reading an article on my iPhone would mark it read on my Mac and my iPad when those clients synced with Google Reader.</p>
<p>On the technical side of things, this RSS feed is represented as an XML document, you can view the feed for <a href="https://www.theverge.com/" target="_blank">The Verge</a> by visiting the following URL: <a href="https://www.theverge.com/rss/frontpage" target="_blank">https://www.theverge.com/rss/frontpage</a>. You should view the RSS feed so that the next paragraph makes sense to you.</p>
<p>An RSS reader maintains a list of all of the feeds that a user has subscribed to, and displays to them a list of posts for each feed. As you saw, the XML document is not pretty. To a human, it is almost unreadable, but it is in the exact format a computer needs in order to be able to understand it as a list of articles. You might have noticed a bunch of similar looking blocks in the RSS feed, such as this one:</p>
<pre><code class="language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">entry</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">published</span>&gt;</span>2013-03-141T17:59:20-05:00<span class="hljs-tag">&lt;/<span class="hljs-name">published</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">updated</span>&gt;</span>2013-03-15T17:59:20-07:04<span class="hljs-tag">&lt;/<span class="hljs-name">updated</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span> ... <span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">content</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;html&quot;</span>&gt;</span> ... <span class="hljs-tag">&lt;/<span class="hljs-name">content</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">&quot;alternate&quot;</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text/html&quot;</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;...&quot;</span>/&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">id</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">id</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">author</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">name</span>&gt;</span> ... <span class="hljs-tag">&lt;/<span class="hljs-name">name</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">author</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">entry</span>&gt;</span></code></pre>
<p>Notice how this item is surrounded by an opening <code>&lt;entry&gt;</code> and a closing <code>&lt;/entry&gt;</code> tag. Each article is represented as an entry, and within each item there is information such as the title, a link, and the date the article was published. This opening and closing tag convention comes in handy for the computer to make sense of the XML document. The opening and closing tags help the reader separate the document into a list of items, and learn important information about each item. The RSS reader does so through a process called <a href="https://en.wikipedia.org/wiki/Parsing" target="_blank">parsing</a>.</p>
<p>Once the RSS reader has parsed the document, it can use the parsed data to display articles in a way that is meaningful to you, the user.</p>
<p>The loss of Google Reader creates a big hole for many people that needs to be filled. I am eager to see who fills it in, hopefully breathing new life into RSS along the way.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/goodbye-google-reader</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/goodbye-google-reader</guid>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Fri, 15 Mar 2013 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Graduation and Beyond]]></title>
            <description><![CDATA[<h1 id="hail-yeah"><a href="#hail-yeah">Hail yeah!!<i class="icon-link"></i></a></h1>
<p>On December 16, 2012, I graduated from the University of Michigan with a Bachelors of Science degree in Computer Science from the College of Literature, Science, and the Arts.</p>
<h1 id="whatve-you-been-up-to"><a href="#whatve-you-been-up-to">What&apos;ve you been up to?<i class="icon-link"></i></a></h1>
<p>A lot of people have asked me what I&apos;ve been up to since graduation, and why I, like most graduates, didn&apos;t start a job straight out the gate. I&apos;ve been doing a few things:</p>
<h2 id="writing-a-tv-show"><a href="#writing-a-tv-show">Writing a TV show<i class="icon-link"></i></a></h2>
<p>I have always loved film, and have taken a few courses through the film department here at Michigan. Last semester, I took SAC 311, an introductory TV writing class in which I wrote an episode of an existing TV show. I wrote an episode of Modern Family.</p>
<p>Last semester, while in this class, I also began working on an original idea for a TV pilot with a friend of mine who recently graduated from Michigan&apos;s Screen Arts and Culture department (read: film). The show is a Louie-esque comedy about recent college graduates in the city of Detroit. We have been working diligently to complete the pilot, and our goal is to have it completed within a couple of months. Since graduating, we have ramped up our efforts on the show, and I have been unofficially auditing SAC 411, the second level TV writing course at Michigan, in order to learn further about writing TV pilots.</p>
<h2 id="working-on-web-development"><a href="#working-on-web-development">Working on web development<i class="icon-link"></i></a></h2>
<p>Since my internship at Zappos this summer, I have taken a big interest in web development (in particular, front end development), and have been doing as much as I can to learn more about it.</p>
<h2 id="tech-advisor-for-bitbox"><a href="#tech-advisor-for-bitbox">Tech advisor for BitBox<i class="icon-link"></i></a></h2>
<p>A good friend of mine is working on starting a company, BitBox. He wants to provide an effortless exchange between <a href="https://en.wikipedia.org/wiki/Bitcoin" target="_blank">Bitcoin</a>, an emerging online currency, and the US dollar; in hopes of helping Bitcoin become more mainstream and accessible to the masses.</p>
<p>I have been helping BitBox flesh out their technical direction, help with their website, spread the word about Bitcoin, and screen potential candidates for employment. Additionally, I will be working with them to perfect their pitch, and joining them on the 2013 <a href="https://web.archive.org/web/20130125004620/http://cfe.umich.edu/startup-treks" target="_blank">Bay Area Entrepreneurial Experience</a> (now called the Weather Underground Startup Trek), a University of Michigan sponsored event for entrepreneurs.</p>
<h2 id="visiting-my-grandma"><a href="#visiting-my-grandma">Visiting my grandma<i class="icon-link"></i></a></h2>
<p>Toward the end of last year, my grandmother has not been doing as well as she&apos;d been doing in months prior, so I&apos;ve been taking out a little extra time to visit her more regularly.</p>
<h2 id="job-hunting"><a href="#job-hunting">Job hunting<i class="icon-link"></i></a></h2>
<p>This should go without saying.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/since-graduation</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/since-graduation</guid>
            <category><![CDATA[portfolio]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Sun, 16 Dec 2012 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[iOS Development: EECS 101]]></title>
            <description><![CDATA[<p>Last semester, I did an independent study to learn iOS development with my best friend, x roommate, and fellow CS student Mike.</p>
<h1 id="introduction"><a href="#introduction">Introduction<i class="icon-link"></i></a></h1>
<p><img class="callout" src="/images/ap_eecs_icon.png" title="AP" eecs app icon> Mike and I, both being Computer Science students, have grown very passionate about Computer Science as a field of study. Unfortunately for us neither of us had any exposure to CS prior to EECS 183/ENGIN 101 here at the University. Such is the case for every student within the Detroit Public School district where there is no curriculum in place to teach students any amount of Computer Science, which is the fastest growing industry in the world today. If we are serious about preparing our children for the future past High School, we are doing them a disservice by not offering them any Computer Science related courses.</p>
<p>Our greater goal is to design an after school program curriculum to expose High School students to Computer Science. A part of that goal, is enabling them to teach themselves, and ultimately prepare for the AP EECS exam.</p>
<p>To help us achieve this goal, we developed an iPad application, with an accompanying study guide that aims to give the student a broad understanding of the content that will be on the AP EECS exam. This app, in conjunction with other resources, helps prepare the student for the AP EECS exam. This app can be used as part of achieving our wider goal of offering an after-school Computer Science course in High Schools that don&#x2019;t otherwise offer any computer science related content.</p>
<h1 id="eecs-101-at-uofm"><a href="#eecs-101-at-uofm">EECS 101 at UofM<i class="icon-link"></i></a></h1>
<p>Last semester marked the first offering of EECS 101, a course taught by Jeff Ringenberg which is designed to be equivalent to the new, more theoretical AP EECS exam. Having this class offered at UofM enables the University to accept AP EECS credit from incoming students who did well on the AP EECS test. We worked with Dr. Ringenberg and used his course slides and information in designing the study guide and accompanying questions for this app.</p>
<h1 id="the-study-guide"><a href="#the-study-guide">The Study Guide<i class="icon-link"></i></a></h1>
<p>Half of the goal of this independent study was to have a study guide that clearly, and concisely presents the student with AP EECS course content. This study guide is embedded within the application behind the &#x201C;Study&#x201D; button in the upper-right hand corner.</p>
<h1 id="the-app"><a href="#the-app">The App<i class="icon-link"></i></a></h1>
<p>The app itself is primarily a question asking application that enables the user to study the content in the study guide. A button in the top right of the app, labeled &#x201C;Topics&#x201D; will present the user with a list of topics that they can study in-app. Selecting a topic causes the app to begin asking the user questions for the selected topic. As the user cycles through the questions, their progress is tracked and saved, so they can track their progress as they learn the material.</p>
<p>The content of the questions that the app asks are defined using xml, and adding new topics or questions is as easy as modifying the xml file. The app supports various question types, and developers can easily add new ones by inheriting from a base class that we created. Additionally, images can be added to the questions within the XML file by just adding an attribute to that question.</p>
<h2 id="the-outcome"><a href="#the-outcome">The Outcome<i class="icon-link"></i></a></h2>
<p>When we first set out to create this app, we had the vision of using it as just a study guide for EECS 101. Along the way, however, we realized that this app can be used as a study platform for literally any subject one wants. After this was decided, we abstracted the app enough to be able to handle questions from any subject, as long as they follow the construct we created for questions. Making the app in this manner opens up the opportunity for growth in any area of study, anyone can create a &apos;course&apos;, upload it to the internet, tell the app where to look for it, and study the materials provided.</p>
<p>I am in talks with a professor at the university about turning the source code over to Michigan for continued development. Unfortunately, neither Mike nor I have had any time to do much with the app since we&apos;ve handed it in, but a few screenshots are below to illustrate the way it works.</p>
<p><img src="/images/apeecs1.png" alt>
<img src="/images/apeecs2.png" alt>
<img src="/images/apeecs3.png" alt></p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/cs-101-app</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/cs-101-app</guid>
            <category><![CDATA[iOS]]></category>
            <category><![CDATA[portfolio]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Sat, 15 Dec 2012 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Video Game Development: B1G Brawl]]></title>
            <description><![CDATA[<p>Last semester, I took <em>EECS 494 - Computer Game Development and Design</em> here at UofM. For our final project, my team made a game called B1G Brawl (Big Ten Brawl), a Super Smash Bros. style fighting game, except instead of Nintendo characters, we used Michigan and our three biggest rivals in football, Ohio State, Michigan State, and Notre Dame. Each school&apos;s &apos;mascot&apos; faces off in an epic battle to the death.</p>
<p>We created the animations in Adobe Flash CS6, and all of the code in C# using Microsoft&apos;s XNA.</p>
<p>Embedded above, you&apos;ll find a video of the game in action. The battle you see takes place at Michigan&apos;s <a href="https://en.wikipedia.org/wiki/Burton_Memorial_Tower" target="_blank">Burton Memorial Tower</a> between Rudy of Notre Dame, Brutus of Ohio State, and Denard Robinson of Michigan.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/b1g-brawl</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/b1g-brawl</guid>
            <category><![CDATA[portfolio]]></category>
            <category><![CDATA[video games]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Fri, 14 Dec 2012 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Welcome to the New lukezilioli.com]]></title>
            <description><![CDATA[<p>When I first created my personal website, I was relatively new to web development. This and other decisions led me to release my site as a WordPress blog despite the fact that I never have been a WordPress fan because I&apos;ve always thought that it is too bloated, and restrictive. It has always been my philosophy that not only do you have to make good software, but you have to make software that people <strong>want</strong> to use. WordPress, at least for me, does not fall into that category, so having to use WordPress to post to my blog has, in the past, discouraged me from actually using it.</p>
<p>Luckily, my <a href="https://www.lukezilioli.com/blog/?id=9">summer experience</a> got me heavily into web development, so I decided to rectify this issue. The new <a href="https://www.lukezilioli.com">lukezilioli.com</a> is a project I built from the ground up. It fits my needs very well, and I suspect the simplicity would be enticing to some would-be bloggers, but currently I only intend on using it for my own personal use.</p>
<p>Right now, much more energy has been put into the site itself, and little has been put into the content. Now that the new version of the site is up and running, I intend to change that, and will be posting more content.</p>
<p>Jeff Atwood has tried to make the argument that <a href="https://www.codinghorror.com/blog/2009/07/software-engineering-dead.html" target="_blank">Software Engineering is dead</a>. I see a lot of merit behind the software engineering process itself, so I don&apos;t agree with Atwood&apos;s conclusion, however I wholeheartedly agree with one of his arguments: there is a certain aspect of craftsmanship involved in making software products that doesn&apos;t exist with other forms of engineering. Nothing makes me feel like a craftsman more than web development, which at its core is a combination of many existing and emerging technologies. In the Shoutouts section below, I discuss many utilities that I have used and integrated while working on my site.</p>
<h1 id="shoutouts"><a href="#shoutouts">Shoutouts<i class="icon-link"></i></a></h1>
<h2 id="markdown"><a href="#markdown">Markdown<i class="icon-link"></i></a></h2>
<p>In the past year, I have fallen in love with <a href="https://daringfireball.net/projects/markdown/" target="_blank">markdown</a> and its syntax. Because of this, I knew I wanted to write my blog posts in markdown, so I took the simplest approach I could think of. Every post you see on this site is a simple .md file. There is a file called meta.json which contains information for each blog post on the site. Each entry in this file corresponds to one markdown file. As an example, the post you are currently viewing is represented as:</p>
<pre><code class="language-json"><span class="hljs-comment">&quot;id&quot;</span>:<span class="hljs-comment">&quot;13&quot;</span>,
<span class="hljs-comment">&quot;title&quot;</span>:<span class="hljs-comment">&quot;Welcome to the New lukezilioli.com&quot;</span>,
<span class="hljs-comment">&quot;filename&quot;</span>:<span class="hljs-comment">&quot;lzcom.md&quot;</span>,
<span class="hljs-comment">&quot;format&quot;</span>:<span class="hljs-comment">&quot;md&quot;</span>,
<span class="hljs-comment">&quot;date&quot;</span>:<span class="hljs-comment">&quot;2012-11-05&quot;</span>,</code></pre>
<p>Currently, I have to enter this information manually, but I plan to implement a page that enables me to create new posts directly on the site.</p>
<h2 id="sass"><a href="#sass">Sass<i class="icon-link"></i></a></h2>
<p>One thing I love about web development is CSS and the ability to directly command the layout of a page. While CSS is great, it definitely has its shortcomings. Designed to rectify many of CSS&apos;s shortcomings, is <a href="https://sass-lang.com/" target="_blank">Sass</a>. There are many great features of Sass which you can check out on their website, but by far my favorite is the ability to add @media queries to your CSS with a few lines of code using mixins.</p>
<p>The following, which declares that the header should have a left margin of 10px, unless the page is being viewed on a mobile device, in which case, it should have a left margin of 0px, would look like this in CSS:</p>
<pre><code class="language-css"><span class="hljs-meta">#header {</span>
    <span class="hljs-comment">// Other styling for header</span>
    margin-left: <span class="hljs-number">10</span>px;
}

@<span class="hljs-function">media only screen <span class="hljs-title">and</span> <span class="hljs-params">(<span class="hljs-built_in">min</span>-device-<span class="hljs-built_in">width</span>: <span class="hljs-number">320</span>px)</span> <span class="hljs-title">and</span> <span class="hljs-params">(<span class="hljs-built_in">max</span>-device-<span class="hljs-built_in">width</span>: <span class="hljs-number">800</span>px)</span> </span>{
    <span class="hljs-meta">#header {</span>
        margin-left: <span class="hljs-number">0</span>px;
    }
}</code></pre>
<p>and like this in Sass:</p>
<pre><code class="language-css">    <span class="hljs-selector-id">#header</span> {
        <span class="hljs-comment">// Other styling for header</span>
        <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">10px</span>;
        <span class="hljs-variable">@include</span> respond-to(mobile) { <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">0px</span>; }
    }</code></pre>
<p>This is much cleaner and easier to read. By looking at the styling under <code>#header</code>, we can easily see what was less obvious in the CSS example.</p>
<p>Such functionality is thanks to mixins, and a tutorial of how to do what I just discussed can be found <a href="http://thesassway.com/intermediate/responsive-web-design-part-2" target="_blank">here</a>. Under the heading: &quot;The Future of <a href="http://cssmediaqueries.com/" target="_blank">Media Queries</a> in Sass&quot;</p>
<h2 id="prettifyjs"><a href="#prettifyjs">Prettify.js<i class="icon-link"></i></a></h2>
<p><a href="https://github.com/google/code-prettify" target="_blank">Prettify.js</a> is a neat little javascript utility that allows me to have syntax highlighting on my site. Once a post has loaded, prettify jumps in and separates the code blocks into a bunch of <code>&lt;span&gt;</code>s, whose classes I can target in my CSS for syntax coloring. Neat, huh?</p>
<h2 id="zeroclipboard"><a href="#zeroclipboard">ZeroClipboard<i class="icon-link"></i></a></h2>
<p>If you are viewing this page on a computer with flash installed and enabled, you should see a little white file icon within code blocks. Hovering on this icon reveals its purpose: to copy the code to the clipboard. To achieve this, I used the plugin <a href="https://github.com/jonrohan/ZeroClipboard" target="_blank">ZeroClipboard</a>, which &apos;glues&apos; a small flash video on top of the file icon. This video captures the click and uses flash to place text on your clipboard.</p>
<h2 id="twitter-bootstrap"><a href="#twitter-bootstrap">Twitter Bootstrap<i class="icon-link"></i></a></h2>
<p><a href="https://twitter.github.com/bootstrap/" target="_blank">Twitter Bootstrap</a> is just fantastic. I relied on it much more this summer, however it was a great reference in styling things such as pre and code blocks.</p>
<h2 id="fontawesome"><a href="#fontawesome">FontAwesome<i class="icon-link"></i></a></h2>
<p><a href="https://fortawesome.github.com/Font-Awesome/" target="_blank">FontAwesome</a> is really great. It offers tons of scalable icons that designers can add to their site. These icons look great no matter the size you make them, and no matter the device on which they are being displayed, no more retina woes with bootstrap&apos;s glyphicons.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/welcome</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/welcome</guid>
            <category><![CDATA[portfolio]]></category>
            <category><![CDATA[web dev]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Mon, 05 Nov 2012 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[My Dream is Bigger Than...]]></title>
            <description><![CDATA[<p>I recently made a website for a protest organized by the <a href="http://tuitionequality.org/" target="_blank">Coalition for Tuition Equality</a> (CTE), a student organization on campus. They, along with a bunch of partner organizations are fighting the UofM Regents for tuition equality; to allow undocumented students who grew up in Michigan, and whose parents pay Michigan taxes to pay in state tuition. Currently, they have to pay out of state tuition, which is entirely unfair and unjust. The current policies treat education as more of a privilege than a human right.</p>
<p>When <a href="http://fokus.org/" target="_blank">FOKUS</a>, a student org I&apos;m in decided to join the CTE last year, I was very excited at the prospect of helping them out in any way possible. This year, when we stepped up to the plate to help them promote their  protest on October 25, I jumped at the opportunity to be on the committee. It was a good opportunity to support a good cause, and learn some more web development.</p>
<p>Check out the website I created <a href="https://www.lukezilioli.com/labs/mdibt/">here</a>. The site was designed by the incredibly talented <a href="http://www.mallikaaroy.com/" target="_blank">Mallika Roy</a>.</p>
<h1 id="update---20121025"><a href="#update---20121025">Update - 2012/10/25<i class="icon-link"></i></a></h1>
<p>The protest was today, and it was a success. The Michigan Daily wrote an article about it. Check that out <a href="https://www.michigandaily.com/news/10students-protest-tuition-equality25" target="_blank">here</a>.</p>
<h1 id="update---20130718"><a href="#update---20130718">Update - 2013/07/18<i class="icon-link"></i></a></h1>
<p>The Regents voted on the issue today. Read more <a href="https://www.lukezilioli.com/blog/?id=25">here</a>.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/my-dream-is-bigger-than</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/my-dream-is-bigger-than</guid>
            <category><![CDATA[portfolio]]></category>
            <category><![CDATA[web dev]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Wed, 17 Oct 2012 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[ToDo Featured on University of Michigan Computer Science and Engineering Homepage]]></title>
            <description><![CDATA[<p><strong>Update 2020-01-01</strong>: Links to Google Play Store removed since ToDo is no longer being sold or maintained.</p>
<p><img class="callout" style="width:300px;" src="/images/finishit_icon.png" title="FinishIt" app icon> <a href="https://starbellysw.com/todo" target="_blank">ToDo (now called Finishit)</a>, an Android application I developed as part of an independent study at UofM, and subsequently started selling under my LLC, Starbelly Software is featured on the University of Michigan CSE Website.</p>
<p>Check it out <a href="https://web.archive.org/web/20150327005216/http://www.eecs.umich.edu/cse/Mobile_at_Michigan/todo_feature.html" target="_blank">here</a>.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/todo-featured-on-umich-cs-site</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/todo-featured-on-umich-cs-site</guid>
            <category><![CDATA[android]]></category>
            <category><![CDATA[starbellysw]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Wed, 10 Oct 2012 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Zappos 2013 College Recruitment Page]]></title>
            <description><![CDATA[<p>Toward the end of my internship at Zappos, I found myself in a position where I didn&apos;t really have any work assigned to me. I spent a couple of days asking around, and finally found out that the HR department needed to create a recruitment page for the 2013 intern program. Once this need was identified, I got together with <a href="http://www.adriantavares.com" target="_blank">Adrian</a>, one of the other interns, and we worked on their 2013 College Recruitment page. Check it out <a href="https://web.archive.org/web/20121213155928/http://internships.zappos.com/" target="_blank">here</a>.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/zappos-recruiting</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/zappos-recruiting</guid>
            <category><![CDATA[portfolio]]></category>
            <category><![CDATA[web dev]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Fri, 28 Sep 2012 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Download Garfield Comic From the Command Line]]></title>
            <description><![CDATA[<p>Garfield has always been one of my favorite comic strips. I read it every day, and always save the ones I like to a folder on my computer.</p>
<p>Because of my OCD, I insist on saving these files with their filenames as <code>yyyy-mm-dd.jpg</code>. This way, Finder sorts them and I can easily revisit them in order.</p>
<p>To save myself some of the effort of renaming these files every day, I went ahead and wrote a ruby script that does it for me. I can get my daily dose of garfield simply by running this script and opening the file it drops on to my desktop.</p>
<p>Instructions below.</p>
<p>Save the following script to a file such as <code>~/Desktop/garfield.rb</code> and run it with <code>ruby ~/Desktop/garfield.rb 2012-09-27</code> or just  <code>ruby ~/Desktop/garfield.rb</code>.</p>
<pre><code class="language-ruby"><span class="hljs-keyword">require</span> <span class="hljs-string">&apos;net/http&apos;</span>
<span class="hljs-keyword">require</span> <span class="hljs-string">&apos;uri&apos;</span>
<span class="hljs-keyword">require</span> <span class="hljs-string">&quot;open-uri&quot;</span>

<span class="hljs-comment"># This regular expression matches a date that</span>
<span class="hljs-comment"># is in the form ####-##-##</span>
regex = <span class="hljs-regexp">/\d\d\d\d-\d\d-\d\d/</span>

<span class="hljs-comment"># Get the date for the comic we are retreiving,</span>
<span class="hljs-comment"># what&apos;s passed to the command line or the current</span>
<span class="hljs-comment"># date if nothing</span>
<span class="hljs-keyword">if</span>(ARGV[<span class="hljs-number">0</span>])
    date = ARGV[<span class="hljs-number">0</span>].gsub(<span class="hljs-regexp">/-/</span>, <span class="hljs-string">&quot;\/&quot;</span>)
<span class="hljs-keyword">else</span>
    <span class="hljs-comment"># Match the date in time.now.to_s using the regex,</span>
    <span class="hljs-comment"># and then replace the dashes with slashes for the url</span>
    date = regex.match(Time.now.to_s).to_s.gsub(<span class="hljs-regexp">/-/</span>, <span class="hljs-string">&quot;\/&quot;</span>)
<span class="hljs-keyword">end</span>

url = <span class="hljs-string">&quot;http://www.gocomics.com/garfield/<span class="hljs-subst">#{date}</span>&quot;</span>

<span class="hljs-comment"># Perform the HTTP get request</span>
url = URI.parse(url)
req = Net::HTTP::Get.new(url.path)
res = Net::HTTP.start(url.host, url.port) { <span class="hljs-params">|http|</span>
    http.request(req)
}

<span class="hljs-comment"># Pull the src url for the comic image itself from</span>
<span class="hljs-comment"># the html for the page</span>
url = <span class="hljs-regexp">/img alt=&quot;Garfield&quot; .*src=&quot;([a-z:\/.0-9]*).*/</span>.match(res.body)[<span class="hljs-number">1</span>]

<span class="hljs-comment"># Reformat the date to contain &apos;-&apos;es instead of &apos;/&apos;</span>
<span class="hljs-comment"># es to save it to the desktop</span>
date = date.gsub(<span class="hljs-regexp">/\//</span>, <span class="hljs-string">&quot;-&quot;</span>)

<span class="hljs-comment"># Save the file to the Desktop in the format yyyy-mm-dd.gif</span>
open(url) {<span class="hljs-params">|f|</span>
    File.open(File.expand_path(<span class="hljs-string">&quot;~/Desktop/<span class="hljs-subst">#{date}</span>.gif&quot;</span>),<span class="hljs-string">&quot;wb&quot;</span>) <span class="hljs-keyword">do</span> <span class="hljs-params">|file|</span>
        file.puts f.read
    <span class="hljs-keyword">end</span>
}</code></pre>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/download-garfield-comic-from-the-command-line</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/download-garfield-comic-from-the-command-line</guid>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Thu, 27 Sep 2012 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[git and github: redux]]></title>
            <description><![CDATA[<p>In the past, I have said that I am not a huge fan of git. After working with it for a summer at Zappos, I can confidently say that I have seen the light. Git is awesome. Eventually, I will migrate Starbelly Software&apos;s projects from svn over to git repos. I just thought I&apos;d put that out there. Git FTW.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/git-and-github-redux</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/git-and-github-redux</guid>
            <category><![CDATA[archive]]></category>
            <category><![CDATA[git]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Sun, 05 Aug 2012 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[My Summer at Zappos]]></title>
            <description><![CDATA[<p>Hello, and sorry I haven&apos;t posted anything in a while. Actually, I&apos;ve kind of been cheating on  this blog in favor of <a href="https://web.archive.org/web/20150907051227/http://blogs.zappos.com/blogs/zappos-family/2012/06/08/internblog2" target="_blank">Zappos&apos; blog</a>, hopefully I am forgiven.</p>
<p>My first day at work here at Zappos, I had a meeting with my superhero (read: mentor) and a few members of the API team. I was given my own project to work on, left in charge of everything from determining what technologies to use, to designing the user interface. Basically the meeting went like this: &quot;We have this API here for you, and we want a front end for these 4 controllers. Now GO!&quot;. The 4 controllers are all controllers pertaining to managing which third party developers have access to the Zappos public API.</p>
<p>I decided to do my project as a Rails app, using Twitter&apos;s bootstrap for the front end. Having not done any web development in the past, I had to spend my first couple of weeks at work teaching myself Ruby, Rails, Javascript, CSS, and HTML. I worked through a few tutorials, and did a lot of research as to the best approach for the project.</p>
<p>I was quite happy with the way the project came out, and based on feedback from the people using it, I think they are too. For the rest of the summer, it looks like I will be working with my actual team: Zeta, on bug fixes, etc. It will be a different experience compared to my first project because I will actually be functioning as a member of a team working on code for the actual Zappos website. I&apos;m very excited to get going with this. Check back for updates.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/my-summer-at-zappos</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/my-summer-at-zappos</guid>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Wed, 01 Aug 2012 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[USA Today Article about my Software Engineering Class]]></title>
            <description><![CDATA[<p>This past semester, I took a software engineering class at the University of Michigan. The only prompt going into the course was that we had to make a Microsoft Kinect game for children with ASD (Autism Spectrum Disorder). My team made a game called <a href="/blog/post/dancezilla">Dancezilla</a>.</p>
<p>USA Today has written an article about video games used as ASD therapy, and it mentions my class by name. I thought it was pretty cool and something worth sharing. Find the USA Today article <a href="http://www.usatoday.com/news/health/story/2012-05-31/video-games-autism-students/55319452/1?csp=34news" target="_blank">here</a>.</p>
<h1 id="update---20120606"><a href="#update---20120606">Update - 2012/06/06<i class="icon-link"></i></a></h1>
<p>To corroborate the story, the kind folks over at the University of Michigan made a video about the class. I&apos;m even in it for a <a href="https://www.youtube.com/watch?feature=player_detailpage&amp;v=CUT-Chcffqc#t=135s" target="_blank">brief moment</a>!</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/usa-today-article-about-my-software-engineering-class</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/usa-today-article-about-my-software-engineering-class</guid>
            <category><![CDATA[video games]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Sat, 02 Jun 2012 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[I Just Signed Up for github]]></title>
            <description><![CDATA[<p>Well, I guess its been a long time coming, but I finally signed up for a github account. In my EECS 493 (User Interfaces) class, we had to work with partners for the final project. I chose to work with my classmates Tony and <a href="http://www.crouchingmonkey.com" target="_blank">Josh</a>. Since I am <a href="https://www.lukezilioli.com/blog/?id=5">overly</a> <a href="https://www.lukezilioli.com/blog/?id=4">familiar</a> <a href="https://www.lukezilioli.com/blog/?id=3">with</a> <a href="https://www.lukezilioli.com/blog/?id=2">SVN</a>, and hadn&apos;t had much exposure to the other popular version control systems, I requested that Tony insist that we use git. So now I can say I have used git, and that I know it enough to use it if I had to (though I am not a huge fan).</p>
<p>Anyway, the other day a friend and I got to talking about adding new music to out libraries, and the headache involved in assimilating the new songs&apos; metadata to our preferred formats. I mentioned an AppleScript I had written that uses <a href="https://linux.die.net/man/1/sed" target="_blank">sed</a> to do a lot of the heavy lifting. He expressed interest in seeing what I had done and I realized there was no good way for me to show him. Enter github. With encouragement from Tony, I have finally registered and set up my first public git repo.</p>
<p><strong>Update 2012-08-01</strong>: I was wrong about git, and have <a href="https://www.lukezilioli.com/blog/?id=8">seen the light</a>.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/i-just-signed-up-for-github</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/i-just-signed-up-for-github</guid>
            <category><![CDATA[archive]]></category>
            <category><![CDATA[git]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Tue, 08 May 2012 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[SVN: Changing Permissions on a Repo]]></title>
            <description><![CDATA[<p>When creating an SVN repository, it&apos;s quite easy to grant permissions to new users:</p>
<pre><code>fs setacl path<span class="hljs-regexp">/to/</span>repo/ rlidwk</code></pre><p><a href="http://pages.citebite.com/l1l6g9p2h6clb" target="_blank">rlidwk - explained</a></p>
<p>However, once the repo has been created, its not quite as easy. From <a href="http://pages.citebite.com/x1d6c9e2n3dnh" target="_blank">what I can tell</a>, this is because this command sets the  access control list (ACL) on the directory, and when you later <code>svnadmin create path/to/repo/</code>, all of the new files (or files added any other way, for that matter) inherit the ACL from the parent directory (I am unclear as to whether this happens upon file creation, or upon access of the file, as it seems the only thing that matters in the solution is the ACL on the directories). Thus, if you need to change the ACL for an already existing repo, you will have to set the ACL on every directory within the repo as well. After much searching, and trial and error, I found that this can be done with the following command:</p>
<pre><code><span class="hljs-built_in">find</span> <span class="hljs-built_in">path</span>/to/repo/ -<span class="hljs-built_in">type</span> d -exec <span class="hljs-built_in">fs</span> setacl {} rlidwk;</code></pre><p>Basically, what this command does is <a href="https://linux.die.net/man/1/find" target="_blank">searches</a> for all of the directories within the repository, and for each one, executes the <code>fs setacl</code> command.</p>
<p><strong>Note</strong>: At the very least this will apply to those on an OpenAFS network file server. At most, it will apply to more than that. Either way, it is the hope that somewhere, somewhat this post ends up helping somebody and saves them the time I put in trying to figure it out.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/svn-changing-permissions-on-a-repo</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/svn-changing-permissions-on-a-repo</guid>
            <category><![CDATA[archive]]></category>
            <category><![CDATA[svn]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Wed, 18 Apr 2012 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Video Games and Autism Spectrum Disorder]]></title>
            <description><![CDATA[<p>Winter semester of 2012, I took a software engineering course (EECS 481) as part of my major design experience.</p>
<p>Our assignment for the semester was to make a Microsoft Kinect game designed to be therapeutically beneficial to people with Autism Spectrum Disorder (ASD). Given that we were a class full of computer scientists, none of us knew anything about ASD; considering that we were making games designed to help people with ASD, we had to figure out what developmental deficiencies we could help improve through our medium of video games.</p>
<p>And theres also a USA today article about us <a href="http://usatoday30.usatoday.com/news/health/story/2012-05-31/video-games-%20autism-students/55319452/1?csp=34news" target="_blank">here</a>.</p>
<hr>
<h1 id="dancezilla"><a href="#dancezilla">Dancezilla<i class="icon-link"></i></a></h1>
<p><img class="callout" src="/images/dancezilla_logo.png" title="Dancezilla" logo> Because of the size of the class, we split into 9 or 10 teams of 3-5 people each. There were a total of five people on my team. We created a 70&apos;s themed dancing game by the name of Dancezilla. The game maps the player&apos;s movements to an in-game 3D character, so that anything the player does is mirrored on-screen. The object of the game is to dance while reaching for 3D spheres that are flying around you. When you successfully come into contact with one of the spheres, it explodes adding points to your funk-o-meter. Once the funk-o-meter is full, you have beaten the level.</p>
<p>Our goals in making this game were to aid in the development of the following skills:</p>
<ol>
<li><strong>Process multiple stimuli</strong> - Certain patients of ASD often get overwhelmed when presented with what most of us would consider to be a reasonable amount of stimuli. Because of this, some ASD patients find it difficult to attend large events, movies, theme parks, etc. due to their very stimulating nature. We addressed this within our game by increasing the amount of stimuli that the user experiences as they advance through the levels&#x2013;on level 1, they would only be presented with one or two spheres at a time, ensuring that they wouldn&apos;t become overwhelmed. As levels advance, the number of spheres increases, in addition to their speed increasing and the complexity of their paths increasing as well.</li>
<li><strong>Improve hand-eye coordination</strong> - Many ASD patients also struggle with simple tasks that require hand-eye coordination. By making it the player&apos;s goal to destroy spheres, and rewarding them when they do so (by adding funk to the funk-o-meter, and animating an explosion, something kids in our testing couldn&apos;t get enough of), Dancezilla encourages players to work on their hand-eye coordination, a skill required to make your body actually come into contact with the spheres.</li>
<li><strong>Remain in control under exertion</strong> - Some ASD patients, particularly younger ones often have a hard time remaining in control when physically or mentally exerted, often getting frustrated beyond being able to complete a task. We all know that dancing is physically tiring, however, Dancezilla-ing is both physically and mentally tiring, because it requires you to focus on destroying spheres while dancing. As I discussed before, Dancezilla is a game of increasing difficulty, so it helps the user grow more accustomed to increasing levels of exertion as the game advances. Similar to how this increasing difficulty helps ASD patients process multiple stimuli, it also helps them grow more comfortable with higher levels of physical exertion.</li>
</ol>
<p>In addition to the features of the game I described above, I implemented what we ended up calling &quot;Caregiver Mode&quot;, a game mode in which a caregiver of the ASD patient can use an Xbox 360 controller to spawn balls on command, or spawn a special ball that they can then control with the joysticks. This enables caregivers to use Dancezilla in any way they see fit. For example, if their patient has particular difficulty doing reaching over their body, I.e. using their right hand to pick something up that is to their left, the caregiver can position the special ball on the side of the player, and instruct them to destroy it using the arm on the opposite side of their body.</p>
<p><img src="/images/dancezilla_screenshot.png" alt title="Dancezilla screenshot"></p>
<p class="blog-caption"><strong>Pictured above:</strong> Screenshot of Dancezilla. I can&apos;t take a screenshot and play at the same time, so the 3D on-screen model is in his default position. Hopefully I can get a video uploaded at some point.</p>]]></description>
            <link>https://www.lukezilioli.com/blog/post/dancezilla</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/dancezilla</guid>
            <category><![CDATA[portfolio]]></category>
            <category><![CDATA[video games]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Mon, 16 Apr 2012 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[SVN: Ignoring Files and Folders]]></title>
            <description><![CDATA[<p>Often times I find that some unwanted file has ended up in my svn repository, be it some computer specific build files, user preferences or anything else. Usually, these files have to lie within your svn repo even if you don&apos;t want svn to track the changes to these files or folders.</p>
<p>Thankfully, there is a way to have svn ignore certain files or folders. These preferences are on a per-directory basis. To tell SVN to ignore a particular file or folder, first navigate to the directory in which the file or folder lies, and type:</p>
<pre><code><span class="hljs-selector-tag">svn</span> <span class="hljs-selector-tag">propedit</span> <span class="hljs-selector-tag">svn</span><span class="hljs-selector-pseudo">:ignore</span> .</code></pre><p>A text editor will open with a file containing everything within that directory that SVN will ignore. Place whatever you like in this file, separating different file or folder names on individual lines. You can use wildcards as well, for example, if you don&apos;t want any .txt files to appear in your SVN repo, enter *.txt.</p>
<p>Happy version-controlling!</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/svn-ignoring-files-and-folders</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/svn-ignoring-files-and-folders</guid>
            <category><![CDATA[archive]]></category>
            <category><![CDATA[svn]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Thu, 22 Mar 2012 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[I Went to Spain!]]></title>
            <description><![CDATA[<p>Last year, I took my first two required spanish courses here at UofM (Spanish 103 and Spanish 231), and quickly realized that the classroom is no place to learn a foreign language. Given this information, I knew that in order to get out of Michigan with a decent handle on Spanish, I had to travel abroad.</p>
<p>I looked into a few programs offered through the University, but ultimately felt like they all cost way more than they were worth&#x2013;so I set out to get the same benefits of those programs without wasting my money.</p>
<p>Fortunately, my Dad has some friends in <a href="https://en.wikipedia.org/wiki/M%C3%A1laga" target="_blank">M&#xE1;laga, Spain</a> that were willing to put me up when I first arrived while I figured out what I was going to do. The first week I was there, I just spent time with my dad&apos;s friends enjoying M&#xE1;laga and practicing my Spanish while I found a local school at which I could take a class to formally learn more of the language.</p>
<p>For the latter two weeks that I was there, I took a Spanish class with people from all over Europe who were also there to learn Spanish; we had people from Morocco, Italy, Russia, Germany, Iceland, and Scotland, among other countries. While I was taking this class, I also paid to live with a local woman. She fed me home-made Spanish food everyday, and spoke nothing but Spanish, so basically, if I wanted to eat, I had to be able to communicate.</p>
<p>Immersing myself in the language was definitely the way to go; when I got back to Michigan for Fall semester, when I took my last required Spanish course (Spanish 232) I was the only person who could understand what our professor was saying to us. Everyone else in the class looked to me to translate.</p>
<p>At the end of my time in Spain, I flew to Hamburg, Germany and spent 5 days with my good friend Rasmus, who I met my Junior year of high school when he was there for a year as a foreign exchange student. To cap it all off, I stopped off in New York for a few days en route back to Detroit to visit my friend Steve, who had a summer internship out there.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/spain</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/spain</guid>
            <category><![CDATA[travel]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Mon, 18 Jul 2011 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[SVN: Migrating a Repository]]></title>
            <description><![CDATA[<p>#svn #archive</p>
<p>I use Subversion (SVN) as my version control software for all of my Android
development. Although a powerful tool, it is not always obvious how to achieve
the goal I want. Here are some Tasks I have needed complete using SVN, and how
I went about doing so.</p>
<p><strong>NOTE</strong>: For all of the following instructions, assume we are working in the user&apos;s home directory.</p>
<p><strong>Moving repo A to a server</strong></p>
<ol>
<li><p>Dump the repo A</p>
<pre><code> <span class="hljs-selector-tag">svnadmin</span> <span class="hljs-selector-tag">dump</span> <span class="hljs-selector-tag">A</span> <span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.dmp</span></code></pre></li>
<li><p>Copy the dump to the server.</p>
<pre><code> scp a.dmp username<span class="hljs-meta">@ssh</span>.<span class="hljs-string">server:</span><span class="hljs-string">path:</span><span class="hljs-string">to:</span>file</code></pre></li>
</ol>
<p>In my example, I use scp, however you can use FTP, or any other means of getting the a.dmp file to the server.</p>
<ol start="3">
<li><p>Connect to the server</p>
<pre><code class="language-bash"><span class="hljs-attribute">ssh</span> username<span class="hljs-variable">@ssh</span>.server</code></pre>
<p>You will likely be prompted for your password.</p>
</li>
<li><p>Create the new repository on the server.</p>
<pre><code class="language-bash"><span class="hljs-attribute">svnadmin create NewRepo</span></code></pre>
</li>
<li><p>Load a.dmp into the new repo.</p>
<pre><code class="language-bash">svnadmin <span class="hljs-built_in">load</span> NewRepo &lt; <span class="hljs-keyword">a</span></code></pre>
</li>
</ol>
<p>What if you want to create a new repo, that acts as a parent for your already
existing repos?</p>
<p><strong>Moving repo A, and repo B into a new parent repo C</strong></p>
<ol>
<li>Create the new repository<pre><code class="language-bash"><span class="hljs-attribute">svnadmin create C</span></code></pre>
</li>
<li>Create A and B directories within the newly created repository<pre><code class="language-bash">svn mkdir file:<span class="hljs-regexp">//</span><span class="hljs-regexp">/path/</span>to<span class="hljs-regexp">/home/</span>dir/A -m <span class="hljs-string">&quot;Adding A directory&quot;</span>
svn mkdir file:<span class="hljs-regexp">//</span><span class="hljs-regexp">/path/</span>to<span class="hljs-regexp">/home/</span>dir/B -m <span class="hljs-string">&quot;Adding B directory&quot;</span></code></pre>
</li>
<li>Create dumps of repo A, and repo B<pre><code class="language-bash"><span class="hljs-selector-tag">svnadmin</span> <span class="hljs-selector-tag">dump</span> <span class="hljs-selector-tag">A</span>     <span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.dmp</span>&quot;
<span class="hljs-selector-tag">svnadmin</span> <span class="hljs-selector-tag">dump</span> <span class="hljs-selector-tag">B</span>     <span class="hljs-selector-tag">b</span><span class="hljs-selector-class">.dmp</span></code></pre>
</li>
<li>Load these dumps into the subdirectories of repo C<pre><code class="language-bash">svnadmin <span class="hljs-keyword">load</span> C/ -<span class="hljs-keyword">parent</span>-dir A &lt; a.dmp
svnadmin <span class="hljs-keyword">load</span> C/ -<span class="hljs-keyword">parent</span>-dir B &lt; b.dmp</code></pre>
</li>
</ol>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/svn-migrating-a-repository</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/svn-migrating-a-repository</guid>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Wed, 01 Jun 2011 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Beware of ProGuard and android:onClick]]></title>
            <description><![CDATA[<h1 id="the-background"><a href="#the-background">The Background<i class="icon-link"></i></a></h1>
<p>As I developed <a href="https://starbellysw.com/todo/" target="_blank">ToDo</a>, I was using a lot of onClickListeners, especially on the Task Details screen. In onCreate, I was setting up onClickListeners for all 4 priority radio buttons, as well as for the Pick Date, and Pick List buttons. While this was an acceptable implementation, I have always thought onClickListeners were an ugly API requirement.</p>
<p>That&apos;s why when I learned about being able to specify <a href="http://developer.android.com/resources/articles/ui-1.6.html" target="_blank">android:onClick</a> for Buttons in the layout.xml files, I immediately jumped on board. I retroactively removed all of my onClickListeners, and changed them to functions specified by the android:onClick xml attribute.</p>
<p>GREAT! Clean code, happy coder. But, of course, it was almost too good to be true.</p>
<p>I do extensive testing of all of my apps before releasing them, however most of this testing is done on the emulator, with the APK as signed by eclipse for debugging. This is a mistake&#x2013;one I will not make again.</p>
<h1 id="the-problem"><a href="#the-problem">The Problem<i class="icon-link"></i></a></h1>
<p>As I got closer to the release of my application, and learned that the Android Market&apos;s copy protection was going to soon be deprecated, I began researching the <a href="http://developer.android.com/guide/publishing/licensing.html" target="_blank">Android Application Licensing</a> scheme, and implementing this in ToDo. All went well. I thought I had licensing implemented and working flawlessly.</p>
<p>Part of implementing licensing (and a good practice in general) is using <a href="http://developer.android.com/guide/developing/tools/proguard.html" target="_blank">ProGuard</a>, as recommended <a href="http://developer.android.com/guide/publishing/licensing.html#app-obfuscation" target="_blank">here</a>, when exporting your unsigned application or obfuscate your application&apos;s code and make it more difficult to hack.</p>
<p>Having tested my application extensively on the emulator, and under the impression I had the licensing working perfectly, I uploaded my app to the Android Market, and published. My friends were the first to download the app, and then immediately reported that anytime they clicked on a button in the TaskDetails screen, the app would crash. I installed it on my Android handset, and sure enough was able to re-create the issue right away. Plugging it into my computer, and looking at the LogCat&apos;s output in the DDMS prospective, I was able to deduce that the app was unable to find any of the functions that were being called by my buttons&apos; onClick xml attribute.</p>
<p>WHAT THE F? I double checked the function names, and they were defined correctly, as specified in my xml files. After much experimentation, I narrowed down the possibilities as to what could be causing this issue, and determined that since it wasn&apos;t happening in the emulator (before I was exporting and signing my application), and it wasn&apos;t happening prior to implementing my application&apos;s licensing, that it had to be something occurring in between exporting my application, and signing, and zipalign-ing it. What is in between these steps that wasn&apos;t before? <strong>ProGuard</strong>. Of course, ProGuard was, unbeknownst to me, making optimizations in my code. Because my onClick functions were never being called from my code (as they were only referenced from my xml), ProGuard decided they were &quot;dead code&quot; and removed from my exported APK.</p>
<h1 id="the-solution"><a href="#the-solution">The Solution<i class="icon-link"></i></a></h1>
<p>Once I identified the problem, conceiving the solution was simple. Implementing it was a whole &apos;nother story. I knew right away I would have to add some kind of additional -keep option in the proguard.cfg file, but was very against adding a line for every function I specified to be called by a button&apos;s onClick attribute. My solution is this:</p>
<p><strong>Step 1:</strong> For every function called by a button&apos;s onClick, pick a naming convention: i.e. onclick_functionName</p>
<p><strong>Step 2:</strong> In the proguard.cfg file, add the following</p>
<pre><code>-keepclassmembers <span class="hljs-keyword">class</span> * {
    <span class="hljs-built_in">public</span> <span class="hljs-type">void</span> onclick_*(android.<span class="hljs-keyword">view</span>.<span class="hljs-keyword">View</span>);
}</code></pre><p>This tells ProGuard to keep any function that is in any (*) class, whose signature is public, returns void, name starts with &quot;onclick_&quot; and who takes a single parameter of type android.view.View.</p>
<p>Don&apos;t forget to update the android:onClick xml attribute in your layouts, or the app will crash for a different reason.</p>
<p>I asked this on StackOverflow but got a <a href="https://stackoverflow.com/questions/6084861/how-can-i-tell-proguard-to-keep-my-function-that-is-used-for-onclick" target="_blank">response</a> I was not entirely happy with. The primary advantages to my approach are that the functions can exist in any class, not just a single class specified as in the StackOverflow response.</p>
<p>I hope this was helpful, and that I saved you the time I spent.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/beware-of-proguard-and-androidonclick</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/beware-of-proguard-and-androidonclick</guid>
            <category><![CDATA[android]]></category>
            <category><![CDATA[archive]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Sun, 22 May 2011 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Android Development: FinishIt and Starbelly Software, LLC.]]></title>
            <description><![CDATA[<h1 id="todo--finishit"><a href="#todo--finishit">ToDo / FinishIt<i class="icon-link"></i></a></h1>
<p><strong>Update 2013-01-01</strong>: This post was updated to remove links to the app on the amazon and google marketplace. As The app is no being longer sold or maintained.</p>
<p><img class="callout" src="/images/finishit_icon.png" title="FinishIt" app icon> Winter term 2011, I did an independent study through the Computer Science department at Michigan in order to better learn Android development. During the course of the semester, I developed ToDo, a simple task management Android app featuring multiple lists, notification reminders, and tons of user-customizable settings. ToDo has since been renamed to <a href="https://www.starbellysw.com/#finishit" target="_blank">FinishIt</a>, but what its about hasn&apos;t changed.</p>
<p><strong>It was also featured by the University of Michigan. <a href="https://web.archive.org/web/20150327005216/http://www.eecs.umich.edu/cse/Mobile_at_Michigan/todo_feature.html" target="_blank">here</a></strong></p>
<h1 id="finishit-features"><a href="#finishit-features">FinishIt Features<i class="icon-link"></i></a></h1>
<ul>
<li><strong>Alarms</strong> - Get reminded of the stuff you have to do.</li>
<li><strong>Password Protection</strong> - Set a numeric passcode to keep your friend&apos;s and relative&apos;s prying eyes away from your tasks. Set an amount of time you can be gone from the app, and not be prompted for your password on return. If you are gone for longer then this amount of time, you will be re-prompted for your passcode. This is great for switching between applications.</li>
<li><strong>Simple Display</strong> - Displays your tasks in an elegant list. See the information you need, when you need it.</li>
<li><strong>Smart bar</strong> - At the top of every list, you will see the smart bar, a quick at-a-glance view of your progress for the currently displayed list.</li>
<li><strong>Multiple List Support</strong> - Create, rename, and delete lists &apos;till you heart&apos;s content. Features 3 smart lists, All Tasks, Done Tasks, and Today so you can view what you want, when you want.</li>
<li><strong>Multi-Edit Mode</strong> - Edit multiple items at a time to mark as done, move to a different list, modify the due date, or delete them in one fell swoop.</li>
<li><strong>Clean Up</strong> - Delete completed tasks, or all tasks quickly, and easily for whatever list you are currently viewing.</li>
<li><strong>Innovative Date Slider</strong> - Slide left and right to intuitively select the month and date in which your task is due. No more clunky + or - buttons to deal with.</li>
<li><strong>Simple Task Creation</strong> - Clean and intuitive task creation screen, featuring task title, done status, list, due date, priority and a note.</li>
</ul>
<p><strong>Plus Many More!</strong></p>
<ul>
<li><strong>Rapid Fire Mode</strong> - quickly create more then 1 task</li>
<li><strong>Sorting Options</strong> - sort your tasks by Name, Due Date, or Priority</li>
<li><strong>Highly Customizable</strong> - offers a plethora of settings so the app behaves the way you want it to</li>
<li><strong>Quick Task Deletion</strong> - turn off the task deletion prompt for even faster task organization.</li>
</ul>
<h1 id="starbelly-software-llc"><a href="#starbelly-software-llc">Starbelly Software, LLC.<i class="icon-link"></i></a></h1>
<p><img class="callout" src="/images/sbsw.png" title="Starbelly" software logo> Once the semester ended, I decided that I wanted to continue development on FinishIt and release it on the Android Market. To do so, I formed a Michigan LLC. I spent the first few weeks of the summer readying ToDo/FinishIt for release and trying to come up with a name for the company. Once that was done, and <em>Starbelly Software, LLC</em> was legit, I released ToDo for both the Google Market and the Amazon app store.</p>
<p class="clearfix">As of 2013/01/01, it has sold over 480 copies.</p>]]></description>
            <link>https://www.lukezilioli.com/blog/post/finishit</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/finishit</guid>
            <category><![CDATA[android]]></category>
            <category><![CDATA[portfolio]]></category>
            <category><![CDATA[starbellysw]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Sat, 21 May 2011 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[SVN Error: Expected FS format '2'; found format '4']]></title>
            <description><![CDATA[<p>I created a SVN repo on my university storage space, and attempted to check it out on my local machine, but kept receiving the following error:</p>
<pre><code>Expected FS <span class="hljs-keyword">format</span> <span class="hljs-string">&apos;2&apos;</span>; <span class="hljs-built_in">found</span> <span class="hljs-keyword">format</span> <span class="hljs-string">&apos;4&apos;</span></code></pre><p>I found many suggestions on the internet, however what ultimately worked for me was this</p>
<pre><code><span class="hljs-attribute">svnadmin</span> create -pre-<span class="hljs-number">1</span>.<span class="hljs-number">5</span>-compatible repoName</code></pre><p>You need to add the -pre-1.5-compatible flag to get it to work correctly. I am not sure what caused the issue, but I assume it was something relating to SVN being upgraded either on my local machine, or the university computers. Just thought I would post this here in case anyone else is having the same issues.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/svn-error-expected-fs-format-2-found-format-4</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/svn-error-expected-fs-format-2-found-format-4</guid>
            <category><![CDATA[archive]]></category>
            <category><![CDATA[svn]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Mon, 07 Feb 2011 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[SHAPE Detroit]]></title>
            <description><![CDATA[<p><strong>Update 2020-05-01</strong>: Links to Shape Detroit websites have been removed, since they are no longer operational.</p>
<p>This summer, while taking Calc III and Physics II at Wayne State, I was also working for SHAPE Detroit, a part of <a href="http://www.awbs.org/" target="_blank">Adult Well-Being Services</a>.</p>
<p><img class="callout" src="/images/shape_logo.gif" title="SHAPE" detroit logo> SHAPE works with women within the city of Detroit to educate them about various health issues. One thing that SHAPE does for the community is put on weekly workshops to educate women about HIV/AIDS. Their problem was that after these workshops, they had no way of remaining in contact with these women and keeping them up to date with the latest news or health risks.</p>
<p>In order to rectify this problem, they hired me as their Social Media Manager under a grant that they received to kickstart a social media campaign. At the beginning of the summer, a consultant and I worked with the director of the SHAPE office in order to determine their social media plan. Once the plan was formulated, it was left up to me to put everything into place, and train the necessary people on how to use/maintain it once I left.</p>
<p>In addition to the obvious social media platforms (facebook, twitter, and blog), SHAPE wanted a sacred place that they could interact with past workshop participants (and past participants could interact with each-other) in order to further discuss HIV/AIDS in a private, anonymous forum.</p>
<p>The first month and a half, I set these things up, ensuring that they had a consistent theme and branding across sites. Additionally, I configured it so that whenever they post to their blog, posts automatically go out to their twitter and facebook pages, eliminating the need for them to post the same content in three different locations.</p>
<p>Check them out here:
<a href="https://twitter.com/shapedetroit" target="_blank">Twitter</a> &#x2022;
<a href="https://www.facebook.com/pages/SHAPE-Detroit/134756353203216?ref=ts" target="_blank">facebook</a></p>
<h2 id="multilingual"><a href="#multilingual">Multilingual<i class="icon-link"></i></a></h2>
<p>Because SHAPE serves English, Spanish, and Arabic speaking women, they wanted the blog to be able to reach people of all three languages. This is something that they did not realize until half-way through the summer, but I was able to accommodate their needs. The SHAPE Detroit blog supports multiple languages in two ways:</p>
<ol>
<li>Authors at SHAPE can post to the blog in any of the three languages. There are separate RSS feeds for each language, and links to view only posts in a particular language.</li>
<li>There is a translate button on each post. Clicking this button allows the user to select any of the three languages, and using Google&apos;s translate API, translates them into the desired language. This way all of the site&apos;s content is accessible to everybody.*</li>
</ol>
<p>*This was the case up until May of 2011, when Google <a href="https://developers.google.com/translate/v2/faq#pricing" target="_blank">discontinued</a> their free Google translate API, in favor of a paid service. This broke this feature, and a few months later, SHAPE temporarily hired me to make some enhancements to the site, and they opted not to move to a paid translate service, so this feature has been discontinued.</p>
<h1 id="training"><a href="#training">Training<i class="icon-link"></i></a></h1>
<p>Once these sites were created, it was my job to ensure that all of SHAPE&apos;s authors knew how to post to the blog, and moderate the forum. Additionally, since SHAPE&apos;s employees were new to the platform, we decided that I would train the first couple groups of women on using the forum and accessing the blog in order to help things get off the ground. To that end, I created workshops, videos, and documents for both parties.</p>
<h1 id="assessing-success"><a href="#assessing-success">Assessing success<i class="icon-link"></i></a></h1>
<p>Since this grant was an experimental venture for organizations like AWBS or SHAPE, it was important to be able to assess the overall success of the efforts in order to determine if it is worth continuing to invest the necessary time and effort. For this, I recommended Google analytics, which I configured for the blog, and they are still using to monitor their success.</p>
<h1 id="putting-it-all-together"><a href="#putting-it-all-together">Putting it all together<i class="icon-link"></i></a></h1>
<p>I was responsible for presenting the social media plan. At the end of the summer, I presented the social media plan we developed and implemented to a group of AWBS partners in order to share insights from what we learned/were learning.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/shape-detroit</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/shape-detroit</guid>
            <category><![CDATA[detroit]]></category>
            <category><![CDATA[portfolio]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Sun, 01 Aug 2010 11:00:00 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[Android Development: TxtArchive]]></title>
            <description><![CDATA[<p><strong>Update 2020-01-01:</strong> Removed links to Google Play store since the app is no longer being developed or maintained.</p>
<p><img class="callout" src="/images/txtarchive.png" title="TxtArchive" main screen> TxtArchive is an Android app I created in the Summer of 2009 for Zill Computer and Engineering, Inc. (ZillCE). It allows the user to archive and export the messages stored in their phone&apos;s SMS database, so that they can be safely removed from the device. It currently has 6700+ active users with an average rating of 4 1/2 stars on the Google Play store (as of 2012/11/15, its two year anniversary).</p>
<p>This was my first time developing a piece of software from its conception to its release. It was also my first experience with Android development.</p>
<p>In the summer of 2009, my friend Steve and I worked at Zill Computer and Engineering. Our primary job was to develop some C++ modules for a waste inventory system that ZillCE created and maintains for Dow Chemical. Fortunately, Steve and I finished this task sooner than expected, and needed to keep busy for the rest of the summer.</p>
<p>Since Android was just starting to take off, and Google was offering prizes to developers who submitted their applications to the <a href="https://web.archive.org/web/20120601012626/https://developers.google.com/android/adc/" target="_blank">Android Developer Challenge 2</a>, our supervisor decided that we should get into Android development.</p>
<p>For the first few weeks, while Steve and I learned the basics of Java and the Android SDK, we also brainstormed ideas for the application. Eventually, we came up with the idea for TxtArchive, and began the design and coding process. After 2-3 weeks of development, our supervisors realized that we had a viable product on our hands, and decided to accelerate its release schedule.</p>
<p>TxtArchive was officially released onto the Android Market on November 15, 2009, and placed in the top 50% of applications submitted to Google&apos;s Android Developer Challenge 2.</p>
<p>In 2011, after forming Starbelly Software, I did some additional work on TxtArchive for ZillCE. There was a bug involving one of the most popular Android phones at the time&#x2013;the Motorola Droid. User&apos;s messages were not showing up within TxtArchive, which was resulting in poor reviews on the Android app store, and in turn, poor sales. ZillCE hired me to track down the issue and implement a fix, which I was able to do by creating a separate Android utility application that we sent to some affected customers. When this application was run on customer&apos;s phones, it would (with the user&apos;s permission) email a diagnostic report to a ZillCE email account. With this diagnostic data, I was able to target and fix the bug, resulting in a four-fold sales increase.</p>
]]></description>
            <link>https://www.lukezilioli.com/blog/post/txtarchive</link>
            <guid isPermaLink="true">https://www.lukezilioli.com/blog/post/txtarchive</guid>
            <category><![CDATA[android]]></category>
            <category><![CDATA[portfolio]]></category>
            <dc:creator><![CDATA[Luke Zilioli]]></dc:creator>
            <pubDate>Sun, 15 Nov 2009 11:00:00 GMT</pubDate>
        </item>
    </channel>
</rss>