Staying in touch
Push notifications
Three things buzz a member's phone. Two of them have an email twin sending on the very same event, and reading them side by side is the fastest way to understand either channel.
At a glance
Push is a separate channel from email, not a mirror of it. Three events reach the phone:
- You were tagged in a proof — to each tagged member. Has an email twin.
- Someone commented on your proof — to the author and anyone tagged on it. Has an email twin.
- You still have a proof due today — the evening nudge. No email twin; this one is push only.
Every push carries the same heading — the single word trythings — because the heading is the app name on the lock screen, not a subject line. All the meaning is in the one sentence underneath it.
The rules every push follows
These hold for all three, because they live in one funnel rather than in each sender:
- The push comes after the work, never before it. The tag, the comment — each is written and committed first, and the buzz is fired afterwards. A push that failed can never cost a member the action they took, and a buzz for a comment that then rolled back would be a lie.
- At most once per recipient, per event, per day. A ledger row is claimed before the send, never after, so a retry or a second server instance sweeping at the same moment cannot double-buzz. Only the insert winner sends.
- Nothing is retried. A failed send is logged and dropped. A lost nudge is cheaper than a repeated one, and the in-app bell row is the record either way.
- Push and email keep separate ledgers. Two tables, same shape, deliberately not one — so a member who muted their email still gets their push, and the two channels can never dedupe each other away.
- No devices are stored. Sends are addressed to a member by their user id; which handsets that fans out to is OneSignal's problem, not the app's.
Getting a device registered
There is no "enable notifications" screen and no device list in the app. Registration is a side effect of being signed in on a phone:
- The app starts. On a native build it initialises OneSignal with the App ID baked into that build. A build shipped without one warns in the console and disables push for that build entirely — it is never user-breaking.
- A member signs in. The device is bound to their user id as its external id. That binding is what makes "send to this member" possible with no device table anywhere in the schema.
- The OS permission prompt follows. It appears only while permission is undetermined; on every later sign-in the same call resolves silently with whatever the member already decided.
- Signing out unbinds the device, so no further pushes reach it.
Signing in as a different member on the same handset rebinds it — pushes follow the new member, and the previous one stops receiving on that device.
1. You were tagged in a proof
Someone posted a proof and put your name on it. Both tagging paths fire it — posting a proof with tags, and adding a tag to a proof that already exists.
This push does name the person who tagged you, and it says exactly what its email twin's subject line says. If the author has no display name, both fall back to "Someone" rather than skipping the send.
- Goes to
- Each member tagged on the proof.
- Fires when
- A proof is posted with tags, or a tag is added to an existing proof — once the tagging transaction commits.
- Says
- “Dan Ochoa tagged you in a proof”
- How often
- Once EVER, per member, per proof. The dedupe day is the proof’s own date, so untagging and re-tagging the same person never buzzes them twice.
- Tapping it opens
- The proof’s own page — the card that names them, and the surface that offers to take the name back off.
- Email twin
- Identical. Same recipients, same dedupe key, same once-ever rule, same destination, same wording.
This is the pair where the two channels agree completely. The push and the email claim the same dedupe key — proof_tag:<proof id> — against the same date, and the only reason a member can receive both is that the two claims land in different tables.
2. Someone commented on your proof
Somebody commented on a proof you posted, or on one you accepted a tag on. This is the one push that can arrive again for the same proof on a later day, and it is the pair where the two channels deliberately say different things.
- Goes to
- The proof’s original author plus every member who accepted a tag on it and still stands in the group — minus whoever wrote the comment.
- Fires when
- A comment is added to a proof, once it commits.
- Says
- “Someone commented on your proof” — always exactly that.
- How often
- At most once per recipient, per proof, per day — measured in that recipient’s own timezone, not the server’s and not the proof’s.
- Tapping it opens
- The proof, where the comment can be read and replied to.
- Email twin
- Same recipients, same key, same once-per-recipient-day throttle — but the email names the commenter and this does not.
The two throttles are worth putting side by side, because they are the same mechanism aimed at different questions:
- Tag push
- Keys its day to the PROOF’s date. The date never moves, so the guard fires once and holds forever — once ever per member per proof.
- Comment push
- Keys its day to the RECIPIENT’s calendar day. A new day is a new key, so a proof that draws comments across a week buzzes once each day.
3. You still have a proof due today
The evening nudge, and the only one of the three with no email counterpart. It is also the only notification in the whole app that reaches a member who did not act — every other one is a reaction to something somebody did.
A background sweep runs every fifteen minutes and visits every member who is past 18:00 on their own clock with a commitment due today and no proof posted. The window is "at or after 18:00", not "at exactly 18:00", so a tick lost to a deploy or a restart is picked up by the next one instead of skipping somebody's day.
- Goes to
- Each member who owes a proof today and has not posted one.
- Fires when
- The first sweep at or after 18:00 in that member’s own timezone.
- Says
- “You still have a proof due today.”
- How often
- At most once per member per day, on their own calendar day.
- Tapping it opens
- The app. This one carries no in-app path.
- Email twin
- None. Push only.
- Not sent when
- The group has been archived. This is the only read in the whole app that treats archiving as more than cosmetic.
Post the proof before the evening and no nudge is sent — the sweep asks whether the day is still unfilled at the moment it looks, and a member who is square with their commitments never becomes a candidate.
What a push never carries
Everything the email channel wraps around its content has no counterpart here, and that is structural rather than an omission:
- No unsubscribe link and no unsubscribe headers. Every notification email carries both. A push has nowhere to put them, and the OS permission is the equivalent lever.
- No plain-text twin — there is no second rendering to send.
- No sender identity beyond the app name. Every push heads with "trythings", so the actor, when there is one, has to fit in the body sentence.
- No comment body, ever — the same rule the email follows, for the same reason.
Turning them off
There is no push switch inside the app. The Notifications toggle on the profile page is the email switch and only the email switch — flipping it off stops every notification email and changes nothing about the phone.
A member turns push off the way they turn any app's push off: in the operating system's own notification settings for trythings. Signing out has the same practical effect, since it unbinds the handset.
For operators
The whole push channel switches off when the OneSignal REST API key is unset. Nothing is sent. Dev, test and CI run this way by default, which is why no local machine ever buzzes a real phone. The App ID is separate and public by design — it is baked into the mobile bundle at build time.
A single failed send is logged as a warning and dropped. It is never retried, and it never surfaces to the member whose comment or tag triggered it.