{"id":51017770,"url":"https://github.com/pol-cova/launchnotes","last_synced_at":"2026-06-21T13:01:16.218Z","repository":{"id":361570154,"uuid":"1254950159","full_name":"pol-cova/LaunchNotes","owner":"pol-cova","description":"A small SwiftUI package for presenting native-feeling “What’s New” release notes in iOS and macOS apps.","archived":false,"fork":false,"pushed_at":"2026-05-31T08:18:40.000Z","size":450,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-31T10:09:54.676Z","etag":null,"topics":["changelog","collaborate","github","ios","ios26","macos","release-notes","swift","swift-package","swiftui","whats-new"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pol-cova.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-31T07:46:43.000Z","updated_at":"2026-05-31T08:31:54.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/pol-cova/LaunchNotes","commit_stats":null,"previous_names":["pol-cova/launchnotes"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/pol-cova/LaunchNotes","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pol-cova%2FLaunchNotes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pol-cova%2FLaunchNotes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pol-cova%2FLaunchNotes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pol-cova%2FLaunchNotes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pol-cova","download_url":"https://codeload.github.com/pol-cova/LaunchNotes/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pol-cova%2FLaunchNotes/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34610829,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-21T02:00:05.568Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["changelog","collaborate","github","ios","ios26","macos","release-notes","swift","swift-package","swiftui","whats-new"],"created_at":"2026-06-21T13:01:15.360Z","updated_at":"2026-06-21T13:01:16.208Z","avatar_url":"https://github.com/pol-cova.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LaunchNotes\n\n[![Swift 6.3](https://img.shields.io/badge/Swift-6.3-orange.svg)](https://swift.org)\n[![Platforms](https://img.shields.io/badge/platform-iOS%2026%20%7C%20macOS%2026-lightgrey.svg)](Package.swift)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n\nLaunchNotes is a small SwiftUI package for presenting native-feeling \"What's New\" screens in iOS and macOS apps.\n\nIt is built for apps that want release notes to be easy to add, easy to customize, and hard to forget. The default API uses the app bundle version automatically, stores the last seen version in `UserDefaults`, and presents only when the current version has not been seen.\n\n## Preview\n\n| Full-screen presentation | Manual sheet presentation |\n| --- | --- |\n| \u003cimg src=\"img/prev-full.png\" alt=\"LaunchNotes full-screen presentation preview\" width=\"280\"\u003e | \u003cimg src=\"img/prev-man.png\" alt=\"LaunchNotes manual sheet presentation preview\" width=\"280\"\u003e |\n\n## Why\n\nMost apps need a simple way to tell users what changed after an update. LaunchNotes keeps that workflow close to SwiftUI:\n\n- Define notes directly where you attach the modifier.\n- Use the app version automatically or pass an explicit version.\n- Keep multiple release definitions in one place.\n- Present automatically, manually, as a sheet, or full-screen.\n- Customize tint, layout, icon behavior, actions, and footer links without building a custom screen.\n\n## Requirements\n\n- Swift 6.3\n- iOS 26 or later\n- macOS 26 or later\n\n## Installation\n\nAdd the package in Xcode:\n\n```text\nFile \u003e Add Package Dependencies...\n```\n\nUse this repository URL:\n\n```text\nhttps://github.com/pol-cova/LaunchNotes\n```\n\nThen import it where you build your app UI:\n\n```swift\nimport LaunchNotes\n```\n\n## Quick Start\n\nAttach `launchNotes` to your root view and list the notes. This uses `Bundle.main` for the current version.\n\n```swift\nstruct ContentView: View {\n    var body: some View {\n        HomeView()\n            .launchNotes {\n                LaunchNote(\"Daily Challenges\", \"Come back every day for a new challenge.\", systemImage: \"calendar\")\n                LaunchNote(\"New Stats\", \"Track your progress with cleaner charts.\", systemImage: \"chart.line.uptrend.xyaxis\")\n                LaunchNote(\"Smoother Animations\", \"The app now feels faster and more polished.\", systemImage: \"sparkles\")\n            }\n    }\n}\n```\n\nLaunchNotes stores the last seen version under `LaunchNotes.lastSeenVersion` in `UserDefaults.standard`. When the resolved version changes, the notes present automatically.\n\n## Basic Customization\n\n```swift\nHomeView()\n    .launchNotes(\n        title: \"Fresh Updates\",\n        subtitle: \"Here's what changed in this version.\",\n        buttonTitle: \"Looks good\",\n        animation: .bouncy,\n        presentation: .sheet,\n        style: .compact\n    ) {\n        LaunchNote(\"Daily Challenges\", \"Come back every day for a new challenge.\", systemImage: \"calendar\")\n        LaunchNote(\"New Stats\", \"Track your progress with cleaner charts.\", systemImage: \"chart.line.uptrend.xyaxis\")\n    }\n```\n\nIf you want to control the version yourself, pass `version:`.\n\n```swift\nHomeView()\n    .launchNotes(version: \"1.2.0\") {\n        LaunchNote(\"New Stats\", \"Cleaner progress charts.\", systemImage: \"chart.line.uptrend.xyaxis\")\n    }\n```\n\n## Multiple Releases\n\nUse `LaunchNotesRelease` when you want to keep a release history in one place. Put the newest release first. In automatic mode, LaunchNotes presents the first release only when its version has not been seen.\n\n```swift\nHomeView()\n    .launchNotes(onFooterAction: showPrivacyInfo) {\n        LaunchNotesRelease(\n            \"1.2.0\",\n            title: \"What's New in 1.2\",\n            subtitle: \"A cleaner update for daily use.\",\n            buttonTitle: \"Continue\",\n            accentColor: .blue,\n            footerTitle: \"About Privacy\"\n        ) {\n            LaunchNote(\"Daily Challenges\", \"Come back every day for a new challenge.\", systemImage: \"calendar\")\n            LaunchNote(\"New Stats\", \"Track your progress with cleaner charts.\", systemImage: \"chart.line.uptrend.xyaxis\")\n        }\n\n        LaunchNotesRelease(\"1.1.0\") {\n            LaunchNote(\"Search\", \"Find previous sessions faster.\", systemImage: \"magnifyingglass\")\n        }\n    }\n```\n\n## Manual Presentation\n\nUse the binding overload for settings screens, debug menus, onboarding flows, or release history buttons.\n\n```swift\nstruct SettingsView: View {\n    @State private var showReleaseNotes = false\n\n    private let release = LaunchNotesRelease(\"1.2.0\", title: \"Release Notes\") {\n        LaunchNote(\"Daily Challenges\", \"Come back every day for a new challenge.\", systemImage: \"calendar\")\n        LaunchNote(\"New Stats\", \"Track your progress with cleaner charts.\", systemImage: \"chart.line.uptrend.xyaxis\")\n    }\n\n    var body: some View {\n        Button(\"Show Release Notes\") {\n            showReleaseNotes = true\n        }\n        .launchNotes(isPresented: $showReleaseNotes, release: release)\n    }\n}\n```\n\n## Styling\n\nUse `LaunchNotesStyle` to customize the default appearance.\n\n```swift\nHomeView()\n    .launchNotes(\n        presentation: .fullScreen,\n        style: .prominent\n    ) {\n        LaunchNote(\"New Stats\", \"Cleaner progress charts.\", systemImage: \"chart.line.uptrend.xyaxis\")\n    }\n```\n\nBuilt-in presets:\n\n- `.default`: clean baseline styling.\n- `.compact`: smaller radius and simple presentation.\n- `.prominent`: shows the header icon and uses a stronger presentation.\n- `.minimal`: simple, quiet styling.\n\nCustom style:\n\n```swift\nLaunchNotesStyle(\n    accentColor: .indigo,\n    cornerRadius: 18,\n    iconStyle: .circle,\n    showsHeaderIcon: false,\n    buttonLayout: .vertical\n)\n```\n\nYou can also set a style higher in the view hierarchy:\n\n```swift\nHomeView()\n    .launchNotes(version: \"1.2.0\", notes: notes)\n    .launchNotesStyle(.init(accentColor: .green))\n```\n\nRelease-level tint overrides the style tint:\n\n```swift\nLaunchNotesRelease(\"1.2.0\", accentColor: .teal) {\n    LaunchNote(\"Privacy\", \"Updated privacy controls.\", systemImage: \"lock\")\n}\n```\n\n## Footer Actions\n\nA release can include a footer link, such as \"About Privacy\". Provide `footerTitle` on the release and `onFooterAction` on the modifier.\n\n```swift\nHomeView()\n    .launchNotes(onFooterAction: showPrivacyDetails) {\n        LaunchNotesRelease(\"1.2.0\", footerTitle: \"About Privacy\") {\n            LaunchNote(\"New Stats\", \"Cleaner progress charts.\", systemImage: \"chart.line.uptrend.xyaxis\")\n        }\n    }\n```\n\n## API Overview\n\n### LaunchNote\n\n```swift\nLaunchNote(\n    \"Title\",\n    \"Description\",\n    systemImage: \"sparkles\"\n)\n```\n\n### LaunchNotesRelease\n\n```swift\nLaunchNotesRelease(\n    \"1.2.0\",\n    title: \"What's New\",\n    subtitle: \"Here's what changed.\",\n    buttonTitle: \"Continue\",\n    secondaryButtonTitle: nil,\n    headerSystemImage: \"sparkles\",\n    accentColor: .blue,\n    footerTitle: \"About Privacy\"\n) {\n    LaunchNote(\"New Stats\", \"Cleaner progress charts.\", systemImage: \"chart.line.uptrend.xyaxis\")\n}\n```\n\nOmit the version to use the current bundle version:\n\n```swift\nLaunchNotesRelease(title: \"Fresh Updates\") {\n    LaunchNote(\"New Stats\", \"Cleaner progress charts.\", systemImage: \"chart.line.uptrend.xyaxis\")\n}\n```\n\n### Presentation\n\n```swift\n.launchNotes(\n    mode: .automatic,\n    animation: .smooth,\n    presentation: .sheet\n) {\n    LaunchNote(\"New Stats\", \"Cleaner progress charts.\", systemImage: \"chart.line.uptrend.xyaxis\")\n}\n```\n\nModes:\n\n- `.automatic`: present when the current version has not been seen.\n- `.always`: present every time the host view appears.\n- `.manual`: never auto-present. Use a binding overload.\n\nPresentations:\n\n- `.sheet`: presents as a sheet.\n- `.fullScreen`: uses `fullScreenCover` on iOS. On macOS, it falls back to a sheet.\n\nAnimations:\n\n- `.smooth`\n- `.bouncy`\n- `.fade`\n- `.slide`\n- `.none`\n\n### Version Helpers\n\n```swift\nlet version = LaunchNotesVersion.current()\n```\n\nResolution order:\n\n1. `CFBundleShortVersionString`\n2. `CFBundleVersion`\n3. `\"1.0\"`\n\n## Storage and Testing\n\nBy default, LaunchNotes stores the seen version using:\n\n```swift\nLaunchNotesDefaultStorageKey // \"LaunchNotes.lastSeenVersion\"\n```\n\nUse a custom store in tests, previews, or debug environments:\n\n```swift\nHomeView()\n    .launchNotes(\n        version: \"1.2.0\",\n        notes: notes,\n        userDefaults: UserDefaults(suiteName: \"PreviewDefaults\")!,\n        storageKey: \"preview.lastSeenLaunchNotesVersion\"\n    )\n```\n\nReset during development:\n\n```swift\nUserDefaults.standard.removeObject(forKey: LaunchNotesDefaultStorageKey)\n```\n\n## Demo\n\nThe package includes an iOS demo app in `Examples/LaunchNotesDemo`.\n\n```bash\nopen LaunchNotes.xcworkspace\n```\n\nUse the `LaunchNotesDemo` scheme to run the demo app.\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## License\n\nLaunchNotes is available under the MIT license. See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpol-cova%2Flaunchnotes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpol-cova%2Flaunchnotes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpol-cova%2Flaunchnotes/lists"}