payhub is an iOS app for splitting shared bills after meals, hangouts, trips, and other group activities. It helps record who paid, who participated, and which settlement transfers are needed.
- Platform: iOS and iPadOS
- UI framework: SwiftUI
- Project file:
payhub.xcodeproj - App target:
payhub - Unit test target:
payhubTests - UI test target:
payhubUITests - Bundle ID:
com.vngbh.payhub - Version:
1.0build1 - iOS deployment target:
18.0
- macOS with the full Xcode app installed.
- An Xcode version that supports the configured iOS deployment target.
- iOS Simulator installed through Xcode.
- Apple Developer account for real-device, TestFlight, or App Store builds.
Check the active developer tools:
xcode-select -p
xcodebuild -versionIf xcodebuild points to Command Line Tools instead of Xcode, switch to Xcode:
sudo xcode-select -s /Applications/Xcode.app/Contents/DeveloperOpen the Xcode project:
open payhub.xcodeprojIn Xcode:
- Select the
payhubscheme. - Select an available iOS simulator.
- Press
Cmd + Rto build and run. - Press
Cmd + Uto run tests.
List project schemes, targets, and configurations:
xcodebuild -list -project payhub.xcodeprojList available simulators:
xcrun simctl list devices availableBuild Debug for iOS Simulator:
xcodebuild \
-project payhub.xcodeproj \
-scheme payhub \
-configuration Debug \
-destination 'generic/platform=iOS Simulator' \
buildRun tests on a simulator:
xcodebuild \
-project payhub.xcodeproj \
-scheme payhub \
-configuration Debug \
-destination 'platform=iOS Simulator,name=iPhone 17' \
testIf iPhone 17 is unavailable, choose a simulator from:
xcrun simctl list devices availableRemove project-specific DerivedData when build cache issues appear:
rm -rf ~/Library/Developer/Xcode/DerivedData/payhub-*Boot a simulator:
xcrun simctl boot 'iPhone 17'
open -a SimulatorBuild into a dedicated derived data folder:
xcodebuild \
-project payhub.xcodeproj \
-scheme payhub \
-configuration Debug \
-destination 'platform=iOS Simulator,name=iPhone 17' \
-derivedDataPath build/DerivedData \
buildInstall and launch the app:
xcrun simctl install booted build/DerivedData/Build/Products/Debug-iphonesimulator/payhub.app
xcrun simctl launch booted com.vngbh.payhubpayhub supports SwiftUI hot reload in Debug builds through the Inject Swift package and the InjectionIII macOS app.
Install InjectionIII:
brew install --cask injectioniiiUse hot reload:
- Open InjectionIII and select the repository folder.
- Open
payhub.xcodeprojin Xcode. - Run the
payhubscheme on a simulator. - Edit a SwiftUI view that uses
@ObserveInjectionand.enableInjection(). - Save the file to inject the updated implementation into the running Debug app.
Hot reload is only for local UI iteration. Run a normal build and relevant tests before opening a PR.
Before starting any task, read the root SKILL.md and any local SKILL.md files for the folders you will touch. Follow those rules for documentation, code style, branch naming, commits, and pull requests.
Every task must be completed on its own branch. Do not commit task work directly on main.
Start from the latest main:
git status --short --branch
git switch main
git pull --ff-only
git switch -c docs/short-doc-nameUse the branch prefix that matches the task:
feature/short-task-name
fix/short-bug-name
docs/short-doc-name
refactor/short-refactor-name
test/short-test-name
chore/short-maintenance-name
ci/short-ci-name
build/short-build-name
Keep each change focused:
- Pick one task.
- Read the relevant skill files.
- Implement the change.
- Build or test the affected area.
- Check the diff.
- Commit with the project commit convention.
- Open a PR before merging to
main.
Suggested commit format:
type(scope): message
Example:
git add README.md SKILL.md
git commit -m "docs(readme): update project guide"Before opening a PR:
- Confirm the branch name follows
SKILL.md. - Re-read the root
SKILL.mdand any local skill files for touched folders. - Confirm documentation is clear, concise, professional, and emoji-free.
- Run relevant build or test commands.
- Review the final diff.
Recommended test command when Xcode is configured:
xcodebuild \
-project payhub.xcodeproj \
-scheme payhub \
-configuration Debug \
-destination 'platform=iOS Simulator,name=iPhone 17' \
testReview changes before committing:
git status --short --branch
git diffPR title format:
[Edited Place] Content Here
PR body format:
## Summary
Short explanation of what changed and why.
## Details
- Added ...
- Updated ...
- Fixed ...
- Tested ...Use a normal merge commit when merging PRs into main, unless the user explicitly asks for another merge method.
Keep app code organized by responsibility:
App: app entry point and root scene wiring.Models: plain Swift domain data.Views: SwiftUI screens and reusable components.ViewModels: screen state, user actions, and coordination.Services: calculation, persistence, formatting, import, export, and integrations.Utilities: small generic helpers and extensions.Resources: localization and static non-asset resources.Assets.xcassets: runtime colors, icons, images, and app icons.
Bill-splitting logic should live in models or services so it can be unit tested. Avoid placing business rules inside SwiftUI views.
- Create a group.
- Add members.
- Add a bill with title, amount, payer, and participants.
- Calculate how much each person paid.
- Calculate how much each person owes.
- Suggest the minimum settlement transactions.
- Edit or delete bills.
- Save data locally.
- Share the settlement summary.
Prioritize unit tests for:
- Even splits across all members.
- One person paying multiple bills.
- Bills involving only some members.
- Decimal amounts and rounding behavior.
- Total received matching total owed.
- No settlements when everyone is balanced.
Prioritize UI tests for:
- App launch.
- Group creation.
- Bill creation.
- Calculation result review.
Build Release for iOS Simulator:
xcodebuild \
-project payhub.xcodeproj \
-scheme payhub \
-configuration Release \
-destination 'generic/platform=iOS Simulator' \
buildArchive for distribution:
xcodebuild \
-project payhub.xcodeproj \
-scheme payhub \
-configuration Release \
-destination 'generic/platform=iOS' \
-archivePath build/payhub.xcarchive \
archiveExporting an archive requires an ExportOptions.plist that matches the distribution method. Add it when TestFlight or App Store distribution begins.
xcodebuild \
-exportArchive \
-archivePath build/payhub.xcarchive \
-exportPath build/export \
-exportOptionsPlist ExportOptions.plist- Update
MARKETING_VERSIONandCURRENT_PROJECT_VERSION. - Confirm the bundle ID matches the Apple Developer portal.
- Configure the signing team in Xcode.
- Add complete app icons.
- Check the launch screen.
- Run unit tests and UI tests.
- Test on at least one iPhone simulator.
- Test on at least one iPad simulator if iPad remains supported.
- Test on a real device when available.
- Write build notes with new features, known issues, and flows to test.
Check the selected Xcode developer directory:
xcode-select -pCheck available simulators:
xcrun simctl list devices availableReset the booted simulator:
xcrun simctl shutdown booted
xcrun simctl erase bootedIf xcrun simctl erase booted fails because no simulator is booted, boot a simulator first or erase a specific device ID from the simulator list.