Mobile App Development with KMP × Unity UaaL ── Multi-Repo Setup and Automation

Hi! We’re the AnotherBall Mobile Engineering Team.

Our app “Avvy” has a somewhat complex architecture: we use KMP (Kotlin Multiplatform) to share business logic across iOS and Android, and Unity as a Library (UaaL) to embed Unity’s 2D avatar rendering into our native apps.

In this article, we’ll share how we coordinate five repositories and how much we’ve automated with GitHub Actions.

Repository Structure

To avoid build complexity and inter-team dependencies, we split our codebase by function into separate repositories.

Repository Role Artifacts
shared-kmm Business logic AAR / XCFramework (KMP library)
unity-module 2D avatar rendering UaaL libraries for Android / iOS
android-app Android app APK / AAB
ios-app iOS app IPA
unity-spm SPM distribution for Unity XCFramework Swift Package

Each repository communicates through pre-built libraries—AAR for Android and XCFramework for iOS. This allows each team to work independently.

What the Unity Module Does

The Unity module handles avatar display and real-time control.

  • Avatar display: Renders avatars with 2D animation
  • Face tracking: Detects facial movements via camera and reflects them on the avatar
  • Customization: Outfit and accessory changes

Communication with native apps requires special handling. Face tracking sends data 60 times per second, so standard bridges would cause latency. On iOS, we use direct pointer access; on Android, we use memory-mapped files for fast data exchange.

How We Automated It

We use GitHub Actions to automate most of the cross-repository coordination. About 1,200 PRs are processed automatically each month (December 2025 figures).

Server API Changes

When the server’s API definition file (OpenAPI) is updated, an update PR is automatically created in the KMP repository.

KMP Library Updates

From KMP library release to update PR creation in each app repository—everything is automated.

The flow is simple: Publish → Trigger → Update.

  1. When a release is triggered in shared-kmm, it publishes to GitHub Packages
  2. On success, gh workflow run triggers the update workflow in each app repository
  3. Each app gets an auto-generated PR with the version update
1
2
3
4
5
6
7
8
9
# On KMP release (excerpt)
- name: Publish to GitHub Packages
run: ./gradlew publish

- name: Trigger Android update
run: |
gh workflow run update-kmm-version.yml \
--repo AnotherBall/android-app \
--field version=${{ env.VERSION }}
1
2
3
4
5
6
7
8
9
10
11
# Android app update workflow (excerpt)
- name: Update version in libs.versions.toml
run: |
sed -i "s/kmm = \".*\"/kmm = \"${{ inputs.version }}\"/" \
gradle/libs.versions.toml

- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
with:
title: "Update KMP to ${{ inputs.version }}"
branch: "auto/kmm-${{ inputs.version }}"

Unity Library Distribution

To use Unity modules in the iOS app, we distribute them via SPM (Swift Package Manager).

  1. Build the Unity XCFramework and upload it to GitHub Releases
  2. Calculate a hash value for the file
  3. Auto-generate Package.swift (embedding the download URL and hash)
  4. Create a PR in the distribution repository (unity-spm)

While we could distribute directly from the unity-module repository, Xcode downloads the entire repository when resolving SPM packages. By creating a separate unity-spm repository that contains only Package.swift, we significantly speed up the download process.

The hash value lets the iOS app verify the file wasn’t corrupted during download.

Auto-Generated Release Branch PRs

When changes are pushed to a release/* branch, multiple merge PRs are automatically created:

  • release/2.10.0main (for production release)
  • release/2.10.0release/2.11.0 (to propagate bug fixes to the next version)

Version numbers are compared to determine the appropriate merge targets, preventing missed merges.

Package.resolved Conflict Resolution (iOS)

When multiple KMM/UaaL update PRs exist simultaneously, Package.resolved file conflicts occur. In the iOS repository, we have a workflow that automatically resolves these conflicts.

Trigger: Push to release/* branch

How it works:

  1. Fetch open PRs targeting the release branch via GitHub API
  2. Filter PRs with titles starting with chore: update KMM or chore: update UaaL
  3. Check if each PR can be merged, and identify those with conflicts
  4. Resolve conflicts for each PR
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Attempt to merge base branch
if git merge "origin/$BASE_REF" --no-edit; then
echo "Merge succeeded"
else
# On conflict: temporarily adopt PR's Package.resolved
git checkout --ours Package.resolved
git add Package.resolved
git merge --continue
fi

# Re-resolve SPM dependencies (incorporates base branch changes)
make resolve-package-dependencies

git commit -m "chore: resolve Package.resolved conflict"
git push

The key is make resolve-package-dependencies (which runs xcodebuild -resolvePackageDependencies internally), re-resolving dependencies including target branch changes. When multiple PRs have conflicts, they’re processed in parallel.

Remaining Challenges

  • CI/CD execution time: Gradle/Xcodebuild can take 40+ minutes; we’re looking into better caching strategies
  • Workflow duplication: Similar logic exists in multiple workflow files; we want to extract it into reusable components
  • Auto-merging update PRs: Currently we only auto-create PRs; we’d like to auto-merge when tests pass

Conclusion

Even with a complex setup combining KMP and Unity UaaL, separating repositories and communicating through artifacts lets each team work independently. We’ve learned that automation isn’t a one-time setup—it requires ongoing improvement.

We’re Hiring

AnotherBall is looking for mobile engineers interested in app development using Kotlin/Swift/Unity/AI!
We’re seeking teammates to grow our product together while adopting new technologies like KMP. If you’re interested, we’d love to hear from you!

Kotlin Fest 2025 Event Report ── AI, KMP, and Developer Experience Frontlines

Hi there!
We’re RIO (@rioX432) and Apippo (@A5th_Faris) from the AnotherBall Mobile Team.

We work on Android/iOS development for Avvy using KMM and Compose Multiplatform. Since we actively use AI for native code development every day, Kotlin Fest 2025 was packed with topics directly relevant to our daily work.

We attended Kotlin Fest 2025 held on November 1, 2025!

This year featured presentations across 3 rooms, recording the highest number of sponsors and talks ever. AnotherBall participated as a Silver Sponsor!

The entire venue was buzzing with excitement—truly a “festival” atmosphere.

What is Kotlin Fest?

Kotlin Fest is Japan’s largest Kotlin community conference, themed around “Celebrating Kotlin,” aimed at sharing knowledge and fostering connections around Kotlin and its ecosystem.

This year’s venue was the Tokyo Conference Center Shinagawa.

The corporate booths and networking spaces after sessions were packed, with conversations buzzing about implementation details and architecture. What stood out most was the clear increase in companies adopting server-side Kotlin.

Beyond Android and KMP, there was a real sense that Kotlin is expanding as a “general-purpose language.”

Session Highlights

Opening Session

“The Role of Kotlin Developers in an Era Where AI Writes Code”
Taro Nagasawa, Atsushi Mori, Eiji Tamaki / Kotlin Fest Organizers

Even in an age where AI writes code, developers remain the “reviewers and decision-makers.”
The session explained why Kotlin is the most suitable language for this era:

  • Simple yet expressive syntax
  • AI-assisted ecosystem through JetBrains IDEs
  • Consistent training data

Not “AI taking our jobs,” but “evolving design together with AI.”
This direction was shared across the entire Kotlin community in the opening.

[Invited Session] The Technology Behind Kotlin: Language Design and Unsung Heroes

Yan Zhulanow / Kotlin Team

The session covered new features in Kotlin 2.3 and the development background of the Build Tools API.

The Build Tools API is particularly relevant for AnotherBall, which uses KMM.
Improvements in per-module incremental builds and KMP support promise significant improvements in build speed and developer experience.

Kotlin’s evolution values “stability and consistency” over “novelty.”

Custom String Interpolation via Kotlin Compiler Plugin

be-hase

A case study on understanding Kotlin Compiler Plugin internals and customizing string interpolation. The code generation mechanism using IR (Intermediate Representation) extension was thoroughly explained. A session that offered perspective from the “extending” side rather than just “using” the language.

At Least Make It Native - Multiplatform and Exit Strategy

RyuNen344

A pragmatic session focused not just on multiplatform adoption, but on how to localize the pain of exit. It covered gradual replacement strategies while considering Swift Export and Kotlin/Native constraints. The philosophy of “don’t adopt all at once, design for clean rollback, especially define clean interfaces” is crucial for hybrid apps like Avvy.

Implementing CPU/GPU “Cooperative” Performance Management in Kotlin

matuyuhi

An explanation of how to safely handle Android Dynamic Performance Framework (ADPF) in Kotlin. Kotlin-like approaches including async data processing with Flow, type-safe design with sealed classes, and DSL-based control. Immediately worth considering for Avvy. Useful not just for thermal management, but also for optimizing face detection inference on low-spec devices.

Inside of Swift Export - A New Bridge Between Kotlin and Swift

giginet

An explanation of how Swift Export enables calling Kotlin code directly from Swift. Without going through the ObjC bridge, the API experience on iOS improves significantly. A meaningful update for both CMP/KMM adoption and exit strategies. While not production-ready yet, we should start preparing for migration from ObjC now.

Rewind & Replay: Kotlin 2.2 Transforms Coroutine Debugging

daasuu

Introduction to debugging improvements in Kotlin 2.2 + IntelliJ IDEA 2025.1. Enhanced local variable retention, stack restoration, and step execution. Definite usability improvements that will gradually boost daily development efficiency.

Building Full Kotlin! MCP Server, AI Agent, and UI All-in-One

Shuzo Takahashi

An introduction to implementing MCP servers, AI agents, and UI entirely in Kotlin using the Kotlin MCP SDK. The presentation included examples of integrating Figma with MCP servers, which was highly inspiring. Worth exploring for Avvy, especially for UI generation assistance and design automation integration.

Getting Started with AI Agent Development Using Koog

hiro

A detailed session on “Koog,” JetBrains’ AI agent construction library. Langfuse integration, DSL construction, parallel execution—enabling serious AI workflow design. This is a topic to tackle immediately.

Shifting to the mindset of “what to make AI do,” we’re thinking about applications from UI code generation assistance to company-wide OKR progress management and PdM decision support.

A Practical Guide to Transforming Legacy Code into Idiomatic Kotlin with AI Collaboration

nishimy432

A presentation on teaching AI “Kotlin-ness” through prompts when converting Java code to Kotlin. The perspective of reflecting team culture in AI—data classes, scope functions, sealed classes, null safety—was impressive. This approach of conveying code style to AI is something AnotherBall can leverage.

Overall Impressions

Kotlin Fest 2025 was structured around three pillars: AI, Multiplatform, and Developer Experience Evolution.

  • Kotlin is becoming the language that drives AI
  • Compose Multiplatform and KMM are becoming “technologies for designing exit strategies”
  • Kotlin development is heading toward “balancing safety and expressiveness”

At AnotherBall, Avvy prioritizes native UIUX optimization while leveraging KMM for shared business logic, along with Unity for FaceTracking—a highly challenging architecture. We’re also actively using AI for native code development, and many of the technologies presented at this conference directly connect to our development work.

We were reminded of the value of an environment where we can tackle the latest architecture with a full Compose setup.

Final Thoughts

Kotlin Fest 2025 was an event that showcased the depth of the Kotlin community. Both speakers and attendees impressed me with their approach of discussing how to use AI and multiplatform “in the real world.” AnotherBall will continue to push forward in the Kotlin × AI space.

Our team at the event

Have a nice Kotlin!

We’re Hiring

AnotherBall is looking for engineers interested in app development using Kotlin/Unity/AI.
We’re seeking teammates to grow our product together while adopting new technologies like KMM and Compose Multiplatform.

AnotherBall Careers

How AI Put Our Company Into BAKUSOKU Mode

Hi, I’m @ramenshim, CTO of AnotherBall.
As we approach the end of the year, I’d like to look back and share how we accelerated our company into “Bakusoku Mode” with AI from April to June.
“Bakusoku” — a Japanese term meaning “explosive speed,” or moving fast and decisively — captures the spirit of how we pushed our organization forward.
We’re a ~30-person team, and before these initiatives only a handful of people used AI. A quick Google Form survey revealed:

  • Some teammates were still on the free tier of ChatGPT.
  • Some had never touched any AI tool besides ChatGPT.

That was a bit of a shock. But it was obvious to us that AI would boost productivity. After we ran a set of company-wide initiatives, people started to say:

  • “I now start work with AI in mind.”
  • “I can tell what AI can and cannot do.”
  • “Let’s try it with AI first.”

This mindset shift was especially impactful for non-engineering roles (marketing, HR, back office, etc.). Here’s exactly what we did.

What We Did to “Bakusoku” the Company

1. Set a slogan — Bakusoku AI 10x

Falling behind on AI is a big risk for a speed-driven startup.
To flip the mood fast, we launched the slogan “Bakusoku AI 10x,” which means “take on challenges 10x faster with AI.” (It’s an homage to Yahoo! JAPAN’s famous “Bakusoku Keiei / Explosive-Speed Management.”)

It might sound like “just a slogan,” but stating it clearly sent a strong message: this isn’t half-hearted; it’s a full-company commitment.

2. Create spaces to talk about AI

Alongside the slogan, we built regular spaces to talk about AI inside our routines: internal lightning talks on good use cases, and hands-on workshops for specific tools.

LTs on AI usage

The most effective was AI Mingle. At morning check-ins, we split into groups of 2–3 and each person shared how they used AI the day before in two minutes. The thought of “I want something to share at AI Mingle” (and “I don’t want to show up empty-handed”) helped people build a daily habit of using AI.

AI Mingle

This tied tightly to the slogan, too. When someone shared a clever use, teammates could say “That’s Bakusoku!” Having a space where that language gets used made the slogan stick.

We also opened a Slack channel, #random-ai-lab, so even remote members could asynchronously share their day-to-day AI usage.

3. Celebrate AI usage

We wanted to praise AI adoption both top-down and peer-to-peer. So leadership picked one post every day to spotlight and celebrate, cheering on AI usage across the org.

Picked posts. We work bilingually in JA/EN.

At the same time, we introduced AI HEROs: anyone who used AI creatively received a “Bakusoku AI 10x” sticker. Because coworkers could give and receive stickers freely, it combined:

  • The experience of being praised (“That workflow is awesome! Very Bakusoku!”)
  • The fun of collecting stickers, almost like a game

It became a neat motivation loop.

4. Solve real workflows together

Some people naturally took off with AI after these steps, but others — like back office or marketing — still struggled to see how to apply it.

So teammates who were strong with AI paired with them to tackle concrete tasks together.

For example, in the Social Media team, planning, outlining, and post-analysis were very person-dependent. We built a Cursor-based workflow together that ran the whole process from ideation to analysis. This cut planning effort and improved analysis depth. It may look scrappy and unscalable, but once one team succeeds, others copy and teach each other — so it was well worth doing.

How we measured it

It’s hard to quantify “AI adoption,” so we set two quarterly goals:

  1. 100% of members publish something AI-related (an LT or a post to #random-ai-lab).
  2. At least 5 posts per day in #random-ai-lab, continuously.

For me, “company-wide AI adoption” means everyone becomes an originator, not just a consumer — that’s why we set #1. And we needed #2 to make sure organic, spontaneous posts kept happening.

We hit both: 150 posts in 20 business days (7.5 per day).

Qualitatively, awareness shifted, too. By the end of the quarter:

  • People started work assuming AI is part of the process.
  • They gained a feel for what AI can and can’t do.
  • “Let’s try it with AI first” became a natural phrase.

Each team is now improving workflows, and AI usage is evolving from individual hacks to a company culture.

Resources we used

This effort was driven by two people — myself and our org development lead — and was only possible because leadership committed and passionate members stepped up. Leaders became the “first dancers” for AI, created “second dancers” via programs and 1:1 support, and the rest naturally followed.

Tools and budget

Here are some tools we currently subsidize for teammates:

  • Canva
  • ChatGPT (Codex)
  • Claude (Claude Code)
  • Cursor
  • Gemini
  • Grok
  • Manus
  • Notion AI

Some were adopted bottom-up. When someone proposes a tool, we subsidize a small pilot for those who want to try it, then roll it out wider if it works — lowering the barrier to experiment. Budgets are case by case; we don’t pre-commit a big pool. We also avoid annual contracts because models and tools evolve so fast.

Wrap-up

AI adoption doesn’t become culture through policies or tools alone.

  1. Set a company-wide slogan.
  2. Create spaces to talk about AI.
  3. Celebrate AI usage.
  4. Tackle real workflows one by one.

By stacking these every day, we steadily moved toward an org where using AI is normal.

Join us

In this post, I shared the initiatives we implemented in the first half of the year to drive AI adoption. I look forward to introducing what we’ve been working on since the summer on another occasion.
AnotherBall is hiring people who want to leverage the latest tech and take Japanese entertainment culture global. We’re actively recruiting — check out our openings and help us build products that win worldwide.
Thanks for reading — brought to you by @ramenshim!