A Decade of Pennant
By Tyler Hillsman
April 2023

A little more than a decade ago, I released an app to the App Store. It wasn't my first (I pushed out a little tic-tac-toe app a few months prior), but it was the first that I was building with a purpose.

I'd always enjoyed baseball and cheered for the Kansas City Royals, but it was a pretty passive fandom. As I moved to Kansas City after college, I wanted to pay more attention. I bought a portable radio and listened to games at my corporate job, we bought some ticket packs and attended quite a few games in person. But there's a lot of games (2430 across all teams in the regular season) and I found myself making Excel spreadsheets to visualize the trends of the AL Central and the MLB as a whole.

That was certainly a nerdy hobby, but it also coincided with the time I was learning to write apps. I'd taken some free classes from a company in town working on a proprietary language called WIRE to write iOS apps and my baseball standings visualization project was a perfect candidate for a mobile app. So I found a data provider, designed my UI, hooked things up, and had an app ready to go before the 2013 MLB season.

I submitted the app, named Race to the Pennant, to the App Store on March 18, 2013, and after a week of waiting (as was the norm at the time), my build was released on the afternoon of March 25, 2013. Anyone with an iOS device and 99 cents could run my app. Users could see a bar chart of the relative position of each team within the league, based on standings. They could tap on a division to see more detailed stats on the divisions' teams. I even pulled in recent articles about each team from mlb.com. The whole app was overlaid with a texture to make it feel authentically weathered. (Gotta love iOS 6 design.)

Pennant Pennant

Even a decade ago, I routinely listened to tech podcasts, and on an episode of the John Gruber's The Talk Show (this was the 5by5 Dan Benjamin version of it), he'd mentioned how he likes to be pitched new apps for Daring Fireball via email: short description of the app, relevant links, promo code, and that's it. I had nothing to lose, so on March 28th, I fired off an email. John's a noted Yankees fan and I pitched the app with this:

I just listened to the latest The Talk Show and thought I'd sent you this blind app pitch: Race to the Pennant is my latest app that makes it easy to visualize who's leading the pennant races (probably your Yankees...) and a whole lot more.

I wasn't expecting a response and never got one via email, and that was that. The app was out there, I could brag about it, and I could benefit from its features myself.

Except...

I was at work on Monday, April 1, 2013. I was recording video at a campus of the company's that I didn't typically work at. It was Opening Day - the first game of the year had been played the night before and I got to see my app in action with data less than a day old - and I was undoubtedly looking forward to the Royals' game. Then things changed. I got a message or two, which quickly turned into a flood.

John had linked to Race to the Pennant with this caption:

Great new iOS app for opening day.

I was stunned. From there, I had messages on Twitter, app reviews (some positive, some with quite valid feedback), and I was contacted by a reporter who wrote up an article. Suddenly I had more than a handful of users. The app became the top paid sports app in the store.

Pennant

One of the primary feedback items from users was that standings only updated once per day, in the early morning, which is how my data provider worked. I agreed that standings should be much more real-time. So I spun up a SQL database and spent a couple weeks teaching myself PHP to build my own API.

Over the course of the summer, I pushed out incremental improvements. I also created a short-lived spin-off app, Race to the Playoffs, for the NFL season. Looking back, I had 2440 downloads of Race to the Pennant over the course of 2013. Race to the Playoffs had a whopping 194.

Summer 2013 was a turning point in iOS history when the original skeuomorphism was retired in favor of the flat, minimalistic design of iOS 7. My primary task for the offseason was to redesign Race to the Pennant to match. Still using WIRE, I rewrote the app, mostly from scratch, without the "worn" texture I had in place at first. I dropped the serifs off my text and smoothed out my pennant logo. I also began displaying game results in the app in addition to the tabulated standings and stats.

Pennant Pennant

That year was a good one for my baseball fandom, as the Royals had a miracle run through the postseason and took the World Series to seven games. Tapping into that drama and good feeling, a friend at a news station featured me and Race to the Pennant as well.

Pennant

In 2014, yet another change hit the iOS world when Swift was introduced. It looked substantially more approachable than the Objective-C I'd lightly dabbled with, opting to build in WIRE, which was more tailored for web-developer happiness. I dove into Swift and devoured any documentation, tutorials, or videos I could find over the summer and fall of 2014. And the best way for me to learn is to try to build something. I set off trying to recreate Race to the Pennant in Apple's new native language. It went well, and by Opening Day 2015, I had yet another rewrite in the store.

Pennant

The 2015 version had some changes under the hood, using Parse as a datastore instead of my homemade API (I still processed stats and standings from game results manually, but stored all the output data in Parse). I also grew beyond just the app window: I added a Today extension and an Apple Watch app. The watch extension was in the store on day one (despite my own Apple Watch not arriving until a month and a half later).

Pennant

In 2016, after Facebook announced Parse was shutting down, I moved to a self-hosted Parse Server instance for my data. And because the only constant for Pennant is change, I rewrote it from the ground up, once again.

Pennant Pennant

In 2017, the biggest change was to the business model. Pennant had been a paid-upfront app from the beginning. Originally it was 99 cents, but I increased it to $1.99 after a year or two. A combination of market trends, additional in-app purchase capabilities, and the realization that the app had some continual costs led me to trying out a subscription model. For the first time, Pennant and its basic functionality were free for users. Free users saw ads, while upgraded users had no ads, could set a favorite team, see game scores, and view data from previous years. Additionally, users had the option to see a quick view of their favorite team's standings and most recent game from the home feed. I also supported the 3D Touch functionality of iPhones of the time to "peek" at division or team views before "pop"-ing to them with a harder press of a finger.

In this version, I dusted off my SQL tables and PHP and got rid of Parse data storage completely, running an API fully in-house. A lot of underlying work was done to move some baseball-specific assumptions from the frontend of the app to the backend of the API, laying the groundwork to support sports other than baseball.

Pennant

In 2018, there wasn't a lot new at the beginning of the season, but after Siri Shortcuts were released in the fall, I added the new feature to Race to the Pennant. This also necessitated a new design for the team view. This release marked the first larger release matching up with new iOS versions in September/October instead of revamping the app around the beginning of the baseball season in March/April.

Pennant Pennant

After a minor bump to support the new season in the spring of 2019 (by this time, it was down to changing a number in the app to support a new year), the app changed substantially. In June, Apple introduced SwiftUI and beginning the day it was announced at WWDC, I rewrote the app using this new framework. Recreating the UI was extremely straightforward and fun, and I took the time to make the biggest changes to the app yet: I added other sports (initially NFL and NBA, NHL and MLS soon followed), and simplified the name to Pennant. Users could use the app in a limited way for free, unlock individual sports, or unlock everything via subscription. Additionally, dark mode was supported from release and Apple even included Pennant in a featured category about it.

Pennant Pennant Pennant

Over the course of the fall and summer of 2020, I started on the largest visual change to Pennant. Combining the glanceability of the quick stats bar at the bottom and the capabilities of SwiftUI, I thought about how I could let the user select "widgets" of different data and build a customizable home screen with the teams and data they care about. I like the Royals and the Chiefs and Sporting KC, so I wanted to see where they all stood at a glance. I began putting together types of "widgets" with league, division, or team standings and built out the backend to support it. Apple threw me a curveball at WWDC when they announced actual home screen widgets that apps could supply and users could place among their apps. These had to be written in SwiftUI, and my UI was, so it was extremely straightforward to adapt them.

I released Pennant version 10.0 in September 2020 with the ability to build your "My Pennant" view, as well as view the classic league standings charts, and the ability to put the same visualizations directly on your home screen. This was definitely the most ambitious and substantive update yet and it allowed users to build their experience as they'd like, instead of viewing the same screens as anyone else. I also removed ads for free users as part of this release and updated the feature gate to include an unlimited amount of My Pennant blocks (instead of two), use all types of visualizations on the Home Screen widgets (instead of just a league view), see game results, view previous years' data, and set alternate app icons.

Pennant Pennant

Through 2021 and 2022, I added some fun alternate app icons, Shortcut support (with proactive suggestions in Spotlight), exporting images of My Pennant blocks, and completely backend-driven configuration, which means I don't have to submit new builds in advance of new seasons. Additionally, I did a ton of improvements to the backend to increase performance and reduce load on my server. At this point, there is no database querying when a request is made from the app and data is coming from static files that my behind-the-scenes tooling is creating.

Pennant Pennant Pennant Pennant

Which brings us to today, the tenth anniversary of John Gruber's post on Daring Fireball mentioning my app. It's been a wild ride, and it's far from over. I'm about 80% of the way through with yet another leap forward for Pennant, leaning into the customization and configurability of the app. (My goal was to have it completed as an anniversary release, alas.)

There are very few things that I've done for ten years. Pennant's older than both of my kids, it's lived longer than any of my jobs (I've had six during the time I've worked on this app), I've lived in two different houses in its lifetime... It's a great playground to try new things (as you can see by its numerous rewrites), and it's generally useful for me, fulfilling my original goal for it. I can't wait to see what it looks like in another ten years. (Probably running on mixed-reality glasses, written in SwiftUI version 14 with an AI-generated visual of the current standings of the World Hoverball League.) I guess we'll see!