Skip to content

Building a Native Mac Calendar App in 48 Hours

What I cut, rebuilt, and shipped during a 48-hour sprint on hora, including PKCE auth, Day View, FreeBusy sharing, and WidgetKit.

6 min read
A 48-hour shipping trace connecting scope cuts, PKCE authentication, Day View, availability sharing, and a macOS widget

Forty-eight hours is enough time to make a prototype much larger. It is not enough time to make every idea good.

That was the useful constraint.

By March 25, hora already had a working Google Calendar foundation. The 48 hours that followed were not a greenfield speed run. They were a concentrated attempt to turn that foundation into something I could use without constantly forgiving it.

The biggest improvement did not come from typing faster. It came from deleting work.

If you want the reason behind the project first, read why I built a native Google Calendar app for Mac. This is the messier story of the 48 hours around that first post.

Day 1: cut the product back to its promise

The prototype had started collecting features before the core experience was stable.

There was a menu bar experiment, Gmail-powered meeting briefings, and a Day View that looked finished until I tried to use it. Each idea was defensible. Together, they made it harder to tell whether the basic product was getting better.

So I removed or paused them.

That sounds dramatic when written as a launch lesson. In practice, it felt uncomfortable. Deleting something that already exists looks like moving backward, especially when the alternative is reliability work that nobody will notice in a screenshot.

The scope test became simple: does this make Google Calendar feel better on a Mac today?

If the answer was not clearly yes, the feature could wait.

Rebuilding the surfaces that remained

Once the product was smaller, I could see the weak parts more clearly.

I rebuilt the sign-in screen, reorganized Settings, and spent time on event interactions. Dragging and resizing gained clearer priorities and 15-minute snapping. The interface around accounts, calendars, notifications, and appearance became less like an internal tool and more like one coherent Mac app.

I was not trying to invent a new design language for calendars. I was trying to remove the moments where the app reminded me it was an early prototype.

One bug from that day is still a good example. A shared calendar can appear under more than one Google account. Treating Google's calendar ID as globally unique inside the local store caused collisions. The fix was to include the account identity in the local calendar key while preserving the original Google ID for API calls.

The code change was small. Finding the assumption behind the crash was not.

The security fix I should have made first

The draft OAuth flow included a client secret in the app bundle.

That does not make a secret safe. A Mac app is distributed to the user, so values embedded in the binary should be treated as recoverable.

I replaced the static secret with PKCE. Each authorization attempt now creates a random code_verifier, derives a code_challenge, and sends the challenge with the initial request. Google only exchanges the returned authorization code when the client presents the matching verifier.

RFC 7636 defines the protocol and the attack it is designed to mitigate. The important lesson was less technical: authentication shortcuts become expensive foundations very quickly.

I could have postponed the work because the app was still small. That was exactly why it was the right time to fix it.

Day 2: build the missing daily loop

With the scope smaller and sign-in safer, I focused on the parts of the day the prototype still could not handle.

Five features converging into a native macOS calendar build during a two-day sprint

A Day View I could trust

The first Day View had been removed because it was too separate from the rest of the calendar.

The replacement reused the same timeline concepts as Week View. Creating, editing, dragging, resizing, and navigating events followed one interaction model instead of two similar implementations slowly drifting apart.

That is less exciting than saying I shipped a new calendar view. It is also the difference between adding a screen and extending a product.

Availability sharing through Google's FreeBusy API

I wanted a faster answer to a common question: "When are you free?"

The new availability flow queried Google's FreeBusy endpoint, converted busy intervals into usable free slots, then produced text that could be pasted into email or chat. Google's FreeBusy API returns busy ranges for the requested calendars and time window. hora did the presentation work locally.

The first shortcut was Cmd+Shift+A. It opened a sheet, let me choose the range, and copied the result to the clipboard.

This was one of the first features that felt distinctly more useful than opening the Google Calendar website.

A second time zone without recomputing the world

Day and Week views gained an optional secondary time zone.

Instead of repeatedly asking the calendar system for the same conversion while drawing the grid, the implementation prepared an offset lookup for the visible range. The result was constant-time access while rendering the time labels.

The user-facing feature was a second column of hours. The engineering work was making sure it did not turn scrolling into a calculation benchmark.

A real macOS widget

The earlier menu bar idea had been paused, but WidgetKit was a clearer native surface to ship.

The first widget showed today's and tomorrow's agenda, calendar colors, event titles, and a route to join supported calls. It shipped in medium and large sizes.

Apple describes widgets as glanceable content available without opening the app. A calendar is almost an unfairly good fit for that idea. The next event is useful precisely because I should not have to open a full calendar to find it.

I also added a Shortcuts-based experiment for toggling a macOS Focus when a meeting began and ended.

The event editor gained an early conference-provider picker too. Google Meet was the native path. Zoom, Microsoft Teams, and custom links were still placeholders or pasted URLs, not the deeper provider integrations hora has today.

That distinction matters in a build log. A visible control is not the same thing as a complete integration.

What did not fit in the sprint

Recurring-event editing still needed work. Keyboard navigation was incomplete. Drag and resize behavior had rough edges. The Mac App Store submission was not ready.

The sprint made hora feel more like a product, but it did not make it finished.

This is the part fast-building stories usually compress. The last 20 percent is not one small final pass. In a calendar app, it is where real accounts, recurrence rules, network failures, invitations, and time zones start combining.

Two days later, the feature list was more convincing. The risk had moved from "can this exist?" to "can I trust it with somebody else's schedule?"

What I learned from the 48 hours

Scope cuts create room for coherence

Removing half-built features did more than save time. It reduced the number of interaction models and states I had to hold in my head. The remaining work could share a direction.

Security debt is still debt in a prototype

PKCE did not need to wait for launch. Fixing the OAuth model early meant every later sign-in flow inherited a safer assumption.

Native surfaces should earn their place

WidgetKit, system authentication, keyboard commands, the clipboard, and Shortcuts were useful because they shortened real calendar tasks. "Native" became a product test, not only a choice of framework.

Shipping reveals the next layer of work

The feature sprint did not close the project. It exposed the reliability work behind it.

Four days later I wrote about the road to launch, and the week one retrospective records what happened when the fast build met a growing issue list.

hora eventually reached the Mac App Store on June 30, 2026. The current product is much more mature than this 48-hour snapshot, but its shape came from the same decision: focus on Google Calendar and make the Mac workflow worth opening.

Try hora Calendar on the Mac App Store

Related stories

Week One Building hora: 107 Commits Later
Build notes

Week One Building hora: 107 Commits Later

A candid snapshot of hora's first ten days: 107 commits, three Swift packages, 21 resolved issues, useful workflows, and plenty still rough.

Maciej Szamowski7 min read
Why I Built a Native Google Calendar App for Mac
Build notes

Why I Built a Native Google Calendar App for Mac

Why I built hora as a native Mac client for Google Calendar, chose the official API over CalDAV, and kept Google as the source of truth.

Maciej Szamowski7 min read
Five Days Later: The Road to Launching hora Calendar
Build notes

Five Days Later: The Road to Launching hora Calendar

Five days after I first wrote about hora, the visible app worked. The road to launch was now OAuth verification, TestFlight, reliability, and feedback.

Maciej Szamowski6 min read
Mobile Beta Sign-up

Want to stay updated?

Subscribe for information about iOS/iPadOS beta availability.