by Lucas Lopez
A Wordle-inspired iOS game built with SwiftUI, async/await networking, and clean MVVM architecture.
Wordish is a Wordle-style word-guessing game redesigned from the ground up using modern iOS development patterns:
- SwiftUI first
- Swift Concurrency (async/await)
- @Observable + @MainActor ViewModel
- Actor-isolated networking
- Fully custom keyboard UI
- Unit tests for the core evaluation algorithm
- Guess the 5-letter word in 6 attempts
- Tile color feedback (π© correct, π¨ present, β¬οΈ absent)
- Duplicate letter-safe evaluation algorithm
- Dynamic on-screen keyboard with matching colors
- Delete + Enter functionality
- Win/Loss screen with solution reveal
- Smooth keypress animation
- Color fade transitions
- Intro splash screen
- Loading overlay while fetching new words
- Custom animated start screen to introduce the game
- Fetches random 5-letter words using:
https://random-word-api.vercel.app/api?words=1&length=5 - Safe async/await word fetch with automatic fallback
Left: Start Game screen | Right: Gameplay screen
Wordish follows a modern MVVM architecture tailored for SwiftUI and Swift Concurrency.
The goal is to keep views simple, centralize logic in the ViewModel, and ensure all state updates are safe, predictable, and testable.
| Layer | Responsibility |
|---|---|
| Model | Defines basic game structures (tiles, rows, states, constants) with no logic. |
ViewModel (GameViewModel) |
Contains all game logic, guess evaluation, async word loading, and screen-state transitions. |
| Views | SwiftUI layouts (grid, keyboard, overlays) that react automatically to ViewModel changes. |
The model layer defines only data, not behavior:
Tileβ letter + evaluation stateRowβ a single 5-letter guessLetterStateβ correct / present / absent / unknownGameStatus&GameResultβ playing / won / lostGameScreenStateβ start / loading / playing / finishedGameConstantsβ shared layout + game rule values
All logic lives in the ViewModel, not in these models.
The ViewModel is annotated with:
@Observablefor SwiftUI-native reactivity@MainActorto ensure UI-safe state updates
Its responsibilities include:
- Managing the 6Γ5 grid
- Typing, deleting, and submitting guesses
- Two-pass evaluation algorithm (duplicate-letter safe)
- Updating keyboard colors based on best-known info
Uses GameScreenState to control UI flow:
.start.loading.playing.finished(GameResult)
This design guarantees the UI is always in exactly one valid state.
- Fetches random words using
WordService - Runs asynchronously using async/await
- Provides a fallback word on failure
- Switches UI state from
.loadingβ.playing
The evaluation method is directly testable and covered by a full test suite.
SwiftUI views remain intentionally βdumbβ:
- Owns the ViewModel
- Displays grid, keyboard, and overlays
- Switches layouts based on
screenState
- Custom Wordle-style keyboard
- Keypress animation + color updates
- Sends input events back to the ViewModel
- RoundedRectangle tiles sized by
GameConstants - Colors driven entirely by
LetterState
- Start screen (animated fade-out)
- Loading screen
- Game end screen (won/lost + answer)
Implemented as an actor for thread-safe concurrency:
- Uses
URLSession+ async/await - Decodes API response (
[String]) - Returns a single uppercase word
- Guarantees safe access even under parallel calls
Evaluation logic is fully unit-tested, covering:
- Perfect match
- All wrong
- Present letters
- Duplicate letter edge cases
A dedicated EvaluationTests.swift suite validates correctness of guess evaluation logic.
- Perfect match
- All letters wrong
- Letters present in wrong positions
- Duplicate letters
func testDuplicateLetters() {
let states = evaluate("COCOA", secret: "CARGO")
let expected: [LetterState] = [.correct, .absent, .absent, .present, .absent]
XCTAssertEqual(states, expected)
}- Xcode 15+
- iOS 17+
- Swift 5.9
- Clone the repo
git clone https://github.com/lucastricanico/wordish-ios-app.git
- Open in Xcode
- Run the Project
- Don't forget to have fun! :)
Wordish/
β
βββ Models/
β βββ GameModels.swift
β
βββ ViewModels/
β βββ GameViewModel.swift
β
βββ Services/
β βββ WordService.swift
β
βββ Views/
β βββ ContentView.swift
β βββ KeyboardView.swift
β
βββ Tests/
β βββ EvaluationTests.swift
β
βββ Screenshots/
β βββ demo.gif
β βββ start_screen.png
β βββ game_screen.png
β
βββ Wordish/
β βββ Assets.xcassets
β βββ WordishApp.swift
β
βββ Wordish.xcodeproj
β
βββ README.md
βββ LICENSE
βββ .gitignoreThis project is a personal project inspired by Wordle.
- Wordle was originally created by Josh Wardle.
- It is now owned and published by The New York Times Company.
Wordish is an independent project and is not affiliated with, endorsed by, or associated with The New York Times or the official Wordle product. This project is non-commercial and built for learning + portfolio purposes.
- Tile flip animation (like Wordle)
- Shake animation for invalid words
- Real dictionary validation
- Haptic feedback
- Dark mode
- Success/Failure animations
- Guess distribution
- Win streak
- Shareable result grid
Released under the MIT License.
See LICENSE for details.