Skip to content

reneweteling/loft-app

Repository files navigation

Loft app icon

Loft

Drag a file to your menu bar. Get a link back.

Loft popover with the four drop panes

https://github.com/reneweteling/loft-app/raw/main/docs/public/assets/ex-upload.mp4

Swift 5.9 macOS 14+

What it does

  • Drag and drop a file (or folder) onto the menu bar popover — folders are zipped on the fly
  • Four TTL panes — Private, 1 Day, 30 Days, Public — each enforcing expiry via S3 lifecycle tags
  • Multipart upload for large files (8 MB parts, 4 concurrent) so big transfers don't stall
  • Custom S3 endpoints out of the box: Cloudflare R2, Backblaze B2, MinIO, DigitalOcean Spaces

Install

git clone https://github.com/reneweteling/loft.git
cd loft
./scripts/build.sh
cp -R build/Loft.app /Applications/

First launch: see First launch (macOS security) below.

First launch (macOS security)

Loft is ad-hoc signed with a local certificate, not Apple-notarized. Apple charges €99/year for a Developer ID and this is a tiny personal tool, so we skip that. The tradeoff: on the very first launch macOS will refuse to open the app and show this:

macOS Gatekeeper warning: Loft Not Opened

Click Done, then open System Settings → Privacy & Security. Scroll to the Security section — you'll see a line about Loft being blocked, with an Open Anyway button:

System Settings — Privacy & Security — Open Anyway

Click Open Anyway, confirm the follow-up prompt, and Loft launches. macOS remembers this choice for this copy of the app — you only do it once per install.

Terminal alternative: xattr -dr com.apple.quarantine /Applications/Loft.app && open /Applications/Loft.app skips the System Settings detour.

Setup

  1. Create your bucket — follow vault/20-Setup/Bucket Setup.md for lifecycle rules and CORS.
  2. Create an IAM user with the minimal policy in vault/20-Setup/IAM Policy.md.
  3. Open Loft Settings (⌘,) → S3 tab — enter Access Key ID, Secret Access Key, Region, Bucket, and (optionally) a custom endpoint.

Screenshots

General Panes S3 About
General Panes S3 About

Requirements

  • macOS 14 (Sonoma) or later
  • Xcode Command Line Tools
xcode-select --install

Project layout

Package.swift              SwiftPM manifest
Sources/Loft/              Application source (Swift 5.9 + SwiftUI)
scripts/
  build.sh                 Builds and ad-hoc signs Loft.app
build/
  Loft.app                 Output of build.sh (git-ignored)
vault/                     Obsidian vault — setup guides and architecture notes
docs/                      GitHub Pages site

Documentation

The vault/ folder is an Obsidian vault with complete setup guides and architecture notes. Open it with Obsidian or read the Markdown files directly. The GitHub Pages site at reneweteling.github.io/loft has a quick-start overview.

Key pages:

  • vault/20-Setup/Bucket Setup.md — lifecycle rules and CORS
  • vault/20-Setup/IAM Policy.md — minimal IAM policy JSON
  • vault/10-Architecture/ — design decisions and component overview

Troubleshooting

Gatekeeper blocks the app — strip quarantine and reopen:

xattr -dr com.apple.quarantine /Applications/Loft.app

Test Connection fails — confirm the region matches the bucket, and that the IAM user has s3:GetBucketLocation and s3:ListBucket on the bucket ARN (not just objects).

Uploads fail silently — for multipart, the policy also needs s3:CreateMultipartUpload, s3:UploadPart, s3:CompleteMultipartUpload, and s3:AbortMultipartUpload. The policy template in vault/20-Setup/IAM Policy.md covers all of these.

Built by

Weteling

René Weteling
Felobo B.V. · Tech Lead · Fullstack · Ruby · Elixir · TypeScript

weteling.com · github.com/reneweteling · rene@weteling.com

License

Copyright © 2026 Felobo B.V. All rights reserved.

About

Small app to share files to s3 with ease

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors