· 6 min read

Building BragLog: Turning Daily Wins Into Brag Documents

I built an app that turns quick daily work logs into polished brag documents using on-device AI. Here's the story behind BragLog.

Performance review season is universally dreaded. Not because people don’t do great work, but because nobody remembers what they did six months ago. You sit down with a blank document, try to recall that critical bug you fixed in July, that feature you shipped under pressure in September, and end up writing something generic that undersells everything.

I’ve been there too many times.

The Problem

The advice is always the same: “keep a brag document.” Write down your wins as they happen. Julia Evans wrote a great post about it years ago, and the concept stuck with me. But every time I tried, I’d keep it up for a week, forget about it, and find myself back at square one come review time.

The friction was the problem. Opening a text file, context-switching from whatever I was working on, writing something coherent. It’s just enough resistance that you skip it on busy days, which are exactly the days worth documenting.

What I Built

BragLog is a native app for iPhone, iPad, and Mac. The core loop is simple: log a quick win (takes seconds), and when review time comes, tap a button and get an AI-generated brag document ready to paste into whatever form your company uses.

Six categories keep things organized: Shipped, Led, Fixed, Learned, Mentored, Improved. They map roughly to the things managers care about in reviews. The app suggests a category as you type using on-device AI, so you don’t even have to think about it.

On-Device AI With Tool Calling

The brag document generation is the feature I’m most proud of, and also the one that caused the most headaches.

I used Apple’s FoundationModels framework, which runs entirely on-device. No API keys, no cloud calls, no data leaving the phone. The model generates structured brag documents using Tool Calling: it can fetch entries for a specific period, get category breakdowns, and pull streak information, then weave it all into a coherent narrative.

You can choose a tone (professional, confident, or modest) and the AI adapts accordingly. The output comes as structured sections that you can export as Markdown, plain text, or HTML compatible with Word, Pages, and Google Docs.

The catch? FoundationModels requires Apple Silicon. On older devices, the AI features gracefully degrade. You can still log, organize, and export everything manually. The AI is a convenience layer, not a hard dependency.

One lesson I learned the hard way: the @Generable macro and Tool Calling have quirks. You can’t capture SwiftData @Model objects in tool closures because they’re not Sendable. I had to create a SendableEntry pattern where I extract plain data from model objects before passing them to the AI pipeline. Not complicated once you know, but it cost me a few hours of confusing compiler errors.

Standard text search feels limiting once you have hundreds of entries. “I know I fixed something related to database performance, but I didn’t use the word ‘database’ in the entry.”

BragLog’s search uses FoundationModels for semantic matching. Search “database” and it’ll surface entries about SQL migrations, query optimization, and PostgreSQL tuning even if those exact words aren’t in the query. There’s a debounce (0.8 seconds) and a cap at 200 entries to keep it responsive.

The Streak Game

I added streak tracking because I know myself. A GitHub-style contribution heatmap, daily progress, and milestone celebrations at 7, 30, and 100 days. It’s a small psychological trick, but it works. There’s a grace period built into the streak calculator so missing a weekend doesn’t break a work-week streak.

The streak also shows as a Live Activity on the Lock Screen and Dynamic Island on iOS. It’s a subtle reminder throughout the day. “You’ve logged for 23 days straight. Don’t break the chain.”

17 Tips and an Animated Onboarding

I went deep on TipKit. Seventeen contextual tips that appear progressively as you use the app. First-time composing? You get a tip about AI category suggestions. Hit 10 entries? A tip about generating your first brag doc. Reach the insights screen? Tips about the heatmap and streak tracking.

The onboarding is a 4-page animated flow with MeshGradient backgrounds, floating particles, and spring animations. I probably spent more time on this than I should have, but first impressions matter, and I wanted the app to feel polished from the moment you open it.

Making It Feel Native Everywhere

The iOS version uses an adaptive tab bar with Liquid Glass styling on iOS 26. On iPad, it switches to a sidebar. On Mac, it’s a full NavigationSplitView with a menu bar extra for quick capture. You can log a win from the menu bar without switching away from your code editor.

Widgets cover Home Screen, Lock Screen, StandBy, and Control Center. Seven Siri Shortcuts let you log wins, check your streak, or generate summaries by voice. Handoff lets you start composing on your iPhone and continue on your Mac. Spotlight indexes all entries so you can find them from system search.

None of these integrations are individually complex, but together they make the app feel like it belongs on the platform rather than just running on it. That’s the goal.

Zero Dependencies

BragLog is built entirely with Apple frameworks. No SPM packages, no CocoaPods, nothing. Swift 6 with strict concurrency, SwiftUI, SwiftData, CloudKit, FoundationModels, TipKit, WidgetKit, AppIntents, CoreSpotlight, ActivityKit. About 7,700 lines across 48 Swift files.

I chose this constraint deliberately. Every third-party dependency is a maintenance burden and a potential privacy concern. For an app that handles people’s work accomplishments, I wanted to be able to say with certainty: nothing in this app talks to anyone except Apple’s iCloud, and only if you have it enabled.

What I’d Do Differently

The @Generable struct wrappers for FoundationModels output were clunky at first. I’d design the model layer around the AI output format from the start instead of retrofitting it.

I’d also invest in screenshot automation earlier. I built a DebugDataSeeder that generates realistic sample data for App Store screenshots, but I added it late in the process. Having it from day one would have made design iteration faster.

And the 17 TipKit tips? I’d still do all of them, but I’d define the milestone triggers in a configuration file rather than scattering them across views. They work great, but they’re harder to maintain than they should be.

Try It

If you’ve ever stared at a blank self-review form trying to remember what you did last quarter, BragLog might help. Log your wins as they happen, let AI do the heavy lifting at review time.

Download on the App Store | Website