Inspiration
Relations started from a very simple need: I wanted to remember more about the people I meet.
Traditional contact apps are excellent at storing names, phone numbers and email addresses, but real relationships contain much more context. Who is this person? Where did we meet? What do they do? How are they connected to other people I know? What should I remember the next time we talk?
I wanted to build something that preserved this context without becoming another social network and without requiring users to upload their address book to yet another cloud service.
That led to the core idea behind Relations:
A contact should help you remember a person, not just how to call them.
What it does
Relations extends the traditional contact manager with tools for understanding and maintaining real-world relationships.
One of its core features is a relationship graph that shows how people are connected to each other. Instead of seeing contacts only as an alphabetical list, users can explore relationships visually and understand the wider context around a person.
For professional contacts, Relations can also represent connections as an organizational graph, making it easier to understand roles and relationships inside companies and other organizations.
The app also helps users maintain relationships over time. Contact reminders can be added to selected people, making it possible to remember when it may be worth getting back in touch instead of relying only on memory.
Relations allows users to store additional information that does not normally fit into a standard address book, while keeping regular contact data compatible with the Android contacts ecosystem.
Day-to-day contact management is also designed to be fast. The app provides:
- a quick way to add new people to the address book;
- an alphabetical index for navigating large contact lists;
- multiple filters for narrowing the list to the contacts currently relevant to the user;
- search designed for quickly finding people;
- example contacts that make it possible to explore the application's features without modifying the user's real address book.
Together, these features turn the contact list from a simple collection of names and phone numbers into a more useful map of the people, organizations and relationships around the user.
An important design principle is interoperability. Relations works with contacts already stored on the device rather than forcing users into a separate proprietary address book.
How I built it
I started Relations as a solo project.
Although I already had software development experience, I had never built an Android application before. Developing Relations therefore meant learning modern Android development while simultaneously designing and implementing a real application.
The app is written in Kotlin and built with Jetpack Compose. Its architecture separates UI, domain logic and data access so that individual features can evolve independently as the application grows.
One of the most important parts of the implementation is its integration with Android's Contacts Provider. Relations has to work safely with data that may originate from Google accounts, device storage, SIM cards and other synchronization providers while adding application-specific information without breaking compatibility with other contact apps.
AI coding agents became an important part of the development workflow. I used them to investigate unfamiliar APIs, challenge architectural decisions, explore alternative implementations, review code and tests, and accelerate debugging and refactoring.
They did not replace understanding the platform. Instead, they dramatically shortened the feedback loop between learning something new and applying it in working code.
Challenges I ran into
The biggest technical challenge was the Android contacts data model.
A contact that appears to the user as a single entry may internally consist of multiple raw contacts, data rows and synchronization sources. Individual fields are represented through different MIME types, contacts may be automatically aggregated, and different providers can behave differently.
Safely reading and modifying this data required a much deeper understanding of the Contacts Provider than I originally expected.
The second major challenge came directly from one of the project's core principles: Relations should not require a central backend containing users' address books.
Contact data is unusually sensitive because it contains information not only about the user, but also about many other people. I therefore wanted the application to remain useful without uploading that information to an external service.
The challenge was to extend the existing contacts ecosystem while ensuring that:
- standard contact information remains usable by other applications;
- Relations-specific information does not interfere with normal contact behavior;
- users are not locked into Relations;
- the data model can support additional relationship-oriented features in the future.
Solving this required a careful boundary between interoperable Android contact data and information owned specifically by Relations.
Accomplishments that I'm proud of
The accomplishment I value most is that Relations has gone from an idea and an unfamiliar development platform to a working application built on top of one of Android's more complex system APIs.
The app can use the existing Android address book rather than forcing users into a separate contact database, while still adding functionality that standard contact managers do not provide.
I am also proud that I resisted the temptation to build only a disposable prototype. Relations now has a modular codebase, automated tests, reusable components and a data layer designed to support further development.
Most importantly, the technical architecture supports the original product idea: adding more context to contacts without taking ownership of the user's address book away from the user.
What I learned
Relations became an intensive introduction to modern Android development.
I learned Jetpack Compose, reactive state management, navigation, permissions, lifecycle handling, testing and the practical differences between Android versions.
The Contacts Provider was a learning project of its own. I had to understand how Contacts, RawContacts and Data interact, how Android aggregates contacts from different sources, how contact fields are represented internally, and how modifications can be made without accidentally affecting data owned by another synchronization provider.
But the most important lesson was broader than Android:
the difficult part of a feature is often not what appears on the screen, but how well it integrates with the system around it.
Adding one piece of context to a contact may look trivial in the UI. Doing it properly requires decisions about data ownership, interoperability, migrations, privacy, error handling and future extensibility.
I also learned how useful AI agents can be when working in an unfamiliar technical domain. They were most valuable not as code generators, but as an interactive engineering tool that allowed me to move quickly between documentation, reasoning, implementation, testing and refactoring.
What's next for Relations
The current version establishes the foundation, but the larger idea goes much further.
I want to add more ways of describing relationships between people, better tools for exploring those connections, and features that help users maintain relationships over time rather than simply store contact information.
I also want to expand Relations beyond its initial Android-focused implementation and make it available to a broader international audience.
The long-term vision is for Relations to become more than an alternative contacts app.
I want it to become a private, user-controlled memory layer for the people in your life — helping you remember not only how to contact someone, but who they are, how they are connected, and why they matter.
Built With
- android-studio
- compose
- gradle
- kotlin
Log in or sign up for Devpost to join the conversation.