# What I learned shipping one of the first AlarmKit apps

> Field notes from building MeetAlarm on iOS 26's AlarmKit: the mental model that makes the framework click, the permission and re-sync gotchas, and what I'd tell anyone starting an AlarmKit app today.

Published 2026-07-13 · MeetAlarm Blog · https://www.meetalarm.app/en/blog/alarmkit-development-notes

When Apple announced AlarmKit at WWDC, I started building the same week — the meeting-alarm idea had been sitting in my notes for a year waiting for exactly this API. That head start means MeetAlarm shipped as one of the earlier AlarmKit apps on the store, and it also means I collected a decent pile of scars while the documentation was still thin. These are the notes I wish I'd had on day one. Nothing here is secret; it's just the stuff you only internalize by shipping.

## The mental model: you declare, the system rings

The most important thing to understand about AlarmKit is that your app is not running when the alarm fires. You don't get a callback at ring time to compute things. You hand the system a complete, self-contained declaration ahead of time — when to fire, what the full-screen alert says, what the buttons are, what sound plays — and the system owns everything from there. It's closer to submitting a form than to scheduling a timer.

Once that clicks, a lot of design questions answer themselves. Anything dynamic — “which meeting link is current,” “what's the traffic like” — has to be resolved at scheduling time, not ring time. If the world changes after you've scheduled, your only move is to cancel and re-schedule. Which leads directly to the biggest architectural consequence:

## Your real job is reconciliation

For a calendar-driven app, the alarm scheduling itself is maybe a tenth of the code. The actual work is reconciliation: every time the app gets a chance to run, diff the calendar's current truth against the alarms you previously scheduled — meetings moved, cancelled, added, rules changed — and converge the two. Do it idempotently, because you will run it far more often than you think, and log what you did, because “why didn't it ring” and “why did it ring twice” are the only two support emails that matter.

MeetAlarm schedules a rolling 7-day window and reconciles on every foreground plus periodic background refresh. A window that size is a deliberate cap — scheduling months ahead multiplies stale-alarm risk for zero user benefit, since the window refills constantly.

## Gotchas that cost me real days

- Alarm authorization is its own permission, separate from notifications. Users have never seen this dialog before and some will reflexively decline. Show a plain-language explainer screen before triggering the system prompt — my grant rate improved noticeably after adding one.
- For a calendar app you're stacking permissions: calendar access and alarm access. Two consecutive cold system dialogs at first launch feels hostile; sequence them with context around each.
- Buttons on the ringing screen run through App Intents, not arbitrary code. The “join the meeting” flow is really: alarm button → intent → app opens → your router deep-links into the right meeting. Getting that chain to survive cold launch deserves its own test pass.
- Treat ring-time UI as static content decided at schedule time. Titles, buttons, sounds — assume everything is frozen when you schedule, and design copy that stays correct even if the meeting shifted after your last sync.
- Build a developer path that fires an alarm seconds from now, on-device. Real alarms are miserable to test by waiting for real meetings, and the simulator will not tell you the truth about ring behavior, sounds, or the Lock Screen.
- Test the ugly states early: Silent switch on, sleep Focus, Low Power Mode, locked device, another alarm ringing simultaneously. This is exactly where AlarmKit is supposed to shine, so it's exactly where your bugs are most embarrassing.

## Be a polite guest with a loud instrument

AlarmKit hands you the single most disruptive capability on the platform: making a phone scream through settings the user chose. The framework polices some of this, but taste has to do the rest. Default lead times should be conservative; skipping and muting a series must be one obvious tap; and “when in doubt, don't ring” is the right bias for edge cases like declined or all-day events. One false positive at 7 AM costs more trust than a hundred correct alarms earn.

## What I'd wish for next

My wishlist after the first weeks in production: recurrence rules expressive enough to follow a calendar series without constant re-scheduling, some form of conditional cancellation so a deleted meeting can't ring even if the app hasn't run since, and richer context on the ring screen. All of it is the natural v2 of a framework that, in v1, already unlocked a category of app that simply couldn't exist before.

## If you're building on AlarmKit

I'd genuinely enjoy comparing notes — the community of people who've shipped against this framework is still tiny. Email me at hi@meetalarm.app. And if you just want your meetings to ring like they mean it, that app exists now: MeetAlarm, free on the App Store, iOS 26+.
