Zettel is a minimalist iOS markdown note-taking app with a unique "tear-off" interaction pattern. The app focuses on single-note editing with a distinctive archiving mechanism through physical tear gestures.
- Platform: iOS 17.6+
- Language: Swift 5.0
- UI Framework: SwiftUI with UIKit integration
- Architecture: MVVM with Document-Based App architecture
- Storage: File-based (.md files) with extended attributes for metadata
- Device Support: iPhone only (portrait orientation)
- Single-Note Focus: One active note at a time with full-screen editing
- Tear-Off Archiving: Physical drag gesture (swipe right) anywhere on the note to archive
- Tag System: Hashtag-based organization with visual tag chips
- Document Integration: Full iOS Files app integration
- Markdown Support: Custom keyboard toolbar for formatting
- Theme Support: Light, dark, and system theme options
- Note.swift: Core note model with metadata serialization
- Tag.swift: Tag model with case-insensitive matching
- TagParser.swift: Regex-based tag extraction from content
- NoteStore.swift: Central state management for notes
- TagStore.swift: Tag usage tracking and management
- ThemeStore.swift: Theme preference persistence
- MainView.swift: Primary editing interface with tear gesture
- OverviewGrid.swift: Archived notes grid with filtering
- SwipeNavigationView.swift: Container for swipe navigation
- TaggableTextEditor.swift: Text editor with tag highlighting
- SettingsView.swift: App configuration interface
- TagChipView.swift: Tag visualization components
- String+Localization.swift: Localization support
- Color+Extensions.swift: Custom color definitions
- CGFloat+Extensions.swift: Safe math operations
- LayoutConstants.swift: UI spacing, sizes, animation durations
- ThemeConstants.swift: Color opacity and visual constants
- Note Creation: User writes → Save on right swipe → Create .md file
- Note Loading: Read .md files → Parse metadata → Display in grid
- Tag Extraction: Regex parsing → Cache management → UI updates
- File Sync: NSFilePresenter → External change detection → Auto-reload
Notes are stored as plain Markdown files:
Note content with #tags and markdown formatting- SwiftUI: Primary UI framework
- UIKit: Text editing (UITextView) and document picker
- Combine: Implicit reactive state management via @Published properties
- FileManager: File operations and monitoring
- NSFilePresenter: External file change detection
- Haptic Feedback: Physical feedback for interactions
- Default Location:
Documents/ - File Format: Markdown (.md) files
- Tag Extraction: Dynamic regex-based parsing
- Security: App sandbox with user-selected file access
- ✅ Document-based app
- ✅ File sharing (iTunes)
- ✅ Opens documents in place
- ✅ User-selected file access
- ❌ No network access
- Bundle ID: Configurable via environment file
- Version: 1.0
- Minimum iOS: 17.6
- Swift Version: 5.0
- Xcode Project: Modern format with automatic signing
- Minimalist Interface: Focus on content, not chrome
- Physical Metaphors: Right swipe gesture mimics tearing paper
- Haptic Feedback: Reinforces physical interactions
- Smooth Animations: Spring animations for natural feel
- Consistent Theming: System-aware color scheme
- Lazy Loading: Notes loaded on demand
- Tag Caching:
TagCacheManagerfor regex performance - File Monitoring: Efficient external change detection
- Memory Management: Automatic with ARC
- Sandboxed: Full app sandbox
- File Access: Only user-selected files
- No Analytics: No tracking or data collection
Recent development focuses on:
- Tag animation improvements
- Color system refinements
- Keyboard functionality fixes
- File naming enhancements
- Welcome note for first-time users
Zettel/
├── Zettel.xcodeproj/ # Xcode project files
├── Zettel/ # Main app source
│ ├── Assets.xcassets/ # App icons and colors
│ ├── Extensions/ # Swift extensions
│ ├── Models/ # Data models
│ ├── Stores/ # State management
│ ├── Views/ # UI components
│ ├── Constants/ # Design system constants
│ ├── ZettelApp.swift # App entry point
│ └── ContentView.swift # Main container
├── plan/ # Development planning docs
├── build.sh # Build script
└── README.md # Basic project info
None - The app uses only Apple frameworks, demonstrating a lean, native-first approach.
Currently no automated tests. The app relies on manual testing and Xcode previews for UI validation.
- File-Based Storage: Simple, user-accessible, no database complexity
- Document-Based App: Leverages iOS document management
- Tag Extraction: Dynamic regex-based rather than stored relationships
- Single Activity Focus: One note at a time reduces complexity
- No Cloud Sync: Simplifies data management and privacy
- UIKit Integration: Custom text editing with SwiftUI wrapper
- NSFilePresenter: Automatic external file change detection
Central state manager handling:
- File I/O operations
- Note lifecycle management
- External file monitoring via NSFilePresenter
- Tag store coordination
- First-time user experience
Simple structure with:
- Title and content properties
- Creation/modification timestamps
- Auto-generated titles from timestamps
- Tag extraction via regex
- Filename-based identity
Manages tag-related functionality:
- Tag extraction caching
- Usage count tracking
- Debounced updates for performance
- Tag-based note filtering
- MainView: Single-note editing with right swipe gesture
- OverviewGrid: Masonry-style grid of archived notes
- TaggableTextEditor: UIKit text view with tag suggestions
- SwipeNavigationView: Container managing swipe transitions
The app integrates deeply with iOS file system:
- Security-scoped resource access for user-selected directories
- NSFileCoordinator for safe file operations
- File monitoring for external changes
- Document picker integration
- Support for opening .md files from Files app
- Tag extraction caching to avoid repeated regex operations
- Debounced tag store updates during typing
- Lazy loading of note content
- Efficient grid layout with proper sizing calculations
- Memory-conscious image and asset loading