Loris Daniel.

Packly

An AI travel planner designed, built, and shipped solo on Google Play. Less a story of obstacles, more an exercise in doing Android architecture properly, from the first module.

Role Design, development, release

Period 2025 – present

Stack Kotlin · Compose · Hilt · Navigation 3

Live Google Play →

In 30 seconds

Packly plans trips with AI: smart packing lists, generated itineraries, multi-currency expenses. I built it alone, end to end, as a technical exercise taken seriously: a greenfield app structured like the codebase of a large team, with an architecture based on researching what Google itself recommends today. This page walks through that architecture and the reasoning behind it.

What it is, and why it exists

Packly gives each trip three surfaces: a packing list with templates and AI suggestions, an itinerary planned day by day (by hand or generated), and expense tracking with live exchange rates. It is live on Google Play in 10+ languages, with a free tier and a Pro subscription via Play Billing.

It was born as an exercise: I wanted to learn how to integrate AI into an Android project for real, and a greenfield app with no legacy was the chance to apply the current state of the art without compromise. Before writing the first module I researched what Google itself recommends today, taking inspiration from Now in Android, their open-source architecture showcase, and adapting it to this product.

My role

Everything is mine: interface design, development, testing, release, and store management. And precisely because nobody else works on it, the architecture matters more, not less: conventions and module boundaries do the job that a team’s code review would otherwise do.

The architecture

30+ Gradle modules with a strict scoping rule

The app is split into 6+ feature modules (packing list, itinerary, expenses...) and 20+ core modules (UI kit, data, database, network, AI...). Feature modules never depend on each other, and code is promoted to a core module only when at least two features need it. Boundaries stay honest, builds stay parallel, and every piece has one clear home.

Convention plugins: build logic written once

Four custom Gradle plugins (library, compose, hilt, feature) live in build-logic and are applied to every module. Creating a new module takes minutes and zero copy-paste, and a build-configuration change lands everywhere at once. This is what keeps 30+ modules manageable for one person.

One UI paradigm, no exceptions

100% Jetpack Compose with Material 3, and type-safe navigation (Navigation 3 with serializable routes). Each screen is a ViewModel exposing a single immutable UI state via StateFlow, with events flowing one way. No screen deviates from the pattern, so every screen is readable in the same way.

Abstraction where it buys testability

Repositories are internal behind public interfaces, and each Hilt module lives next to the implementation it binds, so features only see contracts. Unit tests use fakes rather than mocking frameworks. One deliberate trade-off: the domain model is the Room entity, zero mapping layers, because in an app this size mappers would be ceremony, not protection.

AI as a replaceable component

Three LLM providers (Anthropic, OpenAI, Google) sit behind a single interface with automatic fallback: if one fails, the next answers. The rest of the app does not know which model is talking. Keys never ship in the APK; they are delivered via Remote Config, gated by Play Integrity.

The numbers

  • 30+ Gradle modules, 6+ feature and 20+ core
  • 4 custom convention plugins in build-logic
  • 100% Jetpack Compose, Material 3
  • 10+ locales on the Play Store, releases via Fastlane
  • Live on Google Play with a real business model (free tier plus Pro subscription). No user numbers here by choice: the app is young, and its value in this portfolio is the engineering.
:appFEATURE MODULES (6+):feature:packlist:feature:itinerary:feature:spendingnever depend on each otherCORE MODULES (20+):core:ui:core:designsystem:core:data:core:database:core:network:core:ai:core:modelpromoted here only if 2+ features need itbuild-logic · 4 convention plugins, applied to every module
The module graph, simplified. Inspired by Google's Now in Android.
Packly home screen with upcoming trips
The "Tell us your vibe" form that drives AI itinerary generation: pace, interests, dislikes, budget
Single day plan with map and AI-suggested stops in New York
Full trip itinerary, day by day
Today dashboard: hotel check-in and check-out, current and next stop, day plan
Smart packing list of the trip
Multi-currency expense tracking

What I learned

Working alone, discipline has to live in the structure, not in memory: conventions, module boundaries, and plugins are what keep the hundredth module as clean as the first.

The exercise paid off beyond the app itself: production-grade patterns for LLM integration (pluggable providers, fallback, secret delivery) and a tested blueprint for greenfield Android that I can defend choice by choice.

← Back to all work