Back to course overview
Module 2From idea to spec with AI 12 min

Modeling your data

Design the data model — the single most important decision in the app — and express it as a SwiftData model.

The data model is the shape of the information your app stores. Get it roughly right and everything else follows; get it wrong and you'll fight the app forever. For DayOne it's almost embarrassingly simple — one entity — but the discipline scales to big apps.

What is an entry, exactly?

List the facts you need to store about one journal entry. Ask the model to help, then edit ruthlessly:

Prompt to try

For the DayOne app in SPEC.md, list the fields a single journal Entry needs to store. Include the AI-generated title, mood, and reflection. Mark which fields are optional. Then express it as a SwiftData @Model class for iOS 17+.

Entry.swiftswift
import Foundation
import SwiftData

@Model
final class Entry {
    var body: String
    var createdAt: Date

    // AI-generated, so all optional — they don't exist until you "Reflect".
    var aiTitle: String?
    var mood: String?
    var reflection: String?

    init(body: String, createdAt: Date = .now) {
        self.body = body
        self.createdAt = createdAt
    }
}

@Model is the SwiftData annotation that makes this class persistable — SwiftData handles saving it to disk for you. Note the AI fields are optional (String?): a fresh entry has no title or mood until the user asks for insights. Modeling that honestly now prevents a class of bugs later.

Optional vs. required is a real decision

Every ? you add is a promise that your UI will handle the "not there yet" case. Every field you make required is a promise it always exists. Being deliberate here is exactly the kind of judgment AI can't make for you — it's your app's truth.

Where this goes

Save this as Entry.swift. In the next module you'll wire it into SwiftData's storage and build the screens from SPEC.md on top of it.