Apple
Scaffold a universal SwiftUI application that shares one codebase across iOS and macOS.
Nova stores the Xcode project as a readable project.yml definition, then generates the disposable .xcodeproj file with XcodeGen.
The generated package.json and MARKETING_VERSION share the strategy-aware initial version: 0.0.1 for SemVer or the current UTC YYYY.M.0 period for CalVer. In an existing lock-step project, the app inherits the shared non-freezable version instead. Nova's changelog release flow keeps the two versions synchronized and advances the Apple build number from its initial value of 1.
Why Use This Command?
- Creates iOS and macOS targets together with a generated iOS launch screen so one workspace can serve both Apple platforms.
- Includes a Swift Testing target so the generated app starts with a working verification path.
- Lints and type-checks the generated Node.js lifecycle helper while keeping native tests owned by Xcode.
- Keeps Xcode build data inside the workspace so local and automated builds do not depend on a global DerivedData location.
- Seeds editable App Store Connect metadata and asset directories under the repository's root
assets/folder. - Includes an English Xcode String Catalog and uses SwiftUI's native localizable string types across both Apple destinations.
Requirements
- macOS and Xcode — Xcode supplies the Swift compiler, platform SDKs, and
xcodebuild. - XcodeGen — Install XcodeGen and make
xcodegenavailable on yourPATH. - Empty directory or monorepo root — Nova auto-detects whether to create a project or add a workspace.
Usage
Options
| Flag | Description |
|---|---|
--bundle-id <id> | Apple bundle identifier; defaults to com.example.{workspaceName}. |
-d, --dry-run | Run without writing any files. |
--install | Install dependencies after scaffolding; this is the default. |
--no-install | Skip dependency installation. |
--name <name> | Project slug when creating a new monorepo; omit at an existing root. |
--non-interactive | Require every answer as a flag and do not open prompts. |
--workspace-name <name> | Workspace directory name and generated Xcode target name. |
--output <dir> | Output directory. |
Output Files
| File | Description |
|---|---|
project.yml | XcodeGen definition for the app, tests, scheme, icon, and iOS launch screen. |
Sources/App.swift | SwiftUI application entry point. |
Sources/Assets.xcassets/ | Nova app icon, launchpad mark, and social-link vector assets. |
Sources/ContentView.swift | Starter interface shared by iOS and macOS. |
Sources/Localizable.xcstrings | English String Catalog shared by the iOS and macOS targets. |
Tests/AppTests.swift | Swift Testing smoke test. |
package.json | Nova script groups for project generation, checking, and building. |
eslint.config.mts | Nova ESLint presets and custom rules for the Node.js lifecycle helper. |
tsconfig.scripts.json | Strict Node.js type-checking for generated lifecycle scripts. |
tsconfig.tests.json | Strict type-checking for future helper tests and Vitest configuration. |
vitest.config.mts | Helper-test discovery with an empty-suite-safe starting point. |
assets/app-store-connect/{workspace}/ | Root-owned App Store Connect metadata, screenshots, and creative assets. |
Localization
Xcode discovers localizable SwiftUI literals during builds and keeps their source language in Sources/Localizable.xcstrings. Add languages and translations through Xcode's String Catalog editor; the same catalog serves the generated iOS and macOS application.
Nova types reusable launch-step and accessibility copy as LocalizedStringKey so moving a literal through a helper view does not silently make it untranslatable. No runtime localization dependency is required.
Non-Interactive Mode
Agents and automation can create the root and first Apple app in one command, or omit --name to add the app from an existing monorepo root.
nova scaffold app apple --non-interactive --name my-apple-app --workspace-name client --bundle-id io.example.client --output ./my-apple-app
nova scaffold app apple --non-interactive --workspace-name client --bundle-id io.example.client --output ./apps/client
Registration and Customization
Nova registers the workspace with the app role and trackable policy, then adds swift, ios, and macos to the root project.platforms list without removing existing entries. The generated package name follows {projectSlug}-app-{workspaceName}.
Nova does not guess one file artifact for the native workspace because Xcode emits different app, archive, and test products per Apple platform and signing choice. Add a named artifact after choosing the exact product that belongs in the root assembly.
The bundle identifier defaults to com.example.{workspaceName} when --bundle-id is omitted. Nova accepts ASCII letters, numbers, periods, and hyphens, preserves the supplied value exactly, and gives the unit-test target the matching {bundleId}.tests identifier.
The scaffold creates en-US metadata placeholders for iOS and macOS plus documented screenshot and creative-asset directories. Fill only the fields and asset targets you intend to change, then use nova integration app-store-connect. Nova does not add /assets/ to the generated .gitignore; store assets remain project-owned and trackable by default.