Daytiles
Your Data
Format version 1
Your habits are yours. Daytiles exports them, and your memories, as ordinary zip files of JSON and CSV, and brings those same files back in exactly as they were. None of it needs Pro. The format is published here so you can read your data anywhere, or write a converter from another app into it.
In the app
Settings has a Your data section:
- Export habits writes every habit and its history to a zip holding
habits.json,habits.csvandreminders.csv. - Export memories writes the photos and notes kept with your days, and any photo of your own behind a habit's page, to a zip holding
memories.json,memories.csvand the photos. - Import takes either zip and recreates what was exported. Bring in the habits zip first, then the memories zip, since memories belong to habits.
Importing never deletes anything. A habit that's already in the app (matched by its id) keeps its place and gains any days from the file. Where the app and the file both have the same day, the file wins. Habits that aren't in the app yet are added after the ones you have.
The habits zip
habits.json is the complete record, and the file import reads. habits.csv is the same history for a spreadsheet, one row per recorded day: habit_id, habit, kind, date, done, amount, unit, square, time. Import ignores the CSV, so editing it changes nothing on the way back in.
Schema for habits.json: schema/v1/habits.schema.json (JSON Schema 2020-12). Only format, version and each habit's name are required, so a converter can start small. Import also takes a bare habits.json, without the zip:
{
"format": "daytiles-habits",
"version": 1,
"habits": [
{ "name": "Meditate", "days": ["2026-10-01", "2026-10-02"] },
{ "name": "Water", "kind": "amount", "unit": "oz", "step": 8, "dailyGoal": 64,
"amounts": [{ "day": "2026-10-01", "value": 72 }] },
{ "name": "Push-ups", "kind": "count", "target": 30,
"squares": [{ "square": 1, "day": "2026-10-01" }, { "square": 2 }] }
]
}
| Field | Meaning |
|---|---|
id | A UUID. Matches a habit already in the app, so importing the same file twice doesn't double it. Leave it out to always add a new habit. |
kind | daily (one tile a day, the default), count (squares filled in any order) or amount (how much each day) or quit (something given up, clean every day but the slips). |
color | One of rose, clay, ember, ochre, brass, moss, fern, jade, lagoon, tide, harbor, cornflower, iris, violet, orchid, berry. Picked for you if missing. |
days | Daily habits: days it was done. |
weeklyGoal | Daily habits: days a week that make a full week, 1 to 7. |
schedule | Daily habits on set days instead: {"weekdays": ["monday", "thursday"]}, or {"every": 3, "from": "2026-10-01"} for every third day counting from a day it's due. Days off the schedule don't count against the habit. Leave it out for weeklyGoal days a week. |
target, squares | Count habits: how many squares, and which are filled, with the day when known. |
unit, step, dailyGoal, amounts | Amount habits: what's counted, how much a tap adds, how much makes a day done, and each day's total. |
timerOn | Amount habits counted in minutes or hours: true when the + button runs a timer instead. |
slips | Quit habits: the days slipped. Every other day from createdAt on counts as clean. In habits.csv they're the rows with done 0. |
checkIns | The local time (HH:mm) it was checked off on a day, used to learn reminder times. |
reminders | morningTime and eveningTime: default to follow the app's reminders in settings, the habit's own HH:mm in their place, or off. morning and evening say whether the habit is picked when the app's reminder covers chosen habits. extraTimes lists up to two more HH:mm times the habit is reminded (Pro). |
health | The Apple Health type it counts toward (water, mindful, toothbrushing, caffeine, steps, exercise or workouts), how much each check-off counts as, and the day it started counting. Only what was logged in Daytiles is exported; what other apps put in Health stays in Health. |
pauses | Days off, as {"start", "end"} with both days included. No end means paused until resumed. Paused days don't count against the habit. |
skipped | Daily and amount habits: single days set aside, as dates. Like paused days, they don't count against the habit. |
appearance | How the habit looks in Daytiles. Safe to leave out. |
The file also carries the app's settings: when weeks start, week markers, the morning and evening reminders (who they cover and when), whether reminder times are learned, the size home tiles start at, and the app icon. Importing puts them back. iCloud sync is chosen per device, so it isn't included.
The zip also holds reminders.csv: habit_id, habit, reminder, setting, time, chosen. The first rows are the app's own morning and evening reminders, with no habit, saying who they cover (off, all or choose) and when. Each habit then says default to follow them, own with its own time, or off, followed by an extra row for each extra time. Learned times move from day to day, so they aren't listed.
Days are written YYYY-MM-DD and mean the calendar day where you were, not a moment in time. Other times are ISO 8601.
The memories zip
Schema: schema/v1/memories.schema.json. The zip holds memories.json, a memories.csv listing the same memories for a spreadsheet (habit_id, habit, date, note, photo), and the photos as JPEG files:
memories.json
memories.csv
photos/<habit id>/2026-10-01.jpg
backgrounds/<habit id>.jpg
{
"format": "daytiles-memories",
"version": 1,
"memories": [
{ "habit": "<habit id>", "habitName": "Read", "day": "2026-10-01",
"note": "Finished the book.", "photo": "photos/<habit id>/2026-10-01.jpg" }
],
"backgrounds": [{ "habit": "<habit id>", "photo": "backgrounds/<habit id>.jpg" }]
}
Each memory names its habit by the id from the habits file. Photo paths are relative to memories.json, which can sit at the top of the zip or one folder down, as Finder's Compress makes it. Photos other than JPEG are converted when they come in.
Versions
This is version 1. New fields can appear without a new version, so anything reading these files should ignore fields it doesn't know and treat a missing field as its default. A new version number means something changed in a way older readers can't handle; the schema for it will be published at a new address beside this one, and Daytiles will keep reading version 1.