Delivered remotely for a business based in Dallas, United States. Names withheld by agreement.
Project Overview
Industry: Consumer social and relationship technology — the couples segment rather than the dating and discovery segment.
Type of solution: A cross-platform mobile application backed by a token-authenticated REST API, an administrative back office for content and member management, and scheduled reminder processing.
Business context: The relationship technology market is crowded at the point of introduction and almost empty afterwards. Once two people are together, the software stops helping. What remains is a set of small, recurring coordination problems: the dates neither person quite remembers, the "what do you want to do?" conversation that ends in nothing, the calendar that only one partner maintains, and the accumulated knowledge of what the other person actually likes that is never written down anywhere. This is a product about the relationship that already exists, not the one being sought.
General users: Adult members in a relationship, their invited partners, and platform administrators who manage the interest catalogues, curated suggestions and published content.
General purpose: To move a couple's shared context out of one partner's memory and into a private space both people can see — profiles they each author for themselves, a calendar they both maintain, milestones that remind them, and suggestions that turn "we should do something" into an actual plan.
The Business Challenge
The product is worthless with one user. A couples application is two-sided by definition, but the second person is not a market — they are one specific individual who may take days to respond, or may never install anything. If the app is unusable until they join, the first user abandons it before the second one arrives.
One partner, not many. Unlike a social network or a marketplace, the correct number of connections is exactly one. That constraint sounds simplifying and is the opposite: every invitation, acceptance, rejection, block, removal and re-invitation has to preserve it, from both sides, in every order those actions can occur.
People must own their own profile. If one partner fills in details on the other's behalf to get started, that stand-in information cannot be allowed to persist once the real person arrives and speaks for themselves. Authorship has to transfer — and only when it should.
Two calendars, one plan. A planned date belongs to two people with different rights: one proposes, the other accepts or declines, and both need to see it. Declining also needs to be socially survivable, which is a design problem as much as a technical one.
Reminders are the whole point, so they cannot be wrong. An anniversary reminder that arrives a day late is worse than no reminder. Timing has to be correct in the viewer's local time, generated reliably, without the user maintaining anything.
Intimacy raises the stakes on safety and privacy. This is a product where two identified adults share personal information, plans and locations. Blocking, declining, unpairing and deleting an account all have to work properly, and deletion has to unwind one person's data without damaging the other's.
Inspiration has to become a plan. A feed of date ideas that requires the user to then go and manually create a calendar entry will not be used. The distance between "that looks good" and "it's booked" has to be one action.
It had to be a phone product. Everything here happens in passing — on a commute, in a queue, in the five minutes before bed. There is no desktop version of this behaviour.
Our Approach
Make the app work before the second person arrives. Rather than gating the product behind a second signup, we designed the onboarding so that a user whose partner has not yet joined can proceed as though they had — recording a stand-in profile so reminders, planning and suggestions are all immediately usable. When the partner joins and confirms the connection, authorship of that profile transfers to them and their own answers take over. This is a general pattern for two-sided cold starts, and it is the single most important design decision in the product.
Never lose an invitation to a race. Notifications addressed to someone who has not yet registered are held rather than discarded, and released once that person has an authenticated session. An invitation sent five minutes before a signup behaves identically to one sent five minutes after.
Make onboarding resumable from the server. Multi-step signup progress is recorded server-side rather than held in client state, so a user who closes the app three screens in — or switches device — resumes exactly where they stopped rather than starting again.
Treat the pairing rule as an invariant, not a validation. The single-active-connection rule is checked from both sides on every path that can create, transfer or sever a connection, including the paths that are easy to forget: re-invitation after a rejection, invitation after a block, and account deletion by either party.
Design declining to be survivable. Declining a planned date offers a short list of pre-written, gently worded reasons alongside a free-text option, so the interaction does not force someone to compose a rejection from scratch.
Close the loop from inspiration to calendar. Curated suggestions carry everything a real plan needs — timing, location, description, cost and a link — so a suggestion converts into an actual invitation to the partner in a single action rather than being copied out by hand.
Make media loss impossible. Profile photography is uploaded to cloud object storage, but each stored file records where it actually ended up, so an upload that fails against the cloud provider degrades to a working local file rather than a broken image on someone's profile.
Put safety controls in the product, not in a support inbox. Blocking, declining, unpairing and account deletion are all first-class in-app actions with real effects on the data, not requests a user has to make by email.
Keep content and copy out of the release cycle. Onboarding wording, catalogues and operational configuration live in an administrative store rather than in code, so a consumer product that iterates on its first-run experience can do so without shipping a build.
The Solution
Account creation and verified identity. Registration by email with a verification code, or through the two major mobile identity providers, with an age check on the personal-details step.
Resumable guided onboarding. A guided sequence covering personal details, interests, preferred expressions of affection, important milestone dates and the partner invitation — with progress held server-side so it survives interruption.
Private one-to-one pairing. A partner is invited by email address and chooses to accept or decline. The connection is exclusive: one active partner at a time, enforced on both sides.
Immediate usefulness before the partner joins. A stand-in profile can be recorded so planning, reminders and suggestions work from the first session, with authorship transferring to the partner once they join and confirm.
Self-authored preference profiles. Each person records their own interests — from a managed catalogue they can add to — and their own preferred expressions of affection, so the other partner is working from what that person actually said rather than what they assumed.
Shared date planning. Dates carry title, day, start and end time, location, notes, dress code, an optional link and a reminder offset. One partner proposes; the other accepts or declines with a reason. Both see upcoming, past and cancelled dates, and a month calendar view.
Milestones with automatic reminders. Users record the dates that matter, each with its own reminder offset, and two are seeded automatically at registration so the feature is populated from the start.
Curated date suggestions. An administrator-managed feed of suggestions with imagery, description, location, cost, participant count and an active time window — convertible into a real invitation to the partner in one action.
Shared goals. A monthly target for time spent together, tracked against dates actually attended.
Notifications that go somewhere. Push notifications are paired with durable in-app records and typed payloads, so opening one lands on the specific date, milestone or invitation it refers to rather than on a home screen.
Safety and account controls. Block a connection, decline an invitation, remove a partner, and delete the account entirely from inside the app — with cascading cleanup and identifier anonymisation, and without damaging the other person's records.
Administrative back office. Management of members, interest and preference catalogues, curated suggestions, milestones, dates, published content pages and administrator accounts, plus a runtime settings store covering operational configuration and onboarding copy.
Key Features
Provisional partner profile for two-sided cold start The application is fully usable before the second person joins, with a stand-in profile whose authorship transfers to the partner once they arrive and confirm the connection.
Held notifications for accounts that do not yet exist Invitations and related notifications addressed to unregistered people are retained and released on that person's first authenticated session, so nothing is lost to timing.
Exclusive one-to-one pairing A single active partner connection per person, enforced on both sides across invitation, acceptance, rejection, blocking, removal, re-invitation and deletion.
Server-side resumable onboarding Multi-step signup progress is recorded on the account rather than in client state, so onboarding resumes at the exact step it stopped at, on any device.
Shared two-sided calendar Planned dates with full detail, proposed by one partner and accepted or declined by the other, presented as upcoming, past and cancelled lists and as a month calendar.
Milestone reminders on a schedule User-defined important dates with individual reminder offsets, driven by scheduled background processing and rendered in the viewer's local time.
One-action conversion from suggestion to plan Curated date suggestions carry enough detail to become a real invitation to the partner in a single tap, closing the gap between inspiration and a calendar entry.
Deep-linked push notifications Typed notification payloads routed to the specific screen they concern, with a durable in-app record behind every push.
In-product safety and deletion controls Blocking, declining, unpairing and self-service account deletion as real in-app actions with real data effects, including cascading cleanup and identifier anonymisation.
Resilient media handling Profile photography stored in cloud object storage with a recorded per-file location and a working local fallback, so a failed upload never becomes a broken image.
Technical Architecture
Mobile client. A cross-platform application built around a central state store with local persistence, composed through stack, tab and drawer navigation with a dedicated screen set per flow — onboarding, partner, calendar, suggestions, profile and notifications. Device capabilities include camera and photo library access with cropping for profile imagery, calendar and date/time pickers, connectivity detection and device metadata. A notification payload router maps typed push payloads onto navigation targets so notifications open the right screen. Hosted content pages are rendered in-app through a web view.
API layer. A token-authenticated REST API with controllers partitioned by audience — member API, administrative, authentication and public content — over a shared base controller that standardises response envelopes. Response shaping and partner-visibility rules are handled by a substantial set of resource classes, keeping presentation concerns out of the persistence layer.
Pairing and workflow layer. The connection lifecycle — invitation, acceptance, rejection, blocking, removal and re-invitation — with the exclusivity invariant enforced at every transition and notification dispatch attached to each outcome.
Scheduled processing. Background commands run on a fixed schedule to generate date and milestone reminders, creating in-app notification records and dispatching push messages without any user-facing request being involved.
Notification layer. A single path creates the durable in-app record and dispatches to every registered device for that user, so a push and its in-app counterpart can never diverge.
Storage layer. User media uploaded to cloud object storage with the resulting location recorded per file and a local-disk fallback, so retrieval always knows where a file actually is.
Data layer. A relational database covering accounts, connections, invitations, interests and preferences, planned dates, milestones and their reminders, notifications, device tokens, curated suggestions, published content and runtime settings.
Administrative platform. A server-rendered back office for members, catalogues, curated content, published pages and administrator accounts, with a runtime settings store so operational configuration and onboarding copy change without a deployment.
Delivery pipeline. Continuous integration driving an automated deployment tool across separate staging and production environments, running database migrations, cache invalidation, dependency installation and application server restart as part of every release.
Flow: Mobile client → Token-authenticated REST API → Pairing and planning logic → Relational database → Scheduled reminder processing → Push notifications and transactional email → Cloud object storage for media
Technology Stack
| Category | Technology |
|---|---|
| Backend language | PHP |
| Backend framework | Laravel |
| Database | MySQL, with dedicated index-adding migrations |
| API authentication | OAuth2 bearer tokens (Laravel Passport) |
| Administrative UI | Server-rendered Blade with a data-table layer, Bootstrap and Sass, built through Laravel Mix |
| Object storage | Google Cloud Storage, with a local-disk fallback path |
| Transactional email | SendGrid |
| Push notifications | Firebase Cloud Messaging with a per-device token registry |
| Scheduled processing | Framework console commands on a fixed schedule |
| Web delivery | Progressive Web App support; cross-origin handling; log inspection tooling |
| Testing & style | PHPUnit; automated style checking configuration |
| CI/CD | Continuous integration driving automated deployment across staging and production stages |
| Mobile framework | React Native |
| Mobile state | Redux with thunk middleware and local persistence |
| Mobile navigation | React Navigation — stack, bottom tabs, drawer, material top tabs, tab and pager views |
| Mobile identity | Google Sign-In and Sign in with Apple, alongside email and password |
| Mobile device features | Camera and photo library with cropping, calendar component, date and time pickers, connectivity detection, device metadata |
| Mobile UI | Material-style component library, SVG, vector icons, gesture handling, animation, safe-area handling, intro slider, alerts and modals |
| Mobile time handling | Moment with timezone support for local/UTC conversion |
| Networking | Axios over a token- and device-header-aware request wrapper |
Technical Challenges & Solutions
| Challenge | Our Approach |
|---|---|
| A two-sided product that is useless until the second person joins | A provisional partner profile lets the first user proceed as though their partner were present, with authorship transferring to the partner once they join and confirm the connection — so the product delivers value from the first session rather than from the second signup. |
| Invitations racing against signups and verification | Notifications addressed to people without accounts are held rather than discarded and released on their first authenticated session, making delivery independent of the order in which invitation and registration happen. |
| Keeping exactly one active partner connection, from both sides, forever | The exclusivity rule is treated as an invariant rather than a form validation, checked on both sides of every path that can create, transfer or sever a connection — including re-invitation after rejection, invitation after a block, and deletion by either party. |
| Stand-in data outliving the person it describes | Authorship transfers on confirmation and only on confirmation, so a partner's own answers supersede anything recorded on their behalf — and information recorded about someone who never joins never masquerades as theirs. |
| A plan owned by two people with different rights | Every list and detail query resolves which side of the pair the caller is on, so the same planned date presents correctly to the person who proposed it and the person deciding on it, with accept and decline outcomes visible to both. |
| Reminders that have to be right or are worse than useless | Reminder generation runs as scheduled background processing against stored timestamps, with local-time rendering handled on the client, keeping delivery independent of anyone opening the app. |
| Losing a user's profile photograph to a storage failure | Each stored file records where it actually ended up, so a failed cloud upload degrades to a working local file instead of a broken image — and retrieval never has to guess. |
| Multi-step onboarding abandoned midway | Signup progress is recorded server-side rather than in client state, so an interrupted onboarding resumes at the exact step it stopped at, including after reinstalling or switching device. |
| Safety and privacy on a product handling intimate personal data | Blocking, declining, unpairing and full account deletion are in-app actions with real data effects, with deletion cascading through the account's own records and anonymising its identifiers while leaving the other person's data intact. |
Security & Reliability
Token-based authentication. All member endpoints are protected by OAuth2 bearer tokens, with email verification by code, password reset, and in-app password and email change flows.
Verified adult audience. An age check is applied during onboarding, appropriate to a product handling personal relationship data.
Separated administrative access. The back office runs behind its own authentication guard, entirely separate from the member API, with its own account management and password rotation flows.
User-controlled safety actions. Blocking, declining an invitation, removing a partner and deleting the account are all available in-product. Blocking is checked on invitation and re-invitation paths, and the state of a connection is retained at the point it is severed rather than simply erased.
Deletion that actually deletes. Account deletion cascades through the account's own records, detaches it cleanly from the partner's data without destroying the partner's history, anonymises the account's identifiers and revokes the active session token — implemented as a real product flow rather than a support request.
Durable notification records. Every push has a persisted in-app counterpart, so a notification that fails to arrive on a device is still visible in the application.
Storage resilience. Media uploads record their actual destination, so a cloud storage failure degrades to a working local file rather than a broken asset.
Environment separation. Staging and production are deployed as distinct environments through the same automated pipeline, so changes are exercised before release.
Scalability & Performance
A naturally partitioned workload. Almost every query is scoped to a single account or a single pair, with no cross-population fan-out reads. This is the most favourable scaling characteristic a consumer social product can have, and the data model preserves it.
Deliberate indexing. A dedicated set of schema migrations adds indexes across the high-traffic relationships, reflecting explicit query-performance work rather than incidental indexing.
Media served from object storage. User imagery is delivered from cloud object storage rather than through the application tier, keeping image traffic away from application capacity.
Stateless application tier. Token authentication and externalised media storage keep application instances free of local session state, so capacity can be added horizontally.
Background reminder generation. Reminders are produced by scheduled processing rather than computed on request, so reminder volume does not affect user-facing response times.
Client-side state and persistence. Profile and session data are held in the client state store with local persistence, avoiding repeated network round trips as the user moves between screens.
Push rather than polling. Time-sensitive events — invitations, date proposals, acceptances and reminders — are delivered by push notification rather than by the client polling for changes.
Configuration without redeployment. Operational configuration and onboarding copy are held in a runtime settings store, so consumer-facing iteration does not consume release capacity.
Business Outcomes
- The application is useful from the first session, not from the second signup, because the cold-start problem was designed for rather than deferred.
- Invitations survive real-world timing, arriving correctly whether the partner joins before, during or long after the invitation is sent.
- Each partner's profile reflects what they said themselves, with stand-in information superseded once the real person speaks for themselves.
- A couple's shared context lives in one place — profiles, calendar, milestones and plans — rather than in one partner's memory.
- Important dates are remembered automatically, by scheduled reminders that do not depend on anyone opening the app.
- Inspiration converts to a plan in one action, closing the gap where date-idea content usually dies.
- Members control their own safety and their own data, with blocking, declining, unpairing and complete self-service deletion built into the product.
- Content and onboarding copy can be iterated continuously, without a release, which matters disproportionately for a consumer app tuning its first-run experience.
Why it worked
Consumer social products fail for reasons that have very little to do with engineering throughput. They fail because the first user opens the app, finds nothing there until someone else joins, and never comes back. They fail because an invitation arrives in the wrong order and quietly disappears. They fail because the safety controls were left as a support email address, and the first bad experience becomes a review.
Our team builds with those failure modes in mind. We solved the two-sided cold start as a first-class design problem rather than a growth problem, so the product delivers something from the opening session. We made invitation delivery independent of signup timing, because in a product where the second user is one specific person rather than a market, a lost invitation is a lost customer. We made onboarding resumable from the server, because multi-step signup on a phone gets interrupted constantly. And on a product where two identified adults share personal information and plans, we treated blocking, declining, unpairing and full self-service deletion as product features with real data effects — the standard a relationship product should meet, and the standard the app stores now require.
Our teams work across Laravel and modern PHP, REST API design, cross-platform React Native development, cloud storage and media handling, scheduled background processing, push notification architecture and automated deployment — with the product judgement to recognise which constraint in a consumer application is the one that actually decides whether it gets used.
Final Summary
The relationship technology market is crowded at the point of introduction and largely empty afterwards. Once two people are together, the software stops helping — and what remains is a set of small coordination problems that quietly land on one partner: the anniversary nobody wrote down, the "what should we do?" conversation that ends in nothing, the calendar only one person maintains, and the accumulated knowledge of what the other person actually enjoys that lives nowhere but in someone's head.
Our team built a relationship companion application for the couple that already exists. Two people form a private, exclusive connection. Each authors their own profile of interests and preferred expressions of affection, so both are working from what the other actually said. They share a calendar of planned dates that either can propose and the other can accept or decline gracefully. They record the milestones that matter and receive reminders generated in the background, in their own local time. And a curated feed of ideas converts into a real invitation in a single action, which is the difference between a content feature and a used one.
The design problem underneath all of it was the second person. A couples app is worthless with one user, and the second user is not a market — they are one specific individual who may take days to answer. So the product was built to work before they arrive: a stand-in profile makes everything usable from the first session, invitations addressed to people without accounts are held rather than lost, and when the partner does join and confirm, authorship transfers and their own answers take over. Around that sit the controls an intimate product requires — blocking, declining, unpairing and complete self-service deletion, each with real effects on the data. Delivered as a cross-platform mobile application over a REST API with an administrative back office, scheduled reminder processing and an automated staged deployment pipeline.