Skip to content

danielpassos/unveil

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Unveil

The hidden side of your app, one swipe away.


Build Maven Central KMP Compose License


Why Unveil

Every app has two faces.

The one your users see — polished, intentional, pixel-perfect. And the one underneath — network calls, logs, flags, navigation, state.

That second face is where bugs live. That second face is what QA sees. That second face is what you debug every day.

Unveil makes it visible.

A single swipe. Everything is there.

And when you're done — it's gone.


✨ What You Get

  • 💥 Trigger crashes on demand
  • 📱 Device and environment info
  • 📋 Stream and filter logs
  • 🧭 Visualize navigation state
  • 🌐 Inspect network requests in real time

All inside your app. No external tools. No rebuilds.


⚡ Quick Start

Unveil.configure {
    register(NetworkPlugin(...))
    register(LogPlugin(...))
}

if (BuildConfig.DEBUG) Unveil.enable()

@Composable
fun App() {
    UnveilHost(enabled = Unveil.isEnabled) {
        AppNavHost()
    }
}

That’s it.


🧩 Plugin System

Unveil is not a tool.

It’s a platform for tools.

Everything is a plugin.

Unveil.configure {
    register(NetworkPlugin(...))
    register(LogPlugin(...))
}

And when you need flexibility:

Unveil.register(SomePlugin())

No coupling. No assumptions. Just composition.


🏗 Architecture

  • Zero impact on your app UnveilHost wraps your UI. Nothing else changes.

  • Zero overhead when disabled No UI. No gestures. No background work.

  • Zero dependency on your stack No Material. No DI. No navigation library.

  • Fully modular Core knows nothing about features.


📦 Installation

Unveil is modular.

Start with the core, then add only the plugins you need.


Core

[versions]
unveil = "current_version"

[libraries]
unveil-core = { module = "me.passos.libs.unveil:unveil-core", version.ref = "unveil" }
commonMain.dependencies {
    implementation(libs.unveil.core)
}

Add plugins

Pick the features you need:

unveil-crash  = { module = "me.passos.libs.unveil:unveil-crash", version.ref = "unveil" }
unveil-deviceinfo = { module = "me.passos.libs.unveil:unveil-deviceinfo", version.ref = "unveil" }
unveil-logs = { module = "me.passos.libs.unveil:unveil-logs", version.ref = "unveil" }
unveil-navigation = { module = "me.passos.libs.unveil:unveil-navigation", version.ref = "unveil" }
unveil-network = { module = "me.passos.libs.unveil:unveil-network", version.ref = "unveil" }
commonMain.dependencies {
    implementation(libs.unveil.logs)
    implementation(libs.unveil.network)
}

Add adapters

Adapters connect Unveil to your stack:

unveil-logs-kermit = { module = "me.passos.libs.unveil:unveil-logs-kermit", version.ref = "unveil" }
unveil-network-ktor = { module = "me.passos.libs.unveil:unveil-network-ktor", version.ref = "unveil" }
unveil-navigation-compose  = { module = "me.passos.libs.unveil:unveil-navigation-compose", version.ref = "unveil" }

Full setup (copy & paste)

Want everything?

unveil-core = { module = "me.passos.libs.unveil:unveil-core", version.ref = "unveil" }

unveil-crash = { module = "me.passos.libs.unveil:unveil-crash", version.ref = "unveil" }
unveil-deviceinfo = { module = "me.passos.libs.unveil:unveil-deviceinfo", version.ref = "unveil" }

unveil-logs = { module = "me.passos.libs.unveil:unveil-logs", version.ref = "unveil" }
unveil-logs-kermit = { module = "me.passos.libs.unveil:unveil-logs-kermit", version.ref = "unveil" }

unveil-navigation = { module = "me.passos.libs.unveil:unveil-navigation", version.ref = "unveil" }
unveil-navigation-compose = { module = "me.passos.libs.unveil:unveil-navigation-compose", version.ref = "unveil" }

unveil-network = { module = "me.passos.libs.unveil:unveil-network", version.ref = "unveil" }
unveil-network-ktor = { module = "me.passos.libs.unveil:unveil-network-ktor", version.ref = "unveil" }

Available modules

Category Modules
Core unveil-core
Crash unveil-crash
Device unveil-deviceinfo
Logs unveil-logs, unveil-logs-kermit
Navigation unveil-navigation, unveil-navigation-compose
Network unveil-network, unveil-network-ktor

Requirements

unveil-core requires:

  • compose.ui
  • compose.animation
  • compose.material3
  • androidx.activity:activity-compose (Android only)

🧪 Example Plugin

class MyPlugin : UnveilPlugin {
    override val id = "my_plugin"
    override val title = "My Plugin"
    override val icon = UnveilIcon.Emoji("🔧")

    @Composable
    override fun Content(scope: UnveilPanelScope) {
        // Build anything you want
    }
}

🔌 Adapters

Unveil is stack-agnostic.

Each integration point is defined as an interface. You can use a built-in adapter or provide your own implementation.

Built-in adapters

Integration Interface Adapter
Logs LogSink Kermit
Network NetworkInterceptor Ktor
Navigation NavigationObserver Compose Navigation

Using OkHttp? Timber? Voyager? Implement the interface — it’s a handful of methods.


📱 Platforms

Platform Support
Android
iOS
Desktop 🔲

🧠 Philosophy

Unveil is not a debug panel.

It’s observability inside your UI.


📄 License

Apache 2.0

About

Unveil is a developer panel for Kotlin Multiplatform apps. Swipe right to left, and see everything your app is doing under the hood

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors