Rachel and I play the New York Times (NYT) Games (a.k.a., the app you open when you want to play Wordle) just about every single day, and she also has a daily text thread with her family where they share their results. Aside from my daily routine of testing which obscene words will be allowed through its filters, I’m always thinking about how its interfaces looks-like it could have been created in SwiftUI. This relates to some layout elements, animations, and transitions that are common in native iOS apps, and simplified by SwiftUI.
This post is the first part of a series. To view the second post, where I begin laying out the game tiles, click here.
Overall, I think the design is good, but there are few places where the designers took some creative liberties with how the UI works. These deviate somewhat from Apple’s recommended design patterns, and I think result in some unintuitive interactions. For example, placing left chevrons, or “back” arrows, on full screen covers that don’t have true “back” behavior. I’ll cover some of those deviations when I get to them, and present some possible design alternatives that could be facilitated by SwiftUI.
Getting Started
Given that the NYT Games app is one I use everyday, and I am generally familiar up-and-down with how it works, I thought it might be a good exercise for me to replicate some of its interface elements myself using SwiftUI. This blog is the first of what I hope to be a series where I work from the top-down in the app’s main screens, and demonstrate how the key visual elements can be imitated. This is not truly going to be a “clone” of the app, nor will it be “playable,” but I hope the process will be enlightening, a learning experience for myself, and hopefully for you the reader.
A disclaimer before I start: I am not trying to steal or profit off of NYT’s intellectual property (IP) with this series, this is purely educational. This manifests in a few places, such as fonts or graphics that I know are proprietary. I may “imitate” those, but I resort to using public domain content where possible. If I have incorrectly used unlicensed content, or for any other reason my work infringes on NYT’s IP, please let me know, and I will modify or remove that content.
Finally, if you want to view the source code or track progress of this tutorial, I am hosting a GitHub project.
New Project
Without further ado, lets create an empty project to begin our Games app. From the XCode start screen, I created a new project, using the standard iOS App template. I titled my version of the app Games
, with the organization identifier com.dc-engineer
. The remaining options may stay as their defaults, including keeping the interface as SwiftUI
, and not using storage (the latter will create a template SwiftData
model and associated code, which can always be added on later). I did not create a git repository on my Mac, because I had already created one on GitHub.
Save the new project, and you should shortly be directed into the ContentView.swift
file, with a basic “Hello World” type of template app.
Games Page
Rather than working inside the ContentView.swift
to start, we are going to create a new GamesPage
view. This will eventually resemble the initial screen you see when you open the NYT Games app, or in other words, the reference image that I inserted above. Since we want this to be a SwiftUI view, select “File -> New -> File From Template,” and select “SwiftUI View” from the User Interface section that appears. Save this new file as GamesPage.swift
, making sure that your app target is selected (it should be by default).
Replace the code in ContentView.swift
to reference this new view:
struct ContentView: View {
var body: some View {
GamesPage()
}
}
The above won’t really change the appearance of our template “Hello World” app, but now we can work from the newly created GamesPage
view. Later, we’ll return to this ContentView
for purposes of navigating to the “Friends” or “Stats” tabs. For today, I will focus on creating UI to resemble the top section of the NYT Games app, those will be tasks for a future blog.
Imitating the Title Bar
Referring back to the reference image at the top of this blog, I will start by creating a top app bar that resembles that used for the primary page in the NYT Games app. Focus items for this component include:
- A central title graphic featuring the NYT logo, a vertical divider, and the word “Games” in a blocky serif font.
- A gear icon on the right hand side.
- A white background and subtle horizontal divider between the title bar and content.
The NYT logo is obviously proprietary, as is their typeface for the “Games” title, so I will not attempt to exactly match either of these. I did find that NYT has their own in-house version of a font called “Cheltenham.” I found a similar free font to use in my imitation, which I’ll cover later.
A Custom Icon
Rather than even attempt to find anything resembling the NYT logo icon, I decided I’d create my own that resembles the shield icon that I’ve recently added to the DC-Engineer.com website. In this case, I got a AI assist; I uploaded the graphic on the left, which I created myself in Blender, and requested that ChatGPT create a simplified, black and white version, removing most of the text but retaining the DC and engineering theme elements, as well as the vertical stripes for Athletic Club.

SwiftUI should handle basic monochrome images pretty well as far as assigning tint colors during renders, but I thought I would switch my own icon to have transparent alpha. I removed background in Preview using Instant Alpha, then scaled down to 48×48 and 72×72 for image assets in the app. Then, I created a new image set in the app Assets
, titled “dc,” and selected “Render As: Template” in the inspector on the right hand side. With this done, I can now access this simplified logo as Image(.dc)
in SwiftUI.

SwiftUI Content
To implement the page title, with icon, vertical divider, and stylized text, I created a new header
view as a function inside the GamesPage
view class. As you can see in the code below, this is simply a HStack
with the three UI components, with the DC-Engineer image icon being sized to math the text size, and spacing set to roughly resemble the reference image. For now, I am using the built-in “Times” font, though I will cover adding a custom font shortly.
func header() -> some View {
HStack(spacing: 4) {
Image(.dc)
.resizable()
.frame(width: Constants.headerFontSize, height: Constants.headerFontSize)
Rectangle()
.frame(width: 0.5, height: 28)
Text("Games")
}
.font(.custom("Times", size: Constants.headerFontSize, relativeTo: .title))
.fontWeight(.black)
}
Since I am reusing the same size for both the image and text, I placed this in a Constants
structure, also inside GamesPage
.
private struct Constants {
static let headerFontSize: CGFloat = 34
}
Also create the gear icon button that shows up in the top-right corner, for now with an empty action.
func settingsButton() -> some View {
Button("Settings", systemImage: "gearshape.fill") { }
.tint(.primary)
}
Navigation Toolbar
At this point, the app appearance will not have changed if you run it or view the preview, as the above functions have not been added yet into the body
of the GamesPage
. A relatively simple approach here would be to just build a VStack
, and place the title content at the top. However, I prefer to make use of the navigation toolbar, that requires us wrapping our GamesPage
content inside of a NavigationStack
.
Later we will need a ScrollView
and VStack
to display our main content tiles. Inside our body
property we insert those inside a NavigationStack
, Everything is left empty for now, but this gives us some placeholder content on which we can attach our toolbar modifier, noting that there must be a NavigationStack
at some level in the view hierarchy (eventually, it can move to the ContentView
).
The .toolbar
modifier is constructed with two ToolbarItem
s representing the header and settings button, at principal and trailing placement, respectively. To align with the NYT app’s appearance, we use three additional modifiers.
.inline
display mode assures that the title bar is consistently shrunk down to the space at the top, not leaving space for a default.large
title..background
makes the color be pure white when the device is in light mode, rather than the grayish default.- The
toolbarBackgroundVisibility
modifier makes the subtle divider line appear.
The last modifier is is not exactly what I’d expect based on the syntax. It works, but not quite as clear cut as something like .toolbarHasSubdivider
. The existence of the background visibility modifier to draw this subdivider line is, apparently, a new addition to iOS 18, and one you previously would have had to write some UIKit code for, so I am glad to have found it.
var body: some View {
NavigationStack {
ScrollView {
VStack {
/* Games content will go here */
}
}
.toolbar {
ToolbarItem(placement: .principal, content: header)
ToolbarItem(placement: .navigationBarTrailing, content: settingsButton)
}
.navigationBarTitleDisplayMode(.inline)
.toolbarBackground(.background)
.toolbarBackgroundVisibility(.visible, for: .navigationBar)
}
}
Custom Font
NYT uses a custom version of a Cheltenham font for their header, which is not available for public use. I downloaded a free font that doesn’t exactly match it, but I thought I’d demo the process with it anyway, largely following Apple’s guidance.
In the app, I right clicked on my app on the left side and selected “New Folder,” which I titled “Fonts”. Then I right clicked on the Fonts folder and selected “Add Files,” then navigated to a file I downloaded titled CheltenhamStdBold.otf
. When adding the font, make sure your app target is selected, which it should be by default. After adding the file, my directory structure looked as below.
To use the custom font in the app, you must create a “Fonts provided by application” field in the app info. You can do this by finding the info tab for your app target, hovering over an item until a plus button appears, and adding that field.

The value should be CheltenhamStdBold.otf
. Confusingly, this is not Fonts/CheltenhamStdBold.otf
as the Apple documentation would suggest. In trying the latter, I got “File not found” errors. iOS appears to flatten the directory structure at build time, so you don’t include the subfolder.

In this particular font, accessing it in SwiftUI was not simply its file name, rather, I needed to determine its PostScript name. You can determine the PostScript name by adding the .otf
file as a system font in the FontBook app, which is usually the default if you double click it in Finder. In this case, the PostScript name is “CheltenhamStd-Bold.”

The modified code that accesses this font is below. Note the padding modifier that I added to the games text, which I don’t like, but I needed to properly align the custom font with the other content.
func header() -> some View {
HStack(spacing: 4) {
Image(.dc)
.resizable()
.frame(width: Constants.headerFontSize, height: Constants.headerFontSize)
Rectangle()
.frame(width: 0.5, height: 28)
Text("Games")
.padding(.top, 12)
}
.font(.custom("CheltenhamStd-Bold", size: Constants.headerFontSize, relativeTo: .title))
}
Result
The completed header, imitating the NYT games style, is shown below, as well as its counterpart from the real app. To my eyes, the icons are obviously different, which is no surprise as i was specifically not using NYT’s proprietary content. Likewise, the typeface is somewhat more different than I hoped when I added the custom font, but at least that provided me the opportunity to work through the process.

In terms of what I do have some control over, the sizing of the text and icons is a bit larger still in my imitation than in the original. As seen in the code above, I did set the size of the title content in my code, and could easily shrink that until it looks right. I did not set the size of the gear icon on the right. With that being a toolbar item, resizing is a bit more of a chore, as SwiftUI will restrict moving away from styling defaults for navigation bar items. I may try to rein in those difference later, or I may leave it as it is since I like how it looks either way.
That concludes my lesson for the day. As I mentioned before, I hope you’ll follow along with the GitHub project, or check here for future updates here. Next step will be to add the content tiles for the games!
As always, if you are interested on collaborating on a mobile app development project, especially in the fields of augmented reality or mechanical engineering, shoot me an email at eliott.radcliffe@dc-engineer.com, or add me on LinkedIn.
This post is the first part of a series. To view the second post, where I begin laying out the game tiles, click here.
Pingback: Imitating NYT Games with Swiftui, Part 2: Tiles – DC Engineer