{"id":16061690,"url":"https://github.com/mattmassicotte/packagetemplate","last_synced_at":"2025-05-12T03:32:25.684Z","repository":{"id":191830434,"uuid":"685470419","full_name":"mattmassicotte/PackageTemplate","owner":"mattmassicotte","description":"A template for Swift packages on GitHub","archived":false,"fork":false,"pushed_at":"2024-10-17T12:06:56.000Z","size":82,"stargazers_count":56,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-19T15:14:29.843Z","etag":null,"topics":["ios","macos","spm","swift","tvos","visionos","watchos"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mattmassicotte.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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},"funding":{"github":["mattmassicotte"]}},"created_at":"2023-08-31T09:55:15.000Z","updated_at":"2024-10-17T12:07:00.000Z","dependencies_parsed_at":"2023-09-01T01:32:22.994Z","dependency_job_id":"36fa6cf6-06f4-4328-bf4c-e8283561868c","html_url":"https://github.com/mattmassicotte/PackageTemplate","commit_stats":null,"previous_names":["mattmassicotte/packagetemplate"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattmassicotte%2FPackageTemplate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattmassicotte%2FPackageTemplate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattmassicotte%2FPackageTemplate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattmassicotte%2FPackageTemplate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mattmassicotte","download_url":"https://codeload.github.com/mattmassicotte/PackageTemplate/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221569816,"owners_count":16845116,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["ios","macos","spm","swift","tvos","visionos","watchos"],"created_at":"2024-10-09T04:09:39.745Z","updated_at":"2025-05-12T03:32:25.665Z","avatar_url":"https://github.com/mattmassicotte.png","language":"Swift","funding_links":["https://github.com/sponsors/mattmassicotte"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n[![Build Status][build status badge]][build status]\n[![Platforms][platforms badge]][platforms]\n[![Documentation][documentation badge]][documentation]\n\n\u003c/div\u003e\n\n# PackageTemplate\nA template for Swift packages on GitHub\n\nIt is a little **opinionated**, but mostly just stuff that I've found useful. Feel free to customize as needed. And if you have ideas for ways to improve this, open an issue or PR!\n\n## Repository Details\n\n### Naming\n\nThe golden rule: your package name should **not** be the same as a public type within your package. This can result in a ridiculous situation where the compiler cannot distinguish between the module name and type name, and has made my life difficult in the past. Someone please send me a blog post or something about this and I will link to it.\n\nI'm a fan of CapitalCase. I don't think the word \"Swift\" should be in the name.\n\n### Turn off \"Packages\" and \"Deployments\"\n\nNeither of them currently apply to Swift\n\n### Branch protection\n\nGitHub offers a lot of control here. I've started doing a bare minimum: protecting the `main` branch from accidental force pushes and deletion. You can do this easily with Settings \u003e Code and automation \u003e Branches. Add a rule for `main` with all check boxes unchecked and done.\n\n## Metadata\n\n### License\n\nThis is non-optional. Many users, for very valid reasons, will not even look at a package without a license. GitHub makes this easy. I have been a long-time user of the BSD 3-clause license. It is very permissive, like MIT, but also specifically limits implicit endorsements from those involved.\n\nI'm, in general, not a fan of viral licenses, especially when that virality applies to linking. However, I appreciate why that was designed the way it was. Preventing open source abuse and exploitation is important and your choice of license can really matter there.\n\n### Code of Conduct\n\n\"Let's be excellent to each other\" is great! But, having a concrete set of rules about what that actually means, and what happens should those rules be broken is important. The [Contributor Covenant](https://www.contributor-covenant.org) has become popular and I think it is a great choice.\n\n### Badges\n\nI like throwing a few badges up on my repos to provide some glanceable information. I think it is easy to go overboard here, but you should also feel good about making this your own!\n\n### Install Instructions\n\nMany people find explicit package installation instructions helpful, even just for convenient copy-paste into another `Package.swift` file. I like to include them, but you have to watch out for two things.\n\n- you should regularly bump your version number\n- packages that contain a library of a different name need a more-explicit dependency specification\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/ChimeHQ/PackageTemplate\", from: \"1.0.0\")\n],\ntargets: [\n    .target(\n        name: \"UseCoreFunctionality\",\n        dependencies: [\"PackageTemplate\"]\n    ),\n    .target(\n        name: \"UsesDifferentProduct\",\n        dependencies: [.product(name: \"AnotherProduct\", package: \"PackageTemplate\")]\n    ),\n]\n```\n\n### Funding\n\nIf you are using GitHub sponsorships, you know how this works. But just in case, please **do not** copy my `.github/FUNDING.yml` into your own project.\n\n## Package.swift\n\n### Platforms\n\nFor a long time, I thought leaving platforms empty was the most compatible thing to do. However, this leaves the effective platform/version up to the compiler. And, that can produce surprising results that change over time. Being explicit is best.\n\n### Swift 6.0\n\nPersonally, I have found maintaining support for Swift 5 *compiler* extremely hard. Swift 6 has been out for a while, and I think it is ok to move along.\n\nHowever, you might want to remain in the Swift 5 *language mode*. So. I've made that the default here. But if you do decide to go to 6 mode, you can just delete everything here.\n\n```swift\nlet swiftSettings: [SwiftSetting] = [\n    .swiftLanguageMode(.v5),\n    .enableExperimentalFeature(\"StrictConcurrency\"),\n    .enableUpcomingFeature(\"DisableOutwardActorInference\"),\n    .enableUpcomingFeature(\"GlobalActorIsolatedTypesUsability\"),\n    .enableUpcomingFeature(\"InferSendableFromCaptures\"),\n]\n\nfor target in package.targets {\n    var settings = target.swiftSettings ?? []\n    settings.append(contentsOf: swiftSettings)\n    target.swiftSettings = settings\n}\n```\n\nI got this idea from [Keith Harrison](https://useyourloaf.com/blog/strict-concurrency-checking-in-swift-packages/).\n\n## GitHub Actions\n\nGitHub actions are mostly great. They have gotten better about releasing new macOS versions. But, it's still worth rememebering that \n\"macOS-latest\" may not actually be the released version. However, they are fairly good about keeping newer Xcode versions available.\n\nThe second problem is simulator names change and `xcodebuild` makes it very hard to not care.\n\nI have given up relying on defaults here, and I always make things explicit. Unfortunately this means manual maintenance, especially around WWDC.\n\n- Host OS\n- Xcode version\n- Simulators names\n\nIf you have tricks/hacks/custom actions to make this better, **please** let me know.\n\nNote! If your package contains more than one entry it its `products` array, you'll need to append `-Package` to the scheme name to get `xcodebuild` tests to work.\n\nThis stuff also matters for Linux builds, if you want to run them. I use [swiftly-action](https://github.com/vapor/swiftly-action) for this, but hopefully one day [swiftly](https://github.com/swiftlang/swiftly) is just built into the GitHub action runner images.  keep the Swift version here the same as whatever comes with the Xcode version I'm using.\n\n## Swift Package Index\n\nThe [SPI](https://swiftpackageindex.com) is a no-brainer.\n\n### Discoverability\n\nIf I have an idea for a library, I always do some searching on SPI first.\n\n### Build Checks\n\nKind of like a mini CI. SPI will build your packages for many swift/platform combinations. I think making it clear up front what platforms your package supports is very useful.\n\n### Hosted Documentation\n\nPerhaps the most underrated feature. If you include DocC in your package, SPI will **host** it for you. You need a `.spi.yml` file for this to work.\n\n## Style\n\nFor a very long time, I thought tabs vs spaces was a stupid thing to get worked up about. Then one day I learned that tabs can offer [accessibility improvements](https://adamtuttle.codes/blog/2021/tabs-vs-spaces-its-an-accessibility-issue/) for low-vision people. And that same advantage also helps to style code the way people prefer. So I switched to tabs and I encourage you to do same.\n\nXcode supports [editorconfig](https://editorconfig.org), and I think including it is a great idea.\n\n## Contributing and Feedback\n\nI'd love to hear from you! Get in touch via [mastodon](https://mastodon.social/@mattiem), an issue, or a pull request.\n\nBy participating in this project you agree to abide by the [Contributor Code of Conduct](CODE_OF_CONDUCT.md).\n\n[build status]: https://github.com/mattmassicotte/PackageTemplate/actions\n[build status badge]: https://github.com/mattmassicotte/PackageTemplate/workflows/CI/badge.svg\n[platforms]: https://swiftpackageindex.com/mattmassicotte/PackageTemplate\n[platforms badge]: https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fmattmassicotte%2FPackageTemplate%2Fbadge%3Ftype%3Dplatforms\n[documentation]: https://swiftpackageindex.com/mattmassicotte/PackageTemplate/main/documentation\n[documentation badge]: https://img.shields.io/badge/Documentation-DocC-blue\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmattmassicotte%2Fpackagetemplate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmattmassicotte%2Fpackagetemplate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmattmassicotte%2Fpackagetemplate/lists"}