This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
custom-login is a Kotlin Multiplatform (KMP) authentication library targeting Android and iOS. It provides a configurable login UI and auth flows backed by Firebase Authentication (via GitLive SDK). A sample consumer app lives in composeApp/.
Package namespace: com.apptolast.customlogin
# Android
./gradlew :composeApp:assembleDebug
./gradlew :composeApp:installDebug
# Run all tests
./gradlew :custom-login:testDebugUnitTest
# iOS - build Kotlin framework
./gradlew :custom-login:linkDebugFrameworkIosArm64
./gradlew :custom-login:linkDebugFrameworkIosSimulatorArm64
# Then build/run from Xcode in /iosAppcustom-login/ ← Library module (the deliverable)
src/commonMain/ ← Shared code
src/androidMain/ ← Android-specific (Credential Manager, Logger)
src/iosMain/ ← iOS-specific (GoogleSignIn pod, Logger)
composeApp/ ← Sample consumer app
src/androidMain/ ← Android entry (MainActivity, LoginApplication)
src/iosMain/ ← iOS entry (MainViewController)
Every screen uses: XxxAction (sealed interface) + XxxUiState (data class) + XxxEffect (sealed class) + XxxViewModel + XxxScreen.
UiState= persistent state (drives recomposition)Effect= one-time events (navigation, snackbars)Action= all user inputs routed throughviewModel.onAction()
domain/—AuthProviderinterface,AuthRepositoryinterface, domain models (AuthResult,AuthError,Credentials,IdentityProvider, etc.)data/—FirebaseAuthProvider,AuthRepositoryImpldi/— Koin modules:dataModule,presentationModule;KoinInitializer.ktwithLoginLibraryConfigpresentation/— ViewModels, Screens, Slots system
Consumers replace default UI components via AuthScreenSlots which contains per-screen data class with composable lambdas. All submitButton slots have the same signature: (onClick: () -> Unit, isLoading: Boolean, enabled: Boolean, text: String).
Default implementations live in presentation/slots/defaultslots/.
- Kotlin:
initLoginKoin(config: LoginLibraryConfig, appDeclaration?)— call once at app start - Compose:
AuthNavFlow(authSlots, onAuthSuccess)fromRootNavGraph.kt - iOS helper:
GoogleSignInProviderIOS.signInHandlermust be set from Swift
LoginLibraryConfig is registered as a Koin single. If googleSignInConfig != null, GoogleSignInConfig is also registered. AuthRepositoryImpl takes AuthProvider and LoginLibraryConfig.
platform()— platform name stringgetSocialIdToken(provider)— platform-specific OAuth token acquisitionLogger—internal expect object Logger { d(), w(), e() }inutil/
AuthResult—Success(session),Failure(error),RequiresEmailVerification,PasswordResetSent,PasswordResetSuccessAuthError— typed sealed class (InvalidCredentials,UserNotFound,NetworkError, etc.)Credentials—EmailPassword,OAuthToken(provider),RefreshTokenIdentityProvider—Google,Apple,Facebook,GitHub,Phone,Custom
Key methods: signIn(credentials), signUp(data), signOut(), sendPasswordResetEmail(), confirmPasswordReset(), reauthenticate(credentials), getAvailableProviders(), observeAuthState().
Note: signOut(), deleteAccount(), update*(), sendEmailVerification() return Result<Unit>; auth flow methods return AuthResult.
Library strings live in custom-login/src/commonMain/composeResources/values/strings.xml. Validation message strings (validation_*) are defined there as a foundation for localization, though ViewModels currently use hardcoded English equivalents.