AppendX

active
swiftswift-ui

Download on the App Store

Native iOS. Swift, SwiftUI, SwiftData. iOS 17+, iPhone and iPad.

Architecture

Queue-first writes. Every capture is written to a local SwiftData store in a shared App Group container before any file write is attempted. The queue is the source of truth; the markdown file is the destination. A capture can fail to write, but it can’t be lost — pending items drain when the app next foregrounds, and a history view shows every capture and its status.

One capture pipeline. The share extension and the in-app capture view are separate processes with separate UI, but both run the same CaptureService (enqueue → write → mark synced/failed). One code path, one place for bugs to live.

Coordinated iCloud writes. File writes go through NSFileCoordinator rather than raw FileManager, and folder access persists across launches via security-scoped bookmarks. Works against iCloud Drive or on-device storage, so it covers Obsidian, iA Writer, 1Writer, or a plain folder of .md files.

Isolated failure stages. Write success and status bookkeeping are separate do/catch stages, so a failed bookkeeping save can never report itself as a failed write. The worst case is an item that shows as pending and gets picked up by the next drain.

Capture formats

Rather than a list of template presets, each target picks a container:

  • List — a single line whose content adapts to whatever was shared: selected text, else [title](url), else a bare URL. Optional checkbox and date.
  • Block — every field present on its own line. Never drops data. Optional separators and date.
  • Custom — a token format string ({{url}}, {{title}}, {{text}}, {{date}}, {{time}}) with a live preview.

The share sheet renders the actual captured content through the selected container before you commit, and names anything being dropped — with its value — rather than asserting a summary.

Normalization

iOS apps hand share extensions wildly inconsistent payloads. AppendX runs a normalization layer built from a corpus of 25 apps’ real share data:

Field meaning is resolved at extraction, where the source host is known — no plain-text attachment means attributedContentText is a title; a plain-text attachment means it’s the user’s selection; apple.news is a documented exception where the plain-text is always the article title and the selection arrives URL-encoded in a query parameter.

Value cleaning is a five-step pipeline: promote a URL out of a text field when an app puts it in the wrong place, decode the Apple News highlight parameter, resolve file:// paths to filenames, strip tracking and challenge parameters (utm_*, wprov, hs_amp, Reddit’s bot-challenge tokens) preferring non-AMP URLs, and trim whitespace.

The research behind this is written up separately: What iOS Shares, with the raw corpus as a gist.

Paste as Markdown

UIPasteboard carries public.html when you copy from a browser. The share sheet doesn’t — every app in the corpus flattens rich text before handing it off. So the capture view reads the clipboard’s HTML directly and converts it: bold stays bold, inline links stay links. Citation and footnote links are dropped, and brackets in link text are escaped so [1] can’t be misparsed as an Obsidian wikilink.

Icon suggestions

Typing a target name suggests emoji: “Bird Watching” offers 🦅 🪶 🔭, “Mushroom Foraging” offers 🍄 🌲 🧺. Implemented on-device with NLTagger noun extraction against a curated keyword map with family-bucket fallbacks, plus input sanitization so _inbox.md and 00-books still match. An API call would have been less code, but this is instant, works offline, and costs nothing to run.

Stack

Swift · SwiftUI · SwiftData · App Groups · NSFileCoordinator · StoreKit 2 · NaturalLanguage · UniformTypeIdentifiers · Icon Composer (Liquid Glass) · Astro (marketing site)

A Typical Workflow

Here’s an example of capturing the name of a band from a Reddit post through to a bands.md file.

Project Updates