{"id":32600927,"url":"https://github.com/apparata/bootstrapp","last_synced_at":"2026-04-26T16:03:24.456Z","repository":{"id":145005125,"uuid":"226727422","full_name":"apparata/Bootstrapp","owner":"apparata","description":"A macOS application for generating initial boilerplate primarily for Swift packages and Xcode projects.","archived":false,"fork":false,"pushed_at":"2026-04-20T21:22:05.000Z","size":18851,"stargazers_count":43,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2026-04-20T22:38:20.089Z","etag":null,"topics":["app","macos"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/apparata.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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":"2019-12-08T20:31:24.000Z","updated_at":"2026-04-20T21:22:09.000Z","dependencies_parsed_at":"2025-04-21T11:15:31.067Z","dependency_job_id":null,"html_url":"https://github.com/apparata/Bootstrapp","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/apparata/Bootstrapp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apparata%2FBootstrapp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apparata%2FBootstrapp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apparata%2FBootstrapp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apparata%2FBootstrapp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/apparata","download_url":"https://codeload.github.com/apparata/Bootstrapp/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apparata%2FBootstrapp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32303178,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T09:34:17.070Z","status":"ssl_error","status_checked_at":"2026-04-26T09:34:00.993Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["app","macos"],"created_at":"2025-10-30T07:23:17.107Z","updated_at":"2026-04-26T16:03:24.450Z","avatar_url":"https://github.com/apparata.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Bootstrapp\n\nThe main purpose of the Bootstrapp application for macOS is to generate boilerplate for iOS and macOS apps and Swift packages from templates. However, the template system is general enough for just about any type of boilerplate generation.\n\n![Bootstrapp main window](docs/images/ShoeboxMacApp.png?raw=true)\n\n## License\n\nThe Bootstrapp app for macOS is released under the MIT license. See the `LICENSE` file in the repository for details.\n\nHowever, Bootstrapp depends on other open source software (both first-party and third-party), subject to their own respective licenses. See the `ATTRIBUTIONS` file for details. Most notably, [XcodeGen](https://github.com/yonaskolb/XcodeGen) is used for generating Xcode project files and [Splash](https://github.com/JohnSundell/Splash) is used for generating syntax highlighted Swift code.\n\n### Table of Contents\n\n\u003e ⚠️ This documentation is a work in progress.\n\n- [Installing Bootstrapp](#installing-bootstrapp)\n    - [System Requirements](#system-requirements)\n    - [Pre-built Binaries](#pre-built-binaries)\n- [Using Bootstrapp](#using-bootstrapp)\n- [Templates](#templates)\n    - [Template Types](#template-types)\n    - [Structure of a Template](#structure-of-a-template)\n    - [Bootstrapp.json](#bootstrap-json)\n- [Template Language](#template-language)\n    - [Substitutions](#substitutions)\n    - [Conditionals](#conditionals)\n    - [Conditional Expression](#conditional-expression)\n    - [Loops](#loops)\n    - [Longer Example](#longer-example)\n\n## Installing Bootstrapp\n\nBootstrapp is a regular macOS app and is installed by dragging the app bundle to the `/Applications` folder, as usual.\n\n### System Requirements\n\nBootstrapp was built using SwiftUI, which requires **macOS 10.15 Catalina** or later.\n\n### Pre-built Binaries\n\nWith every release, a pre-built app binary along with some example templates will be attached to the assets section of the release entry here on GitHub.\n\nSimply go to the [releases page](https://github.com/apparata/Bootstrapp/releases) and expand the **Assets** section of the release you want to install. There you will find the `Bootstrapp.app.zip` and `Templates.zip` files. The app binary is signed for distribution and notarized by Apple.\n\n## Using Bootstrapp\n\n**Step 1:** Drag a folder containing one or more templates onto the app window. The application will recursively look for any folder that contains a `Bootstrapp.json` file.\n\n![](docs/images/DraggingTemplates.png?raw=true)\n\n**Step 2:** Select a template in the sidebar on the left.\n\n![](docs/images/SidebarTemplates.png?raw=true)\n\n**Step 3:** Fill out the required fields of the form that appears.\n\n![](docs/images/ParametersForm.png?raw=true)\n\n**Step 4:** Press the hammer icon in the upper right corner to generate the boilerplate.\n\n![](docs/images/Hammer.png?raw=true)\n\n## Templates\n\n### Template Types\n\nThere are three types of templates:\n\n1. General\n2. Swift Package\n3. Xcode Project\n\n**General** templates are not processed in any specific ways during the template instantiation. Files and folders will simply be copied from the `Content/` folder to the output folder, only being subjected to parameter substitutions.\n\n**Swift Package** templates are currently not processed in any specific ways either, but they may be in the future. Currently, the only difference is that they will be sorted in their own group in the sidebar and will be represented by a specific sidebar icon. \n\n**Xcode Project** templates are processed just like the other templates with parameter substitutions, but they also contain an `XcodeProject.yml` file that specifies how the Xcode project file should be generated. The Xcode project file is generated by [XcodeGen](https://github.com/yonaskolb/XcodeGen) and the file format is thus the XcodeGen [project specification file format](https://github.com/yonaskolb/XcodeGen/blob/master/Docs/ProjectSpec.md).\n\n#### Meta Templates\n\nThere are also templates for generating boilerplate for other templates. These are called _Meta Templates_. There's one meta template type per regular template type.\n\n### Structure of a Template\n\nA Bootstrapp template has the following basic structure:\n\n```text\n── Template/\n    ├─ Bootstrapp.json\n    ├─ Bootstrapp.md\n    ├─ Content/\n    │   ├─ \u003cAny files / folders\u003e \n    │   └─ [XcodeProject.yml]\n    └─ Preview/\n        ├─ 1.png\n        ├─ 2.png\n        ⋮\n        └─ n.png\n```\n\nThe main template specification is in the `Bootstrapp.json` file.\n\nTo provide information about the template, such as code examples or other documentation, add a `Bootstrapp.md` file. It will be shown in the Bootstrapp window for the template below the parameters form.\n\nAny file or folder in the `Content/` folder will be copied to the output folder as part of the generation process.\n\nThe `Preview/` folder contains images (600x400 pixels) showcasing what the results will look like. In the case of an app template, it would be a good idea to use screenshots of the app, but any image can be used.  \n\n### Bootstrapp.json\n\nThis is the main template specification file.\n\n#### Top Level JSON Properties\n\n| Name                  | Value                                                                     |\n|-----------------------|---------------------------------------------------------------------------|\n| specificationVersion  | The version of the Bootstap.json file format itself, e.g. `\"1.0.0\"`.      | \n| templateVersion       | The version of this particular template, e.g. `\"1.0.0\"`.                  |\n| id                    | A unique identifier for this template. Also the name, for now.            |\n| type                  | One of `\"Swift Package\"`, `\"Xcode Project\"`, and `\"General\"`.             |\n| description           | A brief description of the template, shown at the top of the detail page. |\n| outputDirectoryName   | The name of the output directory. **Not** the path, just the directory name. Will be processed by substitution engine, e.g. `\"\u003c{LIBRARY_NAME_}\u003e\"`. |\n| substitutions         | Non-user-configurable text substitutions as dictionary, e.g. `[\"DOT\": \".\"]` |\n| parameters            | User configurable text substitutions. Shown as form in template user interface. |\n| parametrizableFiles   | An array of regular expressions. File with names that match at least one of the regular expressions will be processed by the text substitution engine. Non-matching files will not. |\n| includeDirectories    | An array of conditions with expressions that when true will lead to the conditional inclusion of the specified directories. **(Optional)** |\n| includeFiles          | An array of conditions with expressions that when true will lead to the conditional inclusion of the specified files. **(Optional)** |\n\n#### Example: Swift Package Template\n\n```json\n{\n    \"specificationVersion\": \"1.0.0\",\n    \"templateVersion\": \"1.0.0\",\n    \"id\": \"Library Swift Package\",\n    \"type\": \"Swift Package\",\n    \"description\": \"Use this template to quickly set up new static library Swift packages, complete with e.g. MIT license file, SwiftLint configuration, Jazzy documentation build script.\",\n    \"outputDirectoryName\": \"\u003c{LIBRARY_NAME}\u003e\",\n    \"substitutions\": {\n        \"DOT\": \".\"\n    },\n    \"parameters\": [ \n        {\n            \"name\": \"Library Name\",\n            \"id\": \"LIBRARY_NAME\",\n            \"type\": \"String\",\n            \"validationRegex\": \"^[A-Za-z0-9_]+$\"\n        },\n        {\n            \"name\": \"Copyright Holder\",\n            \"id\": \"COPYRIGHT_HOLDER\",\n            \"type\": \"String\",\n            \"default\": \"Apparata AB\"\n        },\n        {\n            \"name\": \"Docs Author URL\",\n            \"id\": \"DOCS_AUTHOR_URL\",\n            \"type\": \"String\",\n            \"default\": \"https://apparata.se\"\n        },\n        {\n            \"name\": \"License\",\n            \"id\": \"LICENSE_TYPE\",\n            \"type\": \"Option\",\n            \"default\": 0,\n            \"options\": [\n                \"MIT\",\n                \"BSD\",\n                \"Apache 2\",\n                \"Zlib\",\n                \"Unlicense\",\n                \"None\"\n            ]\n        },\n        {\n            \"name\": \"Add Executable Target\",\n            \"id\": \"ADD_EXECUTABLE_TARGET\",\n            \"type\": \"Bool\",\n            \"default\": false\n        },\n        {\n            \"name\": \"Executable Name\",\n            \"id\": \"EXECUTABLE_NAME\",\n            \"type\": \"String\",\n            \"validationRegex\": \"^[A-Za-z0-9_]+$\",\n            \"dependsOn\": \"ADD_EXECUTABLE_TARGET\"\n        },\n        {\n            \"name\": \"Add GitHub test action\",\n            \"id\": \"ADD_GITHUB_TEST_ACTION\",\n            \"type\": \"Bool\",\n            \"default\": false\n        },\n        {\n            \"name\": \"Init git repo\",\n            \"id\": \"GIT_INIT\",\n            \"type\": \"Bool\",\n            \"default\": false\n        }\n    ],\n    \"parametrizableFiles\": [\n        \"LICENSE\",\n        \".*\\\\.md\",\n        \".*\\\\.swift\",\n        \".*\\\\.h\",\n        \".*\\\\.m\",\n        \".*\\\\.mm\",\n        \".*\\\\.storyboard\",\n        \".*\\\\.xib\",\n        \".*\\\\.plist\",\n        \".*\\\\.json\",\n        \".*\\\\.yml\",\n        \".*\\\\.txt\",\n        \".*\\\\.sh\"\n    ],\n    \"includeDirectories\": [\n        {\n            \"if\": \"ADD_EXECUTABLE_TARGET\",\n            \"directories\": [\n                \"Sources/\u003c{EXECUTABLE_NAME}\u003e\"\n            ]\n        },\n        {\n            \"if\": \"ADD_GITHUB_TEST_ACTION\",\n            \"directories\": [\n                \"\u003c{DOT}\u003egithub\"\n            ]\n        },\n        {\n            \"if\": \"GIT_INIT\",\n            \"directories\": [\n                \"\u003c{GIT}\u003egit\"\n            ]\n        }\n    ],\n    \"includeFiles\": [\n        {\n            \"if\": \"(LICENSE_TYPE != 'Unlicense') and (LICENSE_TYPE != 'None')\",\n            \"files\": [\n                \"LICENSE\"\n            ]\n        },\n        {\n            \"if\": \"LICENSE_TYPE == 'Unlicense'\",\n            \"files\": [\n                \"UNLICENSE\"\n            ]\n        }\n    ]\n}\n```\n\n## Template Language\n\n### Substitutions\n\n#### Simple Value\n\nInput:\n\n```text\nThis is a \u003c{ thing }\u003e\n```\n\nParameters:\n\n```Swift\n\"thing\": \"test\"\n```\n\nOutput:\n\n```text\nThis is a test\n```\n\n#### Simple Value with Transformer\n\nInput:\n\n```text\nThis is an uppercase \u003c{ #uppercased thing }\u003e\n```\n\nParameters:\n\n```Swift\n\"thing\": \"Test\"\n```\n\nOutput:\n\n```text\nThis is an uppercase test\n```\n\n#### Built-in Transformers\n\n- `#lowercased`\n- `#uppercased`\n- `#uppercasingFirstLetter`\n- `#lowercasingFirstLetter`\n- `#trimmed`\n- `#removingWhitespace`\n- `#collapsingWhitespace`\n\n### Conditionals\n\n#### `if ...` ... `end`\n\nInput:\n\n```text\n\u003c{ if isMonday }\u003e\nThis is only kept if isMonday is true.\n\u003c{ #uppercased whatever }\u003e\nSome more text.\n\u003c{ end }\u003e\n```\n\nParameters:\n\n```Swift\n\"whatever\": \"Test\",\n\"isMonday\": true\n```\n\nOutput:\n\n```text\nThis is only kept if isMonday is true.\nTEST\nSome more text.\n```\n\n####  `if ...` ... `else` ... `end`\n\nInput:\n\n```text\n\u003c{ if thing }\u003e\nThing is true.\n\u003c{ else }\u003e\nThing is false.\n\u003c{ end }\u003e\n```\n\nParameters:\n\n```Swift\n\"thing\": true\n```\n\nOutput:\n\n```text\nThing is true.\n```\n\n### Conditional Expression\n\nThe conditional expression can be more complicated than a simple boolean value. Here is the complete grammar for the conditional expression:\n\n```text\nexpr      := term ('or' term)*\nterm      := factor ('and' factor)*\nfactor    := 'not'? ( statement | '(' expr ')' )\nstatement := terminal ( ('==' | '!=') string )?\nstring    := ('\"' | ''') character* ('\"' | ''')\n```\n\n#### Example: `if not ...`\n\nInput:\n\n```text\n\u003c{ if not isMonday }\u003e\nToday is not Monday.\n\u003c{ end }\u003e\n```\n\nParameters:\n\n```Swift\n\"isMonday\": false\n```\n\nOutput:\n\n```text\nToday is not Monday.\n```\n\n#### Example: `if not (... and ...)`\n\nInput:\n\n```text\n\u003c{ if not (isMonday and isRaining) }\u003e\nToday is not Monday and it is not raining.\n\u003c{ else }\u003e\nToday is either Monday or it is raining.\n\u003c{ end }\u003e\n```\n\nParameters:\n\n```Swift\n\"isMonday\": true,\n\"isRaining\": true\n```\n\nOutput:\n\n```text\nToday is either Monday or it is raining.\n```\n\n#### Example: `if ... == \"...\"`\n\nInput:\n\n```text\n\u003c{ if license == \"MIT\" }\u003e\nThis is the MIT license.\n\u003c{ end }\u003e\n```\n\nParameters:\n\n```Swift\n\"license\": \"MIT\"\n```\n\nOutput:\n\n```text\nThis is the MIT license.\n```\n\n### Loops\n\n#### `for ... in ...`\n\nInput:\n\n```text\nHere are some types of fruits:\n\u003c{ for fruit in fruits }\u003e\nFruit name: \u003c{ fruit }\u003e\n\u003c{ end }\u003e\n```\n\nParameters:\n\n```Swift\n\"fruits\": [\n    \"banana\",\n    \"orange\",\n    \"pineapple\",\n    \"pear\"   \n]\n```\n\nOutput:\n\n```text\nHere are some types of fruits:\nFruit name: banana\nFruit name: orange\nFruit name: pineapple\nFruit name: pear\n```\n\n### Longer Example\n\nInput:\n\n```text\nThis is a test.\n\u003c{ #lowercased whatever }\u003e\nSo is this.\n\u003c{ stuff }\u003e\nWhatever\n\u003c{ if potato }\u003e\n    Only if potato is true.\n    \u003c{ if cucumber }\u003e\n        Only if both potato and cucumber are true.\n    \u003c{ end }\u003e\n\u003c{ end }\u003e\nHere are some types of fruits:\n\u003c{ for fruit in fruits }\u003e\nFruit name: \u003c{ fruit }\u003e\n\u003c{ end }\u003e\n\nHere they are again:\n\u003c{ for fruit in fruits }\u003eFruit name: \u003c{ car }\u003e \u003c{ end }\u003e\n```\n\nParameters:\n\n```Swift\n\"whatever\": \"[WHATEVER]\",\n\"stuff\": 1337,\n\"potato\": true,\n\"cucumber\": 1,\n\"fruits\": [\n    \"banana\",\n    \"orange\",\n    \"pineapple\",\n    \"pear\"\n]\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapparata%2Fbootstrapp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapparata%2Fbootstrapp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapparata%2Fbootstrapp/lists"}