Skip to content

feat(mobile-ios): scaffold Xcode app under mobile/ios#112

Merged
Ur-imazing merged 10 commits intomainfrom
feat/101-scaffold
Feb 25, 2026
Merged

feat(mobile-ios): scaffold Xcode app under mobile/ios#112
Ur-imazing merged 10 commits intomainfrom
feat/101-scaffold

Conversation

@Ur-imazing
Copy link
Copy Markdown
Contributor

@Ur-imazing Ur-imazing commented Feb 25, 2026

Summary

Adds a buildable iOS app target under mobile/ios with minimal SwiftUI entry (ForgeApp), local SPM dependency on ForgeMobile, and documented build commands. Unblocks GraphQL and section-renderer work (issues #102#111).

  • ForgeApp.xcodeproj: App target, Swift 6, iOS 17, XCLocalSwiftPackageReference to ForgeMobile
  • App/ForgeApp.swift: @main app with WindowGroup { ForgeRootView() }
  • README: How to open in Xcode and CLI xcodebuild commands
  • .gitignore: xcuserdata, *.xcuserstate

Resolves #101

Contracts Changed

  • yes
  • no

Regeneration Required

  • yes
  • no

Validation

  • Build: xcodebuild -scheme ForgeApp -destination 'platform=iOS Simulator,name=iPhone 16' build passes
  • SwiftLint: swiftlint lint --strict passes in mobile/ios
  • Contracts validated
  • Generated code verified (no manual edits)
  • Tests and build passed
  • Terraform plan reviewed (if infra change)

Made with Cursor

Summary by CodeRabbit

  • Documentation

    • Added iOS building and running instructions with Xcode IDE and command-line workflows.
  • New Features

    • Established iOS app infrastructure and project configuration for ForgeApp.
  • Accessibility

    • Improved accessibility with labels for iOS components.
  • Chores

    • Updated project configurations for Xcode and VSCode development environments.

Ur-imazing and others added 3 commits February 25, 2026 14:36
- ForgeApp.xcodeproj with ForgeApp target, Swift 6, iOS 17
- Local SPM dependency on ForgeMobile package
- App/ForgeApp.swift with @main and ForgeRootView
Resolves #101

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 25, 2026

Warning

Rate limit exceeded

@Ur-imazing has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 21 minutes and 2 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between acf99b2 and 3a71999.

📒 Files selected for processing (1)
  • .vscode/settings.json

Walkthrough

Introduces a complete iOS Xcode project named ForgeApp with minimal SwiftUI entry point, configured to use the existing ForgeMobile Swift package as a dependency. Includes project configuration files, documentation, and development environment setup files.

Changes

Cohort / File(s) Summary
iOS App Project Structure
mobile/ios/App/ForgeApp.xcodeproj/project.pbxproj, mobile/ios/App/ForgeApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata, mobile/ios/App/ForgeApp/ForgeApp.swift
Creates complete Xcode project definition with PBX build phases, configurations, Swift 6 settings, and ForgeMobile package dependency. Adds minimal SwiftUI app entry point with @main annotation.
Documentation & Build Configuration
.gitignore, mobile/ios/README.md, .vscode/settings.json, .vscode/tasks.json
Excludes Xcode user state files, documents building and running steps (SweetPad and xcodebuild workflows), and adds VSCode workspace configuration with custom build task.
Accessibility Improvements
mobile/ios/Sources/ForgeMobile/ForgeRootView.swift
Adds accessibility label to root view text for assistive technology support.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the main change: scaffolding an Xcode app under mobile/ios, matching the primary objective of the PR.
Linked Issues check ✅ Passed All acceptance criteria from #101 are met: app target builds/runs in Xcode and CLI, minimal SwiftUI entry with Swift 6, Xcode folder structure implemented, and build commands documented in README.
Out of Scope Changes check ✅ Passed All changes are directly related to scaffolding the iOS app: project structure, entry point, documentation, and build configuration. VSCode/SweetPad additions support the build workflow as documented.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/101-scaffold

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@mobile/ios/README.md`:
- Around line 21-30: The xcodebuild commands in the README currently omit the
project flag which can cause ambiguous selection between Package.swift and
ForgeApp.xcodeproj; update each command that calls xcodebuild (the lines using
xcodebuild -list and xcodebuild -scheme ForgeApp -destination ...) to include
the explicit project flag (add -project ForgeApp.xcodeproj) so the commands
become deterministic and always target the ForgeApp.xcodeproj.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b0bf1cf and 69fd582.

📒 Files selected for processing (4)
  • .gitignore
  • mobile/ios/App/ForgeApp.swift
  • mobile/ios/ForgeApp.xcodeproj/project.pbxproj
  • mobile/ios/README.md

Comment thread mobile/ios/README.md
…Mobile

- Move app entry from top-level App/ to Sources/App/ForgeApp.swift
- Update Xcode project to reference Sources/App
- Document Sources/App and Sources/ForgeMobile layout in README

Co-authored-by: Cursor <cursoragent@cursor.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
mobile/ios/ForgeApp.xcodeproj/project.pbxproj (1)

88-96: Xcode tools version metadata suggests Xcode 15, but Swift 6 requires Xcode 16+.

CreatedOnToolsVersion = 15.0 and LastSwiftUpdateCheck = 1500 indicate Xcode 15, yet the target sets SWIFT_VERSION = 6.0 (lines 217, 241), which shipped with Xcode 16. While Xcode will silently update this metadata on first open, it may confuse contributors into thinking Xcode 15 is sufficient.

Consider bumping to 16.0 / 1600 to match reality, or adding a note in the README about the minimum Xcode version.

Suggested metadata update
 			attributes = {
 				BuildIndependentTargetsInParallel = 1;
-				LastSwiftUpdateCheck = 1500;
-				LastUpgradeCheck = 1500;
+				LastSwiftUpdateCheck = 1600;
+				LastUpgradeCheck = 1600;
 				TargetAttributes = {
 					A1B2C3D4E5F60000000A = {
-						CreatedOnToolsVersion = 15.0;
+						CreatedOnToolsVersion = 16.0;
 					};
 				};
 			};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mobile/ios/ForgeApp.xcodeproj/project.pbxproj` around lines 88 - 96, Update
the Xcode tool metadata so it matches the Swift/Xcode requirement: change
CreatedOnToolsVersion and LastSwiftUpdateCheck in the project attributes block
(the attributes / TargetAttributes entries shown) to reflect Xcode 16 (e.g., set
CreatedOnToolsVersion = 16.0 and LastSwiftUpdateCheck = 1600) to align with the
SWIFT_VERSION = 6.0 entries found on the target(s); alternatively add a short
note to the repo README stating Xcode 16+ is required if you prefer not to
modify the pbxproj.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@mobile/ios/ForgeApp.xcodeproj/project.pbxproj`:
- Around line 88-96: Update the Xcode tool metadata so it matches the
Swift/Xcode requirement: change CreatedOnToolsVersion and LastSwiftUpdateCheck
in the project attributes block (the attributes / TargetAttributes entries
shown) to reflect Xcode 16 (e.g., set CreatedOnToolsVersion = 16.0 and
LastSwiftUpdateCheck = 1600) to align with the SWIFT_VERSION = 6.0 entries found
on the target(s); alternatively add a short note to the repo README stating
Xcode 16+ is required if you prefer not to modify the pbxproj.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 69fd582 and ad75562.

📒 Files selected for processing (3)
  • mobile/ios/ForgeApp.xcodeproj/project.pbxproj
  • mobile/ios/README.md
  • mobile/ios/Sources/App/ForgeApp.swift
🚧 Files skipped from review as they are similar to previous changes (1)
  • mobile/ios/README.md

…, Xcode 16 metadata

- README: add -project ForgeApp.xcodeproj to all xcodebuild commands
- README: note Xcode 16+ required for Swift 6
- project.pbxproj: set LastSwiftUpdateCheck/LastUpgradeCheck to 1600, CreatedOnToolsVersion to 16.0

Co-authored-by: Cursor <cursoragent@cursor.com>
@Ur-imazing
Copy link
Copy Markdown
Contributor Author

Review feedback addressed (2050609)

Fixed:

  • README xcodebuild commands: Added -project ForgeApp.xcodeproj to all three xcodebuild commands so builds are deterministic when both Package.swift and the app project exist in the same directory. Also noted that Xcode 16+ is required for Swift 6.
  • project.pbxproj metadata: Updated LastSwiftUpdateCheck and LastUpgradeCheck to 1600, and CreatedOnToolsVersion to 16.0, to align with SWIFT_VERSION = 6.0 (Xcode 16+).

Not changed: n/a — both actionable and nitpick items were applied.

Co-authored-by: Cursor <cursoragent@cursor.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
mobile/ios/Sources/ForgeMobile/ForgeApp.swift (1)

7-9: .accessibilityLabel is redundant when it mirrors the Text content exactly.

SwiftUI's Text view uses its string content as the default VoiceOver label. The explicit modifier here has no effect and can be removed.

♻️ Proposed simplification
  public var body: some View {
    Text("Forge iOS")
-     .accessibilityLabel("Forge iOS")
  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mobile/ios/Sources/ForgeMobile/ForgeApp.swift` around lines 7 - 9, The Text
view in ForgeApp.swift currently applies .accessibilityLabel("Forge iOS") which
is redundant because Text("Forge iOS") already provides the same accessibility
label; remove the .accessibilityLabel modifier from the Text in the ForgeApp
view (locate the Text("Forge iOS") expression) so the accessibility label is
derived from the Text content instead.
mobile/ios/ForgeApp.xcodeproj/project.pbxproj (2)

53-59: Empty Package product dependencies group is dead content.

The group at Line 53–59 has children = (). ForgeMobile is correctly wired through packageProductDependencies on the native target and the XCSwiftPackageProductDependency section; nothing needs to be listed here. Xcode populates this group automatically when the project is opened — it should not be committed empty.

♻️ Proposed fix — remove the orphaned group and its reference
-		A1B2C3D4E5F600000012 /* Package product dependencies */ = {
-			isa = PBXGroup;
-			children = (
-			);
-			name = "Package product dependencies";
-			sourceTree = "<group>";
-		};

Also remove the corresponding child reference from the root group (Line 32 or wherever it appears as a sibling):

-			A1B2C3D4E5F600000012 /* Package product dependencies */,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mobile/ios/ForgeApp.xcodeproj/project.pbxproj` around lines 53 - 59, Remove
the empty PBXGroup named "Package product dependencies" (the PBXGroup entry with
isa = PBXGroup and children = ()) and also remove its child reference from the
root group so there is no orphaned group entry; Xcode will auto-populate package
product dependencies from
packageProductDependencies/XCSwiftPackageProductDependency, so delete the
PBXGroup block for "Package product dependencies" and the corresponding
reference in the root group's children array to fully eliminate the dead
content.

198-245: No DEVELOPMENT_TEAM set — device and CI builds will fail without it.

Neither the Debug (Line 200–221) nor Release (Line 223–244) target build configurations include a DEVELOPMENT_TEAM. With CODE_SIGN_STYLE = Automatic, Xcode requires a team identifier to resolve provisioning for device and archive builds. This is acceptable for a local simulator-only scaffold, but any CI pipeline or on-device run will error out with a signing failure unless the team is set either here or via a CI-level xcodebuild override (DEVELOPMENT_TEAM=...). Document this requirement in the README or add a placeholder.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mobile/ios/ForgeApp.xcodeproj/project.pbxproj` around lines 198 - 245, The
Debug and Release XCBuildConfiguration blocks (names "Debug" and "Release") set
CODE_SIGN_STYLE = Automatic but omit DEVELOPMENT_TEAM, which causes device/CI
signing failures; add a DEVELOPMENT_TEAM = <YOUR_TEAM_ID>; entry inside the
buildSettings for both the A1B2C3D4E5F600000010 (Debug) and A1B2C3D4E5F600000011
(Release) configurations or alternatively document that CI must supply
DEVELOPMENT_TEAM via xcodebuild environment override (e.g.,
DEVELOPMENT_TEAM=...), so automatic signing can resolve provisioning.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@mobile/ios/ForgeApp.xcodeproj/project.pbxproj`:
- Line 6: The project file's objectVersion is incorrect for Xcode 16; update the
pbxproj so objectVersion is 70 (not 56) and set the compatibilityVersion string
to "Xcode 16.0" to match the existing CreatedOnToolsVersion/LastUpgradeCheck
(CreatedOnToolsVersion = 16.0, LastUpgradeCheck = 1600), ensuring the project
metadata is consistent and preventing Xcode from auto-upgrading the file on
first open.

---

Nitpick comments:
In `@mobile/ios/ForgeApp.xcodeproj/project.pbxproj`:
- Around line 53-59: Remove the empty PBXGroup named "Package product
dependencies" (the PBXGroup entry with isa = PBXGroup and children = ()) and
also remove its child reference from the root group so there is no orphaned
group entry; Xcode will auto-populate package product dependencies from
packageProductDependencies/XCSwiftPackageProductDependency, so delete the
PBXGroup block for "Package product dependencies" and the corresponding
reference in the root group's children array to fully eliminate the dead
content.
- Around line 198-245: The Debug and Release XCBuildConfiguration blocks (names
"Debug" and "Release") set CODE_SIGN_STYLE = Automatic but omit
DEVELOPMENT_TEAM, which causes device/CI signing failures; add a
DEVELOPMENT_TEAM = <YOUR_TEAM_ID>; entry inside the buildSettings for both the
A1B2C3D4E5F600000010 (Debug) and A1B2C3D4E5F600000011 (Release) configurations
or alternatively document that CI must supply DEVELOPMENT_TEAM via xcodebuild
environment override (e.g., DEVELOPMENT_TEAM=...), so automatic signing can
resolve provisioning.

In `@mobile/ios/Sources/ForgeMobile/ForgeApp.swift`:
- Around line 7-9: The Text view in ForgeApp.swift currently applies
.accessibilityLabel("Forge iOS") which is redundant because Text("Forge iOS")
already provides the same accessibility label; remove the .accessibilityLabel
modifier from the Text in the ForgeApp view (locate the Text("Forge iOS")
expression) so the accessibility label is derived from the Text content instead.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ad75562 and 9e7641c.

📒 Files selected for processing (3)
  • mobile/ios/ForgeApp.xcodeproj/project.pbxproj
  • mobile/ios/README.md
  • mobile/ios/Sources/ForgeMobile/ForgeApp.swift
🚧 Files skipped from review as they are similar to previous changes (1)
  • mobile/ios/README.md

Comment thread mobile/ios/App/ForgeApp.xcodeproj/project.pbxproj Outdated
Ur-imazing and others added 3 commits February 25, 2026 15:29
- README: document SweetPad (Build & Run, task) as preferred method
- .vscode: SweetPad workspace path and ForgeApp launch task

Co-authored-by: Cursor <cursoragent@cursor.com>
…ad workspace

- Move project and app source under app/ (ForgeApp.xcodeproj, app/ForgeApp/)
- Add project.xcworkspace/contents.xcworkspacedata for SweetPad
- Rename Sources/ForgeMobile/ForgeApp.swift to ForgeRootView.swift
- Update README and SweetPad path to App/ForgeApp.xcodeproj

Co-authored-by: Cursor <cursoragent@cursor.com>
… with Xcode 16

CodeRabbit: set objectVersion to 70 and compatibilityVersion to Xcode 16.0
Co-authored-by: Cursor <cursoragent@cursor.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
mobile/ios/App/ForgeApp.xcodeproj/project.pbxproj (1)

6-6: objectVersion = 70 and compatibilityVersion = "Xcode 16.0" are now correctly aligned.

The previously flagged mismatch (objectVersion 56 / "Xcode 14.0") is fully resolved. Metadata is consistent with Xcode 16 / Swift 6.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mobile/ios/App/ForgeApp.xcodeproj/project.pbxproj` at line 6, The project
metadata mismatch has been resolved by updating objectVersion to 70 and
compatibilityVersion to "Xcode 16.0"; verify that both symbols (objectVersion
and compatibilityVersion) are present and consistent in the project.pbxproj, and
if any other entries still show the old values (e.g., 56 or "Xcode 14.0") update
them to 70 and "Xcode 16.0" respectively so the file is fully aligned with Xcode
16 / Swift 6.
🧹 Nitpick comments (1)
mobile/ios/Sources/ForgeMobile/ForgeRootView.swift (1)

7-9: Redundant .accessibilityLabelText already uses its string content as the label.

Text("Forge iOS") automatically exposes "Forge iOS" as its accessibility label. The explicit modifier is a no-op here and could mislead future contributors into thinking a custom override is intentional.

♻️ Proposed simplification
  Text("Forge iOS")
-     .accessibilityLabel("Forge iOS")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mobile/ios/Sources/ForgeMobile/ForgeRootView.swift` around lines 7 - 9,
Remove the redundant accessibility modifier on the SwiftUI Text view: delete the
explicit .accessibilityLabel call applied to Text("Forge iOS") in ForgeRootView
(the modifier is a no-op because Text uses its string as the accessibility
label), leaving just Text("Forge iOS") so future readers aren’t misled about an
intentional override.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.vscode/settings.json:
- Line 2: Update the SweetPad workspace setting: change the
"sweetpad.workspacePath" value to point to the auto-generated .xcworkspace
(e.g., "mobile/ios/App/ForgeApp.xcodeproj/project.xcworkspace") instead of the
.xcodeproj so SPM/CocoaPods schemes resolve correctly; locate the
"sweetpad.workspacePath" entry in .vscode/settings.json and replace the
.xcodeproj path with the .xcworkspace path.

---

Duplicate comments:
In `@mobile/ios/App/ForgeApp.xcodeproj/project.pbxproj`:
- Line 6: The project metadata mismatch has been resolved by updating
objectVersion to 70 and compatibilityVersion to "Xcode 16.0"; verify that both
symbols (objectVersion and compatibilityVersion) are present and consistent in
the project.pbxproj, and if any other entries still show the old values (e.g.,
56 or "Xcode 14.0") update them to 70 and "Xcode 16.0" respectively so the file
is fully aligned with Xcode 16 / Swift 6.

---

Nitpick comments:
In `@mobile/ios/Sources/ForgeMobile/ForgeRootView.swift`:
- Around line 7-9: Remove the redundant accessibility modifier on the SwiftUI
Text view: delete the explicit .accessibilityLabel call applied to Text("Forge
iOS") in ForgeRootView (the modifier is a no-op because Text uses its string as
the accessibility label), leaving just Text("Forge iOS") so future readers
aren’t misled about an intentional override.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9e7641c and acf99b2.

📒 Files selected for processing (7)
  • .vscode/settings.json
  • .vscode/tasks.json
  • mobile/ios/App/ForgeApp.xcodeproj/project.pbxproj
  • mobile/ios/App/ForgeApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  • mobile/ios/App/ForgeApp/ForgeApp.swift
  • mobile/ios/README.md
  • mobile/ios/Sources/ForgeMobile/ForgeRootView.swift
✅ Files skipped from review due to trivial changes (1)
  • mobile/ios/App/ForgeApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata
🚧 Files skipped from review as they are similar to previous changes (1)
  • mobile/ios/README.md

Comment thread .vscode/settings.json Outdated
…esolution

Co-authored-by: Cursor <cursoragent@cursor.com>
@Ur-imazing Ur-imazing merged commit c6c06d6 into main Feb 25, 2026
9 of 10 checks passed
@Ur-imazing Ur-imazing deleted the feat/101-scaffold branch February 25, 2026 03:28
Kneesal pushed a commit to Kneesal/forge that referenced this pull request Mar 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(mobile-ios): scaffold Xcode app under mobile/ios

1 participant