Skip to content

About

Native macOS focus timer for LSAT prep. Logs every block to Obsidian and Notion.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

4 Commits

Folders and files

Repository files navigation

LSAT Timer

A native macOS focus timer for LSAT prep. Every completed block is written to an Obsidian vault and to a Notion database, so study time tracks itself.

Built in Swift (AppKit + WKWebView). No frameworks, no npm, no local server, no network calls except the Notion API. The whole app is one Swift file, one HTML file, and an icon, and it weighs about 600 KB.

LSAT Timer

Download

Grab the latest .dmg from Releases, open it, and drag LSAT Timer to your Applications folder. Universal binary, macOS 13 or later.

The build is signed ad hoc rather than notarized, so the first launch needs one extra step: right click the app and choose Open, then confirm. macOS remembers the choice. If it still refuses, clear the quarantine flag:

xattr -dr com.apple.quarantine "/Applications/LSAT Timer.app"

Prefer to build it yourself? See Build below. It takes about ten seconds.

What it does

  • Focus blocks with short and long breaks. Defaults to 35 / 5 / 15 with four blocks per cycle, because 35 minutes is a real LSAT section length.
  • Tag each block with an activity: LR drill, RC drill, Full PT, Review, Flashcards, Reading, Other. Optional one line note.
  • Chime plus a macOS notification when a block ends. Breaks can start themselves.
  • Guided Notion setup: paste a token, pick a database, or have the app build one.
  • Today, this week, and day streak, plus the day's blocks listed in the window.
  • Dock badge counts down the minutes remaining. Keep on Top with Cmd+T.
  • Strict monochrome dark UI, matching the Second Brain Companion design system.

Where the data goes

Obsidian. One note per day at 1-raw/law-school/lsat/study-sessions/YYYY-MM-DD.md, rewritten in full each time a block finishes:

---
date: 2026-08-14
type: lsat-study-log
total_minutes: 70
pomodoros: 2
source: LSAT Timer
---
# LSAT study — Friday, August 14, 2026

**70 min** across 2 blocks · LR drill 35m · Review 35m

Plan: [[10-week-study-plan]] · Misses: [[wrong-answer-book]]

| Start | End | Min | Activity | Notes |
| --- | --- | --- | --- | --- |
| 9:05 AM | 9:40 AM | 35 | LR drill | PT 155 section 2 |

Notion. One row per block in a database with these properties: Session, Date, Minutes, Activity, Pomodoros, Started, Ended, Notes, Source. If the request fails or no token is set, the block goes to a local queue and retries on the next launch, or immediately when you click the Notion pill in the footer.

Local. ~/.local/share/lsat-timer/sessions.jsonl is the source of truth. The day notes are derived from it, so deleting a note is safe.

Build

Requires the Xcode command line tools. Nothing else: no package manager, no dependencies. The build produces a universal binary when the x86_64 toolchain is available, and falls back to arm64 alone when it is not.

./build.sh              # builds into ~/Applications
./build.sh /Applications

Connect Notion

Open Connect Notion from the app menu, or click the Notion pill in the footer. The screen walks two steps:

  1. Create an integration. A button opens https://www.notion.so/my-integrations. Make one, name it LSAT Timer, and copy the internal integration secret. Paste it in. The app checks it against Notion live and tells you which workspace answered, so a bad paste is caught immediately rather than at the end of your first block.
  2. Give it a page. In Notion, open the page or database you want, use the ... menu, choose Connections, and add the integration. Then press Find databases and pick one. If you would rather not build the database yourself, press Find pages, pick a page, and Create Study Sessions builds it with the right columns already in place.

The token goes into your login keychain, not a file. Nothing is sent anywhere except api.notion.com. Disconnect clears both the token and the database.

Obsidian needs no credentials at all. Point VAULT at your vault and blocks start landing there immediately.

Editing config by hand

Everything is still readable and editable at ~/.config/second-brain/lsat-timer.env, which the app re-reads on every block:

NOTION_TOKEN=ntn_xxx            # optional: the keychain takes priority
NOTION_DATABASE_ID=...
VAULT=/path/to/your/vault
OBSIDIAN_SUBPATH=1-raw/law-school/lsat/study-sessions

Layout

native/main.swift     the app: window, menus, bridge, file writes, Notion client
native/Info.plist     bundle metadata
app/index.html        the entire UI, one file, no assets
build.sh              compile universal, assemble, ad hoc sign
package-dmg.sh        wrap the built app in a .dmg and .zip

The UI talks to Swift over a WKWebView message handler. A small shim rewrites fetch('/api/…') onto that handler, so the HTML stays plain and portable.

Design

Strict monochrome, dark first. Near-black #0B0B0D behind translucent glass panels, hairline white strokes, and system SF Pro throughout, so there are no bundled font files and nothing to load at runtime.

There is no accent hue. Selection is expressed the one way the language allows: a white fill with black text. That single idiom covers the chosen activity, the primary button, and the settings switches. Breaks are marked by dashing the dial track rather than by changing color, the way a lighter tier is marked elsewhere in the system.

Token Value
Background #0B0B0D
Glass, card rgba(120,120,128,0.14)
Glass, control rgba(120,120,128,0.18)
Strokes 0.5px white at 8 to 16 percent
Text white, then rgba(235,235,245,0.55), then 0.42
Radii card 20, field 14, capsules fully round
Type SF Pro. Title 27/700, body 15, caption 11.5, eyebrow 11/600 caps at 0.8 tracking

Numerals use tabular figures everywhere a value changes in place, so the clock and the totals do not jitter.

License

MIT

About

Native macOS focus timer for LSAT prep. Logs every block to Obsidian and Notion.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages