StreetPass is a local-first iOS app for opt-in, proximity-based social discovery. A person creates a profile on their device; the app exchanges a compact profile card with nearby StreetPass installations over Bluetooth Low Energy (BLE); and each device keeps its own short-lived encounter feed.
There is no account service, analytics SDK, ad network, or required backend. The interesting part is the device-to-device behavior: when two people have StreetPass installed and Bluetooth access enabled, their phones can recognize a crossing without sending the profile through a server.
StreetPass is an independent open-source project. It is not affiliated with, endorsed by, or sponsored by Nintendo.
The core two-device flow has been repeatedly exercised on physical iPhone and iPad hardware, including foreground, background, persisted-profile, high-frequency tester, and unplugged battery trials. Those runs produced reliable bidirectional encounters under stress without a material battery change against the test baseline.
Those results describe the tested devices and conditions; they are not a promise about every iOS release or radio environment. See TESTING.md for reproducible gates and APPLE_BLE_BACKGROUND_PLAYBOOK.md for the physical-device runbook.
StreetPass currently targets iOS 17 and uses:
- SwiftUI for the app and diagnostic interfaces.
- Core Bluetooth central and peripheral roles.
- A versioned, validated profile payload capped at 512 encoded bytes.
- Core Bluetooth state preservation/restoration identifiers derived from the app bundle ID.
- Local
UserDefaultspersistence for profiles, follows, telemetry, and recent encounters. - Optional, off-by-default location wake assist that does not record coordinates.
- Unit, UI, and two-device physical test harnesses.
Requirements:
- A recent Xcode compatible with iOS 17.
- XcodeGen 2.45.4 when regenerating the checked-in project.
jqfor the physical-device scripts.- Two signed physical iOS devices for BLE/background validation.
Generate and open the project:
xcodegen generate
open StreetPass.xcodeprojRun the simulator suite:
xcodebuild test \
-project StreetPass.xcodeproj \
-scheme StreetPass \
-configuration Debug \
-destination 'platform=iOS Simulator,name=iPhone 17'The checked-in defaults intentionally contain no Apple team or personal bundle identifier. Copy the example file and set values that belong to your developer account:
cp Config/Local.xcconfig.example Config/Local.xcconfigConfig/Local.xcconfig is ignored by Git. At minimum, set:
STREETPASS_BUNDLE_ID = com.example.StreetPass
DEVELOPMENT_TEAM = YOUR_TEAM_ID
Background task and Bluetooth restoration identifiers are derived from STREETPASS_BUNDLE_ID, so forks do not need to edit Swift or plist files to use their own namespace.
The product path is deliberately small:
- A local profile is configured as the current BLE payload.
- StreetPass publishes one GATT service and advertises its service UUID.
- A nearby StreetPass central discovers that service, connects, and reads one characteristic.
- The receiver rejects oversized, malformed, or unsupported payloads before creating an encounter.
- The encounter is retained locally for up to 24 hours and can generate a local notification.
Background-optimized mode avoids duplicate discoveries, rejects very weak signals before connecting, and relies on long-lived OS-managed scan/advertising work. Diagnostic mode increases observability and responsiveness for foreground testing.
See docs/architecture.md and docs/privacy-and-threat-model.md for the boundaries and tradeoffs.
The default lab handles are generic and configurable:
export STREETPASS_BUNDLE_ID=com.example.StreetPass
export STREETPASS_IPHONE_PROFILE_HANDLE=@streetpass_one
export STREETPASS_IPAD_PROFILE_HANDLE=@streetpass_twoStart a clean paired background trial:
Scripts/start_background_trial.sh \
<iphone-device-id> \
<ipad-device-id> \
/tmp/streetpass-background-trialVerify that both devices can relaunch from their saved active profiles:
Scripts/start_persisted_profile_trial.sh \
<iphone-device-id> \
<ipad-device-id> \
/tmp/streetpass-persisted-profile-trialFor high-frequency foreground stress on a wired iPad:
Scripts/start_tester_lab.sh <ipad-device-id> reset 40 3 encounterThe complete workflow, output layout, and evidence rules are in TESTING.md.
StreetPass shares the visible parts of the local profile with nearby installations. That includes a stable profile UUID, display name, handle, short bio, avatar styling, birthday month/day, and at most one short post preview. Images and coordinates are not included in the BLE payload.
The current protocol is intentionally local and unauthenticated. A nearby device can observe, copy, replay, or forge a payload, and a stable profile identifier can support local tracking. Do not treat an encounter as verified identity. These limitations and appropriate research directions are documented in docs/privacy-and-threat-model.md.
Please report vulnerabilities privately according to SECURITY.md.
Contributions are welcome. Start with CONTRIBUTING.md, follow the Code of Conduct, and include tests for protocol or persistence changes.
StreetPass is available under the MIT License.