🤝 Contributing
Want to create your own single-file menu app? This guide will help you understand our philosophy and create apps that fit seamlessly into our collection.
🎯 Philosophy
All apps in this collection follow these core principles:
- One file, one purpose - Each app does exactly one thing exceptionally well
- Easy to run - Just execute the Swift file directly:
./app.swift - Easy to modify - All code is visible and editable in one place
- Easy to share - Copy one file and you're done
- No dependencies - Uses only macOS system frameworks
📋 Requirements
Technical Requirements
- macOS 10.15+ (Catalina or later)
- Swift 5.0+ - For modern language features
- Xcode Command Line Tools - For Swift compilation
- Menu bar focus - Apps should provide value through the menu bar interface
Code Standards
- Single Swift file - All code must be in one
.swiftfile - Shebang line - Start with
#!/usr/bin/env swiftfor direct execution - Clean code - Readable, well-structured, and properly documented
- Error handling - Graceful degradation and user-friendly error messages
- Accessibility - Support for VoiceOver and keyboard navigation
🏗️ Project Structure
File Organization
your-app/
├── your-app.swift # Single-file Swift application
├── make_icon.py # Reproducible 1024px/icns icon generator
├── AppIcon.icns # Generated macOS app icon
├── build.sh # Universal .app builder (via ../scripts/build-bundle.sh)
├── package.sh # ditto .zip packager for GitHub Releases
├── tests/run.sh # Optional unit test runner (sed-stripping Main Entry Point)
└── index.md # Documentation pageBundle IDs & Releases
- Use the
ai.thefocus.<slug>reverse-DNS Bundle ID namespace inbuild.sh. - Support
--version(readingCFBundleShortVersionString/CFBundleVersionfromBundle.main.infoDictionary) and--dump-menufor headless verification. - Mark the entry point with
// MARK: - Main Entry Pointso unit tests can strip theNSApplicationstartup withsed '/\/\/ MARK: - Main Entry Point/,$d'. - Verify locally with
./scripts/release-app.sh <your-app> 1.0.0, and add<your-app>-v[0-9]*to.github/workflows/release.yml.
Swift File Structure
swift
#!/usr/bin/env swift
import Cocoa
import Foundation
// Add other imports as needed
// MARK: - Data Structures
struct YourData {
// Define your data structures
}
// MARK: - Main Classes
class YourApp {
// Main application logic
}
class MenuManager {
// Menu bar interface management
}
// MARK: - App Delegate
class AppDelegate: NSObject, NSApplicationDelegate {
// Application lifecycle management
}
// MARK: - Main
let app = NSApplication.shared
let delegate = AppDelegate()
app.delegate = delegate
app.run()🎨 Menu Bar Integration
Basic Menu Bar Setup
swift
class MenuManager {
private let statusItem: NSStatusItem
init() {
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
statusItem.button?.title = "📱" // Your icon
setupMenu()
}
private func setupMenu() {
let menu = NSMenu()
// Add menu items
let infoItem = NSMenuItem(title: "Your App Info", action: nil, keyEquivalent: "")
infoItem.isEnabled = false
menu.addItem(infoItem)
menu.addItem(NSMenuItem.separator())
let quitItem = NSMenuItem(title: "Quit", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q")
menu.addItem(quitItem)
statusItem.menu = menu
}
}Best Practices
- Clear icons - Use emoji or SF Symbols for menu bar icons
- Informative titles - Menu items should clearly indicate their function
- Keyboard shortcuts - Add keyboard shortcuts for common actions
- Separators - Use separators to organize menu sections
- Quit option - Always include a way to quit the app
🔧 Development Workflow
1. Planning
- Define the purpose - What specific problem does your app solve?
- Research existing solutions - Avoid duplicating functionality
- Plan the interface - How will users interact with your app?
- Consider dependencies - Can you achieve this with system frameworks only?
2. Development
bash
# Create your app directory
mkdir my-app
cd my-app
# Create the Swift file
touch my-app.swift
chmod +x my-app.swift
# Start developing
code my-app.swift3. Testing
bash
# Test your app
./my-app.swift
# Test with debug output
./my-app.swift --debug
# Test on different macOS versions if possible4. Documentation
Create a comprehensive README.md:
markdown
# My App
Brief description of what your app does.
## Features
- Key feature 1
- Key feature 2
- Key feature 3
## Installation
```bash
chmod +x my-app.swift
./my-app.swiftUsage
Describe how to use your app.
Requirements
- macOS 10.15+
- Any additional requirements
Troubleshooting
Common issues and solutions.
## 📝 Submission Process
### 1. Prepare Your Submission
- **Test thoroughly** - Ensure your app works reliably
- **Document completely** - Include comprehensive README and usage examples
- **Follow naming conventions** - Use lowercase with hyphens for directory names
- **Include examples** - Provide sample usage and configuration
### 2. Create Pull Request
1. **Fork the repository**
2. **Create a feature branch** - `git checkout -b add-my-app`
3. **Add your app** - Place it in its own directory
4. **Update documentation** - Add your app to the main README and apps list
5. **Submit PR** - Include a clear description of your app
### 3. PR Requirements
- **Clear title** - Describe what your app does
- **Detailed description** - Explain the problem it solves and how it works
- **Screenshots** - If applicable, show the menu bar interface
- **Testing notes** - Describe how you tested the app
## 🎯 Example Apps to Study
### Pdfbar
- **File monitoring** with FSEvents
- **Multi-directory support**
- **ChatGPT integration**
- **Real-time updates**
### Starlink Status
- **Network API integration**
- **Performance monitoring**
- **Historical data tracking**
- **Error handling**
## 🚀 Advanced Patterns
### File System Monitoring
```swift
import CoreServices
class FileMonitor {
private var stream: FSEventStreamRef?
func startMonitoring(paths: [String]) {
var context = FSEventStreamContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
stream = FSEventStreamCreate(
kCFAllocatorDefault,
{ (stream, context, numEvents, eventPaths, eventFlags, eventIds) in
// Handle file system events
},
&context,
paths as CFArray,
FSEventStreamEventId(kFSEventStreamEventIdSinceNow),
1.0,
FSEventStreamCreateFlags(kFSEventStreamCreateFlagUseCFTypes)
)
FSEventStreamScheduleWithRunLoop(stream!, RunLoop.current.getCFRunLoop(), CFRunLoopMode.defaultMode.rawValue)
FSEventStreamStart(stream!)
}
}Network Requests
swift
import Foundation
class NetworkManager {
func fetchData(from url: URL, completion: @escaping (Data?, Error?) -> Void) {
let task = URLSession.shared.dataTask(with: url) { data, response, error in
DispatchQueue.main.async {
completion(data, error)
}
}
task.resume()
}
}Notifications
swift
import UserNotifications
class NotificationManager {
func requestPermission() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, error in
// Handle permission result
}
}
func sendNotification(title: String, body: String) {
let content = UNMutableNotificationContent()
content.title = title
content.body = body
content.sound = .default
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil)
UNUserNotificationCenter.current().add(request)
}
}🤝 Community Guidelines
Code of Conduct
- Be respectful - Treat all contributors with respect
- Be helpful - Provide constructive feedback and assistance
- Be inclusive - Welcome contributors of all skill levels
- Be patient - Development takes time and iteration
Communication
- GitHub Issues - Report bugs and request features
- Pull Requests - Submit improvements and new apps
- Discussions - Share ideas and ask questions
- Documentation - Help improve guides and examples
📚 Resources
Swift Development
Menu Bar Development
Open Source
Ready to contribute? Start by studying the existing apps, then create something amazing that follows our philosophy!
Remember: The best contributions are those that solve real problems with elegant, simple solutions.