Files
ihatepdfs/docs/ENGINEERING.md
Akshay Kolli 085d7a16dc Release v0.3
2026-06-24 17:51:26 -07:00

3.2 KiB

Engineering Principles

I Hate PDFs is intentionally a small native macOS app. Future work should preserve that constraint unless there is a documented, user-visible reason to do otherwise.

Native First

  • Build features with Swift, SwiftUI, AppKit, PDFKit, and other system frameworks that ship with macOS.
  • Do not replace the app with Electron, Chromium, a web runtime, a bundled JavaScript app shell, or a cross-platform UI toolkit.
  • Do not bundle a PDF renderer, OCR engine, database, scripting runtime, or large framework when a macOS system API can satisfy the requirement.
  • Prefer native macOS controls and document behaviors over custom reimplementations when they meet the product need.

Small By Default

Every change should aim for the smallest final app that still delivers the required fluidity, reliability, and functionality.

  • Keep third-party dependencies at or near zero. Any new package must justify its shipped size, runtime cost, maintenance cost, and why system APIs are insufficient.
  • Keep assets minimal. Avoid large raster images, fonts, sample PDFs, videos, model files, or generated resources in the app bundle.
  • Keep build outputs out of source and releases unless they are intentional release artifacts.
  • Prefer dynamic links to Apple system frameworks over vendored libraries.
  • Avoid storing duplicate PDF data, rendered page caches, or annotation indexes unless profiling shows they are required for fluid interaction.
  • Favor targeted updates over whole-document rescans for common interactions such as editing, replying, filtering, hovering, and sidebar refreshes.

Size Budget

The release DMG should stay as small as practical. Treat size growth as a product regression, not just a packaging detail.

Before merging release-impacting work, compare:

scripts/build-app.sh
scripts/make-dmg.sh
du -sh "dist/I Hate PDFs.app" \
  "dist/I Hate PDFs.app/Contents/MacOS/IHatePDFs" \
  "dist/I Hate PDFs.app/Contents/Resources/AppIcon.icns" \
  dist/IHatePDFs-v*-macos.dmg

If a change materially increases the app bundle or DMG size, document why in the PR or commit notes. A useful rule of thumb: any dependency addition, bundled asset addition, or release-size increase above roughly 10% needs explicit justification.

Performance Budget

Small size should not come at the expense of reader fluidity.

  • Opening, scrolling, zooming, searching, annotating, saving, and sidebar navigation should remain responsive on long PDFs.
  • Optimize around measured user workflows instead of speculative micro-optimizations.
  • Keep expensive work page-scoped or lazy when possible.
  • Use swift test plus the PDF verification scripts after behavior changes:
swift test
swift scripts/verify-sample-pdf.swift
swift scripts/verify-pdf-annotations.swift

Release Packaging

Release builds should use the existing lightweight packaging path:

scripts/build-app.sh
scripts/make-dmg.sh

scripts/build-app.sh strips release binaries by default to reduce shipped size. Use STRIP_RELEASE=0 scripts/build-app.sh only when a symbol-rich release build is needed for debugging.

Universal arm64 + x86_64 builds are the default for public releases. Single-architecture builds are acceptable for local testing:

ARCHS="" scripts/build-app.sh