You can belong to multiple groups. Join is not limited to “first time” users.
From the app
Welcome screen (no groups yet)
If you are not in any group, Home shows:
Join a Group (Link/Code/QR)
Create a New Group
Profile (already in one or more groups)
Profile → scroll to Join another group (above Create a New Group):
Join a Group (Code / QR / Link) opens the same join flow.
Join methods
Method
What you do
6-character code
Admin shares code (e.g. A3K9XZ). Enter it on Join group.
QR in the app
On Join group, open the in-app camera scanner (allow camera). Scan the invite QR. Home ⋮ menu has Join a Group.
Nearby (BLE)
An admin can enable Broadcast to Nearby Users on Invite / Onboarding (advertises the group name). Members open ⋮ → Join a Group → BLE Scan to discover and join.
Link / system camera
Open https://swapsanity.com/join/CODE (or scan that QR with the phone camera). If the app is installed and deep links work, SwapSanity opens; if you are signed out you sign in first, then join continues.
NFC / BLE
Optional paths on the same Join screen when offered.
After a successful join request, group admins must approve (unless your email is pre-approved on the roster). You will not see the group’s shifts until approved.
Pending approval notification
In the app: Home shows an amber banner: “Your group join request is pending admin approval.” Tap it for details. The banner stays until an admin approves or rejects.
After you submit: You also get an in-app notification (“Join request pending”).
When decided: Push (FCM) + in-app notification if approved or declined.
Admins: Get a push when someone requests to join (if they have notifications enabled).
How invite codes work
A group admin opens Admin → Invite Members (or CLI create-invite).
The screen shows a QR, the 6-character code, and the invite link, with Copy code, Copy link, and Share.
Server stores group_invites/{CODE} with groupId and 24-hour expiry.
Public URL: https://swapsanity.com/join/CODE (sandbox: https://sandbox.swapsanity.com/join/CODE).
The recipient opens the link or Join a Group and enters the code. A pending request is created in group_requests until an admin approves.
App download
Scanning a join QR does not install the app by itself. Users need SwapSanity from the store (or web). Deep links open the app if already installed and universal links are configured.
Multi-group shared events
Event admins (Organizers) manage cross-group events (races, ski hills, etc.). Host-group members see the event on their group calendar without automatically becoming admins or participants. The event site can be an existing group location or only for this event (not added to the group’s place list).
Ways to get involved
Path
What it means
Open join link / code
Join as racer, spectator, patrol, or staff (participation only — not Event admin). Choosing spectator joins without a team. You still help the mesh and place nearby tags with your GPS. You can turn off Show my position on the map if you do not want a dot. Organizers can include spectator GPS on the event plan. The name you enter at join (or the organizer name when you create the event) is what appears on the live map — not your Google account name.
Invite to participate
Named invite from an Event admin; accept or decline
Invite as Event admin / Safety
Privilege role; accept or decline (separate from participate)
Assign duty (tradable)
Calendar duty on the host group that you can trade — not admin powers
Join / invite methods:
Method
URL / action
Link / QR
https://swapsanity.com/join-event/CODE
Landing page
Opens the app when installed; otherwise shows the code + Continue in web app
In app
Activity Hub → Join multi-group event → enter code
Invite codes are created with the event (or refreshed via generateSharedEventInvite) and expire (default 72 hours).
Who can manage the event?
Only Event admins (Organizers) can change event details, boundaries, and roles — not every host-group lead. The person who created the event is an Event admin; they can invite others as Event admin or Safety. Being a group admin of the host team does not by itself grant event edit.
How to know if deep linking works
Quick device checks
Install the production or sandbox build (package com.swapsanity.app or .sandbox).
Create an invite: https://swapsanity.com/join/TESTCODE (or real code from admin).
Phone: Messages/Notes/Chrome → open the link without opening the app first.
Success: SwapSanity opens (or asks to open) and lands on Join with that code.
Fail: Only the website/browser opens and never offers the app.
Cold start: Force-stop the app, then open the link again (tests install-time / cold deep link).
Signed out: Sign out, open link → should open app → login → then continue join (pending URI is stored).
Android verification (developer)
# Association file must be HTTPS + application/json (no redirect)curl-sI https://swapsanity.com/.well-known/assetlinks.jsoncurl-s https://swapsanity.com/.well-known/assetlinks.json# Should list package + cert fingerprint matching your signing keyadb shell pm get-app-links com.swapsanity.app# Look for swapsanity.com → verified# If not verified:adb shell pm verify-app-links --re-verify com.swapsanity.app
iOS
apple-app-site-association must be served at https://swapsanity.com/.well-known/apple-app-site-association
(no .json suffix required; correct Content-Type).
Team ID in that file must match Apple Developer (not placeholder YOUR_TEAM_ID).
Device: Settings → Developer → Associated Domains Diagnostics (if available), or open the link from Notes.