🚀. Socket Launch Week Day 3:Socket Firewall Now Blocks Malicious VS Code and Open VSX Extensions.Learn more
Sign In

android-pro-max-cli

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

android-pro-max-cli - npm Package Compare versions

Comparing version
1.0.1
to
1.1.0
+18
assets/data/accessibility.csv
Category,Issue,Keywords,Platform,Description,Do,Don't,Code Example Good,Code Example Bad,Severity
Touch,Touch Target Size,tap target 48dp button,Android,"Interactive elements must be at least 48x48dp for comfortable tapping.","Use Modifier.size(48.dp) or Modifier.sizeIn(minWidth = 48.dp, minHeight = 48.dp).","Use small icons without padding as touch targets.","IconButton(modifier = Modifier.size(48.dp)) { Icon(...) }","Icon(modifier = Modifier.size(16.dp).clickable { }) // Too small!",CRITICAL
Semantics,Content Description,contentDescription talkback image,Android,"All meaningful images and icons must have contentDescription for screen readers.","Provide descriptive contentDescription. Use null for decorative images.","Leave contentDescription empty string or missing for meaningful icons.","Icon(Icons.Default.Close, contentDescription = ""Close dialog"")","Icon(Icons.Default.Close, contentDescription = """") // Empty!",CRITICAL
Semantics,Heading Structure,heading semantics section,Android,"Section headings should be marked with heading semantics for navigation.","Use Modifier.semantics { heading() } on section titles.","Use Text without heading semantics for section titles.","Text(""Settings"", Modifier.semantics { heading() })","Text(""Settings"") // No heading semantics",HIGH
Semantics,Custom Actions,actions semantics swipe,Android,"Complex gestures should have semantic alternatives for accessibility.","Add custom actions via Modifier.semantics { customActions = listOf(...) }.","Require swipe/long-press without accessible alternative.","Modifier.semantics { customActions = listOf(CustomAccessibilityAction(""Delete"") { delete(); true }) }","// Swipe-only delete with no accessible alternative",HIGH
Color,Contrast Ratio,contrast wcag color text,Android,"Text must have at least 4.5:1 contrast ratio (3:1 for large text) against background.","Test contrast with Accessibility Scanner. Use MaterialTheme color roles.","Use light gray text on white background.","Text(color = MaterialTheme.colorScheme.onSurface) // High contrast","Text(color = Color(0xFFCCCCCC)) // Low contrast on white",CRITICAL
Color,Color Alone,color blind indicator status,Android,"Don't convey information through color alone - use icons/text too.","Use icon + color + text for status indicators.","Use only red/green to indicate error/success.","Row { Icon(if (ok) Check else Error); Text(if (ok) ""Valid"" else ""Invalid"") }","Box(Modifier.background(if (ok) Green else Red)) // Color only!",HIGH
Font,Font Scaling,font scale sp accessibility,Android,"App must be usable when system font scale is increased to 200%.","Use sp for text sizes. Test with large font settings. Avoid fixed height containers.","Use dp for text sizes or constrain text containers with fixed height.","Text(style = MaterialTheme.typography.bodyMedium) // Uses sp internally","Text(fontSize = 14.dp.value.sp) // Wrong unit conversion",HIGH
Focus,Focus Order,focus tab sequence navigation,Android,"Focus navigation must follow logical reading order.","Use Modifier.focusOrder or Modifier.semantics { traversalIndex } for custom order.","Leave focus order to default when it doesn't match visual layout.","Modifier.semantics { traversalIndex = 1f }","// No focus order customization when layout is complex",MEDIUM
State,State Description,stateDescription toggle switch,Android,"Toggle states must be announced by screen reader.","Set stateDescription for custom toggleable components.","Use custom toggle without accessibility state.","Modifier.semantics { stateDescription = if (enabled) ""On"" else ""Off"" }","// Custom toggle with no state announcement",HIGH
Motion,Reduced Motion,animation motion preference,Android,"Respect user's reduced motion preference.","Check LocalReduceMotion or provide option to disable animations.","Use heavy animations without motion preference check.","if (!LocalReduceMotion.current.enabled()) { AnimatedVisibility(...) }","AnimatedVisibility(...) // Ignores reduced motion preference",MEDIUM
Screen,Screen Reader Testing,talkback test verify,Android,"All screens must be tested with TalkBack enabled.","Run TalkBack on every new screen. Verify reading order and descriptions.","Ship without TalkBack testing.","// Manual: Settings > Accessibility > TalkBack > Test your app","// Skip TalkBack testing entirely",CRITICAL
Gestures,Gesture Alternatives,gesture alternative button,Android,"All gesture-based actions must have a non-gesture alternative.","Provide menu items or buttons as alternatives to swipes and long-press.","Make swipe-to-delete the only way to delete.","SwipeToDismiss(...) + ContextMenu with Delete option","SwipeToDismiss(...) // Only way to delete item",HIGH
Navigation,Skip Navigation,skip link navigation jump main content,Android,"Allow screen reader users to jump to main content quickly.","Add traversal index to main content area for priority focus.","Start focus on decorative header elements.","Modifier.semantics { traversalIndex = -1f } // Main content first","// No traversal customization, reads header decorations first",MEDIUM
Forms,Error Announcement,error announce form validation live region,Android,"Screen reader must announce form errors when they appear.","Use LiveRegion semantics to announce errors automatically.","Only show visual error without screen reader announcement.","Modifier.semantics { liveRegion = LiveRegionMode.Polite }","// Error text appears but is never announced",HIGH
Touch,Spacing Between Targets,spacing gap touch separate adjacent,Android,"Adjacent interactive elements must have sufficient spacing.","Add at least 8dp spacing between adjacent touch targets.","Place buttons edge-to-edge without spacing.","Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { Button() Button() }","Row { Button(); Button() } // No spacing between targets",MEDIUM
Lists,List Announcements,list count position announce spoken,Android,"Screen reader should announce list item position and total count.","Use LazyColumn with semantics for collection info.","Custom scrollable without collection semantics.","Modifier.semantics { collectionInfo = CollectionInfo(rowCount = items.size, columnCount = 1) }","// Custom scroll with no collection info",MEDIUM
Text,Text Selection,selectable copy text paragraph accessible,Android,"Long-form text should be selectable for copy/paste.","Wrap text content in SelectionContainer.","Use non-selectable Text for article body.","SelectionContainer { Text(articleContent) }","Text(articleContent) // Not selectable",LOW
path_pattern,layer,responsibility_description,allowed_dependencies,tech_stack_note
feature/*/presentation/,Presentation,"Screens, ViewModels, UI state, navigation events. Composable functions and UI-related models.",Domain layer only (via UseCase/Repository interface),Use StateFlow for state and Channel for one-shot events
feature/*/domain/,Domain,"Business rules, use cases, domain models. Platform-agnostic. No Android imports.",Nothing (pure Kotlin),Keep use cases thin - single responsibility
feature/*/data/,Data,"Repositories implementation, data sources, DTOs, mappers, API services.",Domain layer (implements interfaces),Map DTOs to domain models at repository boundary
feature/*/data/remote/,Data - Remote,"API services, remote data sources, network DTOs.",OkHttp/Retrofit/Ktor + Domain interfaces,Use suspend functions for all network calls
feature/*/data/local/,Data - Local,"Room DAOs, DataStore, local data sources, cached entities.",Room/DataStore + Domain interfaces,Use Flow for reactive local queries
feature/*/data/mapper/,Data - Mapper,"DTO-to-Entity and Entity-to-Domain mappers.",Domain models + Data DTOs,Keep mappers as extension functions
core/ui/,Core - UI,"Shared composables, theme, design tokens, reusable components.",Compose + Material 3,All composables should be @Preview-able
core/util/,Core - Utility,"Extension functions, date/string formatters, constants.",Pure Kotlin (no Android framework),Keep utilities pure and testable
core/network/,Core - Network,"HTTP client setup, interceptors, base API config.",OkHttp/Retrofit,Auth interceptor + logging interceptor here
core/di/,Core - DI,"Hilt modules, provides, bindings for shared dependencies.",Hilt/Koin,SingletonComponent for app-wide deps
core/navigation/,Core - Navigation,"Route definitions, shared navigation utilities.",Navigation Compose,Define routes as sealed class or enum
core/testing/,Core - Testing,"Shared test utilities, fakes, fixtures.",JUnit + MockK/Mockito,Provide fake repositories and test data factories
app/,App,"Application class, main activity, app-level DI setup.",All layers (composition root),Keep thin - just wiring
buildSrc/ or build-logic/,Build,"Gradle convention plugins, version catalogs, dependency management.",Gradle API only,Use version catalog (libs.versions.toml)
Data Type,Keywords,Best Chart Type,Secondary Options,Color Guidance,Accessibility Notes,Library Recommendation
Time Series,trend over time progress historical daily monthly,Line Chart,"Area Chart, Step Line","Blue primary line, gray secondary, green positive trend, red negative","Label axes clearly. Use markers at key data points.",MPAndroidChart or Vico
Comparison,compare bar versus rank category segment,Bar Chart (Vertical),"Horizontal Bar, Grouped Bar","Distinct hues per category. Max 6-7 colors. Gray for inactive.",Add value labels on bars. Color-blind safe palette required.,MPAndroidChart or Vico
Composition,part of whole percentage distribution breakdown,Pie Chart,"Donut Chart, Treemap","Max 5-6 slices. Use sequential palette. 'Other' slice for small values.",Add labels with percentages. Avoid 3D. Don't start at random angles.,MPAndroidChart
Distribution,spread histogram range frequency density,Histogram,"Box Plot, Violin","Sequential single-hue palette for bins.",Annotate mean/median lines. Label bin ranges.,MPAndroidChart
Flow/Process,funnel conversion pipeline stage step,Funnel Chart,"Sankey Diagram, Stacked Bar","Gradient from dark (top) to light (bottom). Highlight drop-off.",Show conversion rates between stages. Label absolute numbers.,Custom Compose Canvas
Relationship,correlation scatter bubble network connected,Scatter Plot,"Bubble Chart, Heatmap","Distinguish groups by color. Use opacity for density.",Provide tooltip on tap. Accessible descriptions for clusters.,MPAndroidChart
Hierarchy,org tree nested parent child structure,Tree Map,"Sunburst, Indented List","Size = value. Color = category or performance.","Ensure labels are readable at small sizes. Tap to drill down.",Custom Compose or D3 WebView
Geographic,map location region country heat spatial,Map with Overlay,"Choropleth Map, Dot Map","Sequential palette for intensity. Red = high.",Provide list alternative for non-visual access. Clear legend.,Google Maps SDK
Real-time/Live,live updating streaming ticker dashboard,Gauge / Sparkline,"Live Line Chart, Number Card","Green = good, yellow = warn, red = critical. Contextual colors.","Announce significant changes via accessibility. Update rate <= 1/sec.",Custom Compose Canvas
Goal/Progress,target KPI metric achievement completion,Progress Bar / Ring,"Bullet Chart, KPI Card","Progress color toward goal. Gray for remaining.",Show numeric value alongside visual. Announce completion.,Compose Canvas or Material3 indicators
Ranking,top leaderboard sorted ordered list,Horizontal Bar Chart,"Numbered List, Medal Card","Gold/Silver/Bronze for top 3. Sequential for rest.",Number each item. Show value alongside bar.,Vico or Custom Compose
Multi-dimensional,multi-axis radar spider complex metrics,Radar / Spider Chart,"Parallel Coordinates, Small Multiples","Distinct stroke colors per entity. Semi-transparent fills.",Max 5-6 axes. Label each axis. Provide data table fallback.,Custom Compose Canvas
Calendar,schedule events heat calendar daily weekly,Calendar Heatmap,"Timeline, Event List","Intensity palette (light = few, dark = many).",Provide list view alternative. Label each cell value on tap.,Custom Compose or Kizitonwose Calendar
Before/After,change improvement decrease increase delta,Waterfall Chart,"Butterfly Chart, Paired Bar","Green for increase, red for decrease, gray for subtotal.",Label each step with value. Show running total.,MPAndroidChart or Custom Canvas
Survey/Likert,survey opinion scale agree rating response,Stacked Bar Chart,"Horizontal Diverging Bar, Pie","Diverging palette centered on neutral. Strong agree/disagree at ends.",Center on neutral response. Show response counts.,MPAndroidChart
Budget/Financial,budget allocation spend revenue income expense,Treemap,"Sunburst, Stacked Area","Category-based hue grouping. Size = amount. Intensity = trend.",Allow drill-down into subcategories. Show percentages.,Custom Compose Canvas
Network/Relationship,network graph connection node edge social,Force-Directed Graph,"Arc Diagram, Matrix","Node color by group. Edge weight by connection strength.",Interactive zoom and pan. Tap node for details.,Custom Canvas or D3 WebView
Progress/Milestone,milestone progress roadmap checkpoint timeline,Timeline Chart,"Gantt Chart, Horizontal Progress","Completed = green, current = blue, upcoming = gray.",Animate progress fill. Show current position indicator.,Custom Compose Canvas
Correlation Matrix,correlation matrix heatmap multi-variable,Heatmap,"Bubble Matrix, Scatter Matrix","Sequential diverging palette: blue (neg) → white → red (pos).",Show values on hover/tap. Clear axis labels.,Custom Compose Canvas
Stock/Financial,stock candlestick ohlc price trading volume,Candlestick Chart,"OHLC Bar, Line with Volume","Green for up candle, red for down candle. Volume bars below.",Show volume below price. Add moving averages.,MPAndroidChart or TradingView
Gauge/Speedometer,gauge meter speed dial indicator,Gauge Chart,"Radial Progress, Semicircle","Green/yellow/red zones for thresholds.",Animate needle movement. Show numeric value at center.,Custom Compose Canvas
Product Type,Keywords,Primary (Hex),Secondary (Hex),CTA (Hex),Notes
Fintech/Banking,trust finance secure professional,#1E3A5F,#2E86AB,#FF8C42,"High contrast, trust blue palette. Avoid bright colors for financial data."
E-Commerce,shop cart buy product retail,#FF6B35,#004E89,#F7C948,"Warm CTA colors drive purchase. Use accent sparingly for deals/sales."
Healthcare/Medical,health doctor appointment care,#065F5B,#5DB075,#FF6B6B,"Calming greens and teals. Red only for urgent/alert states."
Fitness/Wellness,gym workout track progress health,#FF4500,#1DB954,#FFD700,"Energetic palette. High-contrast for workout metrics. Dark backgrounds."
Social Media,social feed chat connect share,#6366F1,#EC4899,#10B981,"Vibrant gradients. Signature brand color needed. Dark mode priority."
Education/Learning,learn course student study school,#4F46E5,#7C3AED,#F59E0B,"Focused blues/purples. Yellow accents for achievements/progress."
Food Delivery,food order restaurant delivery,#E63946,#FF9F1C,#2EC4B2,"Appetite-stimulating warm colors. Green for confirmation/success."
Travel/Booking,travel hotel flight book destination,#0077B6,#00B4D8,#FF9F43,"Sky blues inspire wanderlust. Orange CTA for booking urgency."
Productivity/Tools,task todo organize plan manage,#3B82F6,#6366F1,#10B981,"Clean blues. Minimal palette. Success green for completed tasks."
Gaming/Entertainment,game play score fun achievement,#8B5CF6,#EC4899,#FBBF24,"Bold neon accents on dark. Gradients for energy. Gold for rewards."
News/Media,news article read inform content,#1E293B,#64748B,#EF4444,"Minimal color. Red for breaking. Content readability is priority."
SaaS/Dashboard,dashboard analytics metrics data,#0F172A,#3B82F6,#22C55E,"Dark mode default. Blue for data visualization. Green for positive KPIs."
Kids/Family,kids children family fun colorful,#FF6B6B,#4ECDC4,#FFE66D,"Bright playful colors. Large touch targets. High contrast required."
Real Estate,property home rent buy listing,#1B4332,#2D6A4F,#D4A373,"Earthy sophisticated tones. Warm accents for CTA. Trust-building palette."
Music/Audio,music listen playlist audio stream,#1DB954,#191414,#B3B3B3,"Spotify-inspired. Dark backgrounds. Accent for playback controls."
Crypto/Web3,blockchain crypto defi token wallet,#6B5CE7,#00D2FF,#FFD700,"Purple/blue gradients for trust+innovation. Gold for token value."
Meditation/Mindfulness,calm zen breathe relax peaceful,#2D3748,#667EEA,#48BB78,"Deep calm blues. Muted green for nature. Dark for nighttime use."
Dating/Social,love match connect heart romance,#FF6B6B,#EE5A24,#4834D4,"Warm reds/pinks for passion. Purple for premium. Gradient CTAs."
Legal/Government,law court official formal government,#1A365D,#4A5568,#C53030,"Conservative navy. Formal gray. Red only for alerts/warnings."
Photography/Art,creative gallery portfolio visual image,#0D0D0D,#F7FAFC,#E53E3E,"Near-black bg for galleries. White for content. Red accent minimal."
Logistics/Delivery,shipping track package fleet route,#FF6600,#003366,#00CC66,"Orange for urgency/tracking. Navy for reliability. Green for delivered."
Agriculture/Farm,farm crop organic natural harvest,#2F855A,#744210,#F6E05E,"Earthy greens and browns. Yellow for harvest/sunlight. Natural palette."
Pet/Animal,pet dog cat vet animal care,#F6AD55,#4FD1C5,#FC8181,"Warm orange for friendly. Teal for vet/health. Coral for alerts."
Automotive,car vehicle auto dealer motor,#1A202C,#E53E3E,#EDF2F7,"Dark sophistication. Red for performance/sport. Silver for premium."
Construction/Home,build property renovation contractor remodel,#D69E2E,#2D3748,#E53E3E,"Hard hat yellow. Dark steel gray. Safety red for warnings."
Insurance,policy claim coverage premium plan,#2B6CB0,#276749,#C05621,"Blue for trust. Green for coverage/positivity. Orange for CTA."
Sustainability/Green,eco green recycle carbon environment,#276749,#2F855A,#48BB78,"Multiple greens. Leaf to forest gradient. Avoid greenwashing cliches."
Wedding/Events,wedding event party celebration ceremony,#D4A843,#FFF5F5,#E8D5B1,"Gold for luxury. Blush pink bg. Cream accents. Elegant palette."
Sport/Betting,sport bet odds score live match,#1A202C,#48BB78,#F6E05E,"Dark bg for immersive. Green for winning. Gold for odds/premium."
Pharmacy/Medical Supply,medicine drug prescription rx,#FFFFFF,#38A169,#E53E3E,"Clean white clinical. Green for pharmacy brand. Red for prescription alerts."
Education Kids,school children learning abc game,#4299E1,#48BB78,#F6E05E,"Primary blue. Success green. Achievement gold. Large clear colors."
IoT/Smart Home,smart home device iot connected sensor,#2D3748,#63B3ED,#9F7AEA,"Dark control panel. Blue for connectivity. Purple for automation."
Music Production,studio mixing daw audio production,#0D0D0D,#6B46C1,#48BB78,"Pure dark for studio feel. Purple for creative. Green for levels."
Streaming Video,video stream watch series movie,#0D0D0D,#E53E3E,#FFFFFF,"Dark immersive. Red for brand (Netflix-style). White text on dark."
Charity/Non-profit,donate give help volunteer support,#F6AD55,#4299E1,#48BB78,"Warm orange for generosity. Trust blue. Green for impact/growth."
Ride Sharing,ride taxi uber driver passenger route,#000000,#00B14F,#FF5722,"Black brand + green action. Orange for surge/premium pricing."
Grocery Delivery,grocery fresh organic delivery produce,#27AE60,#FFFFFF,#FF6B2B,"Fresh greens dominate. White clean bg. Orange for deals."
Task Management,task productivity kanban sprint todo,#6366F1,#F1F5F9,#10B981,"Indigo focus + light bg + green completion."
Weather,weather forecast sky rain sun temperature,#667EEA,#F7FAFC,#F6AD55,"Sky gradient blue + clean bg + warm sun accents."
Calendar/Scheduling,calendar event meeting schedule booking,#3B82F6,#FFFFFF,#EF4444,"Blue events + white bg + red urgent/deadline."
Notes/Writing,notes journal diary writing text editor,#FFF8E7,#1E293B,#6B7280,"Warm paper bg + dark text + subtle gray UI."
Social Commerce,social selling influencer live stream shop,#FF2D55,#7C3AED,#FFD700,"Hot pink + purple premium + gold deals."
Language Learning,language vocabulary grammar quiz progress,#8B5CF6,#10B981,#FBBF24,"Purple learning + green progress + gold achievement."
Home Automation,home iot smart device control sensor,#1E293B,#3B82F6,#22C55E,"Dark control panel + blue connected + green active."
Budgeting/Finance Personal,budget expense income savings tracker,#EF4444,#22C55E,#3B82F6,"Red expenses + green income + blue goals."
Recipe/Cooking,recipe cook ingredient meal step timer,#E85D04,#2D6A4F,#FEFCE8,"Warm appetizing orange + herb green + cream bg."
Parking/EV,parking spot charge ev station map,#3B82F6,#22C55E,#EF4444,"Blue navigation + green available + red occupied."
Telemedicine,telehealth doctor video call health remote,#0EA5E9,#10B981,#F3F4F6,"Trust blue + available green + clean gray bg."
Auction/Marketplace,auction bid listing sell marketplace,#F59E0B,#22C55E,#EF4444,"Bid gold + winning green + ending red urgency."
CRM/Sales,crm pipeline deal lead sales forecast,#1E40AF,#059669,#6B7280,"Deep blue stages + won green + neutral pipeline."
Category,Icon Name,Keywords,Library,Import Code,Usage,Best For
Navigation,arrow_back,back return previous navigate,Material Icons,"import androidx.compose.material.icons.Icons; import androidx.compose.material.icons.filled.ArrowBack","Icon(Icons.Default.ArrowBack, contentDescription = ""Back"")","TopAppBar navigation icon"
Navigation,menu,hamburger sidebar drawer,Material Icons,"import androidx.compose.material.icons.filled.Menu","Icon(Icons.Default.Menu, contentDescription = ""Open menu"")","Navigation drawer toggle"
Navigation,close,dismiss cancel exit,Material Icons,"import androidx.compose.material.icons.filled.Close","Icon(Icons.Default.Close, contentDescription = ""Close"")","Dialog/bottom sheet dismiss"
Navigation,home,main start landing,Material Icons,"import androidx.compose.material.icons.filled.Home","Icon(Icons.Default.Home, contentDescription = ""Home"")","Bottom navigation home tab"
Action,add,create new plus,Material Icons,"import androidx.compose.material.icons.filled.Add","Icon(Icons.Default.Add, contentDescription = ""Add"")","FAB primary action"
Action,search,find filter query,Material Icons,"import androidx.compose.material.icons.filled.Search","Icon(Icons.Default.Search, contentDescription = ""Search"")","Search bar, toolbar action"
Action,share,send distribute,Material Icons,"import androidx.compose.material.icons.filled.Share","Icon(Icons.Default.Share, contentDescription = ""Share"")","Content sharing action"
Action,delete,remove trash discard,Material Icons,"import androidx.compose.material.icons.filled.Delete","Icon(Icons.Default.Delete, contentDescription = ""Delete"")","Destructive action (use with confirmation)"
Action,edit,modify change update,Material Icons,"import androidx.compose.material.icons.filled.Edit","Icon(Icons.Default.Edit, contentDescription = ""Edit"")","Edit mode toggle"
Status,check_circle,success done complete,Material Icons,"import androidx.compose.material.icons.filled.CheckCircle","Icon(Icons.Default.CheckCircle, contentDescription = ""Complete"")","Success state, completed items"
Status,error,fail warning problem,Material Icons,"import androidx.compose.material.icons.filled.Error","Icon(Icons.Default.Error, contentDescription = ""Error"")","Error states, validation failure"
Status,info,help about detail,Material Icons,"import androidx.compose.material.icons.filled.Info","Icon(Icons.Default.Info, contentDescription = ""Information"")","Tooltips, help sections"
Status,notifications,alert badge bell,Material Icons,"import androidx.compose.material.icons.filled.Notifications","Icon(Icons.Default.Notifications, contentDescription = ""Notifications"")","Notification bell, badge indicator"
Content,person,user profile account,Material Icons,"import androidx.compose.material.icons.filled.Person","Icon(Icons.Default.Person, contentDescription = ""Profile"")","User avatar placeholder, profile tab"
Content,favorite,like heart save,Material Icons,"import androidx.compose.material.icons.filled.Favorite","Icon(Icons.Default.Favorite, contentDescription = ""Favorite"")","Like/save toggle action"
Content,star,rating review rank,Material Icons,"import androidx.compose.material.icons.filled.Star","Icon(Icons.Default.Star, contentDescription = ""Rating"")","Rating display, reviews"
Content,settings,preferences config gear,Material Icons,"import androidx.compose.material.icons.filled.Settings","Icon(Icons.Default.Settings, contentDescription = ""Settings"")","Settings screen access"
Content,camera,photo capture picture shoot,Material Icons,"import androidx.compose.material.icons.filled.CameraAlt","Icon(Icons.Default.CameraAlt, contentDescription = ""Camera"")","Camera capture action"
Content,image,photo gallery picture,Material Icons,"import androidx.compose.material.icons.filled.Image","Icon(Icons.Default.Image, contentDescription = ""Image"")","Gallery/photo display"
Content,attach_file,attachment file upload clip,Material Icons,"import androidx.compose.material.icons.filled.AttachFile","Icon(Icons.Default.AttachFile, contentDescription = ""Attach file"")","File attachment in forms/chat"
Content,download,save file export,Material Icons,"import androidx.compose.material.icons.filled.Download","Icon(Icons.Default.Download, contentDescription = ""Download"")","Download action"
Content,upload,send file import,Material Icons,"import androidx.compose.material.icons.filled.Upload","Icon(Icons.Default.Upload, contentDescription = ""Upload"")","File upload action"
Communication,email,mail message envelope send,Material Icons,"import androidx.compose.material.icons.filled.Email","Icon(Icons.Default.Email, contentDescription = ""Email"")","Email/messaging feature"
Communication,chat,message conversation bubble,Material Icons,"import androidx.compose.material.icons.filled.Chat","Icon(Icons.Default.Chat, contentDescription = ""Chat"")","Chat/messaging feature"
Communication,call,phone telephone ring,Material Icons,"import androidx.compose.material.icons.filled.Call","Icon(Icons.Default.Call, contentDescription = ""Call"")","Phone call action"
Communication,send,submit message deliver arrow,Material Icons,"import androidx.compose.material.icons.filled.Send","Icon(Icons.Default.Send, contentDescription = ""Send"")","Submit/send message"
Location,location_on,map pin gps place,Material Icons,"import androidx.compose.material.icons.filled.LocationOn","Icon(Icons.Default.LocationOn, contentDescription = ""Location"")","Location marker"
Location,my_location,current position gps,Material Icons,"import androidx.compose.material.icons.filled.MyLocation","Icon(Icons.Default.MyLocation, contentDescription = ""My location"")","Current location button"
Location,explore,compass direction navigation,Material Icons,"import androidx.compose.material.icons.filled.Explore","Icon(Icons.Default.Explore, contentDescription = ""Explore"")","Explore/discover tab"
Time,schedule,time clock alarm appointment,Material Icons,"import androidx.compose.material.icons.filled.Schedule","Icon(Icons.Default.Schedule, contentDescription = ""Schedule"")","Time/appointment display"
Time,calendar_today,date event day month,Material Icons,"import androidx.compose.material.icons.filled.CalendarToday","Icon(Icons.Default.CalendarToday, contentDescription = ""Calendar"")","Date selector/calendar"
Time,timer,countdown stopwatch duration,Material Icons,"import androidx.compose.material.icons.filled.Timer","Icon(Icons.Default.Timer, contentDescription = ""Timer"")","Timer/countdown"
Commerce,shopping_cart,cart buy purchase checkout,Material Icons,"import androidx.compose.material.icons.filled.ShoppingCart","Icon(Icons.Default.ShoppingCart, contentDescription = ""Cart"")","Shopping cart indicator"
Commerce,payments,money credit card payment,Material Icons,"import androidx.compose.material.icons.filled.Payments","Icon(Icons.Default.Payments, contentDescription = ""Payment"")","Payment/checkout action"
Security,lock,secure private protected password,Material Icons,"import androidx.compose.material.icons.filled.Lock","Icon(Icons.Default.Lock, contentDescription = ""Locked"")","Security/privacy indicator"
Security,visibility,show password eye reveal,Material Icons,"import androidx.compose.material.icons.filled.Visibility","Icon(Icons.Default.Visibility, contentDescription = ""Show"")","Password visibility toggle"
Security,visibility_off,hide password eye conceal,Material Icons,"import androidx.compose.material.icons.filled.VisibilityOff","Icon(Icons.Default.VisibilityOff, contentDescription = ""Hide"")","Password hide toggle"
Editing,content_copy,copy clipboard duplicate,Material Icons,"import androidx.compose.material.icons.filled.ContentCopy","Icon(Icons.Default.ContentCopy, contentDescription = ""Copy"")","Copy to clipboard"
Editing,format_bold,bold text formatting rich,Material Icons,"import androidx.compose.material.icons.filled.FormatBold","Icon(Icons.Default.FormatBold, contentDescription = ""Bold"")","Rich text formatting"
Media,play_arrow,play video audio media start,Material Icons,"import androidx.compose.material.icons.filled.PlayArrow","Icon(Icons.Default.PlayArrow, contentDescription = ""Play"")","Media playback control"
Media,pause,pause video audio media stop,Material Icons,"import androidx.compose.material.icons.filled.Pause","Icon(Icons.Default.Pause, contentDescription = ""Pause"")","Media pause control"
Media,skip_next,next track forward,Material Icons,"import androidx.compose.material.icons.filled.SkipNext","Icon(Icons.Default.SkipNext, contentDescription = ""Next"")","Next track/item"
Media,volume_up,sound speaker audio mute,Material Icons,"import androidx.compose.material.icons.filled.VolumeUp","Icon(Icons.Default.VolumeUp, contentDescription = ""Volume"")","Volume control"
System,dark_mode,theme night dark moon,Material Icons,"import androidx.compose.material.icons.filled.DarkMode","Icon(Icons.Default.DarkMode, contentDescription = ""Dark mode"")","Theme toggle"
System,language,locale globe international i18n,Material Icons,"import androidx.compose.material.icons.filled.Language","Icon(Icons.Default.Language, contentDescription = ""Language"")","Language selector"
System,refresh,reload update sync,Material Icons,"import androidx.compose.material.icons.filled.Refresh","Icon(Icons.Default.Refresh, contentDescription = ""Refresh"")","Refresh/reload action"
System,filter_list,filter sort funnel,Material Icons,"import androidx.compose.material.icons.filled.FilterList","Icon(Icons.Default.FilterList, contentDescription = ""Filter"")","Filter/sort control"
System,more_vert,overflow menu options three dots,Material Icons,"import androidx.compose.material.icons.filled.MoreVert","Icon(Icons.Default.MoreVert, contentDescription = ""More options"")","Overflow menu trigger"
System,logout,signout exit leave account,Material Icons,"import androidx.compose.material.icons.filled.Logout","Icon(Icons.Default.Logout, contentDescription = ""Logout"")","Sign out action"
Pattern Name,Keywords,Section Order,Primary CTA Placement,Color Strategy,Conversion Optimization
Hero + Benefits + CTA,landing hero headline value proposition,"Hero > Value Props > Features > Social Proof > CTA","Bottom sticky + Hero section","Brand primary + contrasting CTA","Clear headline + single CTA + benefit-focused copy"
Onboarding Carousel,onboarding walkthrough tutorial first launch,"Welcome slide > Feature 1 > Feature 2 > Feature 3 > Get Started","Last slide full-width button","Gradient background + white text","Max 3-4 slides. Skip button always visible. No login required."
Feature Tour,feature highlights showcasing capabilities,"Hero > Feature Grid > Detail Cards > Stats > CTA","After feature grid + bottom","Alternating bg colors per section","Show real app screenshots in context"
Social Proof First,testimonial reviews trust rating,"Reviews Banner > Features > Testimonials > Trust Badges > CTA","After testimonials","Neutral + trust blue + gold for ratings","Lead with ratings/reviews then explain features"
Dashboard Entry,dashboard metrics kpi summary,"KPI Cards > Recent Activity > Quick Actions > Trends Chart","Quick action buttons in header","Dark surface + accent for metrics","Show most important data first. Personalized greeting."
Pricing Page,pricing plan subscription tier,"Feature Comparison > Pricing Cards > FAQ > CTA","Pricing card CTA button","Highlight recommended plan with accent","Most popular plan visually emphasized. Annual discount shown."
Login/Signup,login register auth account,Auth Header > Email/Password > Social Login > Terms,"Primary button below form","Brand colors + minimal distractions","Social login buttons first if available. Show/hide password toggle."
Profile/Settings,profile account preferences settings,"Avatar + Name > Account Settings > App Settings > Logout","In-line for each setting","Minimal + section dividers","Group related settings. Use toggles for boolean settings."
Search Results,search filter results sort,"Search Bar > Filters > Results List > Pagination","Search auto-trigger + filter chips","Minimal chrome + content-focused","Debounce search. Show result count. Highlight matching text."
Empty State,empty no data first use zero state,"Icon/Illustration > Title > Description > Primary CTA","Center of empty area","Soft illustration colors + bold CTA","Guide user to first action. Never show blank screen."
Subscription Upsell,subscription premium upgrade paywall pro,"Free Feature Demo > Premium Features > Pricing > Testimonials > Subscribe","Below pricing cards + floating banner","Gold/premium accent + contrast subscribe CTA","Show value before price. Social proof near CTA. Free trial emphasis."
Achievement/Gamification,achievement badge streak reward leaderboard,"Hero with progress > Achievements Grid > Leaderboard > Next Goal > Share CTA","After next goal + share button","Gold/yellow rewards + green progress + dark gamified bg","Show progress toward next achievement. Animate badge unlock."
Settings Hub,settings preferences account profile manage,"Profile Header > Account Settings > App Settings > Notifications > About > Logout","In-line toggles and navigation rows","Minimal + section dividers + accent for destructive actions","Group related settings. Use Switch for boolean. Show current values."
Checkout Flow,checkout cart payment confirm order,"Cart Summary > Shipping > Payment > Review > Confirm > Success","Bottom sticky confirm button on each step","Trust blue + progress green + urgency orange for limited offers","Show progress steps. Minimize fields. Save payment for next time."
Onboarding Permission,permission request rationale why access,"Benefit Illustration > Why We Need It > Permission Request > Skip Option","After benefit explanation + skip visible","Friendly illustration colors + trust blue CTA","Show benefit BEFORE permission dialog. Allow skip. Re-ask later contextually."
Support/Help Center,help support faq contact ticket,"Search > FAQ Categories > Popular Articles > Contact Options > Ticket Status","Floating chat button + contact options visible","Neutral with clear hierarchy + search emphasis","Search first. Popular questions visible. Multiple contact options."
Notification Center,notification inbox alert history message,"Filter Tabs > Notification List > Detail > Mark Read > Settings Link","No CTA needed - content consumption pattern","Minimal + unread accent dot + time grouping","Group by time. Show unread count. Allow mark all read. Settings accessible."
Data Visualization Dashboard,dashboard chart analytics report kpi,"KPI Summary Cards > Trend Charts > Detail Tables > Export > Date Filter","Date filter header + export button","Data blue + success green + alert red + neutral bg","Most important metric first. Progressive disclosure on charts."
Social Feed,feed post share like comment scroll,"Story Bar > Create Post > Feed Items > Load More > Bottom Nav","Floating create button + inline engagement","Brand accent for actions + neutral content bg","Infinite scroll. Pull to refresh. Engagement actions visible on each post."
Map-Based Discovery,map search location nearby filter pin,"Map View > Search Overlay > Filter Bar > List Toggle > Detail Card","Map pin taps + list item taps","Blue for current location + colored pins by category","Toggle between map and list. Filter by category. Show distance."
Comparison Table,comparison versus vs compare features pricing tier,"Feature Header > Comparison Grid > Highlight Winner > CTA Below","CTA below each column + sticky header","Brand accent for recommended + neutral for others","Highlight best value. Show checkmarks not text. Mobile-scroll horizontally."
Testimonial Carousel,testimonial review social proof rating customer,"Star Rating > Quote Cards Carousel > Company Logos > CTA","After carousel + after logos","Warm trust palette + subtle bg + gold stars","Use real photos. Show role + company. Rotate automatically."
Interactive Demo,demo try interactive playground sandbox live,"Headline > Interactive Widget > Feature List > CTA","After trying demo + bottom","Brand primary + interactive accent + clean bg","Let users experience core feature before sign up. Reduce friction."
Step-by-Step Guide,how-to steps tutorial guide numbered process,"Intro > Step 1-3(+) > Summary > CTA","After final step + floating","Sequential colors for steps + completion green","Number each step clearly. Show progress. Keep steps concise."
Video Hero,video hero motion background autoplay trailer,"Autoplay Video > Headline Overlay > CTA > Features Below","Overlaid on video + below fold","Video tint overlay + white text + bright CTA","Mute autoplay. Show fallback image. Video < 30 seconds loop."
Stats/Numbers,stats numbers impact metrics counter animated,"Headline > Counter Animations > Context > CTA","After impact numbers","Accent for numbers + neutral text + brand CTA","Animate counters on scroll-into-view. Show context for each number."
FAQ Accordion,faq questions answers help support accordion,"Category Tabs > Accordion Items > Contact CTA > Search","Contact CTA after FAQ list","Minimal + clear hierarchy + expand arrows","Show most asked first. Search within FAQ. Keep answers concise."
App Download,app store download install mobile promote,"Hero Phone Mockup > Feature Bullets > Reviews > Download Badges","App Store & Play Store badges prominent","Brand colors + store badge standards + social proof","Show real device mockup. Include QR code. Show rating + download count."
Layer,File Template,Class Template,Example File,Example Class,Notes
Presentation - Screen,[Feature]Screen.kt,[Feature]Screen,LoginScreen.kt,LoginScreen,"Top-level @Composable. Collects state from ViewModel."
Presentation - ViewModel,[Feature]ViewModel.kt,[Feature]ViewModel,LoginViewModel.kt,LoginViewModel,"Extends ViewModel(). Exposes StateFlow<UiState>."
Presentation - UiState,[Feature]UiState.kt,[Feature]UiState,LoginUiState.kt,LoginUiState,"Immutable data class. All screen state in one object."
Presentation - Event,[Feature]Event.kt,[Feature]Event,LoginEvent.kt,LoginEvent,"Sealed interface for one-shot events (navigation, snackbar)."
Presentation - Component,[Component].kt,[Component],UserCard.kt,UserCard,"Reusable @Composable. Stateless. Preview-able."
Domain - Model,[Entity].kt,[Entity],User.kt,User,"Pure Kotlin data class. No Android imports."
Domain - UseCase,[Action][Entity]UseCase.kt,[Action][Entity]UseCase,GetUserUseCase.kt,GetUserUseCase,"Single responsibility. operator fun invoke()."
Domain - Repository,[Entity]Repository.kt,[Entity]Repository,UserRepository.kt,UserRepository,"Interface in domain. Implementation in data."
Data - RepositoryImpl,[Entity]RepositoryImpl.kt,[Entity]RepositoryImpl,UserRepositoryImpl.kt,UserRepositoryImpl,"Implements domain interface. Maps DTOs to domain."
Data - DTO,[Entity]Dto.kt,[Entity]Dto,UserDto.kt,UserDto,"Network/DB response model. @Serializable/@JsonClass."
Data - RemoteDataSource,[Entity]RemoteDataSource.kt,[Entity]RemoteDataSource,UserRemoteDataSource.kt,UserRemoteDataSource,"API calls only. Returns DTOs."
Data - LocalDataSource,[Entity]Dao.kt,[Entity]Dao,UserDao.kt,UserDao,"Room DAO. Flow<List<EntityLocal>> return types."
Data - Mapper,[Entity]Mapper.kt,[Entity]Mapper,UserMapper.kt,toUser() / toDto(),"Extension functions: UserDto.toUser(), User.toDto()."
Core - Theme,Theme.kt,AppTheme,Theme.kt,"AppTheme @Composable","MaterialTheme wrapper with custom colorScheme/typography."
Core - Constants,Constants.kt,AppConstants,Constants.kt,AppConstants,"Object with const val. No magic numbers in code."
Core - Extensions,[Type]Extensions.kt,N/A,StringExtensions.kt,N/A,"Extension functions grouped by type."
Resource - String,[feature]_[desc],@string/[feature]_[desc],login_title,@string/login_title,"snake_case. Feature prefix for scoping."
Resource - Drawable,[type]_[desc],@drawable/[type]_[desc],ic_arrow_back,@drawable/ic_arrow_back,"ic_ for icons, bg_ for backgrounds, img_ for images."
pkg_name,category,description,best_practice_snippet,pro_tip,alternatives
retrofit,Networking,"Type-safe HTTP client for Android/Kotlin","val api = Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(MoshiConverterFactory.create()).build().create(ApiService::class.java)","Use suspend functions in service interface. Pair with OkHttp interceptors for auth/logging.",ktor-client
okhttp,Networking,"HTTP client with interceptors and connection pooling","OkHttpClient.Builder().connectTimeout(15, TimeUnit.SECONDS).addInterceptor(HttpLoggingInterceptor()).build()","Use with Retrofit. Add AuthInterceptor for token refresh. Set timeouts explicitly.",ktor-client
ktor-client,Networking,"Multiplatform HTTP client from JetBrains","val client = HttpClient(CIO) { install(ContentNegotiation) { json() } }","Native Kotlin. Good for KMP projects. Plugin-based architecture.",retrofit
coil,Image,"Kotlin-first image loading with Compose support","AsyncImage(model = url, contentDescription = desc, placeholder = painterResource(R.drawable.placeholder))","Use coil-compose for Compose. Supports GIF, SVG, video frames. Disk + memory cache built-in.",glide
glide,Image,"Mature image loading with extensive format support","Glide.with(context).load(url).placeholder(R.drawable.placeholder).into(imageView)","Use glide-compose for Compose support. Best for complex transformations.",coil
hilt,DI,"Compile-time dependency injection built on Dagger","@HiltAndroidApp class App : Application(); @HiltViewModel class VM @Inject constructor(repo: Repo) : ViewModel()","Use @HiltViewModel for ViewModels. Define modules for interface bindings. Test with HiltAndroidRule.",koin
koin,DI,"Lightweight runtime dependency injection","startKoin { modules(appModule) }; val appModule = module { single { ApiService() }; viewModel { MyViewModel(get()) } }","Quick setup. Good for small/medium projects. Less boilerplate than Hilt.",hilt
room,Database,"SQLite abstraction with Flow support","@Database(entities = [UserEntity::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao }","Use Flow return types for reactive queries. Pair with KSP for faster builds.",sqldelight
sqldelight,Database,"Kotlin-first SQL with type-safe queries","CREATE TABLE user (id INTEGER PRIMARY KEY, name TEXT NOT NULL);","Use for KMP projects. Generates type-safe Kotlin from SQL. Good for complex queries.",room
datastore-preferences,Storage,"Modern key-value storage replacing SharedPreferences","val Context.dataStore by preferencesDataStore(name = ""settings"")","Use for simple key-value pairs. Coroutine-based. Thread-safe by default.",datastore-proto
datastore-proto,Storage,"Typed storage with Protocol Buffers","val Context.settingsStore: DataStore<Settings> by dataStore(fileName = ""settings.pb"", serializer = SettingsSerializer)","Use for complex structured settings. Type-safe at compile time.",datastore-preferences
kotlinx-serialization,Serialization,"Kotlin-native JSON serialization","@Serializable data class User(val name: String, val age: Int); Json.decodeFromString<User>(jsonString)","Multiplatform. Compile-time. Use with Retrofit via kotlinx-serialization-converter.",moshi
moshi,Serialization,"JSON library with Kotlin support","@JsonClass(generateAdapter = true) data class User(@Json(name = ""user_name"") val name: String)","Use with KSP for code generation. Null-safe by default. Good Retrofit integration.",kotlinx-serialization
kotlinx-coroutines,Async,"Structured concurrency for Kotlin","viewModelScope.launch { val data = withContext(Dispatchers.IO) { repo.fetchData() }; _uiState.value = UiState.Success(data) }","Use viewModelScope in ViewModels. withContext for thread switching. Flow for streams.",rxjava
kotlinx-coroutines-test,Testing,"Test utilities for coroutines","runTest { viewModel.load(); advanceUntilIdle(); assertEquals(expected, viewModel.uiState.value) }","Use runTest for coroutine tests. advanceUntilIdle for virtual time. StandardTestDispatcher for control.",""
turbine,Testing,"Flow testing library from Cash App","viewModel.uiState.test { assertEquals(UiState.Loading, awaitItem()); assertEquals(UiState.Success(data), awaitItem()) }","Best for testing StateFlow/SharedFlow emissions. Provides timeout and cancellation support.",""
mockk,Testing,"Kotlin-first mocking library","every { repo.getUser(any()) } returns flowOf(user); coEvery { api.fetch() } returns response","Better Kotlin support than Mockito. Use coEvery for suspend functions. relaxed mocks for quick setup.",mockito-kotlin
mockito-kotlin,Testing,"Mockito with Kotlin extensions","whenever(repo.getUser(any())).thenReturn(flowOf(user))","Use with JUnit 5. Good if team already knows Mockito.",mockk
truth,Testing,"Fluent assertions from Google","assertThat(result).isInstanceOf(Success::class.java); assertThat(user.name).isEqualTo(""John"")","More readable than assertEquals. Chain assertions. Good error messages.",""
compose-ui-test,Testing,"UI testing for Compose","rule.onNodeWithText(""Login"").performClick(); rule.onNodeWithText(""Welcome"").assertIsDisplayed()","Use createComposeRule. Find nodes by text/tag/contentDescription. Assert visibility and content.",""
navigation-compose,Navigation,"Compose Navigation with type-safe routes","NavHost(navController, startDestination = ""home"") { composable(""home"") { HomeScreen() } }","Use sealed class for routes. Pass only IDs via arguments. Shared element transitions available.",""
accompanist,UI,"Google's Compose utility collection","No longer actively maintained. Features moved to core Compose libraries.","Check if needed feature is already in Compose foundation/material3 before adding.",""
material3,UI,"Material Design 3 components for Compose","MaterialTheme(colorScheme = colorScheme, typography = typography) { Scaffold { ... } }","Use dynamic color with dynamicLightColorScheme. All components follow M3 spec.",""
compose-animation,Animation,"Animation APIs for Compose","val alpha by animateFloatAsState(if (visible) 1f else 0f, animationSpec = tween(300))","Use animate*AsState for simple values. AnimatedVisibility for enter/exit. updateTransition for complex.",""
paging3,Pagination,"Load large datasets incrementally","val pager = Pager(PagingConfig(pageSize = 20)) { MyPagingSource(api) }","Use with LazyColumn. Handles loading/error states. RemoteMediator for offline caching.",""
work-manager,Background,"Reliable background task scheduling","val request = OneTimeWorkRequestBuilder<SyncWorker>().setConstraints(Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()).build()","Use for deferrable tasks. Survives process death. Chain work with then().",""
timber,Logging,"Better logging with auto-tagging","Timber.d(""User loaded: %s"", user.name); Timber.e(exception, ""Failed to load"")","Plant DebugTree in debug only. Remove logs in release with ProGuard. Auto-generates tag from class name.",""
leakcanary,Debug,"Memory leak detection","debugImplementation(""com.squareup.leakcanary:leakcanary-android:2.x"")","Debug-only dependency. Automatically detects Activity/Fragment/ViewModel leaks.",""
compose-destinations,Navigation,"Type-safe annotation-based Compose Navigation","@Destination @Composable fun HomeScreen() { ... }; DestinationsNavHost(navGraph = NavGraphs.root)","Reduces boilerplate. Generates type-safe navigation code. Good for large apps.",navigation-compose
lottie-compose,Animation,"Lottie animations in Compose","val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.anim)); LottieAnimation(composition)","Use for complex animations (onboarding, empty states, success). Lighter than video.",""
constraintlayout-compose,Layout,"ConstraintLayout for Compose","ConstraintLayout { val (title, button) = createRefs(); Text(modifier = Modifier.constrainAs(title) { top.linkTo(parent.top) }) }","Use when Row/Column nesting gets too complex. Supports barriers and guidelines.",""
compose-bom,Build,"Bill of Materials for consistent Compose versions","implementation(platform(""androidx.compose:compose-bom:2024.01.00""))","Use BOM to ensure all Compose libraries are compatible. Single version management.",""
lifecycle-runtime-compose,Lifecycle,"Lifecycle-aware Compose utilities","val state by viewModel.uiState.collectAsStateWithLifecycle()","Always use collectAsStateWithLifecycle instead of collectAsState. Stops collection when not visible.",""
splashscreen,Startup,"AndroidX Splash Screen API","installSplashScreen().apply { setKeepOnScreenCondition { isLoading } }","Use instead of custom splash Activity. Handles all API levels. Quick and standard.",""
compose-material3-adaptive,Adaptive,"Adaptive layouts for multi-device support","NavigationSuiteScaffold(navigationSuiteItems = { item(...) }) { content() }","Auto-switches nav style based on window size. Use with WindowSizeClass.",""
credential-manager,Auth,"Modern sign-in with passkeys and passwords","val credentialManager = CredentialManager.create(context)","Replaces SmartLock. Supports passkeys, passwords, federated sign-in.",""
biometric,Auth,"Biometric authentication (fingerprint/face)","BiometricPrompt(activity, executor, callback).authenticate(promptInfo)","Always check BiometricManager.canAuthenticate() first. Provide fallback auth.",""
play-app-update,Distribution,"In-app update prompts from Play Store","AppUpdateManagerFactory.create(context).startUpdateFlowForResult(info, FLEXIBLE, activity, RC)","Use FLEXIBLE for non-critical. IMMEDIATE for security updates.",""
play-review,Distribution,"In-app review prompts","val manager = ReviewManagerFactory.create(context); manager.requestReviewFlow().addOnSuccessListener { manager.launchReviewFlow(activity, it) }","Don't show on first launch. Trigger after positive experience. Can't customize UI.",""
kotlinx-datetime,DateTime,"Multiplatform date/time library for Kotlin","val now = Clock.System.now(); val local = now.toLocalDateTime(TimeZone.currentSystemDefault())","Use for KMP projects. Replaces java.time for multiplatform. Integrates with serialization.",java.time
arrow-kt,Functional,"Functional programming library for Kotlin","either { val user = userRepo.getUser(id).bind(); val posts = postRepo.getPosts(user.id).bind(); UserWithPosts(user, posts) }","Use Either for typed error handling. Raise DSL for clean composition. Optics for immutable updates.",kotlin.Result
accompanist-permissions,Permissions,"Easy runtime permission handling for Compose","val permissionState = rememberPermissionState(Manifest.permission.CAMERA); if (permissionState.status.isGranted) CameraContent()","Compose-first API. Handles rationale, denied, permanently denied states.",manual ActivityResultContracts
result-kt,Error,"Kotlin Result extensions with typed errors","result { validate(input).bind(); process(input).bind() }","Chain operations with bind(). Better than nested try-catch. Use with sealed error types.",arrow-kt
napier,Logging,"Multiplatform logging library","Napier.d(""User loaded""); Napier.e(""Error"", throwable = exception)","Use for KMP projects. Similar API to Timber. Platform-specific log implementations.",timber
kermit,Logging,"Multiplatform logging by Touchlab","Logger.d { ""User $userId loaded"" }","KMP-friendly. Lambda-based message building avoids string allocation.",timber
kotlinx-immutable-collections,Collections,"Immutable collections for Kotlin","val list = persistentListOf(1, 2, 3); val updated = list.add(4)","Use with Compose for stable parameters. ImmutableList prevents unnecessary recomposition.",standard List
compose-shimmer,Loading,"Shimmer effect for Compose loading states","Box(modifier = Modifier.shimmer()) { PlaceholderContent() }","Quick shimmer setup. Customize direction, colors, speed.",custom Canvas shimmer
balloon,Tooltip,"Tooltip/popup library for Android","Balloon.Builder(context).setText(""Hint"").setArrowPosition(0.5f).build()","Easy tooltips for feature discovery. Supports Compose with remember pattern.",Material3 RichTooltip
orbit-mvi,Architecture,"MVI framework for Kotlin","container<State, SideEffect> { reduce { state.copy(loading = true) }; postSideEffect(Navigate) }","Clean MVI with container pattern. Built-in test support.",manual MVI setup
molecule,State,"Build StateFlow from Compose runtime","moleculeFlow(RecompositionMode.Immediate) { var count by remember { mutableIntStateOf(0) }; LaunchedEffect(Unit) { while(true) { delay(1000); count++ } }; count }","Use Compose runtime outside UI for reactive state. Good for complex state machines.",StateFlow manual
voyager,Navigation,"Multiplatform navigation for Compose","Navigator(HomeScreen()) { navigator -> SlideTransition(navigator) }","KMP-ready. Screen model pattern. Built-in transitions.",navigation-compose
circuit,Architecture,"Compose-driven architecture by Slack","@CircuitInject(HomeScreen::class, AppScope::class) @Composable fun Home(state: HomeState, modifier: Modifier)","Presenter + UI separation. Zero ViewModel. Testable via FakeNavigator.",MVVM with ViewModel
ktor-client-cio,Networking,"CIO engine for Ktor client","val client = HttpClient(CIO) { install(ContentNegotiation) { json() }; install(Logging) }","Non-blocking. Good for high-throughput. KMP compatible.",okhttp engine
sandwich,Networking,"Type-safe API response handling","val response = apiService.getUser(); response.onSuccess { data -> }.onError { }.onException { }","Clean response handling without try-catch. Maps to sealed types automatically.",manual Result wrapping
compose-rich-editor,Editor,"Rich text editor for Compose","val state = rememberRichTextState(); RichTextEditor(state = state)","WYSIWYG editing in Compose. Supports bold, italic, lists, links.",BasicTextField with manual formatting
zoomable,Gesture,"Pinch-to-zoom for Compose images","Image(modifier = Modifier.zoomable(rememberZoomState()))","Easy image zoom. Supports double-tap, pinch, pan gestures.",custom pointerInput zoom
telephoto,Media,"Advanced media display for Compose","ZoomableImage(model = ZoomableImageSource.coilPainting(url))","Zoomable images with sub-sampling. Handles large images without OOM.",custom image viewer
compose-markdown,Display,"Render Markdown in Compose","MarkdownText(markdown = markdownContent)","Render markdown in Compose. Supports links, images, code blocks.",WebView for markdown
firebase-bom,Backend,"Firebase Bill of Materials","implementation(platform(""com.google.firebase:firebase-bom:33.0.0""))","Single BOM manages all Firebase library versions. Always use BOM.",individual Firebase versions
firebase-crashlytics,Monitoring,"Crash reporting service","FirebaseCrashlytics.getInstance().log(""User action""); recordException(exception)","Essential for production. Auto-captures crashes. Custom keys for context.",manual crash logging
firebase-analytics,Analytics,"Event tracking and user analytics","Firebase.analytics.logEvent(""purchase"") { param(""item_id"", itemId) }","Track key user actions. Use with BigQuery for advanced analysis.",manual analytics
firebase-messaging,Push,"Push notifications via FCM","class MyFcmService : FirebaseMessagingService() { override fun onMessageReceived(msg: RemoteMessage) { } }","Handle foreground and background messages. Update token on refresh.",manual WebSocket push
compose-calendar,Date,"Calendar UI component for Compose","HorizontalCalendar(state = rememberCalendarState())","Customizable calendar. Supports date range selection, event markers.",Material3 DatePicker
compose-destinations-ksp,Navigation,"KSP processor for Compose Destinations","@Destination @Composable fun ProfileScreen(userId: String) { }","Auto-generates navigation code from annotations. Type-safe arguments.",manual composable routes
kotlinx-coroutines-play-services,Integration,"Coroutine support for Play Services Tasks","val location = locationClient.lastLocation.await()","Convert Task<T> to suspend function with .await(). Essential for Firebase/Play APIs.",manual Task callbacks
media3-exoplayer,Media,"Media playback library (ExoPlayer successor)","val player = ExoPlayer.Builder(context).build(); player.setMediaItem(MediaItem.fromUri(uri))","Use for video/audio playback. Supports streaming, DRM, and adaptive bitrate.",VideoView
accompanist-systemuicontroller,UI,"Control system UI bars appearance","val systemUiController = rememberSystemUiController(); systemUiController.setSystemBarsColor(Color.Transparent)","Set status/navigation bar colors. Enable edge-to-edge mode.",manual WindowInsetsController
pattern_name,category,problem_tags,description,key_components,code_snippet,anti_pattern
MVVM with StateFlow,Architecture,state viewmodel compose,"Default architecture pattern for Compose screens. ViewModel exposes immutable UiState via StateFlow.",ViewModel MutableStateFlow StateFlow asStateFlow collectAsStateWithLifecycle,"class MyViewModel : ViewModel() { private val _uiState = MutableStateFlow(MyUiState()); val uiState = _uiState.asStateFlow() }",Exposing MutableStateFlow directly or putting business logic in Composable
MVI with Intent,Architecture,state intent reducer events,"Unidirectional data flow with explicit intents. Best for complex state machines.",ViewModel sealed interface Intent reduce Channel,"sealed interface MyIntent { data class Search(val q: String) : MyIntent; data object Refresh : MyIntent }",Mixing MVI and MVVM in same screen
Clean Architecture Layers,Architecture,layer separation domain data presentation,"Separate UI/Presentation Domain and Data layers with clear dependency rules.",UseCase Repository DataSource DTO Entity Mapper,"class GetUserUseCase(private val repo: UserRepository) { suspend operator fun invoke(id: String): Result<User> = repo.getUser(id) }",Domain layer depending on data/framework classes
Repository Pattern,Architecture,data abstraction cache remote local,"Abstract data sources behind repository interface. Single source of truth.",Repository interface RemoteDataSource LocalDataSource Flow,"interface UserRepository { fun getUsers(): Flow<List<User>>; suspend fun refreshUsers() }",Repository directly returning DTOs without mapping to domain models
UseCase Pattern,Architecture,business logic interactor domain,"Encapsulate single business operation. Keep thin - delegate to repos.",UseCase operator fun invoke suspend,"class ValidateEmailUseCase { operator fun invoke(email: String): ValidationResult = when { email.isBlank() -> Invalid; !email.contains('@') -> Invalid; else -> Valid } }",UseCase with multiple responsibilities or UI dependencies
Sealed UiState,State,loading error success empty,"Represent all screen states with sealed interface/class.","sealed interface UiState data object Loading data class Success data class Error","sealed interface UiState<out T> { data object Loading : UiState<Nothing>; data class Success<T>(val data: T) : UiState<T>; data class Error(val msg: String) : UiState<Nothing> }",Using separate boolean flags (isLoading/isError) instead of sealed state
State Hoisting,State,compose reusable stateless,"Lift state up to caller for reusable stateless composables.",remember mutableStateOf callback,"@Composable fun SearchBar(query: String, onQueryChange: (String) -> Unit) { OutlinedTextField(value = query, onValueChange = onQueryChange) }",Composable managing its own state when it should be controlled by parent
Compose Navigation,Navigation,screen routing deeplink,"Type-safe navigation with Compose Navigation. Define routes as sealed classes.",NavHost composable NavController rememberNavController,"NavHost(navController, startDestination = ""home"") { composable(""home"") { HomeScreen() }; composable(""detail/{id}"") { DetailScreen(it.arguments?.getString(""id"")) } }",Passing complex objects via navigation arguments instead of IDs
Nested Navigation Graphs,Navigation,module feature graph,"Organize navigation by feature with nested graphs.",navigation NavGraphBuilder route startDestination,"fun NavGraphBuilder.authGraph(navController: NavController) { navigation(startDestination = ""login"", route = ""auth"") { composable(""login"") { LoginScreen() } } }",Flat navigation graph with all routes at top level
Bottom Navigation + NavHost,Navigation,tabs bottombar selected,"Bottom navigation with separate back stacks per tab.",NavigationBar NavigationBarItem NavHost saveState restoreState,"NavigationBar { items.forEach { NavigationBarItem(selected = currentRoute == it.route, onClick = { navController.navigate(it.route) { popUpTo(navController.graph.startDestinationId) { saveState = true }; restoreState = true; launchSingleTop = true } }) } }",Recreating screens on tab switch instead of saving/restoring state
Form Validation,Form,input error validate submit,"Validate form fields with sealed results and real-time feedback.",TextField isError supportingText ValidationResult,"data class FormState(val email: String = """", val emailError: String? = null); fun validate(state: FormState): FormState = state.copy(emailError = if (!state.email.contains('@')) ""Invalid email"" else null)",Validating only on submit without inline feedback
Pagination with Paging 3,List,infinite scroll load more page,"Load data in pages as user scrolls. Handles loading/error states.",Pager PagingSource LazyPagingItems collectAsLazyPagingItems,"val pager = Pager(PagingConfig(pageSize = 20)) { MyPagingSource(api) }; val items = pager.flow.cachedIn(viewModelScope)",Loading all data at once for large datasets
Pull to Refresh,List,refresh swipe reload,"Pull down to refresh content. Connect to ViewModel refresh.",pullToRefresh PullToRefreshBox rememberPullToRefreshState,"PullToRefreshBox(isRefreshing = isRefreshing, onRefresh = { viewModel.refresh() }) { LazyColumn { items(data) { ItemRow(it) } } }",Refreshing without showing loading indicator
Swipe to Dismiss,List,delete archive gesture,"Swipe list item to reveal actions (delete/archive).",SwipeToDismissBox DismissValue rememberSwipeToDismissBoxState,"SwipeToDismissBox(state = dismissState, backgroundContent = { DeleteBackground() }) { ListItem(headlineContent = { Text(item.name) }) }",No undo/confirmation for destructive swipe actions
Search with Debounce,Search,filter query delay,"Debounce search input to reduce API calls.","MutableStateFlow debounce flatMapLatest collectAsStateWithLifecycle","private val _query = MutableStateFlow(""""); val results = _query.debounce(300).flatMapLatest { repo.search(it) }.stateIn(viewModelScope, SharingStarted.Lazily, emptyList())",Searching on every keystroke without debounce
Offline-First with Room,Data,cache local sync database,"Cache data locally with Room. Show cached data first then sync.",Room Dao Flow Entity Repository,"@Query(""SELECT * FROM users"") fun observeAll(): Flow<List<UserEntity>>",Blocking UI while waiting for network response
Dependency Injection with Hilt,DI,inject module provides singleton,"Setup Hilt for DI across the app. Modules provide implementations.",@HiltAndroidApp @Inject @Module @Provides @Singleton @HiltViewModel,"@Module @InstallIn(SingletonComponent::class) object AppModule { @Provides @Singleton fun provideApi(): ApiService = Retrofit.Builder().baseUrl(BASE_URL).build().create(ApiService::class.java) }",Manual object creation in ViewModel constructors
Dependency Injection with Koin,DI,inject module factory viewmodel,"Lightweight DI with Koin. Declare modules and inject.",startKoin module single factory viewModel get,"val appModule = module { single<ApiService> { RetrofitApiService(get()) }; factory { GetUserUseCase(get()) }; viewModel { UserViewModel(get()) } }",Using Koin and Hilt together in same project
Error Handling with Result,Error,try catch sealed network,"Wrap operations in Result for explicit error handling.",Result runCatching fold onSuccess onFailure,"suspend fun fetchUser(id: String): Result<User> = runCatching { api.getUser(id).toDomain() }",Empty catch blocks or throwing generic exceptions
Retry with Exponential Backoff,Error,network retry timeout,"Retry failed operations with increasing delay.",delay repeat CancellationException,"suspend fun <T> retry(times: Int = 3, block: suspend () -> T): T { var delay = 1000L; repeat(times - 1) { try { return block() } catch (e: Exception) { if (e is CancellationException) throw e; delay(delay); delay *= 2 } }; return block() }",Retrying non-idempotent requests or ignoring CancellationException
Theme System with Material 3,Theming,color typography shape dark,"Setup Material 3 dynamic theming with light/dark/dynamic color.",MaterialTheme colorScheme typography shapes dynamicColorScheme,"val colorScheme = if (dynamicColor) dynamicLightColorScheme(context) else LightColorScheme; MaterialTheme(colorScheme = colorScheme, typography = AppTypography) { content() }",Hardcoding colors instead of using MaterialTheme.colorScheme
Dark Mode Support,Theming,dark light system theme,"Support system dark mode and manual toggle.",isSystemInDarkTheme darkColorScheme lightColorScheme,"val isDark = isSystemInDarkTheme(); val colors = if (isDark) DarkColorScheme else LightColorScheme",Only testing in light mode or hardcoding light colors
Shimmer Loading,Loading,skeleton placeholder animation,"Show shimmer placeholders while content loads.",Modifier.shimmer placeholder Brush.linearGradient animateFloat,"Box(modifier = Modifier.fillMaxWidth().height(20.dp).background(shimmerBrush())) // Custom shimmer brush with animated gradient",Showing blank screen or only a spinner during load
Image Loading with Coil,Media,image network cache placeholder,"Load images efficiently with Coil. Support placeholder and error states.",AsyncImage rememberAsyncImagePainter SubcomposeAsyncImage,"AsyncImage(model = ImageRequest.Builder(context).data(url).crossfade(true).build(), contentDescription = desc, placeholder = painterResource(R.drawable.placeholder), error = painterResource(R.drawable.error))",Loading images without placeholder or error handling
Permission Request,System,runtime permission rationale,"Request runtime permissions with rationale.",rememberLauncherForActivityResult ActivityResultContracts.RequestPermission,"val launcher = rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { granted -> if (granted) doAction() }; Button(onClick = { launcher.launch(Manifest.permission.CAMERA) }) { Text(""Camera"") }",Requesting all permissions at app startup
WorkManager Background Task,System,background schedule periodic,"Schedule reliable background work that survives process death.",WorkManager OneTimeWorkRequestBuilder PeriodicWorkRequestBuilder CoroutineWorker,"class SyncWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(ctx, params) { override suspend fun doWork(): Result { repo.sync(); return Result.success() } }",Using coroutine launch for work that must survive process death
DataStore Preferences,Storage,key value settings persist,"Modern replacement for SharedPreferences.",DataStore Preferences preferencesDataStore edit,"val Context.dataStore by preferencesDataStore(""settings""); val darkMode = context.dataStore.data.map { it[DARK_MODE_KEY] ?: false }",Using SharedPreferences directly for new code
Proto DataStore,Storage,typed schema binary persist,"Type-safe DataStore with Protocol Buffers.",DataStore Proto Serializer,"val Context.settingsStore: DataStore<Settings> by dataStore(fileName = ""settings.pb"", serializer = SettingsSerializer)",Using JSON string in PreferencesDataStore for complex objects
Compose Preview,Development,preview parameterized dark,"Preview composables in Android Studio.",@Preview @PreviewParameter @PreviewLightDark,"@Preview(showBackground = true) @Preview(showBackground = true, uiMode = UI_MODE_NIGHT_YES) @Composable fun CardPreview() { AppTheme { UserCard(user = sampleUser) } }",Not providing previews for composables or only previewing in light mode
Testing ViewModel,Testing,unit test flow turbine,"Test ViewModel state emissions with Turbine.",runTest Turbine app.cash.turbine advanceUntilIdle,"@Test fun `loading then success`() = runTest { viewModel.uiState.test { assertEquals(UiState.Loading, awaitItem()); viewModel.load(); assertEquals(UiState.Success(data), awaitItem()) } }",Testing ViewModel without verifying intermediate states
Testing Compose UI,Testing,ui test semantics assert,"Test Compose UI with ComposeTestRule.",createComposeRule onNodeWithText performClick assertIsDisplayed,"@Test fun loginButton_triggers_action() { rule.setContent { LoginScreen() }; rule.onNodeWithText(""Login"").performClick(); rule.onNodeWithText(""Welcome"").assertIsDisplayed() }",Testing implementation details instead of user-visible behavior
Adaptive Layout,Responsive,phone tablet foldable window,"Support multiple screen sizes with WindowSizeClass.",calculateWindowSizeClass WindowWidthSizeClass NavigationSuiteScaffold,"val windowSize = calculateWindowSizeClass(this); when (windowSize.widthSizeClass) { WindowWidthSizeClass.Compact -> PhoneLayout(); WindowWidthSizeClass.Medium -> TabletLayout(); WindowWidthSizeClass.Expanded -> DesktopLayout() }",Only designing for phone screens
Baseline Profile,Performance,startup optimization compile,"Generate Baseline Profile for faster app startup.",BaselineProfileGenerator androidx.benchmark.macro,"@ExperimentalBaselineProfilesApi class BaselineProfileGenerator { @get:Rule val rule = BaselineProfileRule() @Test fun startup() { rule.collect(""com.example.app"") { startActivityAndWait() } } }",Not generating baseline profiles before release
ProGuard/R8 Optimization,Build,minify shrink obfuscate release,"Configure code shrinking and obfuscation for release builds.",minifyEnabled shrinkResources proguardFiles,"buildTypes { release { isMinifyEnabled = true; isShrinkResources = true; proguardFiles(getDefaultProguardFile(""proguard-android-optimize.txt""), ""proguard-rules.pro"") } }",Shipping debug builds or not testing release builds with ProGuard
App Widget with Glance,Widget,homescreen widget compose glance,"Build home screen widgets using Jetpack Glance (Compose-like API).",GlanceAppWidget GlanceAppWidgetReceiver provideGlance,"class MyWidget : GlanceAppWidget() { override suspend fun provideGlance(context: Context, id: GlanceId) { provideContent { Text(""Hello Widget"") } } }",Using RemoteViews directly when Glance is available
Biometric Authentication,Security,fingerprint face authentication,"Implement biometric login with BiometricPrompt.",BiometricPrompt BiometricManager CryptoObject,"val promptInfo = BiometricPrompt.PromptInfo.Builder().setTitle(""Login"").setNegativeButtonText(""Cancel"").build(); biometricPrompt.authenticate(promptInfo)",Not providing fallback authentication when biometrics unavailable
In-App Update,System,update mandatory flexible play,"Prompt users to update via Play In-App Update API.",AppUpdateManager AppUpdateType IMMEDIATE FLEXIBLE,"val appUpdateManager = AppUpdateManagerFactory.create(context); appUpdateManager.appUpdateInfo.addOnSuccessListener { info -> if (info.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) { appUpdateManager.startUpdateFlowForResult(info, AppUpdateType.FLEXIBLE, activity, REQUEST_CODE) } }",Force-closing app for updates instead of using flexible update flow
Deep Link Handling,Navigation,deeplink uri intent external,"Handle deep links in Compose Navigation.",navDeepLink NavController intent uri,"""composable(""detail/{id}"", deepLinks = listOf(navDeepLink { uriPattern = ""app://detail/{id}"" })) { DetailScreen(it.arguments?.getString(""id"")) }""",Not validating deep link parameters before using them
Splash Screen API,Startup,splash branding launch,"Modern splash screen with AndroidX SplashScreen API.",installSplashScreen setKeepOnScreenCondition,"installSplashScreen().apply { setKeepOnScreenCondition { viewModel.isLoading.value } }",Using custom Activity for splash screen instead of SplashScreen API
Multi-Module Architecture,Architecture,module gradle feature core,"Split app into feature modules and core modules for scalability.",feature module core module api module shared module build-logic,"// settings.gradle.kts: include("":core:ui"", "":core:network"", "":feature:login"", "":feature:home"")",Single monolithic module for large projects
Mapper Pattern,Data,dto entity mapping transform,"Map between DTOs and domain models at data layer boundary.",extension function Mapper toEntity toDomain,"fun UserDto.toDomain() = User(id = this.id, name = this.fullName, email = this.emailAddress)",Passing DTOs directly to UI layer
Sealed Interface for Events,State,event channel side-effect navigation,"One-shot events (navigation snackbar) via Channel not StateFlow.",Channel sealed interface receiveAsFlow,"sealed interface UiEvent { data class Navigate(val route: String) : UiEvent; data class ShowSnackbar(val msg: String) : UiEvent }",Using StateFlow for one-shot events (they replay on config change)
Compose Side Effects,Compose,effect launched disposable,"Handle side effects properly in Compose lifecycle.",LaunchedEffect DisposableEffect SideEffect rememberUpdatedState,"LaunchedEffect(userId) { viewModel.loadUser(userId) }; DisposableEffect(lifecycle) { observer = ...; onDispose { lifecycle.removeObserver(observer) } }",Calling suspend functions directly in composable body
Slot-based API,Compose,slot composable api reusable,"Design composables with content slots for maximum flexibility.",content: @Composable trailing lambda,"@Composable fun AppCard(title: String, content: @Composable () -> Unit) { Card { Column { Text(title); content() } } }",Hardcoding all content instead of providing slots
CompositionLocal,Compose,local provide implicit dependency,"Provide values implicitly down the composition tree.",CompositionLocalProvider staticCompositionLocalOf,"val LocalAppColors = staticCompositionLocalOf { AppColors() }; CompositionLocalProvider(LocalAppColors provides customColors) { content() }",Overusing CompositionLocal for everything instead of explicit parameters
Modifier Chain Best Practice,Compose,modifier order padding click,"Apply modifiers in correct order for expected behavior.",Modifier.clickable clip padding background,"Modifier.clip(shape).background(color).clickable { }.padding(16.dp) // Order matters: clip before bg, clickable before padding",Wrong modifier order causing unexpected touch/visual behavior
Custom Composable Theme,Theming,theme extension custom token,"Extend MaterialTheme with app-specific tokens.",CompositionLocal ThemeExtension custom colors spacing,"data class AppColors(val success: Color, val warning: Color); val LocalAppColors = staticCompositionLocalOf { AppColors() }",Hardcoding custom colors instead of extending theme
Animated Navigation,Navigation,transition animation shared element,"Add smooth transitions between screens in Navigation.",AnimatedNavHost enterTransition exitTransition,"AnimatedNavHost(navController) { composable(""home"", enterTransition = { slideInHorizontally() }, exitTransition = { slideOutHorizontally() }) { HomeScreen() } }",No transitions between screens (jarring UX)
Type-Safe Navigation,Navigation,typed route safe argument serializable,"Use serializable route classes for type-safe navigation.",@Serializable NavType Companion,"@Serializable data class DetailRoute(val id: String); composable<DetailRoute> { entry -> DetailScreen(entry.toRoute<DetailRoute>().id) }",Using string-based routes with manual argument parsing
Bottom Sheet Navigation,Navigation,bottom sheet modal route,"Navigate to bottom sheets as part of the navigation graph.",BottomSheetNavigator ModalBottomSheetLayout,"ModalBottomSheet(onDismissRequest = { navController.popBackStack() }) { FilterContent() }",Creating standalone dialogs/sheets outside navigation (breaks back gestures)
Flow Operators in ViewModel,State,flow combine map filter debounce,"Use Flow operators for reactive data transformations.",combine map flatMapLatest debounce distinctUntilChanged,"val results = combine(_query.debounce(300), _filters) { q, f -> repo.search(q, f) }.flatMapLatest { it }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())",Recreating search flow on every query change
stateIn Best Practice,State,statin sharing started timeout,"Configure stateIn with proper sharing strategy and timeout.",SharingStarted.WhileSubscribed stateIn cachedIn,"val uiState = repository.observe().map { UiState.Success(it) }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), UiState.Loading)",Using SharingStarted.Eagerly when data is expensive to produce
Remember with Keys,Compose,remember key recalculate cache,"Use remember with keys to recalculate when inputs change.",remember key derivedStateOf,"val filtered = remember(items, query) { items.filter { it.name.contains(query) } }",Using remember without keys causing stale data
Compose State Restoration,State,saveable restore process death,"Preserve UI state across process death with rememberSaveable.",rememberSaveable Saver mapSaver,"var text by rememberSaveable { mutableStateOf("""") }; val scrollState = rememberLazyListState(); rememberSaveable(saver = LazyListState.Saver) { scrollState }",Using remember for state that should survive process death
Shared Element Transition,Animation,shared element transition hero,"Animate shared elements between screens for visual continuity.",SharedTransitionLayout AnimatedVisibilityScope sharedElement,"SharedTransitionLayout { AnimatedContent(targetState) { state -> Image(modifier = Modifier.sharedElement(rememberSharedContentState(key = ""image-$id""), this@SharedTransitionLayout)) } }",Abrupt screen transitions without visual continuity
Gesture-Driven UI,Gesture,drag swipe fling anchor snap,"Build interactive UIs driven by user gestures.",AnchoredDraggable detectDragGestures pointerInput,"Modifier.pointerInput(Unit) { detectHorizontalDragGestures { change, dragAmount -> offset += dragAmount } }",Not providing alternative interaction for gesture-only actions
Custom Layout,Layout,custom measure arrange layout,"Create custom layouts when Row/Column/Box don't fit.",Layout MeasurePolicy Constraints placeable,"Layout(content = content) { measurables, constraints -> val placeables = measurables.map { it.measure(constraints) }; layout(width, height) { placeables.forEach { it.place(x, y) } } }",Deep nesting of Row/Column when a custom layout would be cleaner
Compose Canvas Drawing,Graphics,canvas draw custom shape path,"Draw custom shapes and graphics with Compose Canvas.",Canvas drawCircle drawLine drawPath Path,"Canvas(modifier = Modifier.fillMaxSize()) { drawCircle(color = Color.Blue, radius = 100f, center = center) }",Using Image/Icon when a simple Canvas drawing would be more efficient
Clipboard Pattern,System,copy paste clipboard share,"Copy text to clipboard with user feedback.",ClipboardManager ClipData setPrimaryClip,"val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager; clipboard.setPrimaryClip(ClipData.newPlainText(""label"", text))",Not showing confirmation after copy action
Share Intent,System,share text image content external,"Share content with other apps via Intent.",Intent ACTION_SEND putExtra startActivity,"val intent = Intent(Intent.ACTION_SEND).apply { type = ""text/plain""; putExtra(Intent.EXTRA_TEXT, shareText) }; context.startActivity(Intent.createChooser(intent, ""Share via""))",Not using createChooser (skips user choice on some devices)
Notification Channel,System,notification channel importance heads up,"Create notification channels (required Android 8+).",NotificationChannel NotificationManager IMPORTANCE,"val channel = NotificationChannel(""alerts"", ""Alerts"", NotificationManager.IMPORTANCE_HIGH); notificationManager.createNotificationChannel(channel)",Not creating notification channels (notifications silently fail on Android 8+)
ViewModel Factory,DI,viewmodel factory assisted inject,"Create ViewModel with runtime parameters using assisted injection.",AssistedFactory AssistedInject @AssistedFactory,"@HiltViewModel(assistedFactory = DetailViewModel.Factory::class) class DetailViewModel @AssistedInject constructor(@Assisted val id: String, val repo: Repo) : ViewModel() { @AssistedFactory interface Factory { fun create(id: String): DetailViewModel } }",Passing runtime values through shared ViewModels or global state
Multi-Theme Support,Theming,dynamic theme user preference brand,"Support multiple themes (light/dark/dynamic/brand-specific).",dynamicColorScheme isSystemInDarkTheme DataStore,"val darkTheme = isSystemInDarkTheme(); val dynamicColor = Build.VERSION.SDK_INT >= 31; val colorScheme = when { dynamicColor && darkTheme -> dynamicDarkColorScheme(context); dynamicColor -> dynamicLightColorScheme(context); darkTheme -> DarkColorScheme; else -> LightColorScheme }",Only supporting one fixed color scheme
Edge-to-Edge Layout,Layout,edge to edge status bar system bars,"Extend content behind system bars for immersive UI.",enableEdgeToEdge WindowInsets systemBarsPadding,"enableEdgeToEdge(); Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> Content(Modifier.padding(innerPadding)) }",Not handling system bar insets causing content overlap
Kotlin Delegation,Kotlin,delegate lazy observable property,"Use Kotlin delegation for clean property patterns.",by lazy by viewModels by remember,"val viewModel: MyViewModel by viewModels(); val database by lazy { Room.databaseBuilder(app, AppDatabase::class.java, ""db"").build() }",Manual initialization with nullable vars and null checks
Coroutine Exception Handling,Error,coroutine exception handler supervisor,"Handle coroutine exceptions without crashing the app.",CoroutineExceptionHandler SupervisorJob supervisorScope,"val handler = CoroutineExceptionHandler { _, e -> Log.e(""App"", ""Coroutine failed"", e) }; viewModelScope.launch(handler) { riskyOperation() }",Letting unhandled coroutine exceptions crash the app
Structured Concurrency,Async,structured concurrency scope cancel,"Use structured concurrency for predictable lifecycle.",coroutineScope supervisorScope withContext awaitAll,"coroutineScope { val user = async { repo.getUser(id) }; val posts = async { repo.getPosts(id) }; UiState(user.await(), posts.await()) }",Using GlobalScope or creating unscoped coroutines
Channel vs SharedFlow,State,channel hot flow event stream,"Choose between Channel (one consumer) and SharedFlow (many consumers).","Channel SharedFlow MutableSharedFlow BufferOverflow","private val _events = Channel<UiEvent>(Channel.BUFFERED); val events = _events.receiveAsFlow() // One consumer, no replay",Using SharedFlow with replay for one-shot events
Foreground Service,System,foreground service notification persistent,"Run persistent work with visible notification (music/GPS/recording).",ForegroundService ServiceCompat startForeground Notification,"class TrackingService : Service() { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { startForeground(1, notification); return START_STICKY } }",Using foreground service for short tasks that WorkManager can handle
Content Provider,Data,content provider share data cross-app,"Share structured data between apps via ContentProvider.",ContentProvider ContentResolver query insert update delete,"class MyProvider : ContentProvider() { override fun query(uri: Uri, projection: Array<String>?, ...): Cursor? { return db.query(...) } }",Exposing sensitive data without proper permission checks
BroadcastReceiver Pattern,System,broadcast receiver system events,"Listen to system events (connectivity/battery/boot).",BroadcastReceiver IntentFilter registerReceiver onReceive,"class ConnectivityReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { /* handle */ } }",Registering implicit receivers in manifest for battery-draining events
Compose Layout Inspector,Development,layout inspector debug recomposition,"Debug Compose layout and recomposition counts.",Layout Inspector debugInspectorInfo compositionLocalOf,"@Composable fun Debug() { val recomposeCount = remember { mutableIntStateOf(0) }; SideEffect { recomposeCount.intValue++ } }",Not using Layout Inspector to identify unnecessary recompositions
Compose Stability Config,Performance,stability config annotation class recompose,"Configure stability for classes from external libraries.",stability_config.conf @Stable @Immutable compose compiler,"// stability_config.conf: java.time.LocalDate -> Stable; kotlinx.datetime.Instant -> Stable","Ignoring stability warnings and accepting unnecessary recompositions"
App Shortcuts,System,shortcut static dynamic pinned launcher,"Add launcher shortcuts for quick app actions.",ShortcutManager ShortcutInfo.Builder static dynamic pinned,"ShortcutManagerCompat.setDynamicShortcuts(context, listOf(ShortcutInfoCompat.Builder(context, ""compose"").setShortLabel(""New"").setIntent(intent).build()))",Not providing shortcuts for frequently used actions
Background Location,System,background location gps periodic tracking,"Track location in background with proper permissions.",FusedLocationProviderClient requestLocationUpdates Priority,"val request = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 5000).build(); fusedClient.requestLocationUpdates(request, callback, Looper.getMainLooper())",Not requesting ACCESS_BACKGROUND_LOCATION or not showing rationale
Compose Test Tag,Testing,test tag find semantic compose ui,"Add test tags for finding elements in UI tests.",Modifier.testTag testTag onNodeWithTag semanticsConfiguration,"Text(text, modifier = Modifier.testTag(""welcome_text"")); // In test: rule.onNodeWithTag(""welcome_text"").assertIsDisplayed()",Using brittle text-matching instead of stable test tags
Screenshot Testing,Testing,screenshot visual regression paparazzi,"Capture screenshots of composables for visual regression testing.",Paparazzi Showkase captureScreenshot compareBaseline,"@Test fun homeScreen_default() { paparazzi.snapshot { HomeScreen(state = previewState) } }",Only testing logic without visual regression checks
Coroutine Flow Testing,Testing,flow test turbine emission verify,"Test Flow emissions in order with Turbine testing library.",Turbine test awaitItem expectNoEvents cancelAndIgnoreRemainingEvents,"@Test fun search_emits_results() = runTest { viewModel.search(""query"").test { assertEquals(Loading, awaitItem()); assertEquals(Success(results), awaitItem()); cancelAndIgnoreRemainingEvents() } }",Collecting Flows without asserting emissions or order
Event Bus Replacement,Architecture,event bus replacement sharedflow lifecycle,"Replace EventBus with SharedFlow for decoupled communication.",MutableSharedFlow SharedFlow emit collect lifecycle,"private val _events = MutableSharedFlow<AppEvent>(); fun emit(event: AppEvent) { viewModelScope.launch { _events.emit(event) } }",Using EventBus or other reflection-based message buses
Network Connection Monitor,System,connectivity network monitor online offline,"Monitor network connectivity changes reactively.",ConnectivityManager NetworkCallback Flow callbackFlow,"fun observeConnectivity(context: Context): Flow<Boolean> = callbackFlow { val callback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { trySend(true) }; override fun onLost(network: Network) { trySend(false) } }; connectivityManager.registerDefaultNetworkCallback(callback); awaitClose { connectivityManager.unregisterNetworkCallback(callback) } }",Checking connectivity only once at app startup
Compose Key for LazyList,Compose,key identity lazy list recompose stable,"Provide stable keys for LazyColumn/LazyRow items.",items key contentType stable identity,"LazyColumn { items(items = users, key = { it.id }, contentType = { ""user_card"" }) { UserCard(it) } }",Not providing keys causing full list recomposition on any change
Category,Issue,Keywords,Description,Do,Don't,Code Example Good,Code Example Bad,Severity
Compose,Unnecessary Recomposition,recompose stable immutable,"Composable recomposes when parameters change even if values are same","Use @Stable/@Immutable annotations on data classes. Use ImmutableList.","Pass unstable List<T> or mutable objects as parameters.","@Immutable data class UiState(val items: ImmutableList<Item>)","data class UiState(val items: List<Item>) // Unstable!",HIGH
Compose,Lambda Recreation,lambda remember callback,"New lambda instance created every recomposition triggers child recomposition.","Use remember for lambdas or hoist callbacks to non-composable scope.","Create inline lambdas with captures inside composable.","val onClick = remember { { viewModel.doAction() } }","Button(onClick = { viewModel.doAction() }) // Recreated each recompose",MEDIUM
Compose,derivedStateOf Misuse,derived state combine,"derivedStateOf should wrap expensive computations that depend on other state.","Use derivedStateOf when computation is expensive and triggered by state change.","Use derivedStateOf for simple property access.","val filtered = remember { derivedStateOf { items.filter { it.active } } }","val filtered = items.filter { it.active } // Runs every recompose",MEDIUM
Compose,Key Missing in LazyColumn,lazy key recomposition list,"Without keys LazyColumn can't efficiently diff items.","Always provide unique key parameter in items block.","Rely on position-based identity.","items(users, key = { it.id }) { UserRow(it) }","items(users) { UserRow(it) } // No stable identity",HIGH
Compose,Large Composable,composable split extract,"Single composable with 200+ lines causes slow recomposition.","Extract into smaller focused composables with clear boundaries.","Keep everything in one giant composable function.","@Composable fun ProfileHeader(...); @Composable fun ProfileContent(...)","@Composable fun ProfileScreen() { /* 500 lines */ }",HIGH
Async,Main Thread Blocking,main thread IO dispatcher,"Heavy computation or I/O on main thread causes ANR.","Use withContext(Dispatchers.IO) for I/O and Dispatchers.Default for CPU.","Call suspend functions that do I/O without switching dispatcher.","val data = withContext(Dispatchers.IO) { repo.fetchFromNetwork() }","val data = repo.fetchFromNetwork() // On Main thread!",CRITICAL
Async,Missing Cancellation,coroutine cancel scope,"Not respecting cancellation causes memory leaks and unnecessary work.","Use viewModelScope. Check isActive in long loops. Don't catch CancellationException.","Use GlobalScope or ignore CancellationException.","viewModelScope.launch { fetchData() } // Auto-cancels","GlobalScope.launch { fetchData() } // Never cancels",HIGH
Async,Unnecessary Flow Collection,flow collect lifecycle,"Collecting Flow when UI is not visible wastes resources and battery.","Use collectAsStateWithLifecycle() in Compose.","Use collectAsState() which doesn't respect lifecycle.","val state by flow.collectAsStateWithLifecycle()","val state by flow.collectAsState() // Collects even when backgrounded",MEDIUM
Memory,Image Loading OOM,image bitmap memory cache,"Loading full-resolution images causes OutOfMemoryError.","Use Coil/Glide with proper sizing and caching. Downsample large images.","Load full-res bitmaps into memory directly.","AsyncImage(model = ImageRequest.Builder(ctx).data(url).size(Size.ORIGINAL).build())","BitmapFactory.decodeFile(path) // Full resolution, no caching",HIGH
Memory,View/Activity Leak,leak reference static context,"Holding Activity/Fragment reference in ViewModel or singleton causes leak.","Use Application context or weak references. LeakCanary for detection.","Store Activity context in ViewModel or companion object.","class VM(private val app: Application) : AndroidViewModel(app)","class VM { var activity: Activity? = null } // LEAK!",CRITICAL
Startup,Cold Start,startup splash baseline profile,"Slow cold start causes poor user experience and low retention.","Generate Baseline Profile. Defer non-critical init. Use App Startup library.","Initialize everything in Application.onCreate().","class AppInitializer : Initializer<Unit> { /* deferred init */ }","class App : Application() { onCreate() { /* init ALL libs here */ } }",HIGH
List,Large Dataset,pagination paging lazy,"Loading 10000+ items at once causes OOM and janky scrolling.","Use Paging 3 with RemoteMediator for large datasets.","Load all data into memory from API.","Pager(PagingConfig(20)) { pagingSource }.flow.cachedIn(viewModelScope)","val allItems = api.getAllItems() // Loads everything",HIGH
Network,No Timeout,okhttp timeout hang,"Missing timeouts cause indefinite hangs on poor networks.","Set explicit connect/read/write timeouts on OkHttpClient.","Use default (infinite) timeouts.","OkHttpClient.Builder().connectTimeout(15, SECONDS).readTimeout(30, SECONDS)","OkHttpClient.Builder().build() // No timeouts set",HIGH
Build,APK Size,proguard shrink resources apk,"Large APK reduces install conversion rate.","Enable R8 minification, resource shrinking. Use App Bundle.","Ship debug APK or APK with unused resources.","isMinifyEnabled = true; isShrinkResources = true","isMinifyEnabled = false // Full APK with debug info",MEDIUM
Build,Gradle Build Speed,gradle cache parallel ksp,"Slow builds reduce developer productivity.","Use KSP over KAPT. Enable Gradle cache and parallel execution.","Use KAPT for annotation processing.","ksp(""com.google.dagger:hilt-compiler:x.x"")","kapt(""com.google.dagger:hilt-compiler:x.x"") // Slower",MEDIUM
Compose,Unstable Collections,list set map unstable recompose parameter,Android,"Passing standard List/Set/Map causes unnecessary recomposition.","Use kotlinx.collections.immutable ImmutableList/PersistentList.","Pass mutable ArrayList or standard List.","data class State(val items: ImmutableList<Item>)","data class State(val items: List<Item>) // Unstable!",HIGH
Compose,Excessive Modifier Nesting,modifier nested combine chain performance,Android,"Deeply nested modifiers create excessive layout passes.","Combine modifiers in a single chain. Extract common modifiers.","Create new Modifier chains inside composition.","val cardModifier = remember { Modifier.padding(16.dp).clip(RoundedCornerShape(12.dp)) }","// Creating Modifier.then(Modifier.then(...)) deeply nested",MEDIUM
Database,Query on Main Thread,room database query main ui thread anr,Android,"Database queries on main thread cause ANR.","Always use suspend functions or Flow for Room queries.","Call blocking DAO methods on main dispatcher.","@Query(""SELECT * FROM users"") fun observeAll(): Flow<List<User>>","@Query(""SELECT * FROM users"") fun getAll(): List<User> // Blocking!",CRITICAL
Network,Response Caching,okhttp cache etag modified response,Android,"Not caching API responses wastes bandwidth and increases latency.","Configure OkHttp cache directory and cache-control headers.","Fetch fresh data every time without caching.","OkHttpClient.Builder().cache(Cache(cacheDir, 10 * 1024 * 1024))","// No cache configured, always hits network",MEDIUM
Animation,Animation Frame Drops,animation jank frame drop 16ms render,Android,"Complex animations dropping below 60fps cause janky UI.","Use Compose animation APIs. Profile with GPU rendering overlay.","Running heavy computation during animations.","val anim by animateFloatAsState(target, tween(300))","// Custom frame loop with heavy computation per frame",HIGH
Stage,Goal,Prompt Template,Output Schema,Required Inputs,Length/Limit,Quality Gate,Notes
App Identity,Extract app USP and target audience,"Analyze this Android app: {app_description}. Extract: 1) Core value proposition 2) Target audience 3) Top 3 differentiators 4) Primary category 5) Secondary category","{ ""usp"": """", ""audience"": """", ""differentiators"": [], ""primary_category"": """", ""secondary_category"": """" }","App description, target market","N/A","USP must be clear and specific, not generic",Start here before any listing copy
App Name,Generate Play Store app name,"Generate 5 app name options for: {app_description}. Rules: max 30 chars, include brand + 1 keyword, no special characters, easy to remember.","{ ""options"": [{ ""name"": """", ""chars"": 0, ""keyword"": """" }] }","Brand name, core keyword","30 characters max","Must include brand name. No keyword stuffing.",Test search rankings with different names
Short Description,Write compelling short description,"Write 3 short descriptions for {app_name}: {usp}. Rules: max 80 chars, lead with benefit, include 1 keyword, end with action verb or outcome.","{ ""options"": [{ ""text"": """", ""chars"": 0 }] }","App name, USP, primary keyword","80 characters max","Must fit in 80 chars. No claims without proof.",Shows below app name in search results
Full Description,Write structured full description,"Write full Play Store description for {app_name}. Structure: Para 1 (core value 50-100 words) + Bullet features (5-7) + Para 2 (how it works) + Para 3 (social proof) + CTA. Include keywords naturally.","{ ""paragraphs"": [], ""bullets"": [], ""keywords_used"": [] }","App name, USP, features list, keywords","4000 characters max","No keyword stuffing. Benefits over features. Policy-safe claims.","Use unicode bullets ★ and line breaks for readability"
Content Rating,Complete IARC content rating questionnaire,"Based on this app: {app_description}. Answer IARC questionnaire: 1) Violence? 2) Sexual content? 3) Language? 4) Controlled substances? 5) User interaction? 6) Location sharing? 7) Personal info collection?","{ ""violence"": ""none/mild/moderate"", ""sexual"": ""none/mild"", ""language"": ""none/mild"", ""substances"": ""none/reference"", ""user_interaction"": ""yes/no"", ""location"": ""yes/no"", ""personal_info"": ""yes/no"" }","App features, data collection, user interaction","N/A","Must be accurate. False declarations = policy violation.",Review after each major feature update
Data Safety,Generate data safety form answers,"For app {app_name} with features: {features}. List: 1) Data collected (type + purpose) 2) Data shared (type + recipient) 3) Data handling practices (encryption, deletion).","{ ""collected"": [{ ""type"": """", ""purpose"": """", ""required"": true }], ""shared"": [], ""security"": { ""encrypted"": true, ""deletion_policy"": """" } }","App features, SDKs used, analytics tools","N/A","Must match actual app behavior. Include all third-party SDKs.",Update when adding new SDKs or analytics
Privacy Policy,Generate privacy policy outline,"Generate privacy policy sections for {app_name}: data collected, purpose, sharing, retention, security, user rights, contact info. Must comply with GDPR and CCPA.","{ ""sections"": [{ ""title"": """", ""content"": """" }] }","Data practices, company info, contact email","N/A","Must be accurate and legally compliant. Link must be accessible.",Host on public URL. Update when data practices change
Screenshot Strategy,Plan screenshot story flow,"Plan 8 screenshots for {app_name}. Each: 1) Screen shown 2) Caption (max 2 lines) 3) Benefit highlighted. Flow: Hook > Core Feature > Key Benefit > Social Proof.","{ ""screenshots"": [{ ""order"": 1, ""screen"": """", ""caption"": """", ""benefit"": """" }] }","App screens, key features, target audience","8 screenshots, 16:9 or 9:16","First screenshot must convey core value in 1 second.",Use real app UI with benefit-focused captions
Feature Graphic,Design feature graphic brief,"Create feature graphic brief for {app_name}: 1024x500px. Include: app logo, tagline (max 5 words), key visual, brand colors. Must be readable at small sizes.","{ ""tagline"": """", ""visual_elements"": [], ""colors"": { ""bg"": """", ""text"": """" } }","Brand assets, tagline, key visual","1024 x 500 px","Text readable on mobile card size. No fine details.",Shown in Play Store featured sections
Release Notes,Write version release notes,"Write release notes for {app_name} v{version}: New: {new_features}. Fixed: {bug_fixes}. Rules: user-facing language, bullet format, most important first.","{ ""whats_new"": """", ""chars"": 0 }","Version number, new features, bug fixes","500 characters max","User-friendly language. No technical jargon.",Keep concise. Users scan, don't read
Product Type,Keywords,Primary Style Recommendation,Secondary Styles,Color Palette Focus
Fintech/Banking,finance money transfer payment wallet,"Material 3 Clean + Corporate","Dark Mode Premium, Flat Modern","Trust blue + security green + minimal accent"
E-Commerce,shopping cart product catalog checkout,"Material 3 Clean + Gradient Accent","Flat Modern, Playful Colorful","Warm CTA (orange/red) + neutral background"
Healthcare/Medical,health appointment doctor patient record,"Material 3 Clean + Organic Soft","Flat Modern, Corporate Professional","Calming teal/green + white + alert red"
Fitness/Wellness,workout gym tracking exercise health,"Dark Mode Premium + Gradient Accent","Flat Modern, Brutalist","High-energy orange/red + success green + dark bg"
Social Media,feed posts stories chat messaging,"Gradient Accent + Dark Mode Premium","Glassmorphism, Playful Colorful","Vibrant brand colors + gradient backgrounds"
Education/Learning,course lesson quiz student progress,"Material 3 Clean + Flat Modern","Playful Colorful, Organic Soft","Blue/purple + yellow accents for achievements"
Food Delivery,restaurant menu order delivery tracking,"Material 3 Clean + Playful Colorful","Flat Modern, Gradient Accent","Appetite warm (red/orange) + fresh green"
Travel/Booking,hotel flight booking trip destination,"Material 3 Clean + Organic Soft","Glassmorphism, Editorial Clean","Sky blue + warm accent + white space"
Productivity/Tools,task project kanban calendar notes,"Material 3 Clean + Flat Modern","Dark Mode Premium, Corporate Professional","Focused blue + neutral + success green"
Gaming/Entertainment,game score leaderboard achievement play,"Dark Mode Premium + Glassmorphism","Gradient Accent, Brutalist","Neon accents on dark + gold for rewards"
News/Media,article feed read publication magazine,"Editorial Clean + Material 3 Clean","Dark Mode Premium, Flat Modern","Minimal: dark text + white bg + red accent"
SaaS/Dashboard,analytics metrics graph report KPI,"Dark Mode Premium + Material 3 Clean","Corporate Professional, Flat Modern","Data blue + success green + alert red"
Kids/Family,children family game educational fun,"Playful Colorful + Organic Soft","Flat Modern, Material 3 Clean","Bright primaries + soft pastels + large touch"
Real Estate,property listing house rent buy mortgage,"Material 3 Clean + Corporate Professional","Organic Soft, Editorial Clean","Earthy tones + warm accent + white space"
Music/Audio,streaming playlist podcast listen DJ,"Dark Mode Premium + Glassmorphism","Gradient Accent, Brutalist","Dark surfaces + signature green + vibrant art"
Crypto/Web3,blockchain crypto defi token nft,"Dark Mode Premium + Glassmorphism","Cyberpunk Neon, Gradient Accent","Purple/blue gradients + gold for value + neon accents"
Dating/Social,dating match swipe profile romance,"Gradient Accent + Organic Soft","Playful Colorful, Glassmorphism","Romantic pinks/reds + gradient backgrounds + warm tones"
Meditation/Mindfulness,meditation calm breathe sleep zen,"Organic Soft + Scandinavian Minimal","Japanese Zen, Soft Gradient","Muted earth tones + calm blues + minimal interface"
Legal/Government,law court official government tax,"Corporate Professional + Material 3 Clean","Swiss Grid, Flat Modern","Conservative navy + formal gray + minimal accent"
Photography/Art,photo gallery portfolio creative visual,"Dark Mode Premium + Flat Modern","Brutalist, Editorial Clean","Dark galleries + minimal chrome + accent for actions"
Logistics/Delivery,shipping delivery track fleet route,"Material 3 Clean + Flat Modern","Corporate Professional, Gradient Accent","Orange tracking + navy reliability + green confirmed"
Agriculture/Farm,farm crop organic harvest agriculture,"Organic Soft + Material 3 Clean","Scandinavian Minimal, Flat Modern","Earth greens + harvest yellow + natural brown"
Pet/Animal,pet dog cat vet animal wellness,"Playful Colorful + Organic Soft","Material 3 Clean, Soft Gradient","Warm orange + friendly teal + playful accents"
Automotive,car vehicle auto dealer motor service,"Dark Mode Premium + Material 3 Clean","Brutalist, Swiss Grid","Dark sophistication + red performance + silver premium"
Construction/Home,construction property renovation build,"Material 3 Clean + Corporate Professional","Flat Modern, Dark Industrial","Safety yellow + steel gray + alert red"
Insurance,insurance policy claim coverage premium,"Corporate Professional + Material 3 Clean","Flat Modern, Swiss Grid","Trust blue + coverage green + CTA orange"
Sustainability/Green,eco green recycle carbon environment,"Organic Soft + Material 3 Clean","Scandinavian Minimal, Flat Modern","Multi-green palette + natural textures + earth tones"
Wedding/Events,wedding event party celebration ceremony,"Soft Gradient + Organic Soft","Art Deco, Editorial Clean","Gold luxury + blush pink + cream elegance"
Sport/Betting,sport bet odds score live match,"Dark Mode Premium + Glassmorphism","Cyberpunk Neon, Gradient Accent","Dark immersive + green winning + gold premium odds"
IoT/Smart Home,smart home device iot connected sensor,"Dark Mode Premium + Material 3 Clean","Flat Modern, Glassmorphism","Dark control + blue connectivity + purple automation"
Music Production,studio mixing daw audio production,"Dark Mode Premium + Dark Industrial","Brutalist, Cyberpunk Neon","Pure dark studio + purple creative + green levels"
Streaming Video,video stream watch series movie,"Dark Mode Premium + Material 3 Clean","Glassmorphism, Flat Modern","Dark immersive + red brand + white text"
Charity/Non-profit,donate charity volunteer nonprofit give,"Material 3 Clean + Organic Soft","Playful Colorful, Flat Modern","Warm orange + trust blue + impact green"
Pharmacy/Medical Supply,pharmacy medicine prescription drug rx,"Material 3 Clean + Corporate Professional","Flat Modern, Swiss Grid","Clean white + pharmacy green + prescription red"
Restaurant/Cafe,restaurant cafe menu order table reserve,"Material 3 Clean + Playful Colorful","Organic Soft, Vintage Warm","Warm appetizing + fresh accents + inviting palette"
Ride Sharing,ride taxi uber lyft driver passenger,"Material 3 Clean + Flat Modern","Dark Mode Premium, Gradient Accent","Map green + CTA orange + dark ride tracking"
Grocery/Shopping,grocery supermarket fresh delivery meal,"Material 3 Clean + Playful Colorful","Organic Soft, Flat Modern","Fresh green + appetizing warm + clean white"
Task Management,task kanban board todo checklist sprint,"Material 3 Clean + Flat Modern","Dark Mode Premium, Swiss Grid","Focus blue + done green + overdue red + minimal"
Weather,weather forecast temperature rain sun climate,"Glassmorphism + Soft Gradient","Dark Mode Premium, Organic Soft","Sky gradient + warm yellow sun + rain blue + dynamic"
Podcast,podcast audio episode listen subscribe queue,"Dark Mode Premium + Material 3 Clean","Flat Modern, Editorial Clean","Dark bg + vibrant cover art + clean player controls"
Calendar/Scheduling,calendar schedule event meeting booking slot,"Material 3 Clean + Flat Modern","Corporate Professional, Swiss Grid","Event color-coding + clean white bg + focus blue"
Notes/Writing,notes markdown journal writing diary doc,"Material 3 Clean + Editorial Clean","Dark Mode Premium, Scandinavian Minimal","Minimal chrome + reading-focused + warm paper tones"
Social Commerce,social commerce live selling influencer shop,"Gradient Accent + Playful Colorful","Material 3 Clean, Dark Mode Premium","Vibrant social + shopping CTA + live badge red"
Home Automation,home automation device control schedule routine,"Dark Mode Premium + Material 3 Clean","Glassmorphism, Flat Modern","Blue connectivity + green active + red alert + dark"
Language Learning,language learn vocabulary grammar quiz flashcard,"Material 3 Clean + Playful Colorful","Flat Modern, Gamification","Level gold + progress green + friendly accent colors"
Budgeting/Finance Personal,budget expense track income savings goal,"Material 3 Clean + Flat Modern","Dark Mode Premium, Corporate Professional","Expense red + income green + goal gold + neutral bg"
Parking/EV Charging,parking spot ev charge station map reserve,"Material 3 Clean + Flat Modern","Dark Mode Premium, Glassmorphism","Available green + occupied red + reserved blue + map"
Recipe/Cooking,recipe cook meal prep ingredient timer step,"Material 3 Clean + Organic Soft","Playful Colorful, Vintage Warm","Appetizing warm + step-by-step green + timer accent"
Inventory/Warehouse,inventory stock warehouse barcode scan manage,"Corporate Professional + Material 3 Clean","Flat Modern, Swiss Grid","Neutral gray + alert red/yellow/green stock levels"
Telemedicine,telehealth video call doctor remote consult,"Material 3 Clean + Corporate Professional","Organic Soft, Flat Modern","Calm teal + trust blue + availability green"
HR/Employee,hr employee payroll leave attendance portal,"Corporate Professional + Material 3 Clean","Flat Modern, Swiss Grid","Professional navy + action blue + approved green"
Auction/Marketplace,auction bid marketplace listing sell buy,"Material 3 Clean + Gradient Accent","Dark Mode Premium, Playful Colorful","Bid orange + winning green + time urgency red"
CRM/Sales,crm sales pipeline lead deal contact,"Corporate Professional + Dark Mode Premium","Material 3 Clean, Swiss Grid","Pipeline blue stages + won green + lost gray"
Ticketing/Events,ticket event concert venue seat booking,"Material 3 Clean + Gradient Accent","Dark Mode Premium, Glassmorphism","Event vibrant + seat map blue + booking CTA orange"
Survey/Feedback,survey feedback poll questionnaire form rating,"Material 3 Clean + Flat Modern","Corporate Professional, Playful Colorful","Progress blue + completion green + neutral form bg"
Style Category,AI Prompt Keywords (Copy-Paste Ready),CSS/Technical Keywords,Implementation Checklist
Material 3 Clean,"modern material3 clean android compose surface elevation tonal","MaterialTheme colorScheme typography shapes RoundedCornerShape Surface elevated","Use MaterialTheme tokens | Define custom ColorScheme | Setup Typography with Google Fonts | Use Surface for containers"
Dark Mode Premium,"dark amoled premium sleek contrast neon glow android compose","darkColorScheme isSystemInDarkTheme Color(0xFF121212) elevated surface contrast","Define darkColorScheme | Test on AMOLED | Verify contrast ratios | Use tonal elevation"
Glassmorphism,"glass blur transparent frosted overlay mobile android","Modifier.blur graphicsLayer alpha BackdropFilter frosted","Use Modifier.blur for glass effect | Semi-transparent Surface | Vibrant content behind glass | Test on low-end devices"
Neumorphism,"soft shadow emboss raised pressed material surface android","Modifier.shadow shape offset blur spread ElevatedCard","Custom shadow with offset | Light/dark shadow pairs | Press state with inset | Test accessibility contrast"
Gradient Accent,"gradient colorful vibrant energy linear radial android compose","Brush.linearGradient Brush.horizontalGradient animateColorAsState","Define gradient as Brush | Apply to Box background | Animate gradient colors | Keep text readable on gradient"
Flat Modern,"flat clean minimal no-shadow bold typography compose","elevation(0.dp) shape = RectangleShape bold Typography","Remove all elevation | Sharp corners | Bold headings | Strong color blocks | White space"
Editorial Clean,"editorial serif content magazine reading long-form android","fontFamily(serif) lineHeight letterSpacing readability","Custom serif Typography | Generous lineHeight | Reading-optimized text size | Pull quotes styling"
Corporate Professional,"corporate enterprise structured hierarchy clean data dashboard","structured grid consistent spacing subdued palette icon-driven nav","Define design tokens early | Consistent spacing scale | Subdued palette | Clear visual hierarchy"
Playful Colorful,"playful colorful fun bright rounded bouncy kids android","RoundedCornerShape(50) animateDpAsState spring animation vibrant","Full rounded corners | Spring animations | Vibrant colors | Generous padding | Fun illustrations"
Brutalist,"raw bold oversized monospace industrial grunge android","fontFamily(monospace) large fontSize borderWidth sharp edges","Monospace typography | Oversized headings | Thick borders | Minimal decoration | Black + white + accent"
Organic Soft,"organic natural rounded earth warm gentle calm android","RoundedCornerShape warm Color earth tones gentle animation","Organic rounded shapes | Earth tone palette | Gentle animations | Nature-inspired icons | Warm backgrounds"
Skeuomorphic Detail,"realistic textured depth shadow 3d detailed android compose","Modifier.shadow elevation gradients texture overlay detailed icons","Multiple shadow layers | Textured backgrounds | Gradient overlays | Detailed icon work | Realistic buttons"
Dark Mode Premium,"dark premium sleek amoled contrast neon cyber glow","darkColorScheme Color(0xFF121212) tonalElevation contrast neon glow","Define DarkColorScheme | Test on AMOLED | Neon accent borders | Surface tonal elevation"
Glassmorphism,"glass frosted blur transparent crystal overlay acrylic","Modifier.blur alpha graphicsLayer BackdropFilter translucent","Background Modifier.blur | Semi-transparent Cards | Vibrant accent | Test GPU load"
Soft Gradient,"gradient aurora pastel blend dreamy soft flowing","Brush.linearGradient animateColorAsState gradient mesh","Multi-stop gradients | Animate hue shifts | Pastel palette | Keep text readable"
Neumorphism,"soft emboss raised pressed shadow light dark inset","Modifier.shadow offset shape inset outset pressed raised","Light shadow + dark shadow | Match bg hue | Press state invert | Accessibility concern"
Brutalist,"raw bold oversized monospace industrial concrete grid","fontFamily(monospace) large fontSize thick border Weight","Oversized type | Monospace body | Thick borders | Black + white + accent"
Retro Pixel,"pixel retro 8bit nostalgic chiptune gameboy lo-fi","custom pixelated font Bitmap sharp rendering","Pixel fonts | Step animations | Limited palette | 8-bit sound effects"
Art Deco,"art deco gatsby gold luxury geometric ornate premium","Gold Color(0xFFD4A843) geometric patterns serif display","Gold accents | Geometric patterns | Serif headings | Premium cards"
Japanese Zen,"zen wabi-sabi japanese eastern calm asymmetric minimal","warm white Color(0xFFFFF8E7) asymmetric spacing fade","Warm white bg | Asymmetric layouts | Fade transitions | Ink-wash motifs"
Swiss Grid,"swiss bauhaus grid modular rational structured helvetica","strict grid Column spacing consistent typography scale","Grid-based layout | Rational spacing | Bold headings | Single accent"
Cyberpunk Neon,"cyberpunk neon tron digital glow scanline matrix","neon Color(0xFFFF0080) cyan glitch scanline glow","Neon borders | Glitch effects | Scanline overlays | Dark backgrounds"
Scandinavian Minimal,"scandinavian nordic hygge cozy warm natural wood","off-white Color(0xFFF7F3F0) sage green natural shadow","Off-white backgrounds | Natural shadows | Sage green accents | Generous whitespace"
Material You Dynamic,"material you dynamic monet wallpaper android 12 adaptive","dynamicLightColorScheme dynamicDarkColorScheme Build.VERSION.SDK_INT","Check SDK >= 31 | Fall back to static scheme | Test with multiple wallpapers | Handle dark mode"
Vintage Warm,"vintage warm retro analog cozy sepia film nostalgic","warm Color sepia rounded corners film grain texture","Warm tinted backgrounds | Rounded corners | Film grain overlay | Vintage typography"
Layered Paper,"layered paper stacked depth shadow card offset pile","elevation shadow offset Card stacked padding overlap","Multiple Card layers | Offset shadows | Slight rotation | Peek backgrounds"
Dashboard Dark,"dashboard dark data grid card metric chart graph","Color(0xFF0F172A) card grid system Chart metric","Dark Surface cards | Grid layout system | Color-coded metrics | Chart integration"
Duotone,"duotone two-tone dual color monotone image filter","ColorFilter colorMatrix duotone blend overlay","Duotone image filter | Two-color gradients | Monotone sections | High contrast"
Terminal CLI,"terminal console hacker matrix green code command","Color(0xFF00FF41) monospace fontFamily cursor blink","Green on black | Monospace font | Typing animation | Cursor blink | Code blocks"
Parallax Depth,"parallax scroll depth layered immersive storytelling","graphicsLayer translationX translationY scroll offset","Multi-layer parallax | Scroll-driven position | Fade on scroll | Scale on depth"
Neo Brutalism,"neo brutalism bold border offset thick colorful web","thick Border offset shadow saturated bold fontSize","Black borders 3-4dp | Offset box shadows | Bold saturated fills | No border-radius"
Frosted Acrylic,"frosted acrylic blur panel reveal highlight depth","Modifier.blur alpha overlay tinted panel","Tinted blur panels | Acrylic overlay | Depth layering | Reveal highlight"
Style Category,Type,Keywords,Primary Colors,Effects & Animation,Best For,Do Not Use For
Material 3 Clean,Modern,"material3 clean minimal surface elevation","Surface + Primary + Tertiary","Tonal elevation, smooth transitions, ripple effects","Most Android apps, productivity, enterprise","Creative/artistic apps needing unique identity"
Glassmorphism,Premium,"glass blur transparent frosted overlay","White/Black with alpha + vibrant accent","Background blur, frosted glass cards, subtle transparency","Dashboards, weather, music players","Text-heavy apps or low-end devices (blur is expensive)"
Dark Mode Premium,Dark,"dark amoled contrast neon accent","Dark surface (#121212) + vibrant accents","Subtle glow, neon borders, smooth fade transitions","Media, gaming, night-mode apps","Apps used primarily outdoors in bright light"
Neumorphism,Soft,"soft shadow emboss raised pressed","Light grays (#E0E5EC) + subtle shadows","Inset/outset shadows, pressed/raised states","Settings panels, calculators, casual apps","Data-heavy screens or accessibility-critical apps"
Flat Modern,Minimal,"flat clean no-shadow bold color","Bold primary + white space + gray","No shadows, sharp edges, bold typography","Landing pages, text-focused apps","Apps needing depth perception or layering"
Gradient Accent,Vibrant,"gradient colorful vibrant energy","Multi-color gradients + white text","Animated gradients, color transitions","Social media, fitness, entertainment","Financial apps, medical, enterprise"
Brutalist,Bold,"raw bold oversized monospace industrial","Black + White + single accent","Large typography, hard edges, no rounded corners","Portfolio, art, creative tools","Children's apps, healthcare, gentle UX"
Organic Soft,Natural,"organic rounded warm earth nature","Earth tones + soft greens + warm whites","Organic shapes, gentle animations, nature-inspired","Wellness, meditation, food, sustainability","Tech/dev tools, gaming"
Editorial Clean,Content,"editorial serif readable newspaper magazine","Dark text + cream/white + red accents","Smooth scroll, pull quotes, reading progress bar","News, blogs, reading apps","Interactive/gamified apps"
Skeuomorphic Detail,Realistic,"realistic texture shadow 3d depth","Natural textures + realistic shadows","3D buttons, textured backgrounds, detailed icons","Utility apps, instruments, luxury product showcase","Scalable enterprise apps or text-heavy screens"
Corporate Professional,Enterprise,"corporate clean structured hierarchy","Navy + gray + green accents","Minimal animations, structured grids, clear hierarchy","CRM, ERP, B2B enterprise","Consumer-facing playful apps"
Playful Colorful,Fun,"playful bright cartoon friendly kids","Primary rainbow + soft pastels","Bouncy animations, rounded corners, confetti effects","Kids apps, casual games, social","Medical, financial, security apps"
Retro Pixel,Nostalgic,"retro pixel 8bit nostalgic game boy","Pixel borders + limited palette + chiptune vibes","Pixel-perfect alignment, step animations, 8-bit sound effects","Retro games, nostalgia apps, indie games","Professional/enterprise apps or financial services"
Art Deco,Luxury Vintage,"art deco gatsby luxury gold geometric ornate","Gold + black + geometric patterns","Fan/sunburst patterns, geometric borders, serif typography","Luxury brands, premium subscriptions, fashion","Kids apps, utility tools, data-heavy interfaces"
Cyberpunk Neon,Futuristic,"cyberpunk neon glow futuristic tron digital","Neon pink (#FF0080) + cyan (#00FFFF) on black","Glitch effects, scanline overlays, neon glow borders","Gaming, tech demos, music apps, nightlife","Healthcare, banking, kids/family apps"
Scandinavian Minimal,Clean Nordic,"scandinavian nordic hygge minimal cozy warm","Off-white + light wood (#DEB887) + sage green","Very minimal transitions, natural shadows, lots of white space","Lifestyle, meditation, home decor, journaling","Data dashboards, gaming, high-action apps"
Paper/Card Material,Tactile,"paper card material tactile shadow craft","White #FFFFFF + soft shadows + colored accents","Card lift on tap, subtle paper texture, stacking animations","Note-taking, task management, CMS, forms","Immersive media, gaming, photography portfolios"
Japanese Zen,Eastern Minimal,"zen japanese wabi-sabi minimal eastern calm","Warm white (#FFF8E7) + charcoal + muted green","Fade transitions, bamboo/ink-wash motifs, asymmetric balance","Meditation, poetry, cultural, tea ceremony, spa","Fast-paced gaming, social media, e-commerce"
Swiss Grid,Structured,"swiss grid bauhaus structured rational modular","Pure white + pure black + single accent color","Grid-based positioning, rational spacing, bold type hierarchies","Business tools, typography-focused, editorial","Playful consumer apps, kids, entertainment"
Material You,Adaptive,"material you dynamic color monet android 12+","Dynamic from wallpaper via MaterialTheme","Tonal color harmony, shape morphing, adaptive icons","General Android apps, Google-style, system-aligned","Apps needing strict brand identity across platforms"
Isometric 3D,Dimensional,"isometric 3d depth perspective illustrated","Rich accent palette + depth shadows + illustrated elements","Isometric card animations, depth parallax, illustrated icons","Onboarding, dashboards, marketing, portfolio","Text-heavy reading apps, accessibility-critical"
Monochrome High Contrast,Accessible,"monochrome bw high contrast accessibility stark","Pure black + pure white + one accent","Sharp transitions, no gradients, high readability","Accessibility-first apps, legal, document viewers","Visual portfolios, photography, creative apps"
Frosted Material,Modern Glass,"frosted glass material acrylic blur modern","Semi-transparent panels + vibrancy + tinted blur","Layer blur, vibrancy effects, depth through opacity","Audio players, overlays, dashboards, weather","Low-end device targets, GPU-constrained apps"
Memphis Design,Postmodern Fun,"memphis postmodern geometric bold pattern squiggle","Bold primaries + geometric patterns + confetti","Bouncing shapes, pattern-filled backgrounds, irregular grids","Creative tools, marketing, portfolios, events","Formal enterprise, medical, legal applications"
Line/Wireframe,Development,"wireframe line outline sketch prototype minimal","Thin stroke colors + white fill + minimal accent","Line drawing animations, outline-to-fill on interaction","Developer tools, prototyping, design reference","Consumer-facing polished apps"
Soft Gradient,Dreamy,"soft gradient dreamy aurora pastel blend","Pastel gradients (pink→blue, peach→lavender)","Gradient morphing, smooth color transitions, floating elements","Social, dating, lifestyle, creative, wellness","Enterprise, data-heavy, serious professional tools"
Dark Industrial,Rugged,"industrial dark steel concrete raw rugged metal","Dark grays (#1A1A1A) + steel blue + rust orange","Metal textures, heavy borders, mechanical transitions","Automotive, construction, tools, manufacturing","Kids apps, wellness, meditation, gentle UX"
Vintage Warm,Nostalgic Cozy,"vintage warm retro cozy analog film grain","Sepia (#704214) + cream (#FFF8DC) + rust + forest green","Film grain overlay, rounded corners, warm color grading, analog feel","Photography, recipes, journals, craft apps","Tech/programming tools, modern SaaS"
Neo Brutalism,Bold Web,"neo-brutalism bold border thick offset colourful web","Thick black borders + bold saturated fills + offset shadows","Box shadow offset, thick borders, bold typography, no border-radius","Web-inspired apps, creative tools, bold statements","Subtle luxury, medical, financial"
Vaporwave,Aesthetic Retro,"vaporwave aesthetic 80s 90s synthwave pink purple retro","Neon pink (#FF71CE) + electric blue (#01CDFE) + purple (#B967FF)","Retro grid, chromatic text, gradient sky backgrounds, glitch effects","Music, creative, social, portfolio, retro gaming","Enterprise, healthcare, children"
Claymorphism,3D Soft,"clay soft 3d rounded inflated pastel cute","Pastel backgrounds + inner shadow + rounded 3D shapes","Inner shadows for inflated look, soft outer shadows, pastel palette, very rounded","Social, wellness, lifestyle, casual apps","Data-heavy, enterprise, developer tools"
Liquid Design,Fluid Organic,"liquid fluid blob amorphous flowing dynamic organic","Organic curved shapes + flowing gradients + animated blobs","SVG blob shapes, morphing animations, fluid color transitions, organic layouts","Creative, art, music visualization, meditation","Structured data, tables, precise layouts"
Maximalism,Bold Saturated,"maximalism bold saturated pattern busy energetic mix","Multiple patterns + bold colors + layered textures + mixed fonts","Pattern overlays, multiple typefaces, rich layering, animated backgrounds","Fashion, art, entertainment, gaming, creative","Minimal apps, productivity, reading, medical"
Kinetic Typography,Motion Text,"kinetic typography motion text animated words dynamic","Dark bg + large animated type + accent color for keywords","Text reveal animations, word-by-word transitions, scroll-triggered type effects","Portfolio, agency, storytelling, presentations","Utility apps, data entry, forms"
Material You Dynamic,Android 12+,"material you dynamic color monet wallpaper android","Dynamic from user wallpaper via dynamicColorScheme","Tonal palette auto-generated, shape morphing, adaptive icons, system harmony","General Android apps targeting Android 12+, Google-aligned apps","Apps needing strict brand consistency unaffected by wallpaper"
Dashboard Dark,Data Focused,"dashboard dark data widget card metric chart grid","Dark bg (#0F172A) + data blue (#3B82F6) + grid cards","Card grid layout, metric animations, chart transitions, real-time updates","Analytics, monitoring, admin panels, IoT control","Content reading, creative portfolios, consumer apps"
Parallax Depth,Immersive Scroll,"parallax depth scroll layered immersive storytelling","Layered backgrounds + scroll-driven animations + depth effect","Multi-layer scroll at different speeds, fade on scroll, scale on scroll","Storytelling apps, portfolios, long-form content, marketing","Quick-action utility apps, settings, data entry"
Micro-interaction Rich,Detail Focused,"micro interaction detail animation feedback responsive polish","Neutral base + accent animations + haptic-paired visuals","Button press feedback, toggle animations, loading transitions, pull effects","Premium apps wanting polished feel, banking, luxury","MVP/prototype stage apps where speed matters over polish"
Split Screen,Dual Panel,"split screen dual panel two-tone contrast half side-by-side","Two contrasting bg sections + shared accent","Before/after comparisons, dual-panel navigation, contrasting info sections","Comparison tools, split-view editors, A/B views","Simple single-flow apps, mobile-first narrow UIs"
Neon Glassmorphism,Vibrant Glass,"neon glass blur vibrant glow transparent border","Neon border glow + frosted glass cards + dark bg","Animated neon borders, blur backdrop, vibrant glow effects, dark ambient bg","Music players, gaming, nightlife, entertainment","Professional enterprise, medical, accessibility-first"
Stacked Cards,Z-Depth,"stacked cards depth z-index layered pile carousel","Card shadows + z-offset + peek animation","Stacked card reveal, swipe through stack, depth parallax on cards","Dating (Tinder-like), flashcards, photo review, shopping","Text-heavy content, long lists, data tables"
Sidebar Navigation,Desktop Pattern,"sidebar navigation rail drawer menu desktop tablet persistent","Persistent side panel + content area + collapsed mode","Expand/collapse animation, selected state highlight, nested menu support","Tablet/desktop apps, admin panels, email clients","Phone-only simple apps with 3-4 destinations"
Aura Glow,Premium Glow,"aura glow halo radiance luminous premium shiny","Radiant gradients + glow behind elements + deep dark base","Glow/halo behind cards, radiant gradient borders, luminous text effects","Premium features, hero sections, subscription upsell, gaming achievements","Text-heavy apps, accessibility-critical, data tables"
Hand-Drawn Sketch,Casual Craft,"hand drawn sketch doodle informal casual illustration","White bg + pen-stroke borders + handwritten font vibes","Wobbly borders, hand-drawn icon overlays, informal spacing","Brainstorming, whiteboarding, educational, creative note apps","Corporate professional, banking, legal"
Gradient Mesh,Complex Visual,"gradient mesh multi-color blending aurora borealis","Multi-color gradient mesh backgrounds + clean white foreground","Mesh gradient CSS-like backgrounds, color morphing, aurora effects","Hero sections, splash screens, creative portfolios, music apps","Data dashboards, settings screens, forms"
Terminal/CLI,Developer Hacker,"terminal cli console hacker matrix code green","Green (#00FF41) on black (#0D0208) + monospace everything","Typing cursor blink, command-line text reveal, matrix rain optional","Developer tools, server monitoring, hacking simulators, GitHub-style apps","Consumer-facing mainstream apps, kids, elderly"
Layered Paper,Depth Stack,"layered paper stacked depth shadow card offset material","White cards + subtle shadows + slight offset positioning","Stacked card depth, parallax on scroll, background peek through gaps","Card-heavy UIs, discovery feeds, portfolio showcases, recipe apps","Dense data tables, forms, settings"
Duotone,Two-Tone,"duotone two-tone dual color monotone spotlight","Two-color palette applied to images and UI + white text","Duotone image filter, two-color gradient, monotone sections","Photography, portfolio, editorial, music, fashion","Multi-category apps needing distinct color per section"
Split Complementary,Color Theory,"split complementary color theory harmonious vibrant balanced","Complementary pair + neutral + accent triads","Harmonious color combinations, section color shifts, accent interactions","Style-focused apps, design tools, fashion, home decor","Apps not focused on visual branding"
Frosted Acrylic,Microsoft Fluent,"frosted acrylic fluent design microsoft blur smooth","Acrylic panels + reveal highlight + depth layering","Frosted panels with tinted blur, reveal highlight on hover/press, smooth depth","Cross-platform apps, Windows-compatible, music players, dashboards","Apps targeting very low-end hardware"
Font Pairing Name,Category,Heading Font,Body Font,Mood/Style Keywords,Best For,Google Fonts URL,Notes
Inter + Inter,Modern Sans,Inter,Inter,"clean modern neutral versatile","SaaS, dashboards, productivity apps",https://fonts.google.com/specimen/Inter,"Most versatile. Excellent readability at all sizes."
Roboto + Roboto,System Default,Roboto,Roboto,"standard android material familiar","Any Android app following Material guidelines",https://fonts.google.com/specimen/Roboto,"Android system font. Zero download cost. Always available."
Poppins + Inter,Geometric Modern,Poppins,Inter,"geometric friendly approachable","E-commerce, social, lifestyle apps",https://fonts.google.com/specimen/Poppins,"Poppins for headings adds personality. Inter for body readability."
Outfit + Source Sans 3,Clean Professional,Outfit,Source Sans 3,"professional clean corporate trust","Fintech, banking, enterprise apps",https://fonts.google.com/specimen/Outfit,"Outfit is modern yet professional. Source Sans for long-form."
Playfair Display + Lora,Editorial Serif,Playfair Display,Lora,"elegant editorial premium luxury","News, magazines, luxury products",https://fonts.google.com/specimen/Playfair+Display,"Serif pairing for premium feel. Not for UI-heavy screens."
Space Grotesk + DM Sans,Tech Modern,Space Grotesk,DM Sans,"tech futuristic innovative startup","Tech startups, dev tools, gaming",https://fonts.google.com/specimen/Space+Grotesk,"Distinctive geometric headings. Clean body text."
Nunito + Open Sans,Friendly Rounded,Nunito,Open Sans,"friendly warm rounded approachable","Kids apps, education, social",https://fonts.google.com/specimen/Nunito,"Rounded terminals feel welcoming. Good for casual apps."
Montserrat + Hind,Bold Impact,Montserrat,Hind,"bold impactful strong sports","Fitness, sports, media apps",https://fonts.google.com/specimen/Montserrat,"Strong headings with Montserrat. Hind is highly readable."
Merriweather + Source Sans 3,Readability Serif,Merriweather,Source Sans 3,"readable content focused editorial","Reading apps, documentation, blogs",https://fonts.google.com/specimen/Merriweather,"Designed for screen reading. Excellent at small sizes."
Work Sans + IBM Plex Sans,Corporate Clean,Work Sans,IBM Plex Sans,"corporate structured professional","Enterprise, B2B, productivity",https://fonts.google.com/specimen/Work+Sans,"Work Sans for headings, IBM Plex for professional body text."
Sora + Plus Jakarta Sans,Contemporary,Sora,Plus Jakarta Sans,"contemporary fresh modern","Design tools, creative apps, portfolios",https://fonts.google.com/specimen/Sora,"Fresh and modern. Great for creative and design-focused apps."
JetBrains Mono + Inter,Developer,JetBrains Mono,Inter,"code developer technical monospace","Dev tools, code editors, technical",https://fonts.google.com/specimen/JetBrains+Mono,"Mono for code blocks. Inter for UI text. Perfect for dev tools."
Lato + Merriweather,Mixed Paired,Lato,Merriweather,"professional readable mixed serif-sans","Business apps, long-form content, enterprise",https://fonts.google.com/specimen/Lato,"Classic combo: sans headings + serif body. High readability."
Josefin Sans + Quicksand,Soft Elegant,Josefin Sans,Quicksand,"soft elegant feminine stylish luxury","Fashion, beauty, lifestyle, luxury brands",https://fonts.google.com/specimen/Josefin+Sans,"Thin elegant headings with soft body text."
Raleway + Lato,Thin Modern,Raleway,Lato,"thin modern elegant sleek","Landing pages, portfolios, design tools",https://fonts.google.com/specimen/Raleway,"Ultra-thin headings for design-focused apps. Use heavier weights for body."
Rubik + Inter,Rounded Modern,Rubik,Inter,"rounded modern friendly corporate","SaaS dashboards, productivity, project management",https://fonts.google.com/specimen/Rubik,"Rounded without being childish. Good for corporate-friendly apps."
Archivo + Manrope,Bold Editorial,Archivo,Manrope,"bold editorial strong headlines","News apps, media platforms, magazine style",https://fonts.google.com/specimen/Archivo,"Condensed bold for strong headlines. Manrope for readable body."
DM Serif Display + DM Sans,Display Pair,DM Serif Display,DM Sans,"display premium brand modern","Branding, marketing, premium features",https://fonts.google.com/specimen/DM+Serif+Display,"Same family: serif display + sans body. Perfect harmony."
Lexend + Source Code Pro,Reading Optimized,Lexend,Source Code Pro,"reading optimized dyslexia friendly code","Education, document readers, developer tools",https://fonts.google.com/specimen/Lexend,"Lexend designed for reading ease. Source Code Pro for inline code."
Manrope + Open Sans,Geometric Clean,Manrope,Open Sans,"geometric clean modern minimal","General purpose apps, clean modern UI",https://fonts.google.com/specimen/Manrope,"Modern geometric headings with universally readable body."
Bitter + Source Sans 3,Slab Serif,Bitter,Source Sans 3,"slab serif sturdy reliable serious","Finance, insurance, government, legal",https://fonts.google.com/specimen/Bitter,"Sturdy slab serif conveys reliability. Source Sans for clean body."
Cabin + Lora,Warm Humanist,Cabin,Lora,"warm humanist welcoming friendly","Non-profit, community, social good, health",https://fonts.google.com/specimen/Cabin,"Humanist warmth in headings + elegant serif body."
Barlow + Barlow,Condensed Family,Barlow,Barlow,"condensed family space efficient data dense","Data tables, dashboards, inventory, admin panels",https://fonts.google.com/specimen/Barlow,"Condensed variant for data density. Normal for body. Same family consistency."
Noto Sans + Noto Sans,Universal,Noto Sans,Noto Sans,"universal multilingual i18n global","Multi-language apps, global products",https://fonts.google.com/noto,"Supports ALL languages. Essential for i18n apps. Zero tofu characters."
Figtree + Inter,Modern Geometric,Figtree,Inter,"modern geometric friendly tech startup","Modern startups, SaaS, productivity",https://fonts.google.com/specimen/Figtree,"New geometric sans with great personality. Pairs well with Inter."
Red Hat Display + Red Hat Text,Brand Pair,Red Hat Display,Red Hat Text,"brand pair consistent cohesive","Open source projects, tech companies, developer marketing",https://fonts.google.com/specimen/Red+Hat+Display,"Display + Text variants from same family. Consistent branding."
Fira Sans + Fira Code,Developer Dual,Fira Sans,Fira Code,"developer technical code documentation","IDE companions, documentation apps, developer portals",https://fonts.google.com/specimen/Fira+Sans,"Fira Code for code blocks with ligatures. Fira Sans for surrounding UI."
Libre Baskerville + Source Sans 3,Classic Readable,Libre Baskerville,Source Sans 3,"classic traditional readable scholarly","Book readers, libraries, academic, publishing",https://fonts.google.com/specimen/Libre+Baskerville,"Classic serif for headings. Clean sans for navigation and UI."
Oswald + Roboto,Condensed Impact,Oswald,Roboto,"condensed impact bold headline newspaper","Sports, news, magazine covers, event apps",https://fonts.google.com/specimen/Oswald,"Tall condensed headings save space. Roboto body is always safe."
Ubuntu + Ubuntu,System Ubuntu,Ubuntu,Ubuntu,"friendly linux open-source approachable geometric","Open source projects, Linux-related, community apps",https://fonts.google.com/specimen/Ubuntu,"Distinctive personality. Full weight range. OpenType features."
Karla + Inconsolata,Mixed Mono,Karla,Inconsolata,"mixed mono technical casual code documentation","Technical blogs, dev tools, documentation readers",https://fonts.google.com/specimen/Karla,"Karla for headings, Inconsolata for inline code. Casual tech feel."
Comfortaa + Nunito,Soft Rounded,Comfortaa,Nunito,"soft rounded geometric friendly playful","Kids learning, casual games, friendly social apps",https://fonts.google.com/specimen/Comfortaa,"Fully rounded geometry. Very friendly. Best at larger sizes."
Crimson Text + Work Sans,Elegant Mixed,Crimson Text,Work Sans,"elegant serif body editorial literary","Literary apps, poetry, journals, storytelling",https://fonts.google.com/specimen/Crimson+Text,"Beautiful serif body text. Work Sans for UI elements."
Overpass + Overpass Mono,Transport,Overpass,Overpass Mono,"transport highway clear legible government","Maps, navigation, transit, government, signage",https://fonts.google.com/specimen/Overpass,"Inspired by Highway Gothic. Excellent for wayfinding and navigation."
Spectral + Inter,Scholarly,Spectral,Inter,"scholarly academic research paper journal","Research papers, academic references, scholarly apps",https://fonts.google.com/specimen/Spectral,"Google serif designed for long-form reading. Inter for UI."
Atkinson Hyperlegible + Inter,Accessibility First,Atkinson Hyperlegible,Inter,"accessible hyperlegible low vision readable","Accessibility-focused apps, senior users, low vision",https://fonts.google.com/specimen/Atkinson+Hyperlegible,"Designed for maximum legibility. Each character visually distinct."
Antonio + Space Grotesk,Bold Geometric,Antonio,Space Grotesk,"bold geometric architectural industrial modern","Architecture, engineering, automotive, Bold brands",https://fonts.google.com/specimen/Antonio,"Super bold condensed for headings. Distinctive character."
Gabarito + Plus Jakarta Sans,Contemporary Warm,Gabarito,Plus Jakarta Sans,"contemporary warm geometric friendly modern","Modern startups, community apps, social platforms",https://fonts.google.com/specimen/Gabarito,"Fresh face with warmth. Good x-height. Pairs well with geometric sans."
Bricolage Grotesque + Inter,Display Modern,Bricolage Grotesque,Inter,"display modern variable optical personality","Branding, headlines, marketing, creative apps",https://fonts.google.com/specimen/Bricolage+Grotesque,"Variable font with optical sizing. Expressive at large sizes, readable at small."
General Sans + General Sans,Variable Family,General Sans,General Sans,"variable universal clean professional modern","Any professional app with variable font support",https://fontshare.com/fonts/general-sans,"Clean variable sans. Free from Fontshare. All weights in one file."
Instrument Sans + Instrument Serif,Complementary Pair,Instrument Sans,Instrument Serif,"complementary pair mixed editorial premium","Editorial, premium brands, luxury products",https://fonts.google.com/specimen/Instrument+Sans,"Perfect pair from same designer. Sans UI + serif content."
Geist + Geist Mono,Vercel System,Geist,Geist Mono,"system modern vercel developer clean","Next.js dashboards, developer tools, SaaS",https://vercel.com/font,"Modern system font by Vercel. Excellent for developer-facing products."
Satoshi + Cabinet Grotesk,Trendy Modern,Satoshi,Cabinet Grotesk,"trendy 2024 modern variable geometric startup","Startups, modern SaaS, portfolio, design tools",https://fontshare.com/fonts/satoshi,"Most popular free font 2023-2024. Clean geometric with personality."
Epilogue + Work Sans,Versatile Modern,Epilogue,Work Sans,"versatile flexible modern professional all-purpose","Any modern app needing flexibility across weights",https://fonts.google.com/specimen/Epilogue,"Wide weight range. Good for condensed/expanded headings."
Be Vietnam Pro + Be Vietnam Pro,Vietnamese Optimized,Be Vietnam Pro,Be Vietnam Pro,"vietnamese vi diacritics southeast asian regional","Vietnamese-language apps, SE Asian markets",https://fonts.google.com/specimen/Be+Vietnam+Pro,"Optimized for Vietnamese diacritics. Clean modern design."
Clash Display + Clash Grotesk,Bold Statement,Clash Display,Clash Grotesk,"bold statement display impactful hero","Hero sections, landing pages, event apps",https://fontshare.com/fonts/clash-display,"Extremely bold display. High impact headings."
App_Category,Recommended_Pattern,Style_Priority,Color_Mood,Typography_Mood,Key_Effects,Decision_Rules,Anti_Patterns,Severity
Fintech/Banking,Clean Architecture + MVVM,Material 3 Clean + Corporate Professional,Trust Blue with Security Green,Professional and clean with high readability,"Subtle transitions, tonal elevation, smooth progress indicators","{""must_have"": ""biometric auth"", ""security"": ""encryption mandatory"", ""trust"": ""green checkmarks for verified""}","Flashy animations + neon colors + playful fonts + gamification of financial data",CRITICAL
E-Commerce,Clean Architecture + MVVM,Material 3 Clean + Gradient Accent,Warm CTAs with Neutral Background,Clean modern sans-serif with clear hierarchy,"Quick add-to-cart animation, smooth image zoom, skeleton loading for products","{""must_have"": ""search with filters"", ""conversion"": ""sticky CTA"", ""cart"": ""always visible count""}","Complex checkout flow + hidden prices + no product reviews + slow image loading",HIGH
Healthcare/Medical,Clean Architecture + Repository,Material 3 Clean + Organic Soft,Calming Teal with White Space,Clean readable with excellent contrast,"Gentle transitions, calm loading states, smooth form flow","{""must_have"": ""appointment booking"", ""a11y"": ""WCAG AA mandatory"", ""trust"": ""credentials visible""}","Bright aggressive colors + gamification + small text + complex navigation",CRITICAL
Fitness/Wellness,MVVM + MVI for tracking,Dark Mode Premium + Gradient Accent,High-energy Orange with Success Green,Bold sporty with strong data display,"Progress animations, achievement unlocks, motivational pulses","{""must_have"": ""progress tracking"", ""gamification"": ""streak and badges"", ""data"": ""charts and history""}","Cluttered dashboard + too many metrics at once + no dark mode + boring static UI",HIGH
Social Media,MVI with shared state,Gradient Accent + Dark Mode Premium,Vibrant Brand with Dark Background,Friendly modern with personality,"Pull to refresh, double-tap like, story progress bar, smooth transitions","{""must_have"": ""real-time feed"", ""engagement"": ""reactions and sharing"", ""identity"": ""unique brand color""}","Slow feed loading + no offline mode + generic Material defaults + no personality",HIGH
Education/Learning,Clean Architecture + MVVM,Material 3 Clean + Flat Modern,Focused Blue with Achievement Gold,Readable friendly with progress emphasis,"Progress bar animations, quiz transitions, completion celebrations","{""must_have"": ""progress tracking"", ""gamification"": ""achievements and streaks"", ""content"": ""offline access""}","Overwhelming content dump + no progress indication + tiny text + complex navigation",HIGH
Food Delivery,MVVM with Paging,Material 3 Clean + Playful Colorful,Appetite Warm with Fresh Green,Clean with food-friendly warmth,"Quick add animation, order tracking pulse, rating stars animation","{""must_have"": ""search and filters"", ""conversion"": ""reorder in 2 taps"", ""tracking"": ""real-time status""}","Complex menu navigation + hidden delivery fees + slow image loading + no reorder",HIGH
Travel/Booking,Clean Architecture + MVVM,Material 3 Clean + Organic Soft,Sky Blue with Warm Accent,Clean professional with wanderlust feel,"Date picker smooth flow, price animation, image gallery swipe","{""must_have"": ""search with dates"", ""trust"": ""reviews visible"", ""booking"": ""clear pricing""}","Hidden fees + complex booking flow + no saved searches + ugly date picker",HIGH
Productivity/Tools,MVVM + Clean Architecture,Material 3 Clean + Flat Modern,Focused Blue with Minimal Palette,Clean efficient with minimal distraction,"Quick action animations, smooth list reorder, minimal transitions","{""must_have"": ""quick add action"", ""efficiency"": ""keyboard shortcuts"", ""sync"": ""across devices""}","Feature bloat + complex onboarding + too many settings + aggressive notifications",MEDIUM
Gaming/Entertainment,MVI with event-driven,Dark Mode Premium + Glassmorphism,Neon Accents on Dark with Gold Rewards,Bold energetic with strong visual impact,"Achievement unlock effects, score animations, haptic feedback","{""must_have"": ""leaderboard"", ""engagement"": ""daily rewards"", ""social"": ""sharing achievements""}","Slow load times + intrusive ads + pay-to-win perception + no offline play",HIGH
News/Media,MVVM with Paging,Editorial Clean + Material 3 Clean,Minimal Dark Text with Red Breaking,High readability serif with clean hierarchy,"Reading progress indicator, smooth article transitions, save animation","{""must_have"": ""offline reading"", ""engagement"": ""personalized feed"", ""trust"": ""source attribution""}","Clickbait design + too many ads + auto-play video + non-accessible text sizes",MEDIUM
SaaS/Dashboard,Clean Architecture + MVVM,Dark Mode Premium + Corporate Professional,Data Blue with Success Green,Professional clean with excellent data readability,"Smooth chart animations, real-time data updates, tooltip hover","{""must_have"": ""real-time data"", ""export"": ""PDF and CSV"", ""filters"": ""date range and segments""}","Too many charts at once + no empty states + complex filters UI + missing loading states",HIGH
Kids/Family,MVVM simple,Playful Colorful + Organic Soft,Bright Primary with Soft Pastels,Friendly rounded with large readable text,"Bouncy spring animations, reward confetti, sound effects","{""must_have"": ""parental controls"", ""safety"": ""COPPA compliant"", ""a11y"": ""large touch targets > 56dp""}","Small touch targets + complex text + scary animations + in-app purchases without gate",CRITICAL
Ride Sharing,Clean Architecture + MVVM,Material 3 Clean + Flat Modern,Map Green with CTA Orange,Clean professional with clear map readability,"Map animations, ride tracking pulse, ETA countdown, price animation","{""must_have"": ""real-time location"", ""conversion"": ""quick booking"", ""trust"": ""driver rating visible""}","Complex booking flow + hidden surge pricing + small map + no ETA",HIGH
Grocery Delivery,MVVM with Paging + Clean Architecture,Material 3 Clean + Organic Soft,Fresh Green with Appetizing Warm,Clean modern with food-appropriate warmth,"Quick add to cart, category scroll, recipe integration","{""must_have"": ""search + categories"", ""conversion"": ""reorder 1-tap"", ""freshness"": ""delivery time visible""}","Slow image loading + hidden delivery fees + complex checkout",HIGH
Task Management,MVVM + Clean Architecture,Material 3 Clean + Flat Modern,Focus Blue with Minimal Palette,Clean efficient with task status emphasis,"Drag reorder, swipe complete, quick add animation, progress ring","{""must_have"": ""quick add"", ""efficiency"": ""keyboard friendly"", ""sync"": ""real-time sync""}","Feature bloat + complex views + too many categories + aggressive notifications",MEDIUM
Weather,MVVM simple,Glassmorphism + Soft Gradient,Sky Gradient with Dynamic Palette,Beautiful atmospheric with readable data,"Background weather animation, temperature transition, radar animation","{""must_have"": ""current conditions"", ""visual"": ""matches weather"", ""data"": ""hourly + weekly""}","Too many data points at once + no visual weather cue + cluttered layout",MEDIUM
Podcast/Audio,MVVM + MVI for player,Dark Mode Premium + Material 3 Clean,Dark Immersive with Vibrant Art,Clean player with album art focus,"Waveform progress, queue animation, sleep timer countdown","{""must_have"": ""background playback"", ""discovery"": ""personalized feed"", ""control"": ""lock screen controls""}","Bright distracting UI during playback + no background play + complex queue management",HIGH
Category,Issue,Platform,Description,Do,Don't
Navigation,Bottom Navigation Labels,Android,"Bottom nav items should always show labels for clarity.","Always show labels. Use 3-5 destinations max.","Hide labels or use more than 5 items."
Navigation,Back Button Behavior,Android,"Back should always have predictable behavior.","Follow platform back behavior. Save state on back.","Override back to exit without confirmation on forms."
Forms,Input Field Labels,Android,"Every input field must have a visible persistent label.","Use OutlinedTextField with label parameter.","Use placeholder as the only label (disappears on focus)."
Forms,Inline Validation,Android,"Show validation errors inline near the field.","Display error as supportingText under the field.","Show error in dialog or toast far from the field."
Forms,Keyboard Type,Android,"Match keyboard to input type for faster entry.","Use keyboardOptions with correct KeyboardType.","Show full keyboard for phone number or email input."
Forms,Submit Button State,Android,"Disable submit button when form is invalid.","Disable button with clear visual feedback.","Allow submit with invalid data then show errors."
Loading,Skeleton Screens,Android,"Show content skeleton while loading for perceived speed.","Use shimmer/skeleton matching content layout.","Show only a centered spinner with blank screen."
Loading,Progress Feedback,Android,"Show determinate progress for actions with known duration.","Use LinearProgressIndicator with progress value.","Use indeterminate spinner for file uploads."
Empty States,Empty List,Android,"Guide users when a list has no content.","Show icon + message + primary CTA (add/create).","Show blank screen or just text 'No items'."
Errors,Error Recovery,Android,"Always provide a path to recovery from errors.","Show error message + retry button + alternative action.","Show only error message without any action."
Touch,Pull to Refresh,Android,"Allow manual refresh with pull-to-refresh gesture.","Use PullToRefreshBox with loading indicator.","Auto-refresh without user control."
Touch,Haptic Feedback,Android,"Use subtle haptics for important interactions.","Add haptics for toggles, confirmation, boundaries.","Overuse haptics on every tap/scroll."
Content,Text Truncation,Android,"Handle long text gracefully with ellipsis.","Use maxLines + TextOverflow.Ellipsis. Show full on tap.","Let text wrap indefinitely or clip abruptly."
Content,Image Aspect Ratio,Android,"Maintain consistent image aspect ratios in lists.","Use ContentScale.Crop with fixed aspect ratio.","Stretch images to fill arbitrary containers."
Motion,Transition Consistency,Android,"Use consistent transitions throughout the app.","Define shared transition specs in theme/constants.","Different transition for each screen."
Motion,Loading to Content,Android,"Animate transition from loading to content state.","Use AnimatedContent or Crossfade for state transitions.","Abruptly swap loading for content without transition."
Onboarding,Permission Rationale,Android,"Explain why the app needs a permission before requesting it.","Show clear rationale screen with icon + benefit before system dialog.","Request permission cold with no context."
Onboarding,Progressive Disclosure,Android,"Don't overwhelm new users with all features at once.","Reveal features progressively as user advances. Use tooltips for discovery.","Show every feature on first screen."
Onboarding,Skip Option,Android,"Always allow users to skip onboarding flows.","Provide visible Skip button on every onboarding screen.","Force users through mandatory tutorial."
Navigation,Gesture Navigation Support,Android,"Support Android gesture navigation (back, swipe).","Test with gesture nav enabled. Handle predictive back animation.","Override back gesture behavior unpredictably."
Navigation,Deep Link Landing,Android,"Users arriving via deep link should see relevant content immediately.","Show target content with clear navigation path to rest of app.","Show splash or login before deep link content."
Navigation,Tab Persistence,Android,"Maintain scroll position and state when switching tabs.","Save and restore tab state on switch. Use SavedStateHandle.","Reset tab content on every switch."
Content,Skeleton Content Types,Android,"Match skeleton shapes to actual content shapes.","Use rectangles for text, circles for avatars, rounded rects for images.","Use generic shimmer that doesn't match content layout."
Content,Pull to Refresh Feedback,Android,"Give clear feedback during and after refresh.","Show indicator while refreshing. Briefly show success or 'up to date' after.","Silent refresh with no visual feedback."
Content,Infinite Scroll vs Pagination,Android,"Choose based on content type and user intent.","Use infinite scroll for feeds. Use pagination for search results.","Use infinite scroll for ordered/numbered content."
Interaction,Undo Support,Android,"Provide undo for destructive actions.","Show Snackbar with Undo action after delete/archive.","Immediately delete without undo option."
Interaction,Long Press Discovery,Android,"Long press actions are hidden - provide alternative access.","Show context menu icon or use tooltip to teach long press.","Rely solely on long press with no visual hint."
Interaction,Drag Handle Visibility,Android,"Make draggable elements clearly draggable.","Show drag handle icon (≡) on reorderable items.","Allow drag but show no visual indicator."
Feedback,Success Confirmation,Android,"Confirm successful actions explicitly.","Show brief success Snackbar or checkmark animation.","No feedback after save/submit succeeds."
Feedback,Error Inline vs Toast,Android,"Show errors close to where they occurred.","Inline errors for forms. Snackbar for general errors.","Toast for form validation errors."
Feedback,Loading Button State,Android,"Show loading state on the button that triggered the action.","Replace button text with CircularProgressIndicator.","Show full-screen loader for button actions."
Accessibility,Focus Visible,Android,"Show clear focus indicators for keyboard/switch access.","Use default Compose focus indicators. Add custom for dark themes.","Remove or hide focus indicators."
Search,Recent Searches,Android,"Help users find previous searches quickly.","Show recent searches below search bar. Allow clearing history.","Empty search suggestions on every visit."
Search,No Results Guidance,Android,"Help users recover from empty search results.","Show suggestions, check spelling prompt, or browse categories CTA.","Just show 'No results found' text."
Settings,Setting Confirmation,Android,"Confirm changes to important settings.","Show confirmation dialog for critical setting changes (delete account).","Allow one-tap account deletion."
Settings,Setting Search,Android,"Allow searching within settings for large setting lists.","Add search bar at top of settings screen.","Nested settings with no search capability."
Gesture,Scroll to Top,Android,"Allow quick return to top of long lists.","Tap status bar or show FAB after scrolling down.","No way to return to top except manual scroll."
Performance,Perceived Speed,Android,"Make the app feel faster than it is.","Show optimistic UI updates. Animate content in progressively.","Block entire screen until all data loads."
Navigation,Breadcrumb Trail,Android,"Show user's location in navigation hierarchy on complex apps.","Show breadcrumb or back title in top app bar.","Only show generic 'Back' without context."
Content,Card Tap Target,Android,"Entire card should be tappable, not just text or icon.","Make the whole Card composable clickable.","Only make the title text inside the card clickable."
Content,Contextual Actions,Android,"Show relevant actions based on content context.","Use context menus, swipe actions, or action mode for selection.","Show same actions regardless of content type."
Interaction,Optimistic Updates,Android,"Show result immediately while syncing in background.","Update UI instantly, sync in background, revert on failure.","Wait for server confirmation before updating UI."
Interaction,Destructive Action Hierarchy,Android,"Make destructive actions harder to trigger accidentally.","Require confirmation dialog for delete. Use red color warning.","Place delete button next to save with same styling."
Feedback,Progress Percentage,Android,"Show percentage for deterministic long operations.","Display progress bar with percentage for uploads/downloads.","Show indeterminate spinner for 30-second file upload."
Feedback,Empty vs Loading vs Error,Android,"Clearly distinguish between no data, loading, and error states.","Use distinct visuals for each: skeleton, empty illustration, error+retry.","Show same blank screen for all three states."
Accessibility,Touch Target Feedback,Android,"Provide visual feedback for all interactive elements.","Use ripple effect on clickable elements. Highlight focused items.","Clickable elements with no visual press feedback."
Forms,Auto-Save Draft,Android,"Save form progress automatically to prevent data loss.","Auto-save to local storage periodically or on field blur.","Lose all form data when user accidentally navigates away."
Forms,Smart Defaults,Android,"Pre-fill form fields with smart defaults where possible.","Use user history, location, or common values as defaults.","Show all fields empty requiring manual entry."
Navigation,Sheet vs Dialog vs Screen,Android,"Choose the right container for the content amount.","Sheet for < 5 actions, dialog for confirmations, screen for complex content.","Use full screen for 2 option choices."
Loading,Background Task Progress,Android,"Show progress for tasks running in background.","Use notification progress bar for downloads/uploads.","No indication that background task is running."
Component Name,Category,Description,Key Properties,Usage Context & Pro-Tips
LazyColumn,List,"Vertically scrolling list, renders only visible items","items(), itemsIndexed(), key, contentPadding, verticalArrangement","Always provide stable keys. Use contentType for heterogeneous lists. Pair with Paging 3 for infinite scroll."
LazyRow,List,"Horizontally scrolling list, renders only visible items","items(), key, contentPadding, horizontalArrangement","Use for carousels, chips, or horizontal galleries. Set flingBehavior for snap-to-item."
LazyVerticalGrid,Grid,"Grid layout with lazy rendering","columns (Fixed/Adaptive), items(), key, contentPadding","Use GridCells.Adaptive for responsive grids. Good for image galleries and product grids."
LazyVerticalStaggeredGrid,Grid,"Staggered grid (Pinterest-style) with lazy rendering","columns (Fixed/Adaptive), items(), key","Use for variable-height items like image boards. Requires foundation library."
Column,Layout,"Vertical linear layout, arranges children top-to-bottom","verticalArrangement, horizontalAlignment, Modifier","For small lists only (< 20 items). Use LazyColumn for longer lists."
Row,Layout,"Horizontal linear layout, arranges children left-to-right","horizontalArrangement, verticalAlignment, Modifier","Use weight modifier for flex layouts. Good for toolbars, action rows."
Box,Layout,"Stack children on top of each other","contentAlignment, Modifier","Use for overlays, badges on icons, or positioning content absolutely."
Scaffold,Layout,"Material 3 app structure with slots","topBar, bottomBar, floatingActionButton, snackbarHost, content","Always use innerPadding from content lambda. Handles insets automatically."
Surface,Layout,"Material surface with elevation, shape, and color","shape, color, tonalElevation, shadowElevation, onClick","Use for cards, dialogs, and any elevated container. Replaces Card in many cases."
ConstraintLayout,Layout,"Complex positioning with constraints","createRefs(), constrain, linkTo, Barrier, Chain, Guideline","Use when Row/Column nesting gets too deep. Import constraintlayout-compose."
Text,Display,"Render text with Material typography","text, style, color, maxLines, overflow, textAlign","Always use MaterialTheme.typography styles. Support font scaling."
BasicTextField,Input,"Low-level customizable text input","value, onValueChange, textStyle, decorationBox, keyboardOptions","Use for custom-styled inputs. For Material styling, prefer OutlinedTextField."
OutlinedTextField,Input,"Material 3 outlined text field","value, onValueChange, label, isError, supportingText, trailingIcon","Default choice for form inputs. Always provide label and error state."
TextField,Input,"Material 3 filled text field","value, onValueChange, label, colors, isError","Use when filled style matches design. Pair with supportingText for validation."
Button,Action,"Material 3 filled button (primary CTA)","onClick, enabled, colors, contentPadding, shape","Primary action button. Use for most important action on screen."
OutlinedButton,Action,"Material 3 outlined button (secondary)","onClick, enabled, border, colors","Secondary actions. Less visual weight than filled Button."
TextButton,Action,"Material 3 text button (tertiary)","onClick, enabled, colors","Tertiary or inline actions. Dialogs, links, less important actions."
FilledTonalButton,Action,"Material 3 tonal button (medium emphasis)","onClick, enabled, colors, shape","Between Button and OutlinedButton in emphasis. Good for secondary CTAs."
FloatingActionButton,Action,"Material 3 FAB","onClick, shape, containerColor, contentColor","Primary screen-level action. Use ExtendedFloatingActionButton for label + icon."
IconButton,Action,"Clickable icon with touch target","onClick, enabled, colors, content: @Composable","Minimum 48dp touch target automatic. Use for toolbar actions."
Card,Container,"Material 3 card with elevation","shape, colors, elevation, onClick","Use for list items, content groups. ElevatedCard, OutlinedCard variants available."
ElevatedCard,Container,"Card with tonal elevation","shape, elevation, colors, onClick","Higher emphasis than Card. Good for featured content."
TopAppBar,Navigation,"Material 3 top app bar","title, navigationIcon, actions, scrollBehavior","Use CenterAlignedTopAppBar for centered titles. Connect to scrollBehavior."
BottomAppBar,Navigation,"Material 3 bottom app bar","actions, floatingActionButton, containerColor","Use for secondary navigation with optional FAB cutout."
NavigationBar,Navigation,"Material 3 bottom navigation","content: NavigationBarItem","Use for 3-5 top-level destinations. Always show labels."
NavigationRail,Navigation,"Material 3 side navigation for tablets","selectedDestination, onDestinationSelected, header","Use for larger screens (tablets, foldables). Responsive alternative to NavigationBar."
NavigationDrawer,Navigation,"Material 3 navigation drawer (modal or permanent)","drawerContent, gesturesEnabled","Use ModalNavigationDrawer for phone, PermanentNavigationDrawer for tablet."
TabRow,Navigation,"Material 3 tab row","selectedTabIndex, tabs: @Composable","Use for switching between related content views. Max 5-7 tabs."
ModalBottomSheet,Overlay,"Material 3 bottom sheet","onDismissRequest, sheetState, dragHandle","Use for contextual actions, filters, or detail views. Always provide dismiss."
AlertDialog,Overlay,"Material 3 alert dialog","onDismissRequest, confirmButton, dismissButton, title, text","Use for confirmations, destructive actions. Keep text concise."
Snackbar,Feedback,"Material 3 snackbar for brief messages","message, action, duration","Show after actions (save, delete). Use with SnackbarHost in Scaffold."
CircularProgressIndicator,Feedback,"Indeterminate or determinate circular progress","progress (optional), color, strokeWidth","Use indeterminate for unknown duration. Determinate for file uploads etc."
LinearProgressIndicator,Feedback,"Indeterminate or determinate linear progress","progress (optional), color, trackColor","Use at top of screen for page loading. Determinate for progress tracking."
Checkbox,Selection,"Material 3 checkbox","checked, onCheckedChange, enabled, colors","Use for multi-select scenarios. Always pair with Text label."
RadioButton,Selection,"Material 3 radio button","selected, onClick, enabled, colors","Use for single-select from small set. Group with Column and selectionContainer."
Switch,Selection,"Material 3 toggle switch","checked, onCheckedChange, enabled, thumbContent","Use for on/off settings. Can include icon in thumb."
Slider,Selection,"Material 3 slider","value, onValueChange, valueRange, steps","Use for continuous value selection (volume, brightness). Support discrete steps."
DropdownMenu,Selection,"Material 3 dropdown menu","expanded, onDismissRequest, content: DropdownMenuItem","Use for overflow menus, action menus. Position relative to anchor."
ExposedDropdownMenuBox,Selection,"Material 3 exposed dropdown (select box)","expanded, onExpandedChange, content","Use for form select fields. Better than DropdownMenu for forms."
Divider,Decoration,"Material 3 divider line","thickness, color, Modifier","Use sparingly. Prefer spacing over dividers for visual separation."
HorizontalPager,Pager,"Swipeable horizontal pages","state, pageCount, content","Use for onboarding, image galleries, tab content. Pair with PagerState."
VerticalPager,Pager,"Swipeable vertical pages","state, pageCount, content","Use for TikTok-style feeds or vertical carousels."
AsyncImage,Media,"Coil image loader composable","model, contentDescription, contentScale, placeholder, error","Requires coil-compose. Always provide contentDescription and error placeholder."
Icon,Display,"Material icon display","imageVector, contentDescription, tint","Always provide contentDescription (null if decorative). Use Material Icons."
Badge,Display,"Material 3 badge indicator","content: @Composable","Use on NavigationBarItem or IconButton for notification counts."
Chip,Display,"Material 3 chip (various types)","onClick, label, selected, leadingIcon","AssistChip, FilterChip, InputChip, SuggestionChip. Use for tags, filters."
AnimatedVisibility,Animation,"Animate enter/exit of content","visible, enter, exit, content","Use for showing/hiding UI elements with animation. Better than if/else."
AnimatedContent,Animation,"Animate between different content","targetState, transitionSpec, content","Use for state transitions (loading → content). Provides smooth crossfade."
Crossfade,Animation,"Simple crossfade between content","targetState, animationSpec, content","Simplest content transition. Use for tab content switching."
rememberInfiniteTransition,Animation,"Creates infinite repeating animation","rememberInfiniteTransition().animateFloat()","Use for pulsing, rotating, or shimmer effects."
pullToRefresh,Gesture,"Pull-to-refresh indicator","state, isRefreshing, onRefresh","Use Modifier.pullToRefresh(). Connect to ViewModel refresh action."
Modifier.clickable,Gesture,"Make any composable clickable","onClick, indication, interactionSource","Use for custom clickable areas. Includes ripple by default."
Modifier.draggable,Gesture,"Enable drag gesture on composable","orientation, state: DraggableState","Use for sliders, reorder, or swipe-to-dismiss."
Modifier.swipeable,Gesture,"Swipe with anchored states","state, anchors, thresholds, orientation","Use for swipe-to-reveal actions (archive, delete)."
WindowSizeClass,Adaptive,"Detect device size class","calculateWindowSizeClass(activity)","Compact/Medium/Expanded. Use to switch between phone/tablet/desktop layouts."
AdaptiveNavigationSuite,Adaptive,"Auto-switch between nav styles","selectedDestination, destinations, content","Automatically uses NavBar (phone), NavRail (tablet), NavDrawer (desktop)."
ListDetailPaneScaffold,Adaptive,"List-detail adaptive layout","listPane, detailPane, extraPane","Auto-switches between single/dual pane based on window size."
SearchBar,Search,"Material 3 search bar (expanded)","query, onQueryChange, onSearch, active, content","Use for primary search. Shows suggestions in expanded state."
DockedSearchBar,Search,"Material 3 docked search bar","query, onQueryChange, onSearch, active, content","Use when search is secondary. Stays docked, doesn't expand full screen."
DatePicker,Picker,"Material 3 date picker","state: DatePickerState, headline, title","Use rememberDatePickerState(). Wrap in DatePickerDialog for modal."
TimePicker,Picker,"Material 3 time picker","state: TimePickerState","Use rememberTimePickerState(). Wrap in dialog for modal usage."
RichTooltip,Tooltip,"Material 3 rich tooltip with actions","title, action, caretSize, text","Use for feature discovery, onboarding hints."
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Android Pro Max Core - BM25 search engine for Android/Kotlin knowledge base
Zero dependencies - self-contained BM25 implementation
"""
from __future__ import annotations
import csv
import re
from pathlib import Path
from math import log
from collections import defaultdict
from typing import Any
# ============ CONFIGURATION ============
def _get_data_dir() -> Path:
"""Auto-detect data directory based on script location"""
script_dir = Path(__file__).parent
possible_paths = [
# Full install: .claude/skills/android-pro-max/scripts/ -> data/ (sibling)
script_dir.parent / "data",
# Reference install: .shared/android-pro-max/scripts/ -> ../data
script_dir.parent.parent / "data",
# When running from root/scripts/
script_dir.parent / ".shared" / "data",
# When running from .agents/workflows/scripts/ (nested 3 levels deep)
script_dir.parent.parent.parent / ".shared" / "data",
# When running from .claude/skills/android-pro-max/scripts/ (reference mode)
script_dir.parent.parent.parent.parent / ".shared" / "data",
# Fallback: cwd
Path.cwd() / ".shared" / "data",
]
for p in possible_paths:
if p.exists():
return p.resolve()
return possible_paths[0] # Default to first option
DATA_DIR = _get_data_dir()
MAX_RESULTS = 5
# Domain configuration: file, search columns, output columns
CSV_CONFIG: dict[str, dict[str, str | list[str]]] = {
"view": {
"file": "view.csv",
"search_cols": ["Component Name", "Category", "Description", "Key Properties", "Usage Context & Pro-Tips"],
"output_cols": ["Component Name", "Category", "Description", "Key Properties", "Usage Context & Pro-Tips"]
},
"package": {
"file": "package.csv",
"search_cols": ["pkg_name", "category", "description", "best_practice_snippet", "pro_tip", "alternatives"],
"output_cols": ["pkg_name", "category", "description", "best_practice_snippet", "pro_tip", "alternatives"]
},
"pattern": {
"file": "pattern.csv",
"search_cols": ["pattern_name", "category", "problem_tags", "description", "key_components", "code_snippet", "anti_pattern"],
"output_cols": ["pattern_name", "category", "problem_tags", "description", "key_components", "code_snippet", "anti_pattern"]
},
"architect": {
"file": "architect.csv",
"search_cols": ["path_pattern", "layer", "responsibility_description", "allowed_dependencies", "tech_stack_note"],
"output_cols": ["path_pattern", "layer", "responsibility_description", "allowed_dependencies", "tech_stack_note"]
},
"chart": {
"file": "chart.csv",
"search_cols": ["Data Type", "Keywords", "Best Chart Type", "Secondary Options", "Accessibility Notes"],
"output_cols": ["Data Type", "Keywords", "Best Chart Type", "Secondary Options", "Color Guidance", "Accessibility Notes", "Library Recommendation"]
},
"color": {
"file": "color.csv",
"search_cols": ["Product Type", "Keywords", "Notes"],
"output_cols": ["Product Type", "Keywords", "Primary (Hex)", "Secondary (Hex)", "CTA (Hex)", "Notes"]
},
"typography": {
"file": "typography.csv",
"search_cols": ["Font Pairing Name", "Category", "Mood/Style Keywords", "Best For", "Heading Font", "Body Font"],
"output_cols": ["Font Pairing Name", "Category", "Heading Font", "Body Font", "Mood/Style Keywords", "Best For", "Google Fonts URL", "Notes"]
},
"style": {
"file": "style.csv",
"search_cols": ["Style Category", "Type", "Keywords", "Best For"],
"output_cols": ["Style Category", "Type", "Keywords", "Primary Colors", "Effects & Animation", "Best For", "Do Not Use For"]
},
"ux": {
"file": "ux.csv",
"search_cols": ["Category", "Issue", "Platform", "Description", "Do", "Don't"],
"output_cols": ["Category", "Issue", "Platform", "Description", "Do", "Don't"]
},
"icon": {
"file": "icon.csv",
"search_cols": ["Category", "Icon Name", "Keywords", "Best For"],
"output_cols": ["Category", "Icon Name", "Keywords", "Library", "Import Code", "Usage", "Best For"]
},
"landing": {
"file": "landing.csv",
"search_cols": ["Pattern Name", "Keywords", "Section Order", "Conversion Optimization"],
"output_cols": ["Pattern Name", "Keywords", "Section Order", "Primary CTA Placement", "Color Strategy", "Conversion Optimization"]
},
"naming": {
"file": "naming.csv",
"search_cols": ["Layer", "File Template", "Class Template", "Example File", "Example Class", "Notes"],
"output_cols": ["Layer", "File Template", "Class Template", "Example File", "Example Class", "Notes"]
},
"product": {
"file": "product.csv",
"search_cols": ["Product Type", "Keywords", "Primary Style Recommendation"],
"output_cols": ["Product Type", "Keywords", "Primary Style Recommendation", "Secondary Styles", "Color Palette Focus"]
},
"prompt": {
"file": "prompt.csv",
"search_cols": ["Style Category", "AI Prompt Keywords (Copy-Paste Ready)", "CSS/Technical Keywords"],
"output_cols": ["Style Category", "AI Prompt Keywords (Copy-Paste Ready)", "CSS/Technical Keywords", "Implementation Checklist"]
},
"play-store": {
"file": "play-store.csv",
"search_cols": ["Stage", "Goal", "Prompt Template", "Output Schema", "Required Inputs", "Length/Limit", "Quality Gate", "Notes"],
"output_cols": ["Stage", "Goal", "Prompt Template", "Output Schema", "Required Inputs", "Length/Limit", "Quality Gate", "Notes"]
},
"performance": {
"file": "performance.csv",
"search_cols": ["Category", "Issue", "Keywords", "Description", "Do", "Don't"],
"output_cols": ["Category", "Issue", "Keywords", "Description", "Do", "Don't", "Code Example Good", "Code Example Bad", "Severity"]
},
"ui-reasoning": {
"file": "ui-reasoning.csv",
"search_cols": ["App_Category", "Recommended_Pattern", "Style_Priority", "Color_Mood", "Key_Effects", "Decision_Rules"],
"output_cols": ["App_Category", "Recommended_Pattern", "Style_Priority", "Color_Mood", "Typography_Mood", "Key_Effects", "Decision_Rules", "Anti_Patterns", "Severity"]
},
"accessibility": {
"file": "accessibility.csv",
"search_cols": ["Category", "Issue", "Keywords", "Platform", "Description", "Do", "Don't"],
"output_cols": ["Category", "Issue", "Keywords", "Platform", "Description", "Do", "Don't", "Code Example Good", "Code Example Bad", "Severity"]
}
}
# Stack exclusion mapping for filtering conflicting packages
STACK_EXCLUSIONS = {
"compose": ["xml-views", "data-binding", "view-binding"],
"xml": ["compose-ui", "compose-navigation", "compose-material3"],
"hilt": ["koin", "kodein", "manual-di"],
"koin": ["hilt", "dagger", "manual-di"],
}
AVAILABLE_DOMAINS = list(CSV_CONFIG.keys())
AVAILABLE_STACKS = list(STACK_EXCLUSIONS.keys())
# ============ BM25 IMPLEMENTATION ============
class BM25:
"""BM25 ranking algorithm for text search - zero dependencies"""
def __init__(self, k1: float = 1.5, b: float = 0.75) -> None:
self.k1 = k1
self.b = b
self.corpus: list[list[str]] = []
self.doc_lengths: list[int] = []
self.avgdl: float = 0
self.idf: dict[str, float] = {}
self.doc_freqs: defaultdict[str, int] = defaultdict(int)
self.n: int = 0
def tokenize(self, text: str) -> list[str]:
"""Lowercase, split, remove punctuation, filter short words"""
text = re.sub(r'[^\w\s]', ' ', str(text).lower())
return [w for w in text.split() if len(w) > 1]
def fit(self, documents: list[str]) -> None:
"""Build BM25 index from documents"""
self.corpus = [self.tokenize(doc) for doc in documents]
self.n = len(self.corpus)
if self.n == 0:
return
self.doc_lengths = [len(doc) for doc in self.corpus]
self.avgdl = sum(self.doc_lengths) / self.n
for doc in self.corpus:
seen: set[str] = set()
for word in doc:
if word not in seen:
self.doc_freqs[word] += 1
seen.add(word)
for word, freq in self.doc_freqs.items():
self.idf[word] = log((self.n - freq + 0.5) / (freq + 0.5) + 1)
def score(self, query: str) -> list[tuple[int, float]]:
"""Score all documents against query"""
query_tokens = self.tokenize(query)
scores: list[tuple[int, float]] = []
for idx, doc in enumerate(self.corpus):
score: float = 0.0
doc_len = self.doc_lengths[idx]
term_freqs: defaultdict[str, int] = defaultdict(int)
for word in doc:
term_freqs[word] += 1
for token in query_tokens:
if token in self.idf:
tf = term_freqs[token]
idf = self.idf[token]
numerator = tf * (self.k1 + 1)
denominator = tf + self.k1 * (1 - self.b + self.b * doc_len / self.avgdl)
score += idf * numerator / denominator
scores.append((idx, score))
return sorted(scores, key=lambda x: x[1], reverse=True)
# ============ HELPER FUNCTIONS ============
def _load_csv(filepath: Path) -> list[dict[str, str]]:
"""Load CSV and return list of dicts"""
with open(filepath, 'r', encoding='utf-8') as f:
return list(csv.DictReader(f))
def _search_csv(filepath: Path, search_cols: list[str], output_cols: list[str], query: str, max_results: int, boost_col: str | None = None, boost_query: str | None = None) -> list[dict[str, Any]]:
"""Core search function using BM25 with optional boosting"""
if not filepath.exists():
return []
data = _load_csv(filepath)
# Build documents from search columns
documents = [" ".join(str(row.get(col, "")) for col in search_cols) for row in data]
# BM25 search
bm25 = BM25()
bm25.fit(documents)
ranked = bm25.score(query)
# Apply boosting if specified (component name match, etc.)
if boost_col and boost_query:
boost_query_lower = boost_query.lower()
boosted: list[tuple[int, float]] = []
for idx, score in ranked:
boosted_score = score
if score > 0:
boost_value = str(data[idx].get(boost_col, "")).lower()
if boost_value in boost_query_lower or boost_query_lower in boost_value:
boosted_score = score * 2.0 # Double score for exact/partial match
boosted.append((idx, boosted_score))
ranked = sorted(boosted, key=lambda x: x[1], reverse=True)
# Get top results with score > 0
results: list[dict[str, Any]] = []
for idx, score in ranked[:max_results]:
if score > 0:
row = data[idx]
result: dict[str, Any] = {col: row.get(col, "") for col in output_cols if col in row}
result["_score"] = round(score, 4)
results.append(result)
return results
def detect_domain(query: str) -> str:
"""Auto-detect the most relevant domain from query keywords"""
query_lower = query.lower()
domain_keywords = {
"view": ["composable", "compose", "layout", "lazycolumn", "lazyrow", "scaffold", "topappbar", "bottombar",
"text", "button", "card", "surface", "box", "column", "row", "modifier", "view", "xml"],
"package": ["package", "library", "dependency", "gradle", "retrofit", "okhttp", "room", "hilt", "koin",
"coil", "glide", "moshi", "serialization", "datastore"],
"pattern": ["pattern", "mvvm", "mvi", "repository", "usecase", "state", "intent", "navigation",
"compose navigation", "sealed", "uistate"],
"architect": ["layer", "folder", "structure", "clean", "feature", "domain", "data", "presentation",
"module", "modular"],
"chart": ["chart", "graph", "visualization", "bar", "pie", "line", "scatter", "heatmap", "dashboard"],
"color": ["color", "palette", "hex", "theme", "dark mode", "light mode", "material"],
"typography": ["font", "typography", "heading", "text style", "google fonts", "typeface"],
"style": ["style", "design", "ui", "glassmorphism", "neumorphism", "minimal", "modern", "material3"],
"ux": ["ux", "usability", "user experience", "touch", "scroll", "animation", "gesture", "haptic"],
"icon": ["icon", "material icons", "outlined", "rounded", "filled"],
"landing": ["landing", "onboarding", "splash", "hero", "cta", "section", "welcome"],
"naming": ["naming", "convention", "file name", "class name", "snake_case", "PascalCase", "camelCase"],
"product": ["saas", "ecommerce", "fintech", "healthcare", "education", "food", "travel", "social"],
"prompt": ["prompt", "ai", "implementation", "checklist"],
"play-store": [
"play store", "google play", "play console", "aso", "app store optimization",
"data safety", "content rating", "privacy policy", "app listing", "store listing",
"app name", "short description", "full description", "screenshot", "feature graphic"
],
"performance": ["performance", "recomposition", "memory", "startup", "lazy", "coroutine", "anr",
"jank", "frame", "baseline profile"],
"ui-reasoning": ["reasoning", "decision", "app category", "app type", "which style"],
"accessibility": ["accessibility", "a11y", "talkback", "semantics", "contrast", "touch target",
"content description", "screen reader"],
}
scores: dict[str, int] = {domain: sum(1 for kw in keywords if kw in query_lower) for domain, keywords in domain_keywords.items()}
best = max(scores, key=lambda k: scores[k])
return best if scores[best] > 0 else "view"
# ============ MAIN SEARCH FUNCTIONS ============
def search(query: str, domain: str | None = None, max_results: int = MAX_RESULTS) -> dict[str, Any]:
"""
Main search function with auto-domain detection
Args:
query: Search query string
domain: Optional domain (view, package, pattern, etc.)
max_results: Number of results to return
Returns:
Dict with domain, query, file, count, and results
"""
if domain is None:
domain = detect_domain(query)
if domain not in CSV_CONFIG:
return {"error": f"Unknown domain: {domain}. Available: {', '.join(AVAILABLE_DOMAINS)}"}
config = CSV_CONFIG[domain]
filepath = DATA_DIR / str(config["file"])
if not filepath.exists():
return {"error": f"File not found: {filepath}", "domain": domain}
# Apply view boosting for view domain
boost_col = "Component Name" if domain == "view" else None
boost_query = query if domain == "view" else None
search_cols = config["search_cols"]
output_cols = config["output_cols"]
if isinstance(search_cols, list) and isinstance(output_cols, list):
results = _search_csv(
filepath,
search_cols,
output_cols,
query,
max_results,
boost_col=boost_col,
boost_query=boost_query
)
else:
results = []
return {
"domain": domain,
"query": query,
"file": config["file"],
"count": len(results),
"results": results
}
def search_with_stack(query: str, stack: str, domain: str | None = None, max_results: int = MAX_RESULTS) -> dict[str, Any]:
"""
Search with stack-specific filtering (excludes conflicting packages)
Args:
query: Search query string
stack: Stack preference (compose, xml, hilt, koin)
domain: Optional domain filter
max_results: Number of results to return
Returns:
Dict with filtered results
"""
if stack not in STACK_EXCLUSIONS:
return {"error": f"Unknown stack: {stack}. Available: {', '.join(AVAILABLE_STACKS)}"}
result = search(query, domain, max_results * 2) # Get more to filter
if "error" in result:
return result
# Filter out conflicting packages
excluded = STACK_EXCLUSIONS[stack]
filtered_results: list[dict[str, Any]] = []
for item in result["results"]:
# Check package name field
pkg_name = str(item.get("pkg_name", "")).lower()
if pkg_name not in excluded:
filtered_results.append(item)
if len(filtered_results) >= max_results:
break
result["results"] = filtered_results
result["count"] = len(filtered_results)
result["stack"] = stack
result["excluded"] = excluded
return result
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Android Pro Max Design System Generator - Aggregates search results and applies reasoning
to generate comprehensive design system recommendations for Android/Kotlin apps.
Usage:
from design_system import generate_design_system
result = generate_design_system("fintech banking app", "MyApp")
# With persistence (Master + Overrides pattern)
result = generate_design_system("fintech banking app", "MyApp", persist=True)
result = generate_design_system("fintech banking app", "MyApp", persist=True, page="dashboard")
"""
from __future__ import annotations
import csv
import json
from datetime import datetime
from pathlib import Path
from typing import Any
from core import search, DATA_DIR
# ============ CONFIGURATION ============
REASONING_FILE = "ui-reasoning.csv"
SEARCH_CONFIG = {
"product": {"max_results": 1},
"style": {"max_results": 3},
"color": {"max_results": 2},
"typography": {"max_results": 2},
"pattern": {"max_results": 3},
"architect": {"max_results": 2},
"landing": {"max_results": 2}
}
# ============ DESIGN SYSTEM GENERATOR ============
class DesignSystemGenerator:
"""Generates design system recommendations from aggregated searches."""
def __init__(self) -> None:
self.reasoning_data: list[dict[str, str]] = self._load_reasoning()
def _load_reasoning(self) -> list[dict[str, str]]:
"""Load reasoning rules from CSV."""
filepath = DATA_DIR / REASONING_FILE
if not filepath.exists():
return []
with open(filepath, 'r', encoding='utf-8') as f:
return list(csv.DictReader(f))
def _multi_domain_search(self, query: str, style_priority: list[str] | None = None) -> dict[str, Any]:
"""Execute searches across multiple domains."""
results: dict[str, Any] = {}
for domain, config in SEARCH_CONFIG.items():
if domain == "style" and style_priority:
priority_query = " ".join(style_priority[:2]) if style_priority else query
combined_query = f"{query} {priority_query}"
results[domain] = search(combined_query, domain, config["max_results"])
else:
results[domain] = search(query, domain, config["max_results"])
return results
def _find_reasoning_rule(self, category: str) -> dict[str, str]:
"""Find matching reasoning rule for a category."""
category_lower = category.lower()
for rule in self.reasoning_data:
if rule.get("App_Category", "").lower() == category_lower:
return rule
for rule in self.reasoning_data:
app_cat = rule.get("App_Category", "").lower()
if app_cat in category_lower or category_lower in app_cat:
return rule
for rule in self.reasoning_data:
app_cat = rule.get("App_Category", "").lower()
keywords = app_cat.replace("/", " ").replace("-", " ").split()
if any(kw in category_lower for kw in keywords):
return rule
return {}
def _apply_reasoning(self, category: str, search_results: dict[str, Any]) -> dict[str, Any]:
"""Apply reasoning rules to search results with intelligent decision processing."""
rule = self._find_reasoning_rule(category)
if not rule:
return {
"pattern": "Clean Architecture + Feature-First",
"style_priority": ["Material 3", "Minimalism"],
"color_mood": "Professional",
"typography_mood": "Clean",
"key_effects": "Subtle animations, smooth transitions",
"anti_patterns": "",
"decision_rules": {},
"severity": "MEDIUM",
"must_have_features": [],
"conversion_focus": ""
}
decision_rules: dict[str, Any] = {}
must_have_features: list[Any] = []
try:
decision_rules = json.loads(str(rule.get("Decision_Rules", "{}")))
for key, value in decision_rules.items():
if key == "must_have" or key.startswith("must_have"):
must_have_features.append(value)
except json.JSONDecodeError:
pass
conversion_focus = self._determine_conversion_focus(category)
return {
"pattern": rule.get("Recommended_Pattern", ""),
"style_priority": [s.strip() for s in rule.get("Style_Priority", "").split("+")],
"color_mood": rule.get("Color_Mood", ""),
"typography_mood": rule.get("Typography_Mood", ""),
"key_effects": rule.get("Key_Effects", ""),
"anti_patterns": rule.get("Anti_Patterns", ""),
"decision_rules": decision_rules,
"severity": rule.get("Severity", "MEDIUM"),
"must_have_features": must_have_features,
"conversion_focus": conversion_focus
}
def _determine_conversion_focus(self, category: str) -> str:
"""Determine conversion focus based on app category."""
category_lower = category.lower()
conversion_map: dict[str, str] = {
"e-commerce": "Purchase conversion, Add to cart, Quick checkout",
"fintech": "Trust building, Security perception, Transaction completion",
"banking": "Trust building, Security perception, Transaction completion",
"health": "Appointment booking, Trust signals, Accessibility",
"fitness": "Engagement, Progress motivation, Habit formation",
"social": "Engagement, Retention, Content sharing",
"education": "Progress tracking, Completion rates, Engagement",
"productivity": "Task completion, Efficiency, Quick actions",
"food": "Order conversion, Reorder, Quick checkout",
"travel": "Booking conversion, Search efficiency, Trust",
"gaming": "Engagement, Retention, In-app purchases",
}
for key, focus in conversion_map.items():
if key in category_lower:
return focus
return "User engagement and task completion"
def _select_best_match(self, results: list[dict[str, Any]], priority_keywords: list[str]) -> dict[str, Any]:
"""Select best matching result based on priority keywords."""
if not results:
return {}
if not priority_keywords:
return results[0]
for priority in priority_keywords:
priority_lower = priority.lower().strip()
for result in results:
style_name = result.get("Style Category", "").lower()
if priority_lower in style_name or style_name in priority_lower:
return result
scored: list[tuple[int, dict[str, Any]]] = []
for result in results:
result_str = str(result).lower()
score = 0
for kw in priority_keywords:
kw_lower = kw.lower().strip()
if kw_lower in result.get("Style Category", "").lower():
score += 10
elif kw_lower in result.get("Keywords", "").lower():
score += 3
elif kw_lower in result_str:
score += 1
scored.append((score, result))
scored.sort(key=lambda x: x[0], reverse=True)
return scored[0][1] if scored and scored[0][0] > 0 else results[0]
def _extract_results(self, search_result: dict[str, Any]) -> list[dict[str, Any]]:
"""Extract results list from search result dict."""
return search_result.get("results", [])
def generate(self, query: str, project_name: str | None = None) -> dict[str, Any]:
"""Generate complete design system recommendation with landing pattern intelligence."""
product_result = search(query, "product", 1)
product_results = product_result.get("results", [])
category = "General"
product_info = {}
if product_results:
product_info = product_results[0]
category = product_info.get("Product Type", "General")
reasoning = self._apply_reasoning(category, {})
style_priority = reasoning.get("style_priority", [])
search_results = self._multi_domain_search(query, style_priority)
search_results["product"] = product_result
style_results = self._extract_results(search_results.get("style", {}))
color_results = self._extract_results(search_results.get("color", {}))
typography_results = self._extract_results(search_results.get("typography", {}))
pattern_results = self._extract_results(search_results.get("pattern", {}))
architect_results = self._extract_results(search_results.get("architect", {}))
landing_results = self._extract_results(search_results.get("landing", {}))
best_style = self._select_best_match(style_results, reasoning.get("style_priority", []))
best_color = color_results[0] if color_results else {}
best_typography = typography_results[0] if typography_results else {}
best_landing = landing_results[0] if landing_results else {}
style_effects = best_style.get("Effects & Animation", "")
reasoning_effects = reasoning.get("key_effects", "")
combined_effects = style_effects if style_effects else reasoning_effects
landing_effects = best_landing.get("Recommended Effects", "")
if landing_effects and not combined_effects:
combined_effects = landing_effects
return {
"project_name": project_name or query.upper(),
"category": category,
"pattern": {
"name": reasoning.get("pattern", "Clean Architecture"),
"architecture": architect_results[0].get("layer", "") if architect_results else "Feature-First",
"state_management": "ViewModel + StateFlow",
"recommended_patterns": [p.get("pattern_name", "") for p in pattern_results[:3]]
},
"screen_pattern": {
"name": best_landing.get("Pattern Name", "Hero + Features + CTA"),
"sections": best_landing.get("Section Order", "Hero > Features > CTA"),
"cta_placement": best_landing.get("Primary CTA Placement", "Bottom + Sticky"),
"color_strategy": best_landing.get("Color Strategy", ""),
"conversion_optimization": best_landing.get("Conversion Optimization", "")
},
"style": {
"name": best_style.get("Style Category", "Material 3"),
"type": best_style.get("Type", "General"),
"effects": style_effects,
"keywords": best_style.get("Keywords", ""),
"best_for": best_style.get("Best For", ""),
"do_not_use": best_style.get("Do Not Use For", "")
},
"colors": {
"primary": best_color.get("Primary (Hex)", "#2563EB"),
"secondary": best_color.get("Secondary (Hex)", "#3B82F6"),
"cta": best_color.get("CTA (Hex)", "#F97316"),
"background": "#FFFFFF",
"surface": "#F8FAFC",
"text": "#1E293B",
"notes": best_color.get("Notes", ""),
"strategy": best_landing.get("Color Strategy", reasoning.get("color_mood", ""))
},
"typography": {
"heading": best_typography.get("Heading Font", "Roboto"),
"body": best_typography.get("Body Font", "Roboto"),
"mood": best_typography.get("Mood/Style Keywords", reasoning.get("typography_mood", "")),
"best_for": best_typography.get("Best For", ""),
"google_fonts_url": best_typography.get("Google Fonts URL", "")
},
"key_effects": combined_effects,
"anti_patterns": reasoning.get("anti_patterns", ""),
"decision_rules": reasoning.get("decision_rules", {}),
"severity": reasoning.get("severity", "MEDIUM"),
"conversion_focus": reasoning.get("conversion_focus", ""),
"must_have_features": reasoning.get("must_have_features", [])
}
# ============ OUTPUT FORMATTERS ============
BOX_WIDTH = 90
def format_ascii_box(design_system: dict[str, Any]) -> str:
"""Format design system as ASCII box for Android apps with screen pattern intelligence."""
project = design_system.get("project_name", "PROJECT")
pattern = design_system.get("pattern", {})
screen_pattern = design_system.get("screen_pattern", {})
style = design_system.get("style", {})
colors = design_system.get("colors", {})
typography = design_system.get("typography", {})
effects = design_system.get("key_effects", "")
anti_patterns = design_system.get("anti_patterns", "")
conversion_focus = design_system.get("conversion_focus", "")
must_have_features = design_system.get("must_have_features", [])
def wrap_text(text: str, prefix: str, width: int) -> list[str]:
if not text:
return []
words = text.split()
lines: list[str] = []
current_line = prefix
for word in words:
if len(current_line) + len(word) + 1 <= width - 2:
current_line += (" " if current_line != prefix else "") + word
else:
if current_line != prefix:
lines.append(current_line)
current_line = prefix + word
if current_line != prefix:
lines.append(current_line)
return lines
lines: list[str] = []
w = BOX_WIDTH - 1
lines.append("+" + "-" * w + "+")
lines.append(f"| TARGET: {project} - ANDROID DESIGN SYSTEM".ljust(BOX_WIDTH) + "|")
lines.append("+" + "-" * w + "+")
lines.append("|" + " " * BOX_WIDTH + "|")
if screen_pattern.get("name"):
lines.append(f"| SCREEN PATTERN: {screen_pattern.get('name', '')}".ljust(BOX_WIDTH) + "|")
if screen_pattern.get("sections"):
sections_str = screen_pattern.get("sections", "")[:65]
lines.append(f"| Sections: {sections_str}".ljust(BOX_WIDTH) + "|")
if screen_pattern.get("cta_placement"):
lines.append(f"| CTA: {screen_pattern.get('cta_placement', '')}".ljust(BOX_WIDTH) + "|")
if screen_pattern.get("conversion_optimization"):
for line in wrap_text(f"Conversion: {screen_pattern.get('conversion_optimization', '')}", "| ", BOX_WIDTH):
lines.append(line.ljust(BOX_WIDTH) + "|")
lines.append("|" + " " * BOX_WIDTH + "|")
lines.append(f"| ARCHITECTURE: {pattern.get('name', '')}".ljust(BOX_WIDTH) + "|")
lines.append(f"| Structure: Feature-First / Clean Architecture".ljust(BOX_WIDTH) + "|")
lines.append(f"| State: {pattern.get('state_management', 'ViewModel + StateFlow')}".ljust(BOX_WIDTH) + "|")
if pattern.get('recommended_patterns'):
patterns_str = ", ".join(filter(None, pattern.get('recommended_patterns', [])))[:60]
lines.append(f"| Patterns: {patterns_str}".ljust(BOX_WIDTH) + "|")
lines.append("|" + " " * BOX_WIDTH + "|")
lines.append(f"| UI STYLE: {style.get('name', '')}".ljust(BOX_WIDTH) + "|")
if style.get("keywords"):
for line in wrap_text(f"Keywords: {style.get('keywords', '')}", "| ", BOX_WIDTH):
lines.append(line.ljust(BOX_WIDTH) + "|")
if style.get("best_for"):
for line in wrap_text(f"Best For: {style.get('best_for', '')}", "| ", BOX_WIDTH):
lines.append(line.ljust(BOX_WIDTH) + "|")
lines.append("|" + " " * BOX_WIDTH + "|")
lines.append("| COLOR PALETTE:".ljust(BOX_WIDTH) + "|")
lines.append(f"| Primary: {colors.get('primary', '')}".ljust(BOX_WIDTH) + "|")
lines.append(f"| Secondary: {colors.get('secondary', '')}".ljust(BOX_WIDTH) + "|")
lines.append(f"| CTA: {colors.get('cta', '')}".ljust(BOX_WIDTH) + "|")
lines.append(f"| Background: {colors.get('background', '')}".ljust(BOX_WIDTH) + "|")
lines.append(f"| Surface: {colors.get('surface', '')}".ljust(BOX_WIDTH) + "|")
lines.append(f"| Text: {colors.get('text', '')}".ljust(BOX_WIDTH) + "|")
if colors.get("notes"):
for line in wrap_text(f"Notes: {colors.get('notes', '')}", "| ", BOX_WIDTH):
lines.append(line.ljust(BOX_WIDTH) + "|")
if colors.get("strategy"):
for line in wrap_text(f"Strategy: {colors.get('strategy', '')}", "| ", BOX_WIDTH):
lines.append(line.ljust(BOX_WIDTH) + "|")
lines.append("|" + " " * BOX_WIDTH + "|")
lines.append(f"| TYPOGRAPHY: {typography.get('heading', '')} / {typography.get('body', '')}".ljust(BOX_WIDTH) + "|")
if typography.get("mood"):
for line in wrap_text(f"Mood: {typography.get('mood', '')}", "| ", BOX_WIDTH):
lines.append(line.ljust(BOX_WIDTH) + "|")
if typography.get("best_for"):
for line in wrap_text(f"Best For: {typography.get('best_for', '')}", "| ", BOX_WIDTH):
lines.append(line.ljust(BOX_WIDTH) + "|")
lines.append("|" + " " * BOX_WIDTH + "|")
if effects:
lines.append("| KEY EFFECTS:".ljust(BOX_WIDTH) + "|")
for line in wrap_text(effects, "| ", BOX_WIDTH):
lines.append(line.ljust(BOX_WIDTH) + "|")
lines.append("|" + " " * BOX_WIDTH + "|")
if conversion_focus:
lines.append("| CONVERSION FOCUS:".ljust(BOX_WIDTH) + "|")
for line in wrap_text(conversion_focus, "| ", BOX_WIDTH):
lines.append(line.ljust(BOX_WIDTH) + "|")
lines.append("|" + " " * BOX_WIDTH + "|")
if must_have_features:
lines.append("| MUST-HAVE FEATURES:".ljust(BOX_WIDTH) + "|")
for feature in must_have_features:
lines.append(f"| ✓ {feature}".ljust(BOX_WIDTH) + "|")
lines.append("|" + " " * BOX_WIDTH + "|")
if anti_patterns:
lines.append("| AVOID (Anti-patterns):".ljust(BOX_WIDTH) + "|")
for line in wrap_text(anti_patterns, "| ", BOX_WIDTH):
lines.append(line.ljust(BOX_WIDTH) + "|")
lines.append("|" + " " * BOX_WIDTH + "|")
lines.append("| PRE-DELIVERY CHECKLIST:".ljust(BOX_WIDTH) + "|")
checklist_items = [
"[ ] Compose previews for all screens",
"[ ] Proper ViewModel scoping and state hoisting",
"[ ] Material 3 theme tokens used consistently",
"[ ] Responsive: phone, tablet, large screen layouts",
"[ ] Accessibility: contentDescription, touch targets >= 48dp",
"[ ] Performance: LazyColumn/Row for long lists, no main-thread blocking",
"[ ] Error handling: sealed UI state with loading/error/success"
]
for item in checklist_items:
lines.append(f"| {item}".ljust(BOX_WIDTH) + "|")
lines.append("|" + " " * BOX_WIDTH + "|")
lines.append("+" + "-" * w + "+")
return "\n".join(lines)
def format_markdown(design_system: dict[str, Any]) -> str:
"""Format design system as markdown with screen pattern intelligence."""
project = design_system.get("project_name", "PROJECT")
pattern = design_system.get("pattern", {})
screen_pattern = design_system.get("screen_pattern", {})
style = design_system.get("style", {})
colors = design_system.get("colors", {})
typography = design_system.get("typography", {})
effects = design_system.get("key_effects", "")
anti_patterns = design_system.get("anti_patterns", "")
conversion_focus = design_system.get("conversion_focus", "")
must_have_features = design_system.get("must_have_features", [])
lines: list[str] = []
lines.append(f"## Android Design System: {project}")
lines.append("")
if screen_pattern.get("name"):
lines.append("### Screen Pattern")
lines.append(f"- **Pattern:** {screen_pattern.get('name', '')}")
if screen_pattern.get("sections"):
lines.append(f"- **Sections:** {screen_pattern.get('sections', '')}")
if screen_pattern.get("cta_placement"):
lines.append(f"- **CTA Placement:** {screen_pattern.get('cta_placement', '')}")
if screen_pattern.get("conversion_optimization"):
lines.append(f"- **Conversion:** {screen_pattern.get('conversion_optimization', '')}")
lines.append("")
lines.append("### Architecture")
lines.append(f"- **Pattern:** {pattern.get('name', '')}")
lines.append(f"- **Structure:** Feature-First / Clean Architecture")
lines.append(f"- **State Management:** {pattern.get('state_management', 'ViewModel + StateFlow')}")
if pattern.get('recommended_patterns'):
patterns_str = ", ".join(filter(None, pattern.get('recommended_patterns', [])))
lines.append(f"- **Recommended Patterns:** {patterns_str}")
lines.append("")
lines.append("### UI Style")
lines.append(f"- **Name:** {style.get('name', '')}")
if style.get('keywords'):
lines.append(f"- **Keywords:** {style.get('keywords', '')}")
if style.get('best_for'):
lines.append(f"- **Best For:** {style.get('best_for', '')}")
if style.get('do_not_use'):
lines.append(f"- **Do Not Use For:** {style.get('do_not_use', '')}")
lines.append("")
lines.append("### Color Palette")
lines.append(f"| Role | Hex | Compose |")
lines.append(f"|------|-----|---------|")
lines.append(f"| Primary | `{colors.get('primary', '')}` | `Color(0xFF{colors.get('primary', '#2563EB')[1:]})` |")
lines.append(f"| Secondary | `{colors.get('secondary', '')}` | `Color(0xFF{colors.get('secondary', '#3B82F6')[1:]})` |")
lines.append(f"| CTA | `{colors.get('cta', '')}` | `Color(0xFF{colors.get('cta', '#F97316')[1:]})` |")
lines.append(f"| Background | `{colors.get('background', '')}` | `Color(0xFF{colors.get('background', '#FFFFFF')[1:]})` |")
lines.append(f"| Surface | `{colors.get('surface', '')}` | `Color(0xFF{colors.get('surface', '#F8FAFC')[1:]})` |")
lines.append(f"| Text | `{colors.get('text', '')}` | `Color(0xFF{colors.get('text', '#1E293B')[1:]})` |")
if colors.get("notes"):
lines.append(f"\n*Notes: {colors.get('notes', '')}*")
if colors.get("strategy"):
lines.append(f"\n*Color Strategy: {colors.get('strategy', '')}*")
lines.append("")
lines.append("### Typography")
lines.append(f"- **Heading:** {typography.get('heading', '')}")
lines.append(f"- **Body:** {typography.get('body', '')}")
if typography.get("mood"):
lines.append(f"- **Mood:** {typography.get('mood', '')}")
if typography.get("best_for"):
lines.append(f"- **Best For:** {typography.get('best_for', '')}")
if typography.get("google_fonts_url"):
lines.append(f"- **Google Fonts:** {typography.get('google_fonts_url', '')}")
lines.append("")
if effects:
lines.append("### Key Effects")
lines.append(f"{effects}")
lines.append("")
if conversion_focus:
lines.append("### Conversion Focus")
lines.append(f"{conversion_focus}")
lines.append("")
if must_have_features:
lines.append("### Must-Have Features")
for feature in must_have_features:
lines.append(f"- ✓ {feature}")
lines.append("")
if anti_patterns:
newline_bullet = '\n- '
lines.append("### Avoid (Anti-patterns)")
lines.append(f"- {anti_patterns.replace(' + ', newline_bullet)}")
lines.append("")
lines.append("### Pre-Delivery Checklist")
lines.append("- [ ] Compose previews for all screens")
lines.append("- [ ] Proper ViewModel scoping and state hoisting")
lines.append("- [ ] Material 3 theme tokens used consistently")
lines.append("- [ ] Responsive: phone, tablet, large screen layouts")
lines.append("- [ ] Accessibility: contentDescription, touch targets >= 48dp")
lines.append("- [ ] Performance: LazyColumn/Row for long lists")
lines.append("- [ ] Error handling: sealed UI state with loading/error/success")
lines.append("")
return "\n".join(lines)
# ============ PERSISTENCE FUNCTIONS ============
def persist_design_system(design_system: dict[str, Any], page: str | None = None, output_dir: str | None = None, page_query: str | None = None) -> dict[str, Any]:
"""
Persist design system to design-system/<project>/ folder using Master + Overrides pattern.
"""
base_dir = Path(output_dir) if output_dir else Path.cwd()
project_name = design_system.get("project_name", "default")
project_slug = project_name.lower().replace(' ', '-')
design_system_dir = base_dir / "design-system" / project_slug
pages_dir = design_system_dir / "pages"
created_files: list[str] = []
design_system_dir.mkdir(parents=True, exist_ok=True)
pages_dir.mkdir(parents=True, exist_ok=True)
master_file = design_system_dir / "MASTER.md"
master_content = format_master_md(design_system)
with open(master_file, 'w', encoding='utf-8') as f:
f.write(master_content)
created_files.append(str(master_file))
if page:
page_file = pages_dir / f"{page.lower().replace(' ', '-')}.md"
page_content = format_page_override_md(design_system, page, page_query)
with open(page_file, 'w', encoding='utf-8') as f:
f.write(page_content)
created_files.append(str(page_file))
return {
"status": "success",
"design_system_dir": str(design_system_dir),
"created_files": created_files
}
def format_master_md(design_system: dict[str, Any]) -> str:
"""Format design system as MASTER.md with hierarchical override logic."""
project = design_system.get("project_name", "PROJECT")
pattern = design_system.get("pattern", {})
style = design_system.get("style", {})
colors = design_system.get("colors", {})
typography = design_system.get("typography", {})
effects = design_system.get("key_effects", "")
anti_patterns = design_system.get("anti_patterns", "")
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
lines: list[str] = []
lines.append("# Android Design System Master File")
lines.append("")
lines.append("> **LOGIC:** When building a specific screen, first check `design-system/pages/[screen-name].md`.")
lines.append("> If that file exists, its rules **override** this Master file.")
lines.append("> If not, strictly follow the rules below.")
lines.append("")
lines.append("---")
lines.append("")
lines.append(f"**Project:** {project}")
lines.append(f"**Generated:** {timestamp}")
lines.append(f"**Category:** {design_system.get('category', 'General')}")
lines.append("")
lines.append("---")
lines.append("")
lines.append("## Architecture")
lines.append("")
lines.append(f"- **Pattern:** {pattern.get('name', 'Clean Architecture')}")
lines.append(f"- **Structure:** Feature-First")
lines.append(f"- **State Management:** {pattern.get('state_management', 'ViewModel + StateFlow')}")
lines.append("")
lines.append("### Module Structure")
lines.append("```")
lines.append("app/src/main/java/com/example/")
lines.append("├── core/ # Shared utilities, constants, themes")
lines.append("│ ├── theme/")
lines.append("│ ├── util/")
lines.append("│ └── ui/ # Reusable composables")
lines.append("├── feature/")
lines.append("│ └── [feature_name]/")
lines.append("│ ├── data/ # Repositories, data sources, DTOs")
lines.append("│ ├── domain/ # Use cases, models")
lines.append("│ └── presentation/ # Screens, ViewModels, UI state")
lines.append("└── App.kt")
lines.append("```")
lines.append("")
lines.append("## Global Rules")
lines.append("")
lines.append("### Color Palette")
lines.append("")
lines.append("| Role | Hex | Compose Color |")
lines.append("|------|-----|---------------|")
primary_hex = colors.get('primary', '#2563EB').lstrip('#')
secondary_hex = colors.get('secondary', '#3B82F6').lstrip('#')
cta_hex = colors.get('cta', '#F97316').lstrip('#')
bg_hex = colors.get('background', '#FFFFFF').lstrip('#')
surface_hex = colors.get('surface', '#F8FAFC').lstrip('#')
text_hex = colors.get('text', '#1E293B').lstrip('#')
lines.append(f"| Primary | `#{primary_hex}` | `Color(0xFF{primary_hex.upper()})` |")
lines.append(f"| Secondary | `#{secondary_hex}` | `Color(0xFF{secondary_hex.upper()})` |")
lines.append(f"| CTA/Accent | `#{cta_hex}` | `Color(0xFF{cta_hex.upper()})` |")
lines.append(f"| Background | `#{bg_hex}` | `Color(0xFF{bg_hex.upper()})` |")
lines.append(f"| Surface | `#{surface_hex}` | `Color(0xFF{surface_hex.upper()})` |")
lines.append(f"| Text | `#{text_hex}` | `Color(0xFF{text_hex.upper()})` |")
lines.append("")
if colors.get("notes"):
lines.append(f"**Color Notes:** {colors.get('notes', '')}")
lines.append("")
lines.append("### Typography")
lines.append("")
lines.append(f"- **Heading Font:** {typography.get('heading', 'Roboto')}")
lines.append(f"- **Body Font:** {typography.get('body', 'Roboto')}")
if typography.get("mood"):
lines.append(f"- **Mood:** {typography.get('mood', '')}")
if typography.get("google_fonts_url"):
lines.append(f"- **Google Fonts:** [{typography.get('heading', '')} + {typography.get('body', '')}]({typography.get('google_fonts_url', '')})")
lines.append("")
lines.append("**Material 3 Type Scale:**")
lines.append("```kotlin")
lines.append("// Display")
lines.append("displayLarge: 57.sp, displayMedium: 45.sp, displaySmall: 36.sp")
lines.append("// Headline")
lines.append("headlineLarge: 32.sp, headlineMedium: 28.sp, headlineSmall: 24.sp")
lines.append("// Title")
lines.append("titleLarge: 22.sp, titleMedium: 16.sp, titleSmall: 14.sp")
lines.append("// Body")
lines.append("bodyLarge: 16.sp, bodyMedium: 14.sp, bodySmall: 12.sp")
lines.append("// Label")
lines.append("labelLarge: 14.sp, labelMedium: 12.sp, labelSmall: 11.sp")
lines.append("```")
lines.append("")
lines.append("### Spacing")
lines.append("")
lines.append("| Token | Value | Usage |")
lines.append("|-------|-------|-------|")
lines.append("| `xs` | `4.dp` | Tight gaps |")
lines.append("| `sm` | `8.dp` | Icon gaps, inline spacing |")
lines.append("| `md` | `16.dp` | Standard padding |")
lines.append("| `lg` | `24.dp` | Section padding |")
lines.append("| `xl` | `32.dp` | Large gaps |")
lines.append("| `xxl` | `48.dp` | Section margins |")
lines.append("")
lines.append("### Corner Radius")
lines.append("")
lines.append("| Token | Value | Usage |")
lines.append("|-------|-------|-------|")
lines.append("| `xs` | `4.dp` | Small chips, badges |")
lines.append("| `sm` | `8.dp` | Buttons, inputs |")
lines.append("| `md` | `12.dp` | Cards |")
lines.append("| `lg` | `16.dp` | Modals, bottom sheets |")
lines.append("| `xl` | `24.dp` | Large containers |")
lines.append("| `full` | `9999.dp` | Pills, circular |")
lines.append("")
lines.append("---")
lines.append("")
lines.append("## Style Guidelines")
lines.append("")
lines.append(f"**Style:** {style.get('name', 'Material 3')}")
lines.append("")
if style.get("keywords"):
lines.append(f"**Keywords:** {style.get('keywords', '')}")
lines.append("")
if style.get("best_for"):
lines.append(f"**Best For:** {style.get('best_for', '')}")
lines.append("")
if effects:
lines.append(f"**Key Effects:** {effects}")
lines.append("")
lines.append("---")
lines.append("")
lines.append("## Anti-Patterns (Do NOT Use)")
lines.append("")
if anti_patterns:
anti_list = [a.strip() for a in anti_patterns.split("+")]
for anti in anti_list:
if anti:
lines.append(f"- ❌ {anti}")
lines.append("")
lines.append("### Android-Specific Forbidden Patterns")
lines.append("")
lines.append("- ❌ **God Activities/Fragments** — Activities > 200 lines, split into composables")
lines.append("- ❌ **Business logic in UI** — Move to ViewModel/UseCase/Domain layer")
lines.append("- ❌ **Blocking main thread** — Use coroutines with proper Dispatchers")
lines.append("- ❌ **MutableState abuse** — Use StateFlow for complex state")
lines.append("- ❌ **Hardcoded strings/colors** — Use theme and string resources")
lines.append("- ❌ **Missing error states** — Always handle loading/error/empty with sealed classes")
lines.append("")
lines.append("---")
lines.append("")
lines.append("## Pre-Delivery Checklist")
lines.append("")
lines.append("Before delivering any Android code, verify:")
lines.append("")
lines.append("- [ ] Compose previews for all screens and components")
lines.append("- [ ] Proper ViewModel scoping (no leaked references)")
lines.append("- [ ] Material 3 theme tokens (no hardcoded colors/sizes)")
lines.append("- [ ] Responsive: works on phone, tablet, foldable")
lines.append("- [ ] Accessibility: contentDescription, touch targets >= 48dp")
lines.append("- [ ] Performance: LazyColumn/Row for lists, no main-thread blocking")
lines.append("- [ ] State management: immutable UiState, one-way data flow")
lines.append("- [ ] Theme: colors and text styles from MaterialTheme")
lines.append("- [ ] Error handling: sealed UiState with Loading/Success/Error")
lines.append("- [ ] Null safety: no force unwrapping (!!)")
lines.append("")
return "\n".join(lines)
def format_page_override_md(design_system: dict[str, Any], page: str, page_query: str | None = None) -> str:
"""Format a page-specific override file."""
project = design_system.get("project_name", "PROJECT")
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
colors = design_system.get("colors", {})
typography = design_system.get("typography", {})
lines: list[str] = []
lines.append(f"# Page Override: {page.title()}")
lines.append("")
lines.append(f"> This file overrides `MASTER.md` for the **{page}** screen only.")
lines.append(f"> Generated: {timestamp}")
lines.append(f"> Project: {project}")
lines.append("")
lines.append("---")
lines.append("")
lines.append("## Screen-Specific Rules")
lines.append("")
lines.append(f"### {page.title()} Screen")
lines.append("")
lines.append("**Layout:**")
lines.append("- Top: TopAppBar with title")
lines.append("- Content: scrollable area")
lines.append("- Bottom: action buttons or navigation")
lines.append("")
lines.append("**Color Overrides:** _(inherit from MASTER unless specified)_")
lines.append("")
lines.append("| Element | Color | Notes |")
lines.append("|---------|-------|-------|")
lines.append(f"| Header | `{colors.get('primary', '')}` | Inherit |")
lines.append(f"| CTA Button | `{colors.get('cta', '')}` | Inherit |")
lines.append("| _custom_ | _specify_ | _override reason_ |")
lines.append("")
lines.append("**Typography Overrides:** _(inherit from MASTER unless specified)_")
lines.append("")
lines.append(f"- Heading: {typography.get('heading', 'Roboto')}")
lines.append(f"- Body: {typography.get('body', 'Roboto')}")
lines.append("")
lines.append("**Spacing Overrides:** _(inherit from MASTER unless specified)_")
lines.append("")
lines.append("- Standard padding: 16.dp (md)")
lines.append("")
lines.append("---")
lines.append("")
lines.append("## Compose Structure")
lines.append("")
lines.append("```kotlin")
page_pascal = page.replace("-", " ").replace("_", " ").title().replace(" ", "")
lines.append(f"@Composable")
lines.append(f"fun {page_pascal}Screen(")
lines.append(f" viewModel: {page_pascal}ViewModel = hiltViewModel()")
lines.append(f") {{")
lines.append(f" val uiState by viewModel.uiState.collectAsStateWithLifecycle()")
lines.append(f"")
lines.append(f" when (uiState) {{")
lines.append(f" is UiState.Loading -> LoadingIndicator()")
lines.append(f" is UiState.Success -> {page_pascal}Content(data = uiState.data)")
lines.append(f" is UiState.Error -> ErrorScreen(message = uiState.message)")
lines.append(f" }}")
lines.append(f"}}")
lines.append("```")
lines.append("")
return "\n".join(lines)
# ============ PUBLIC API ============
def generate_design_system(
query: str,
project_name: str | None = None,
output_format: str = "ascii",
persist: bool = False,
page: str | None = None,
output_dir: str | None = None
) -> str:
"""
Main entry point for design system generation.
Args:
query: Product/app description query
project_name: Optional project name
output_format: 'ascii' or 'markdown'
persist: Whether to save to disk
page: Optional page name for override file
output_dir: Output directory for persistence
Returns:
Formatted design system string
"""
generator = DesignSystemGenerator()
design_system = generator.generate(query, project_name)
if persist:
persist_design_system(design_system, page=page, output_dir=output_dir, page_query=query)
if output_format == "markdown":
return format_markdown(design_system)
else:
return format_ascii_box(design_system)
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Android Pro Max Search - CLI for Android/Kotlin knowledge base search
Usage: python search.py "<query>" [--domain <domain>] [--stack <stack>] [--top 5]
python search.py "<query>" --design-system [-p "Project Name"]
python search.py "<query>" --design-system --persist [-p "Project Name"] [--page "dashboard"]
Domains: view, package, pattern, architect, chart, color, typography, style, ux, icon, landing, naming, product, prompt, play-store, performance, ui-reasoning, accessibility
Stacks: compose, xml, hilt, koin
Persistence (Master + Overrides pattern):
--persist Save design system to design-system/MASTER.md
--page Also create a page-specific override file in design-system/pages/
"""
import argparse
import json
from core import (
CSV_CONFIG,
AVAILABLE_DOMAINS,
AVAILABLE_STACKS,
MAX_RESULTS,
search,
search_with_stack
)
from design_system import generate_design_system, persist_design_system
from typing import Any
def format_output(result: dict[str, Any]) -> str:
"""Format results for human-readable output (token-optimized for AI)"""
if "error" in result:
return f"❌ Error: {result['error']}"
output = []
# Header
output.append(f"\n🔍 Android Pro Max Search Results")
if result.get("stack"):
output.append(f" Stack: {result['stack']} (excluding: {', '.join(result.get('excluded', []))})")
output.append(f" Domain: {result['domain']} | Query: '{result['query']}'")
output.append(f" Source: {result['file']} | Found: {result['count']} results\n")
# Results
for i, row in enumerate(result['results'], 1):
output.append(f"{'='*60}")
output.append(f"[{i}] Score: {row.get('_score', 'N/A')}")
for key, value in row.items():
if key == "_score":
continue
value_str = str(value)
if len(value_str) > 200:
value_str = value_str[:200] + "..."
output.append(f" {key}: {value_str}")
output.append("")
return "\n".join(output)
def main():
parser = argparse.ArgumentParser(
description="Android Pro Max Search - BM25 search for Android/Kotlin knowledge base",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
python search.py "LazyColumn pagination" --top 3
python search.py "network http" --domain package
python search.py "state management" --stack compose
python search.py "google play store listing" --domain play-store
python search.py "login" --json
"""
)
parser.add_argument("query", help="Search query")
parser.add_argument(
"--domain", "-d",
choices=AVAILABLE_DOMAINS,
help=f"Search domain (auto-detected if not specified)"
)
parser.add_argument(
"--stack", "-s",
choices=AVAILABLE_STACKS,
help="Stack preference to exclude conflicting packages"
)
parser.add_argument(
"--top", "-n",
type=int,
default=MAX_RESULTS,
help=f"Max results (default: {MAX_RESULTS})"
)
parser.add_argument(
"--json", "-j",
action="store_true",
help="Output as JSON"
)
# Design system generation
parser.add_argument(
"--design-system", "-ds",
action="store_true",
help="Generate complete design system recommendation"
)
parser.add_argument(
"--project-name", "-p",
type=str,
default=None,
help="Project name for design system output"
)
parser.add_argument(
"--format", "-f",
choices=["ascii", "markdown"],
default="ascii",
help="Output format for design system"
)
# Persistence (Master + Overrides pattern)
parser.add_argument(
"--persist",
action="store_true",
help="Save design system to design-system/MASTER.md (creates hierarchical structure)"
)
parser.add_argument(
"--page",
type=str,
default=None,
help="Create page-specific override file in design-system/pages/"
)
parser.add_argument(
"--output-dir", "-o",
type=str,
default=None,
help="Output directory for persisted files (default: current directory)"
)
args = parser.parse_args()
# Design system takes priority
if args.design_system:
result = generate_design_system(
args.query,
args.project_name,
args.format,
persist=args.persist,
page=args.page,
output_dir=args.output_dir
)
print(result)
# Print persistence confirmation
if args.persist:
project_slug = args.project_name.lower().replace(' ', '-') if args.project_name else "default"
print("\n" + "=" * 60)
print(f"✅ Design system persisted to design-system/{project_slug}/")
print(f" 📄 design-system/{project_slug}/MASTER.md (Global Source of Truth)")
if args.page:
page_filename = args.page.lower().replace(' ', '-')
print(f" 📄 design-system/{project_slug}/pages/{page_filename}.md (Screen Overrides)")
print("")
print(f"📖 Usage: When building a screen, check design-system/{project_slug}/pages/[screen].md first.")
print(f" If exists, its rules override MASTER.md. Otherwise, use MASTER.md.")
print("=" * 60)
return
# Perform search
if args.stack:
result = search_with_stack(args.query, args.stack, args.domain, args.top)
else:
result = search(args.query, args.domain, args.top)
# Output
if args.json:
print(json.dumps(result, indent=2, ensure_ascii=False))
else:
print(format_output(result))
if __name__ == "__main__":
main()
## Quick Reference
### AI Tools Commands
```bash
# Format code (ALWAYS run after changes)
ktlint -F
# Static analysis
./gradlew detekt
# Android linting
./gradlew lint
# Run unit tests
./gradlew test
# Run connected tests
./gradlew connectedDebugAndroidTest
# Build debug APK
./gradlew assembleDebug
# Clean build
./gradlew clean
```
### Search Commands
```bash
# Auto-detect domain
python3 {{SCRIPT_PATH}}/search.py "LazyColumn" --top 5
# Specific domain
python3 {{SCRIPT_PATH}}/search.py "network http" --domain package --top 5
# Stack filter (compose, xml, hilt, koin)
python3 {{SCRIPT_PATH}}/search.py "state" --stack compose --top 5
# JSON output
python3 {{SCRIPT_PATH}}/search.py "login" --json --top 3
# Google Play Console workflow
python3 {{SCRIPT_PATH}}/search.py "google play listing" --domain play-store --top 5
python3 {{SCRIPT_PATH}}/search.py "data safety content rating" --domain play-store --json --top 5
```
### Package Management
```bash
# Add dependency (build.gradle.kts)
implementation("group:artifact:version")
# Add KSP dependency
ksp("group:artifact:version")
# Refresh dependencies
./gradlew --refresh-dependencies
# Show dependency tree
./gradlew dependencies
./gradlew :app:dependencyInsight --dependency kotlinx-coroutines-core
```
### Example Workflow
**User Request:** "Tạo màn hình đăng nhập"
1. **Search views:**
```bash
python3 {{SCRIPT_PATH}}/search.py "form input" --domain view --top 5
```
2. **Search patterns:**
```bash
python3 {{SCRIPT_PATH}}/search.py "authentication login" --domain pattern --top 5
```
3. **Search packages:**
```bash
python3 {{SCRIPT_PATH}}/search.py "validation" --domain package --top 5
```
4. **Apply results** với native state management (ViewModel + StateFlow)
### Google Play Console Workflow
1. Search `play-store` for ASO, listing copy, and compliance guidance.
2. Generate text assets with the correct limits before writing anything final.
3. Validate content rating, data safety, screenshots, and privacy policy details.
4. Export Markdown for humans and JSON for machine-readable handoff.
5. **Validate:**
```bash
ktlint -F && ./gradlew lint && ./gradlew test
```
### Quick Code Templates
```kotlin
// Structured Logging (use instead of println)
import android.util.Log
Log.d("App.Module", "Message")
// Sealed UI State
sealed interface UiState<out T> {
data object Loading : UiState<Nothing>
data class Success<T>(val data: T) : UiState<T>
data class Error(val message: String) : UiState<Nothing>
}
// ViewModel Pattern
class LoginViewModel(
private val repository: AuthRepository,
) : ViewModel() {
private val _uiState = MutableStateFlow(LoginUiState())
val uiState: StateFlow<LoginUiState> = _uiState.asStateFlow()
fun onEmailChanged(value: String) {
_uiState.update { it.copy(email = value) }
}
}
// Compose Navigation
val navController = rememberNavController()
NavHost(navController, startDestination = "home") {
composable("home") { HomeScreen() }
composable("profile/{userId}") { backStackEntry ->
ProfileScreen(userId = backStackEntry.arguments?.getString("userId"))
}
}
```
---
description: Tự động sử dụng skill search trước khi viết code Android/Kotlin
globs: "**/*.kt"
---
# Rule: Tự động sử dụng Skill
> Kích hoạt: Khi làm việc với Android/Kotlin files
**TRƯỚC KHI viết code Android**, bạn PHẢI tự động sử dụng skill để lấy knowledge phù hợp. Không được bỏ qua bước này.
| Tình huống | Domains cần search |
|------------|-------------------|
| Tạo UI/Screen mới | `view`, `pattern`, `color`, `typography`, `landing` |
| Chọn package/thư viện | `package` (kèm `--stack` filter nếu có) |
| Thiết kế kiến trúc | `architect`, `pattern` |
| Tối ưu performance | `performance` |
| Accessibility | `accessibility` |
| Không chắc UI style | Dùng `--design-system` để generate design system |
**Workflow bắt buộc:**
```
User request → Xác định task type (Greenfield/Brownfield) theo Architecture Decision Matrix → Search skill (≥2 domains) → Đọc kết quả → Áp dụng vào code
```
> Tham chiếu: `19_architecture_decision_matrix.md` để chọn architecture strategy, state strategy, và refactor scope trước khi implement.
> ⚠️ Viết code Android mà không tham khảo skill trước = thiếu context = code chất lượng thấp.
---
description: Tiêu chuẩn Code Quality, Think-Before-Code, Hard Constraints cho Android/Kotlin
globs: "**/*.kt"
---
# Rule: Code Quality & Hard Constraints
> Kích hoạt: Khi tạo/chỉnh sửa files `.kt`
## Architecture Policy
- **Mặc định:** Code mới follow **Clean Architecture** (UI/Presentation -> Domain -> Data).
- **Maintenance dự án cũ:** Follow kiến trúc đang có (MVC/MVVM/Layered), không ép đổi framework state/architecture nếu user không yêu cầu.
- **Nguyên tắc bất biến:** Không trộn concerns, không logic leakage, refactor tăng dần theo từng feature.
## Think-Before-Code Protocol
**TRƯỚC KHI tạo file mới hoặc viết composable/class**, bạn PHẢI trả lời 5 câu hỏi:
1. **File này có vượt 300 dòng không?** → Nếu có khả năng, TÁCH ngay từ đầu
2. **Class/Composable này đã tồn tại chưa?** → Search codebase trước, REUSE nếu có
3. **Component này có thể reuse cho nơi khác không?** → Nếu có, đặt vào `core/ui/` hoặc shared module
4. **Logic này thuộc layer nào?** → UI / Domain / Data — KHÔNG được trộn layers
5. **Có class/hàm nào đang lặp logic tương tự không?** → Nếu có, REFACTOR thành shared component
## Hard Constraints (Vùng Cấm)
### 🚫 NO GOD CLASSES
| Indicator | Threshold | Action |
|-----------|-----------|--------|
| Public methods | > 10 methods | 🔴 **REFACTOR** |
| Lines of logic | > 200 lines | 🔴 **REFACTOR** |
| Mixed concerns | Logic + UI + DB | 🔴 **TÁCH NGAY** |
### 🚫 NO GOD FILES
| Rule | Limit |
|------|-------|
| **File size** | ≤ 300 dòng (tối đa 500) |
| **Classes per file** | 1 Class chính duy nhất |
### 🚫 NO LOGIC LEAKAGE
| Violation | Clean (mặc định) | Legacy-compatible |
|-----------|------------------|-------------------|
| Business Logic trong Composable/Activity | ➜ Move to `UseCase` / `Service` | ➜ Move to `ViewModel` / `Service` |
| SQL/Query trong ViewModel | ➜ Move to `Repository` | ➜ Move to data layer hiện hữu (`Repository` / `Dao` / `DataSource`) |
| API calls trong UI | ➜ Move to `DataSource` | ➜ Move to `ViewModel` / `Repository` theo project |
## Nguyên tắc cứng
| ❌ Sai | ✅ Đúng |
|--------|---------|
| Tạo `UserCard` mới khi đã có `ProfileCard` tương tự | Mở rộng `ProfileCard` hoặc extract shared `BaseCard` |
| Screen 500+ dòng | Tách thành `HeaderSection`, `ContentBody`, `ActionBar` |
| 3 screens cùng copy-paste search bar | Tạo `SearchableScaffold` composable dùng chung |
| Hardcode colors, padding, font sizes | Dùng `MaterialTheme`, design tokens, constants |
| Business logic trong `@Composable` | Tách vào UseCase/Service (Clean) hoặc ViewModel (legacy) |
> 🔴 **REUSE > CREATE.** Không bao giờ tạo file mới mà không kiểm tra codebase hiện tại trước.
---
description: Quy trình làm việc ABCR (Audit-Block-Critique-Refactor) khi nhận request
globs: "**/*.kt"
---
# Rule: Interaction Flow (ABCR)
> Kích hoạt: Khi review, refactor, hoặc fix bugs
## Architecture Mode Selection (Bắt buộc)
Trước khi vào ABCR, xác định mode kiến trúc:
1. **Greenfield/New Module** -> Mặc định dùng **Clean Architecture** + Compose.
2. **Maintenance dự án cũ** -> **Tôn trọng kiến trúc hiện hữu** (MVC/MVVM/Layered), không ép migrate tổng thể.
3. **Thêm feature trong dự án cũ** -> Follow convention hiện tại của feature, chỉ refactor tăng dần để giảm nợ kỹ thuật.
## Mandatory Execution Header (Bắt buộc)
Trước mỗi lần implement, refactor, hoặc review code, phải bắt đầu bằng header sau:
```md
Task Type: <Greenfield | Brownfield Feature | Brownfield Hotfix>
Architecture Strategy: <Clean default | Follow existing architecture>
State Strategy: <stack được chọn cho module>
Refactor Scope: <minimal | incremental | structured>
```
Nếu thiếu header này, coi như chưa đạt quy trình ABCR.
Khi nhận request liên quan đến code hiện tại, luôn tuân thủ quy trình:
1. **AUDIT** - Quét code smells, kiểm tra God Class/File
2. **BLOCK** - Cảnh báo nếu vi phạm, giải thích Technical Debt
3. **REFACTOR** - Refactor tối thiểu trong kiến trúc hiện hữu trước khi fix bug (chỉ đề xuất migrate tổng thể khi user yêu cầu)
4. **EXPLAIN** - Giải thích lý do tách/refactor
### Khi nào áp dụng ABCR?
| Tình huống | Áp dụng? |
|------------|----------|
| User yêu cầu fix bug | ✅ AUDIT trước, refactor nếu có code smell |
| User yêu cầu thêm feature | ✅ AUDIT file đích trước khi thêm code |
| User yêu cầu tạo file mới | ⚠️ Chỉ AUDIT các file liên quan |
| User hỏi kiến thức chung | ❌ Không cần ABCR |
> 💡 **Mục đích:** Không bao giờ thêm code rác lên code rác. Fix nền tảng trước.
---
description: Đảm bảo tính nhất quán (Consistency) của UI, Design Tokens, Component Patterns
globs: "**/*.kt"
---
# Rule: App Consistency
> Kích hoạt: Khi tạo UI, thêm screen, hoặc chỉnh sửa composable
## Nguyên tắc: Mọi thứ phải nhất quán
**TRƯỚC KHI viết UI code**, bạn PHẢI kiểm tra các pattern hiện có trong project để đảm bảo consistency.
## 1. Design Tokens — Dùng chung, không hardcode
| ❌ Sai | ✅ Đúng |
|--------|---------|
| `Color(0xFF1A73E8)` | `MaterialTheme.colorScheme.primary` |
| `Modifier.padding(16.dp)` | `Modifier.padding(AppSpacing.md)` hoặc constant |
| `TextStyle(fontSize = 14.sp)` | `MaterialTheme.typography.bodyMedium` |
| `RoundedCornerShape(8.dp)` | `RoundedCornerShape(AppRadius.sm)` |
## 2. Component Patterns — Copy style từ existing screens
**TRƯỚC KHI tạo screen mới:**
1. Tìm screen tương tự trong codebase (list, detail, form, dashboard)
2. Sao chép cấu trúc, spacing, và layout pattern
3. Dùng cùng composable wrappers (Scaffold, TopAppBar style, padding)
| Element | Quy tắc |
|---------|---------|
| **TopAppBar** | Dùng chung 1 style/component cho toàn app |
| **Empty States** | Dùng chung composable, không tạo mới mỗi screen |
| **Loading States** | Dùng chung shimmer/skeleton, không mỗi chỗ 1 kiểu |
| **Error States** | Dùng chung error composable với retry action |
| **List Items** | Cùng padding, divider style, tap behavior |
| **Forms** | Cùng validation style, field spacing, button placement |
| **Dialogs** | Cùng shape, padding, button alignment |
## 3. Navigation & Transitions
- Dùng chung transition animations (không mỗi screen 1 kiểu)
- Consistent back button behavior
- Cùng pattern cho bottom sheets, modals, popups
## 4. Spacing System
Định nghĩa và tuân thủ spacing scale:
```kotlin
// ✅ Dùng constants
object AppSpacing {
val xs = 4.dp
val sm = 8.dp
val md = 16.dp
val lg = 24.dp
val xl = 32.dp
}
```
> 🔴 **Khi có nghi ngờ:** Mở screen hiện tại có cùng chức năng → copy exact spacing và layout pattern. **Không sáng tạo riêng.**
---
description: Xử lý lỗi, Try-catch, Result pattern, Không fail im lặng
globs: "**/*.kt"
---
# Rule: Error Handling
> Kích hoạt: Khi viết logic xử lý dữ liệu, API calls, hoặc coroutine operations
## Nguyên tắc: Không bao giờ fail im lặng
### Bắt buộc
| Tình huống | Cách xử lý |
|------------|------------|
| API call | Luôn wrap trong `try-catch`, log lỗi, hiển thị message cho user |
| Parse JSON/data | Dùng `runCatching` hoặc `try-catch`, KHÔNG để crash |
| File I/O | Handle `IOException` cụ thể |
| Navigation args | Validate params trước khi dùng |
| Coroutine cancellation | Không nuốt `CancellationException` |
### Pattern chuẩn
```kotlin
// ✅ Structured error handling with sealed result
suspend fun fetchUser(id: String): Result<User> {
return try {
val response = api.getUser(id)
Result.success(User.fromDto(response))
} catch (e: HttpException) {
Log.e("UserRepo", "API failed", e)
Result.failure(e.toAppError())
} catch (e: CancellationException) {
throw e // Never swallow coroutine cancellation
} catch (e: Exception) {
Log.e("UserRepo", "Unexpected", e)
Result.failure(AppError.Unexpected(e))
}
}
```
### Cấm
| ❌ Sai | Lý do |
|--------|-------|
| `catch (e: Exception) {}` (empty catch) | Nuốt lỗi, debug nightmare |
| `println(e)` | Dùng `Log.e()` hoặc structured logging |
| Throw generic `Exception("Error")` | Tạo sealed exceptions có context |
| Ignore `CancellationException` | Phá vỡ structured concurrency |
| Catch `Throwable` without rethrow | Có thể nuốt cả `OutOfMemoryError` |
> 🔴 **Mỗi `try` phải có `catch` có ý nghĩa.** Log + User message + Recovery action.
---
description: Viết Unit Test, UI Test, Integration Test cho Android
globs: "**/*.kt"
---
# Rule: Testing
> Kích hoạt: Khi tạo feature mới, fix bug, hoặc refactor logic
## Nguyên tắc: Không có test = Không hoàn thành
### Khi nào PHẢI viết test
| Loại code | Test bắt buộc | Ví dụ |
|-----------|---------------|-------|
| Business logic | Unit test | UseCase, Service, Validator |
| Repository/DataSource | Unit test với mock | API calls, Room queries |
| ViewModel | Unit test với Turbine | StateFlow assertions |
| Composable có logic | UI test | Form validation, state changes |
| User flow quan trọng | Integration test | Login, checkout, onboarding |
### Khi nào KHÔNG cần test
- Pure UI composable không có logic (chỉ layout/styling)
- Generated code (Room DAOs, Moshi adapters)
- Constants, enums đơn giản
### Pattern chuẩn
```kotlin
// ✅ Test structure: Arrange → Act → Assert
@Test
fun `should return user when API succeeds`() = runTest {
// Arrange
coEvery { mockApi.getUser("123") } returns UserDto(name = "John")
// Act
val result = useCase.execute("123")
// Assert
assertThat(result).isInstanceOf(Result.Success::class.java)
assertThat((result as Result.Success).data.name).isEqualTo("John")
}
```
### Quy tắc
- File test đặt cùng tên: `UserService.kt` → `UserServiceTest.kt`
- Dùng `mockk` hoặc `Mockito-Kotlin` cho mocking
- Dùng `kotlinx.coroutines.test` cho coroutine testing
- Dùng `app.cash.turbine` cho Flow testing
- Mỗi test case chỉ test 1 behavior
- Tên test mô tả behavior: `` `should [expected] when [condition]` ``
> 🔴 **Fix bug?** Viết test reproduce bug TRƯỚC, rồi mới fix.
---
description: Tối ưu hiệu năng, recomposition, LazyColumn, coroutine, memory
globs: "**/*.kt"
---
# Rule: Performance
> Kích hoạt: Khi viết composable, xử lý danh sách, hoặc coroutine operations
## Nguyên tắc: Performance là requirement, không phải nice-to-have
### Compose Recomposition
| ❌ Sai | ✅ Đúng | Impact |
|--------|---------|--------|
| Unstable parameters trong composable | `@Stable` hoặc `@Immutable` annotations | Giảm recomposition |
| `List<T>` parameters | `ImmutableList<T>` hoặc `PersistentList<T>` | Prevent unnecessary recomposition |
| Lambda captures mutable state | Extract và hoist callbacks | Tránh tạo lambda mỗi recomposition |
| Inline function trong `@Composable` | Extract method hoặc `remember` | Tránh tạo closure mỗi frame |
| Rebuild toàn tree | Scoped state với `derivedStateOf` | Chỉ rebuild phần thay đổi |
### Async & Coroutine
| Quy tắc | Lý do |
|----------|-------|
| KHÔNG gọi suspend function trong `@Composable` trực tiếp | Block UI thread |
| Heavy JSON parsing → dùng `withContext(Dispatchers.Default)` | Chạy trên background thread |
| Image loading → dùng `Coil` hoặc `Glide` | Tránh OOM, tự cache |
| Debounce search input (300-500ms) | Giảm API calls |
| Structured concurrency → dùng `viewModelScope` | Tự cancel khi ViewModel cleared |
### State Management Performance
```kotlin
// ❌ Toàn composable tree recompose
var counter by remember { mutableStateOf(0) }
// ✅ Scoped recomposition
val counter = remember { mutableIntStateOf(0) }
// Chỉ Text recompose
Text("${counter.intValue}")
```
### Performance (Bài toán Scale)
Code chạy mượt ở 10 items có thể crash app ở 10,000 items. ANR và OOM thường âm thầm và khó debug.
| Quy mô | Giải pháp Render |
|--------|------------------|
| Ít items (< 20) | `Column` bọc trong `verticalScroll` (Có thể chấp nhận) |
| Nhiều items (Hàng ngàn) | **BẮT BUỘC** dùng `LazyColumn` kết hợp Pagination |
| Grid dữ liệu lớn | `LazyVerticalGrid` hoặc Paging 3 |
### Checklist trước ship
- [ ] Tất cả composable parameters stable/immutable
- [ ] LazyColumn/LazyRow dùng `key` parameter
- [ ] Màn hình danh sách có hỗ trợ phân trang (Paging) nếu data có thể phình to
- [ ] Không có `Log.d()` còn sót (dùng `Timber` hoặc ProGuard strip)
- [ ] Baseline Profile đã generate cho critical user journeys
> 🔴 **Nếu list > 20 items → BẮT BUỘC dùng `LazyColumn`.** Luôn tự hỏi: *"Nếu user có 1 triệu record thì sao?"*
---
description: Bảo vệ secrets, user data, network flows cho Android
globs: "**/*.kt"
---
# Rule: Security
> Kích hoạt: Khi xử lý authentication, storage, hoặc network
## Nguyên tắc: Security by Default
### Bắt buộc
| Tình huống | Cách xử lý |
|------------|------------|
| Lưu token/credentials | `EncryptedSharedPreferences` hoặc Android Keystore |
| API calls | HTTPS only, Certificate Pinning khi cần |
| Secrets (API keys) | `local.properties` + BuildConfig, KHÔNG commit vào git |
| User data | Encryption at rest với AndroidX Security |
| Deep links | Validate intent data trước khi xử lý |
| WebView | Disable JavaScript nếu không cần, validate URLs |
### Cấm
| ❌ Sai | ✅ Đúng |
|--------|---------|
| `SharedPreferences` cho token | `EncryptedSharedPreferences` |
| Hardcode API key trong source | `BuildConfig.API_KEY` từ `local.properties` |
| HTTP (không TLS) | HTTPS only, Network Security Config |
| Log sensitive data | Chỉ log non-PII, strip logs ở release |
| `android:exported="true"` không filter | Intent filter cụ thể hoặc `exported="false"` |
### Code Example
```kotlin
// ✅ Secure token storage
val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
val securePrefs = EncryptedSharedPreferences.create(
context, "secure_prefs", masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
```
> 🔴 **Không bao giờ commit secrets vào git.** Dùng `local.properties` và `.gitignore`.
---
description: Quản lý state theo cấp độ (Native-first), ViewModel + StateFlow
globs: "**/*.kt"
---
# Rule: State Management
> Kích hoạt: Khi quản lý state trong composable, screen, hoặc app-level
## Nguyên tắc: Native-First, Escalate khi cần
## Architecture-Aware Policy
1. **Mặc định (code mới):** Follow Clean Architecture, state đặt ở presentation layer (ViewModel).
2. **Maintenance dự án cũ:** Giữ nguyên state stack hiện có của module (LiveData, RxJava, Flow...), không ép migrate nếu không có yêu cầu rõ ràng.
3. **Feature mới trong module cũ:** Ưu tiên giống pattern state của module đó để giảm chi phí maintain.
### Hierarchy (Ưu tiên từ trên xuống)
| Level | Giải pháp | Khi nào dùng |
|-------|-----------|-------------|
| 1️⃣ | `remember { mutableStateOf() }` | UI state đơn giản (toggle, counter) |
| 2️⃣ | `rememberSaveable` | State cần survive configuration changes |
| 3️⃣ | `ViewModel` + `StateFlow` | Screen-level state với business logic |
| 4️⃣ | `ViewModel` + `MutableState` | Compose-specific screen state |
| 5️⃣ | Shared ViewModel / Navigation Args | State giữa nhiều screens |
### Mapping theo kiến trúc
| Kiến trúc | State owner ưu tiên |
|----------|----------------------|
| Clean Architecture | ViewModel + StateFlow |
| MVVM | ViewModel + LiveData/StateFlow |
| MVI | ViewModel + Intent/State reducer |
| Legacy Activity | Local state scoped Activity/Fragment |
### Quy tắc cứng
| ❌ Sai | ✅ Đúng |
|--------|---------|
| MutableStateFlow exposed trực tiếp | Private `_uiState`, public `uiState: StateFlow` |
| Mutable state trong composable cho complex logic | ViewModel + immutable UiState |
| Global state cho state chỉ 1 screen dùng | Local state trong ViewModel scoped |
| Mutable data class | Immutable data class + `copy()` |
### Pattern chuẩn
```kotlin
// ✅ Standard: ViewModel + StateFlow + Immutable UiState
data class LoginUiState(
val email: String = "",
val password: String = "",
val isLoading: Boolean = false,
val error: String? = null,
)
class LoginViewModel(
private val authRepository: AuthRepository,
) : ViewModel() {
private val _uiState = MutableStateFlow(LoginUiState())
val uiState: StateFlow<LoginUiState> = _uiState.asStateFlow()
fun onEmailChanged(value: String) {
_uiState.update { it.copy(email = value) }
}
}
```
> ⚠️ **Không tự ý thay state framework của dự án cũ.** Chỉ escalate (migrate) khi user yêu cầu rõ ràng.
---
description: Quy ước đặt tên Kotlin, Android resources, module naming
globs: "**/*.kt"
---
# Rule: Naming & Conventions
> Kích hoạt: Khi tạo files, classes, functions, resources mới
## Nguyên tắc: Rõ nghĩa, nhất quán, dự đoán được
### Kotlin Naming
| Loại | Convention | Ví dụ |
|------|-----------|-------|
| **Class/Interface** | PascalCase, danh từ | `UserRepository`, `LoginViewModel` |
| **Function** | camelCase, động từ | `fetchUser()`, `validateEmail()` |
| **Property** | camelCase | `userName`, `isLoading` |
| **Constant** | SCREAMING_SNAKE_CASE | `MAX_RETRY_COUNT`, `BASE_URL` |
| **Package** | lowercase, no underscore | `com.example.feature.login` |
| **File** | Match primary type | `UserRepository.kt`, `LoginScreen.kt` |
### Android-Specific Naming
| Loại | Convention | Ví dụ |
|------|-----------|-------|
| **Activity** | `[Feature]Activity` | `LoginActivity`, `MainActivity` |
| **Fragment** | `[Feature]Fragment` | `ProfileFragment` |
| **ViewModel** | `[Feature]ViewModel` | `LoginViewModel` |
| **Screen (Compose)** | `[Feature]Screen` | `LoginScreen`, `HomeScreen` |
| **Component (Compose)** | PascalCase mô tả | `UserCard`, `SearchBar` |
| **UseCase** | `[Action][Entity]UseCase` | `GetUserUseCase`, `ValidateEmailUseCase` |
| **Repository** | `[Entity]Repository` | `UserRepository`, `AuthRepository` |
| **DataSource** | `[Entity][Type]DataSource` | `UserRemoteDataSource`, `UserLocalDataSource` |
### Resource Naming
| Loại | Convention | Ví dụ |
|------|-----------|-------|
| **Layout** | `[type]_[feature]` | `activity_login`, `fragment_profile` |
| **String** | `[feature]_[description]` | `login_title`, `profile_edit_button` |
| **Drawable** | `[type]_[description]` | `ic_arrow_back`, `bg_gradient_blue` |
| **Color** | `[usage]_[shade]` | `primary_500`, `text_secondary` |
| **Dimen** | `[type]_[size]` | `margin_medium`, `text_body` |
### Layer-Specific File Structure
| Layer | Folder | File Pattern |
|-------|--------|-------------|
| Presentation | `feature/[name]/presentation/` | `[Feature]Screen.kt`, `[Feature]ViewModel.kt` |
| Domain | `feature/[name]/domain/` | `[Entity].kt`, `[Action]UseCase.kt` |
| Data | `feature/[name]/data/` | `[Entity]Repository.kt`, `[Entity]Dto.kt` |
| Core UI | `core/ui/` | `AppButton.kt`, `SearchBar.kt` |
| Core Util | `core/util/` | `DateUtils.kt`, `Extensions.kt` |
### Quy tắc cứng
| ❌ Sai | ✅ Đúng |
|--------|---------|
| `Util.kt` (quá chung) | `DateUtils.kt`, `StringExtensions.kt` |
| `Data.kt` (mơ hồ) | `UserDto.kt`, `LoginResponse.kt` |
| `Helper.kt` | Extension functions trong file mô tả rõ |
| `myFun()` | `validateUserInput()` |
| `process()` | `transformDtoToEntity()` |
> 🔴 **Tên phải tự giải thích.** Nếu cần comment để hiểu tên, tên đó chưa đủ rõ.
---
description: Đảm bảo Android UIs accessible cho TalkBack, touch targets, contrast
globs: "**/*.kt"
---
# Rule: Accessibility
> Kích hoạt: Khi tạo hoặc chỉnh sửa UI composables
## Nguyên tắc: Accessibility là requirement, không phải optional
### Bắt buộc
| Quy tắc | Chi tiết |
|---------|----------|
| **Content Description** | Mọi interactive element và image phải có `contentDescription` |
| **Touch Target** | Tối thiểu 48dp x 48dp cho tất cả interactive elements |
| **Contrast** | Text-to-background contrast ratio >= 4.5:1 (WCAG AA) |
| **Font Scaling** | UI phải hoạt động khi user tăng font size lên 200% |
| **Focus Order** | Tab/focus order phải logic và tuần tự |
| **Headings** | Dùng `semantics { heading() }` cho section headings |
### Code Examples
```kotlin
// ✅ Image with content description
Image(
painter = painterResource(R.drawable.profile),
contentDescription = "User profile picture"
)
// ✅ Decorative image (no announcement)
Image(
painter = painterResource(R.drawable.bg),
contentDescription = null // Decorative
)
// ✅ Minimum touch target
IconButton(
onClick = { /* action */ },
modifier = Modifier.size(48.dp) // Minimum 48dp
) {
Icon(Icons.Default.Close, contentDescription = "Close")
}
// ✅ Custom semantics
Text(
text = "Settings",
modifier = Modifier.semantics { heading() }
)
```
### Checklist
- [ ] Mọi `Icon` và `Image` có `contentDescription` hoặc explicitly null
- [ ] Tất cả buttons, toggles >= 48dp touch target
- [ ] Colors pass WCAG AA contrast (4.5:1 text, 3:1 large text)
- [ ] App responsive với font scaling (không bị cắt/overflow)
- [ ] TalkBack đọc đúng thứ tự và mô tả
> 🔴 **App không accessible = app không hoàn thành.** Test với TalkBack bật trước khi ship.
---
description: Thiết kế network flows resilient với retry, timeout, backoff
globs: "**/*.kt"
---
# Rule: Network Resiliency
> Kích hoạt: Khi viết API calls, network operations, hoặc data sync
## Nguyên tắc: Mạng luôn có thể fail
### Bắt buộc
| Quy tắc | Giải pháp |
|---------|-----------|
| **Timeout** | Set connect/read/write timeout (15s/30s/30s) |
| **Retry** | Exponential backoff cho idempotent requests |
| **Cancellation** | Respect coroutine cancellation, cancel khi scope cleared |
| **Error mapping** | Map HttpException → domain errors cụ thể |
| **Connectivity check** | Kiểm tra network state trước heavy operations |
### Pattern chuẩn
```kotlin
// ✅ OkHttp với timeout
val client = OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.addInterceptor(AuthInterceptor(tokenProvider))
.addInterceptor(HttpLoggingInterceptor().apply {
level = if (BuildConfig.DEBUG) Level.BODY else Level.NONE
})
.build()
// ✅ Retry with exponential backoff
suspend fun <T> retryWithBackoff(
times: Int = 3,
initialDelay: Long = 1000,
factor: Double = 2.0,
block: suspend () -> T,
): T {
var currentDelay = initialDelay
repeat(times - 1) {
try { return block() }
catch (e: Exception) {
if (e is CancellationException) throw e
delay(currentDelay)
currentDelay = (currentDelay * factor).toLong()
}
}
return block() // Last attempt
}
```
> 🔴 **Không giả định mạng luôn OK.** Thiết kế cho worst case: mất kết nối giữa chừng.
---
description: Ưu tiên offline-first experiences với Room, DataStore, cache strategy
globs: "**/*.kt"
---
# Rule: Offline-First
> Kích hoạt: Khi thiết kế data flow cho user-facing features
## Nguyên tắc: Local trước, Remote sau
### Strategy
| Bước | Hành động |
|------|-----------|
| 1 | Đọc data từ local cache (Room/DataStore) → hiển thị ngay |
| 2 | Gọi API remote → cập nhật local cache |
| 3 | Emit data mới từ local cache → UI tự update |
| 4 | Nếu mất mạng → hiển thị data cũ + indicator offline |
### Pattern chuẩn
```kotlin
// ✅ Repository: local-first with remote refresh
class UserRepository(
private val localSource: UserDao,
private val remoteSource: UserApi,
) {
fun getUsers(): Flow<List<User>> = flow {
// 1. Emit cached data first
val cached = localSource.getAll()
emit(cached.map { it.toEntity() })
// 2. Fetch remote and update cache
try {
val remote = remoteSource.getUsers()
localSource.insertAll(remote.map { it.toLocal() })
} catch (e: Exception) {
if (e is CancellationException) throw e
// Silent fail: user already has cached data
Log.w("UserRepo", "Remote fetch failed", e)
}
// 3. Emit updated data from cache
emitAll(localSource.observeAll().map { list ->
list.map { it.toEntity() }
})
}
}
```
### Sync Status
| Status | Hiển thị |
|--------|----------|
| `SYNCED` | Data mới nhất, no indicator |
| `PENDING` | Badge hoặc icon "đang đồng bộ" |
| `OFFLINE` | Banner "Đang offline, hiển thị data cũ" |
| `ERROR` | Error message + retry button |
> 🔴 **Không chặn user khi mất mạng.** Hiển thị data cached + offline indicator.
---
description: Giữ UI functional khi partial failures, fallback composables
globs: "**/*.kt"
---
# Rule: Graceful Degradation
> Kích hoạt: Khi viết UI hiển thị remote data, images, hoặc complex content
## Nguyên tắc: Không bao giờ blank screen hoặc crash
### Bắt buộc
| Tình huống | Fallback |
|------------|----------|
| Image load fail | Placeholder → error icon |
| API error | Error composable + retry button |
| Empty list | Empty state composable (icon + message + CTA) |
| Partial data | Hiển thị fields có data, ẩn fields thiếu |
| Network timeout | Cached data + "Đang offline" banner |
### Sealed UiState Pattern
```kotlin
// ✅ Sealed UI state covers all cases
sealed interface UiState<out T> {
data object Loading : UiState<Nothing>
data class Success<T>(val data: T) : UiState<T>
data class Error(val message: String) : UiState<Nothing>
data object Empty : UiState<Nothing>
}
// ✅ Composable handles all states
@Composable
fun <T> StateHandler(
state: UiState<T>,
onRetry: () -> Unit,
content: @Composable (T) -> Unit,
) {
when (state) {
is UiState.Loading -> LoadingIndicator()
is UiState.Success -> content(state.data)
is UiState.Error -> ErrorScreen(state.message, onRetry)
is UiState.Empty -> EmptyState()
}
}
```
### Reusable Error/Placeholder Composables
- `LoadingIndicator()` — Shared loading across app
- `ErrorScreen(message, onRetry)` — Error + retry action
- `EmptyState(icon, title, subtitle, action)` — Empty list/search
- `ImageWithFallback(url, placeholder, error)` — Image with states
> 🔴 **User thấy blank screen = app hỏng.** Luôn có fallback cho mọi trạng thái.
---
description: Respect Android lifecycle, configuration changes, process death
globs: "**/*.kt"
---
# Rule: State Lifecycle
> Kích hoạt: Khi quản lý state qua rotation, background, process death
## Nguyên tắc: State phải survive đúng cách
### Lifecycle-Aware State
| Sự kiện | Giải pháp |
|---------|-----------|
| **Configuration change** (rotation) | ViewModel giữ state tự động |
| **App backgrounded** | `rememberSaveable` cho UI state |
| **Process death** | `SavedStateHandle` trong ViewModel |
| **Navigation back** | Restore state từ ViewModel hoặc SavedStateHandle |
| **Coroutine scope** | Dùng `viewModelScope`, tự cancel khi ViewModel cleared |
### SavedStateHandle Pattern
```kotlin
// ✅ State survives process death
class SearchViewModel(
private val savedStateHandle: SavedStateHandle,
private val searchUseCase: SearchUseCase,
) : ViewModel() {
val query = savedStateHandle.getStateFlow("query", "")
fun onQueryChanged(newQuery: String) {
savedStateHandle["query"] = newQuery
performSearch(newQuery)
}
}
```
### Lifecycle Collection
```kotlin
// ✅ Lifecycle-aware Flow collection in Compose
@Composable
fun ProfileScreen(viewModel: ProfileViewModel = hiltViewModel()) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
// UI responds to state changes, stops collecting when not visible
}
```
### Cấm
| ❌ Sai | ✅ Đúng |
|--------|---------|
| Giữ Activity/Context reference trong ViewModel | Dùng `Application` context nếu cần |
| Collect Flow trong `onCreate` không cancel | `collectAsStateWithLifecycle()` |
| Static mutable state | ViewModel scoped state |
| `GlobalScope.launch` | `viewModelScope.launch` |
| Forget to handle `onCleared()` | Clean up resources in `onCleared()` |
> 🔴 **Test process death:** Developer Options → "Don't keep activities" → verify state restore.
---
description: Optimize Play Store listing copy và discoverability
globs: "**/*.md"
---
# Rule: Google Play ASO
> Kích hoạt: Khi tạo, review, hoặc tối ưu Play Store listing
## Nguyên tắc: Tối ưu cho người dùng thật, không nhồi keyword
### Text Asset Limits
| Asset | Limit | Quy tắc |
|-------|-------|---------|
| **App Name** | 30 ký tự | Brand + core keyword |
| **Short Description** | 80 ký tự | Value proposition rõ ràng |
| **Full Description** | 4000 ký tự | Structured, benefit-first |
### Full Description Structure
```
Paragraph 1: Core value (50-100 words)
- Bullet points: Key features (5-7 items)
Paragraph 2: How it works / unique differentiator
Paragraph 3: Social proof / trust signals
Call to action: Download now / Get started
```
### Keyword Strategy
| ❌ Sai | ✅ Đúng |
|--------|---------|
| Nhồi keyword lặp lại | Tự nhiên, đa dạng từ đồng nghĩa |
| Dùng từ kỹ thuật (API, SDK) | Dùng lợi ích user hiểu được |
| Copy competitor listing | Unique voice và USP |
| ALL CAPS hoặc emoji spam | Professional, clean format |
### Localization
- Ưu tiên dịch short description và title trước
- Dùng keyword research cho mỗi locale
- Screenshots cần localize text overlays
> 🔴 **ASO = first impression.** Listing phải trả lời "Tại sao tôi nên cài app này?" trong 3 giây.
---
description: Keep store listings compliant, data safety, content rating
globs: "**/*.md"
---
# Rule: Google Play Compliance
> Kích hoạt: Khi chuẩn bị publish hoặc update app trên Play Store
## Nguyên tắc: Compliance trước, publish sau
### Pre-Publish Checklist
| Hạng mục | Chi tiết | Bắt buộc? |
|----------|----------|-----------|
| **Content Rating** | Hoàn thành IARC questionnaire | ✅ |
| **Data Safety** | Khai báo data collection/sharing | ✅ |
| **Privacy Policy** | URL valid, accessible, cập nhật | ✅ |
| **Target Audience** | Chọn đúng age group | ✅ |
| **Permissions** | Chỉ request permissions thật sự cần | ✅ |
| **Ads Declaration** | Khai báo nếu có quảng cáo | ✅ nếu có ads |
### Data Safety Form
| Loại data | Cần khai báo nếu |
|-----------|-----------------|
| Name, Email, Phone | Đăng ký, profile |
| Location | GPS, IP-based location |
| Photos/Videos | Camera access, gallery |
| Device ID | Analytics, crash reporting |
| Purchase history | In-app purchases |
### Permissions Best Practice
| ❌ Sai | ✅ Đúng |
|--------|---------|
| Request ALL permissions at startup | Request khi cần (just-in-time) |
| `READ_PHONE_STATE` không cần thiết | Chỉ request permissions app thật sự dùng |
| Không giải thích tại sao cần permission | Hiển thị rationale trước khi request |
### Policy Violations to Avoid
- **Deceptive behavior**: App phải làm đúng như listing mô tả
- **User data**: Không collect data không cần thiết
- **Background location**: Cần approval riêng từ Google
- **Accessibility services**: Chỉ dùng cho đúng mục đích
> 🔴 **Vi phạm policy = app bị gỡ, account bị ban.** Review checklist trước mỗi lần publish.
---
description: Guide store visuals: screenshots, feature graphic, icon
globs: "**/*.md"
---
# Rule: Google Play Visuals
> Kích hoạt: Khi tạo hoặc review store listing visuals
## Nguyên tắc: Visual storytelling, không phải random screenshots
### Screenshot Requirements
| Spec | Chi tiết |
|------|----------|
| **Số lượng** | 2-8 (recommended 6-8) |
| **Size** | 16:9 hoặc 9:16, min 320px, max 3840px |
| **First screenshot** | Phải hook user trong 1 giây → core value |
| **Story flow** | Login → Core feature → Key benefit → Social proof |
### Screenshot Best Practices
| ❌ Sai | ✅ Đúng |
|--------|---------|
| Raw screenshots không text | Screenshots + benefit-focused captions |
| Quá nhiều text overlay | 1-2 dòng text ngắn gọn, readable |
| Dark/cluttered UI | Clean, bright, representative UI |
| Cùng 1 screen nhiều lần | Mỗi screenshot 1 feature khác nhau |
### Feature Graphic
| Spec | Chi tiết |
|------|----------|
| **Size** | 1024 x 500 px |
| **Content** | App logo + tagline + key visual |
| **Text** | Readable ở kích thước nhỏ (mobile) |
| **Brand** | Consistent với app theme |
### App Icon
| Spec | Chi tiết |
|------|----------|
| **Size** | 512 x 512 px |
| **Format** | PNG, 32-bit |
| **Shape** | Adaptive icon (foreground + background layers) |
| **Style** | Simple, recognizable, no text (too small to read) |
> 🔴 **First screenshot = quảng cáo.** Phải truyền tải core value proposition ngay lập tức.
---
description: Chọn architecture path đúng cho new hoặc existing Android apps
globs: "**/*.kt"
---
# Rule: Architecture Decision Matrix
> Kích hoạt: Trước khi bắt đầu implement bất kỳ feature nào
So sánh greenfield và brownfield trước khi chọn stack, module boundaries, và migration strategy. Chọn giữa Compose-only, hybrid View/Compose, hay legacy XML theo bối cảnh thật.
## Decision Matrix
| Context | Recommended Direction | Why |
|---------|----------------------|-----|
| Greenfield, small team, modern target SDK | Compose-first, ViewModel + StateFlow | Fast feedback loop, less legacy overhead, simpler UI state |
| Greenfield, enterprise scale | Modular Compose-first with feature boundaries | Easier ownership, testability, and parallel development |
| Brownfield, large XML surface | Hybrid View/Compose migration | Reduce risk while introducing Compose gradually |
| Brownfield, technical debt in presentation layer | Extract ViewModel/domain first, then migrate UI | Stabilize behavior before changing framework surface |
| App with heavy form flow and legacy widgets | Keep XML where stable, isolate new surfaces in Compose | Avoid rewrite cost when UI is already working |
| App with simple screens and high iteration pace | Compose-only | Lower ceremony and better preview/test workflow |
## State Strategy Matrix
| Context | State Tool | Reasoning |
|---------|-----------|-----------|
| New feature, simple state | `remember` + `mutableStateOf` | Lightweight, local |
| New feature, complex state | ViewModel + StateFlow | Survives config changes |
| Legacy module with LiveData | Keep LiveData | Avoid migration cost |
| Cross-screen shared state | Shared ViewModel / Navigation args | Scoped to navigation graph |
| App-wide state (auth, theme) | DataStore / Repository singleton | Single source of truth |
## Refactor Scope Matrix
| Task Type | Scope | Example |
|-----------|-------|---------|
| Greenfield feature | `structured` | Full Clean Architecture layers |
| Brownfield new screen | `incremental` | Follow existing patterns, improve locally |
| Brownfield hotfix | `minimal` | Fix + unit test only, no architecture changes |
| Tech debt sprint | `structured` | Planned migration with test coverage |
## Architecture Signals
- Choose **Compose-only** when the product is still early, the team knows Compose, and there is no major legacy UI constraint.
- Choose **hybrid** when migration needs to happen incrementally or when a design system must coexist with old screens.
- Choose **XML-first** only when the codebase is deeply legacy and migration cost is not justified yet.
## Kotlin Boundaries
- Presentation: immutable UiState, intent handlers, and navigation events.
- Domain: use cases, business rules, and platform-agnostic models.
- Data: DTOs, mappers, repositories, and data sources.
- Cross-cutting: logging, dispatchers, serializers, and error mapping.
## Migration Strategy
1. Stabilize state model before moving UI.
2. Introduce ViewModel boundaries.
3. Extract reusable composables or XML fragments by feature.
4. Move shared logic into domain/use-case layer.
5. Measure behavior after each migration slice.
> 🔴 **Luôn xác định Task Type + Architecture Strategy + State Strategy + Refactor Scope TRƯỚC khi code.** Tham chiếu rule `03_interaction_flow.md` cho Mandatory Execution Header.
# {{TITLE}}
{{DESCRIPTION}}
## How to Use
### Search: `python3 {{SCRIPT_PATH}}/search.py "<query>" [--domain <d>] [--stack <s>] [--top 5]`
**Domains (18):** `view`, `package`, `pattern`, `architect`, `chart`, `color`, `typography`, `style`, `ux`, `icon`, `landing`, `naming`, `product`, `prompt`, `play-store`, `performance`, `ui-reasoning`, `accessibility`
**Stacks:** `compose`, `xml`, `hilt`, `koin`
### Design System: `python3 {{SCRIPT_PATH}}/search.py "<query>" --design-system [-p "Name"]`
### Workflow
1. Identify task type (Greenfield/Brownfield)
2. Search ≥2 domains
3. Apply results with Agent Rules
| Domain | Content |
|--------|---------|
| `view` | Compose/View components |
| `package` | Libraries and pairings |
| `pattern` | Architecture and UI patterns |
| `architect` | Clean Architecture layers |
| `play-store` | ASO, listing, compliance |
{{QUICK_REFERENCE}}
# {{TITLE}}
{{DESCRIPTION}}
## Search: `python3 {{SCRIPT_PATH}}/search.py "<query>" [--domain <d>] [--top 5]`
Domains: `view`, `package`, `pattern`, `architect`, `performance`, `color`, `typography`, `style`, `ux`, `icon`, `landing`, `naming`, `product`, `prompt`, `play-store`, `chart`, `ui-reasoning`, `accessibility`
{{QUICK_REFERENCE}}
# {{TITLE}}
{{DESCRIPTION}}
---
## Prerequisites
```bash
python3 --version || python --version
```
---
## How to Use This {{SKILL_OR_WORKFLOW}}
### Step 1: Analyze User Requirements
Trích xuất thông tin từ request:
- **Language**: Kotlin first, idiomatic null-safety, data classes, sealed classes, extension functions
- **Architecture**: Clean Architecture, Feature-First, modularization
- **UI Stack**: Jetpack Compose, Material 3, adaptive layouts
- **State**: ViewModel, StateFlow, MutableState, LiveData only if needed
### Step 2: Search Relevant Data
```bash
python3 {{SCRIPT_PATH}}/search.py "<keyword>" --top 5
```
**Với domain cụ thể:**
```bash
python3 {{SCRIPT_PATH}}/search.py "<keyword>" --domain view --top 5
python3 {{SCRIPT_PATH}}/search.py "<keyword>" --domain package --top 5
```
**Với stack filter:**
```bash
python3 {{SCRIPT_PATH}}/search.py "<keyword>" --stack compose --top 5
```
**JSON output:**
```bash
python3 {{SCRIPT_PATH}}/search.py "<keyword>" --json --top 5
```
**Available domains (18):** `view`, `package`, `pattern`, `architect`, `chart`, `color`, `typography`, `style`, `ux`, `icon`, `landing`, `naming`, `product`, `prompt`, `play-store`, `performance`, `ui-reasoning`, `accessibility`
**Available stacks:** `compose`, `xml`, `hilt`, `koin`
### Step 3: Apply Results
Áp dụng kết quả search vào code theo các Agent Rules đã cài đặt.
---
## Search Reference
| Domain | File | Content |
|--------|------|---------|
| Views | `view.csv` | 65+ Compose/View components |
| Packages | `package.csv` | 100+ Kotlin/Android libraries |
| Patterns | `pattern.csv` | 100+ design patterns |
| Architecture | `architect.csv` | Clean Architecture layers |
| Performance | `performance.csv` | 35+ performance patterns |
| Accessibility | `accessibility.csv` | 35+ accessibility patterns |
| UI Reasoning | `ui-reasoning.csv` | 35+ UI decision rules |
| Charts | `chart.csv` | Chart recommendations |
| Colors | `color.csv` | Color palettes |
| Typography | `typography.csv` | Font pairings |
| Styles | `style.csv` | UI style guidelines |
| UX Guidelines | `ux.csv` | UX best practices |
| Icons | `icon.csv` | Icon recommendations |
| Landing | `landing.csv` | Landing/onboarding patterns |
| Naming | `naming.csv` | Kotlin/Android naming conventions |
| Products | `product.csv` | Product type styling |
| Prompts | `prompt.csv` | AI prompt templates |
| Play Store | `play-store.csv` | ASO, store listing, compliance, privacy |
---
## Google Play Console Workflow
Use the `play-store` domain when the user asks for ASO, app listing copy, content rating, data safety, screenshots, privacy policy, or Play Console export.
### Suggested Flow
1. Analyze the app input and extract USP, persona, keywords, category, and tags.
2. Generate store text assets with strict length limits.
3. Validate compliance details for content rating, data safety, and privacy.
4. Produce screenshot and feature graphic guidance.
5. Export the result as Markdown and JSON when needed.
### Example Queries
```bash
python3 {{SCRIPT_PATH}}/search.py "google play store listing" --domain play-store --top 5
python3 {{SCRIPT_PATH}}/search.py "content rating data safety" --domain play-store --top 5
python3 {{SCRIPT_PATH}}/search.py "app name short description" --domain play-store --json --top 5
```
### Output Targets
- App Name: max 30 characters, brand + core keyword
- Short Description: max 80 characters, concise value proposition
- Full Description: max 4000 characters, structured and policy-safe
- Compliance Pack: content rating answers, data safety table, privacy notes
- Visual Pack: first screenshot guidance, feature graphic, icon rules
## Example Workflow
**User Request:** "Tạo màn hình đăng nhập"
1. **Search views:**
```bash
python3 {{SCRIPT_PATH}}/search.py "form input" --domain view --top 5
```
2. **Search patterns:**
```bash
python3 {{SCRIPT_PATH}}/search.py "authentication login" --domain pattern --top 5
```
3. **Search packages:**
```bash
python3 {{SCRIPT_PATH}}/search.py "validation" --domain package --top 5
```
4. **Apply results** theo Agent Rules (consistency, error handling, testing...)
5. **Validate:**
```bash
ktlint -F && ./gradlew lint && ./gradlew test
```
{{QUICK_REFERENCE}}
{
"platform": "antigravity",
"displayName": "Antigravity / Generic Agent",
"installType": "full",
"folderStructure": {
"root": ".agents",
"skillPath": "skills/android-pro-max",
"filename": "SKILL.md"
},
"scriptPath": "skills/android-pro-max/scripts/search.py",
"frontmatter": {
"name": "android-pro-max",
"description": "Android design intelligence. Compose, Kotlin, packages, patterns, architecture, UI/UX best practices."
},
"sections": {
"quickReference": true
},
"template": "skill-content-10k.md",
"title": "android-pro-max",
"description": "Android development guide with Compose components, Kotlin libraries, patterns, architecture, performance, and UI/UX best practices.",
"skillOrWorkflow": "Skill",
"rulesFile": {
"path": ".agents/rules/android-pro-max.md",
"mode": "create"
}
}
{
"platform": "claude",
"displayName": "Claude Code",
"installType": "full",
"folderStructure": {
"root": ".claude",
"skillPath": "skills/android-pro-max",
"filename": "SKILL.md"
},
"scriptPath": "skills/android-pro-max/scripts/search.py",
"frontmatter": {
"name": "android-pro-max",
"description": "Android design intelligence. Compose, Kotlin, packages, patterns, architecture, performance optimization, accessibility, and UI/UX best practices. Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check Android code."
},
"sections": {
"quickReference": true
},
"template": "skill-content.md",
"title": "Android Pro Max - Android Design Intelligence",
"description": "Comprehensive Android development guide with searchable database of Compose components, Kotlin libraries, design patterns, architecture guidelines, performance optimization, accessibility, and UI/UX best practices.",
"skillOrWorkflow": "Skill",
"rulesFile": {
"path": "CLAUDE.md",
"mode": "append"
}
}
{
"platform": "codebuddy",
"displayName": "CodeBuddy",
"installType": "full",
"folderStructure": {
"root": ".codebuddy",
"skillPath": "skills/android-pro-max",
"filename": "SKILL.md"
},
"scriptPath": "skills/android-pro-max/scripts/search.py",
"frontmatter": {
"name": "android-pro-max",
"description": "Android design intelligence with searchable database"
},
"sections": {
"quickReference": true
},
"template": "skill-content.md",
"title": "android-pro-max",
"description": "Comprehensive Android development guide with searchable database of Compose components, Kotlin libraries, design patterns, architecture guidelines, performance optimization, accessibility, and UI/UX best practices.",
"skillOrWorkflow": "Skill",
"rulesFile": {
"path": ".codebuddy/rules/android-pro-max.md",
"mode": "create"
}
}
{
"platform": "codex",
"displayName": "Codex",
"installType": "full",
"folderStructure": {
"root": ".codex",
"skillPath": "skills/android-pro-max",
"filename": "SKILL.md"
},
"scriptPath": "skills/android-pro-max/scripts/search.py",
"frontmatter": {
"name": "android-pro-max",
"description": "Android design intelligence with searchable database"
},
"sections": {
"quickReference": true
},
"template": "skill-content.md",
"title": "android-pro-max",
"description": "Comprehensive Android development guide with searchable database of Compose components, Kotlin libraries, design patterns, architecture guidelines, performance optimization, accessibility, and UI/UX best practices.",
"skillOrWorkflow": "Skill",
"rulesFile": {
"path": ".codex/rules/android-pro-max.md",
"mode": "create"
}
}
{
"platform": "continue",
"displayName": "Continue",
"installType": "full",
"folderStructure": {
"root": ".continue",
"skillPath": "skills/android-pro-max",
"filename": "SKILL.md"
},
"scriptPath": "skills/android-pro-max/scripts/search.py",
"frontmatter": {
"name": "android-pro-max",
"description": "Android design intelligence with searchable database"
},
"sections": {
"quickReference": true
},
"template": "skill-content.md",
"title": "android-pro-max",
"description": "Comprehensive Android development guide with searchable database of Compose components, Kotlin libraries, design patterns, architecture guidelines, performance optimization, accessibility, and UI/UX best practices.",
"skillOrWorkflow": "Skill",
"rulesFile": {
"path": ".continue/rules/android-pro-max.md",
"mode": "create"
}
}
{
"platform": "copilot",
"displayName": "GitHub Copilot",
"installType": "full",
"folderStructure": {
"root": ".github",
"skillPath": "skills/android-pro-max",
"filename": "SKILL.md"
},
"scriptPath": "skills/android-pro-max/scripts/search.py",
"frontmatter": {
"name": "android-pro-max",
"description": "Android design intelligence. Compose, Kotlin, packages, patterns, architecture, performance optimization, accessibility, and UI/UX best practices."
},
"sections": {
"quickReference": true
},
"template": "skill-content.md",
"title": "Android Pro Max - Android Design Intelligence",
"description": "Comprehensive Android development guide with searchable database of Compose components, Kotlin libraries, design patterns, architecture guidelines, performance optimization, accessibility, and UI/UX best practices.",
"skillOrWorkflow": "Skill",
"rulesFile": {
"path": ".github/copilot-instructions.md",
"mode": "append"
}
}
{
"platform": "cursor",
"displayName": "Cursor",
"installType": "reference",
"folderStructure": {
"root": ".cursor",
"skillPath": "commands",
"filename": "android-pro-max.md"
},
"scriptPath": ".shared/android-pro-max/scripts/search.py",
"frontmatter": null,
"sections": {
"quickReference": true
},
"template": "skill-content.md",
"title": "android-pro-max",
"description": "Comprehensive Android development guide with searchable database of Compose components, Kotlin libraries, design patterns, architecture guidelines, performance optimization, accessibility, and UI/UX best practices.",
"skillOrWorkflow": "Workflow",
"rulesFile": {
"path": ".cursor/rules/android-pro-max.mdc",
"mode": "create"
}
}
{
"platform": "gemini",
"displayName": "Gemini CLI",
"installType": "full",
"folderStructure": {
"root": ".gemini",
"skillPath": "skills/android-pro-max",
"filename": "SKILL.md"
},
"scriptPath": "skills/android-pro-max/scripts/search.py",
"frontmatter": {
"name": "android-pro-max",
"description": "Android design intelligence with searchable database"
},
"sections": {
"quickReference": true
},
"template": "skill-content.md",
"title": "Android Pro Max - Android Design Intelligence",
"description": "Comprehensive Android development guide with searchable database of Compose components, Kotlin libraries, design patterns, architecture guidelines, performance optimization, accessibility, and UI/UX best practices.",
"skillOrWorkflow": "Skill",
"rulesFile": {
"path": ".gemini/rules/android-pro-max.md",
"mode": "create"
}
}
{
"platform": "junie",
"displayName": "JetBrains AI (Junie)",
"installType": "full",
"folderStructure": {
"root": ".junie",
"skillPath": "skills/android-pro-max",
"filename": "guidelines.md"
},
"scriptPath": "skills/android-pro-max/scripts/search.py",
"frontmatter": null,
"sections": {
"quickReference": true
},
"template": "skill-content.md",
"title": "Android Pro Max - Android Design Intelligence",
"description": "Comprehensive Android development guide with searchable database of Compose components, Kotlin libraries, design patterns, architecture guidelines, performance optimization, accessibility, and UI/UX best practices.",
"skillOrWorkflow": "Skill",
"rulesFile": {
"path": ".junie/rules/android-pro-max.md",
"mode": "create"
}
}
{
"platform": "kiro",
"displayName": "Kiro",
"installType": "reference",
"folderStructure": {
"root": ".kiro",
"skillPath": "steering",
"filename": "android-pro-max.md"
},
"scriptPath": ".shared/android-pro-max/scripts/search.py",
"frontmatter": null,
"sections": {
"quickReference": true
},
"template": "skill-content.md",
"title": "android-pro-max",
"description": "Comprehensive Android development guide with searchable database of Compose components, Kotlin libraries, design patterns, architecture guidelines, performance optimization, accessibility, and UI/UX best practices.",
"skillOrWorkflow": "Workflow",
"rulesFile": {
"path": ".kiro/rules/android-pro-max.md",
"mode": "create"
}
}
{
"platform": "opencode",
"displayName": "OpenCode",
"installType": "full",
"folderStructure": {
"root": ".opencode",
"skillPath": "skills/android-pro-max",
"filename": "SKILL.md"
},
"scriptPath": "skills/android-pro-max/scripts/search.py",
"frontmatter": {
"name": "android-pro-max",
"description": "Android design intelligence with searchable database"
},
"sections": {
"quickReference": true
},
"template": "skill-content.md",
"title": "android-pro-max",
"description": "Comprehensive Android development guide with searchable database of Compose components, Kotlin libraries, design patterns, architecture guidelines, performance optimization, accessibility, and UI/UX best practices.",
"skillOrWorkflow": "Skill",
"rulesFile": {
"path": ".opencode/rules/android-pro-max.md",
"mode": "create"
}
}
{
"platform": "qoder",
"displayName": "Qoder",
"installType": "reference",
"folderStructure": {
"root": ".qoder",
"skillPath": "skills/android-pro-max",
"filename": "SKILL.md"
},
"scriptPath": ".shared/android-pro-max/scripts/search.py",
"frontmatter": {
"name": "android-pro-max",
"description": "Android design intelligence with searchable database"
},
"sections": {
"quickReference": true
},
"template": "skill-content.md",
"title": "android-pro-max",
"description": "Comprehensive Android development guide with searchable database of Compose components, Kotlin libraries, design patterns, architecture guidelines, performance optimization, accessibility, and UI/UX best practices.",
"skillOrWorkflow": "Skill",
"rulesFile": {
"path": ".qoder/rules/android-pro-max.md",
"mode": "create"
}
}
{
"platform": "roocode",
"displayName": "Roo Code",
"installType": "reference",
"folderStructure": {
"root": ".roo",
"skillPath": "commands",
"filename": "android-pro-max.md"
},
"scriptPath": ".shared/android-pro-max/scripts/search.py",
"frontmatter": null,
"sections": {
"quickReference": true
},
"template": "skill-content.md",
"title": "android-pro-max",
"description": "Comprehensive Android development guide with searchable database of Compose components, Kotlin libraries, design patterns, architecture guidelines, performance optimization, accessibility, and UI/UX best practices.",
"skillOrWorkflow": "Workflow",
"rulesFile": {
"path": ".roo/rules/android-pro-max.md",
"mode": "create"
}
}
{
"platform": "trae",
"displayName": "Trae",
"installType": "full",
"folderStructure": {
"root": ".trae",
"skillPath": "skills/android-pro-max",
"filename": "SKILL.md"
},
"scriptPath": "skills/android-pro-max/scripts/search.py",
"frontmatter": {
"name": "android-pro-max",
"description": "Android design intelligence with searchable database"
},
"sections": {
"quickReference": true
},
"template": "skill-content.md",
"title": "android-pro-max",
"description": "Comprehensive Android development guide with searchable database of Compose components, Kotlin libraries, design patterns, architecture guidelines, performance optimization, accessibility, and UI/UX best practices.",
"skillOrWorkflow": "Skill",
"rulesFile": {
"path": ".trae/rules/android-pro-max.md",
"mode": "create"
}
}
{
"platform": "vscode",
"displayName": "VS Code",
"installType": "full",
"folderStructure": {
"root": ".github",
"skillPath": "skills/android-pro-max",
"filename": "SKILL.md"
},
"scriptPath": "skills/android-pro-max/scripts/search.py",
"frontmatter": {
"name": "android-pro-max",
"description": "Android design intelligence. Compose, Kotlin, packages, patterns, architecture, performance optimization, accessibility, and UI/UX best practices."
},
"sections": {
"quickReference": true
},
"template": "skill-content.md",
"title": "Android Pro Max - Android Design Intelligence",
"description": "Comprehensive Android development guide with searchable database of Compose components, Kotlin libraries, design patterns, architecture guidelines, performance optimization, accessibility, and UI/UX best practices.",
"skillOrWorkflow": "Skill",
"rulesFile": {
"path": ".vscode/rules/android-pro-max.md",
"mode": "create"
}
}
{
"platform": "windsurf",
"displayName": "Windsurf",
"installType": "reference",
"folderStructure": {
"root": ".windsurf",
"skillPath": "skills",
"filename": "android-pro-max.md"
},
"scriptPath": ".shared/android-pro-max/scripts/search.py",
"frontmatter": null,
"sections": {
"quickReference": true
},
"template": "skill-content.md",
"title": "android-pro-max",
"description": "Comprehensive Android development guide with searchable database of Compose components, Kotlin libraries, design patterns, architecture guidelines, performance optimization, accessibility, and UI/UX best practices.",
"skillOrWorkflow": "Skill",
"rulesFile": {
"path": ".windsurf/rules/android-pro-max.md",
"mode": "create"
}
}
import chalk from 'chalk';
import ora from 'ora';
import prompts from 'prompts';
import { AI_TYPES } from '../types/index.js';
import { generatePlatformFiles, generateAllPlatformFiles } from '../utils/template.js';
import { detectAIType, getAITypeDescription } from '../utils/detect.js';
import { logger } from '../utils/logger.js';
export async function initCommand(options) {
logger.title('🚀 Android Pro Max Skill Installer');
let aiType = options.ai;
if (!aiType) {
const { detected, suggested } = detectAIType();
if (detected.length > 0) {
logger.info(`Detected: ${detected.map(t => chalk.cyan(t)).join(', ')}`);
}
const response = await prompts({
type: 'select',
name: 'aiType',
message: 'Select AI assistant to install for:',
choices: AI_TYPES.map(type => ({
title: getAITypeDescription(type),
value: type,
})),
initial: suggested ? AI_TYPES.indexOf(suggested) : 0,
});
if (!response.aiType) {
logger.warn('Installation cancelled');
return;
}
aiType = response.aiType;
}
logger.info(`Installing for: ${chalk.cyan(getAITypeDescription(aiType))}`);
const spinner = ora('Generating skill files from templates...').start();
const cwd = process.cwd();
try {
let copiedFolders;
if (aiType === 'all') {
copiedFolders = await generateAllPlatformFiles(cwd);
}
else {
copiedFolders = await generatePlatformFiles(cwd, aiType);
}
spinner.succeed('Generated from templates!');
console.log();
logger.info('Installed folders:');
copiedFolders.forEach(folder => {
console.log(` ${chalk.green('+')} ${folder}`);
});
console.log();
logger.success('Android Pro Max Skill installed successfully!');
console.log();
console.log(chalk.bold('Next steps:'));
console.log(chalk.dim(' 1. Restart your AI coding assistant'));
console.log(chalk.dim(' 2. Try: "Tạo màn hình Login với Kotlin & Compose"'));
console.log();
}
catch (error) {
spinner.fail('Installation failed');
if (error instanceof Error) {
logger.error(error.message);
}
process.exit(1);
}
}
import { initCommand } from './init.js';
import { logger } from '../utils/logger.js';
export async function updateCommand(options) {
logger.title('🔄 Android Pro Max Skill Update');
logger.info('Updating installed skill files to latest version...');
// For now, update is just a re-init with current settings
await initCommand({
ai: options.ai,
force: true
});
}
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
import chalk from 'chalk';
import { logger } from '../utils/logger.js';
export function versionsCommand() {
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const pkg = JSON.parse(readFileSync(join(__dirname, '../../package.json'), 'utf-8'));
logger.title('📋 Android Pro Max — Version Info');
console.log(`${chalk.bold('Installed CLI Version:')} ${chalk.green(pkg.version)}`);
console.log(`${chalk.bold('Status:')} Up to date`);
console.log();
console.log(chalk.bold('Release History:'));
console.log(` ${chalk.cyan('v1.1.0')} - Major Parity Upgrade: Modular CLI, AI Detection, 16 Platforms`);
console.log(` ${chalk.cyan('v1.0.2')} - Bug Fix: Global bin command fix`);
console.log(` ${chalk.cyan('v1.0.1')} - Initial Expansion: CSV & Rules parity`);
console.log(` ${chalk.cyan('v1.0.0')} - Core Architecture: Brain & Hands separation`);
console.log();
}
export const AI_TYPES = [
'claude',
'cursor',
'windsurf',
'antigravity',
'copilot',
'kiro',
'roocode',
'codex',
'qoder',
'gemini',
'trae',
'codebuddy',
'opencode',
'continue',
'junie',
'vscode',
'all',
];
import { existsSync } from 'node:fs';
import { join } from 'node:path';
export function detectAIType() {
const cwd = process.cwd();
const detected = [];
// Claude
if (existsSync(join(cwd, '.claude')) || existsSync(join(cwd, 'CLAUDE.md'))) {
detected.push('claude');
}
// Cursor
if (existsSync(join(cwd, '.cursor')) || existsSync(join(cwd, '.cursorrules'))) {
detected.push('cursor');
}
// Windsurf
if (existsSync(join(cwd, '.windsurf')) || existsSync(join(cwd, '.codeium'))) {
detected.push('windsurf');
}
// Copilot
if (existsSync(join(cwd, '.github', 'prompts'))) {
detected.push('copilot');
}
// Agent
if (existsSync(join(cwd, '.agents'))) {
detected.push('antigravity');
}
// Continue
if (existsSync(join(cwd, '.continue'))) {
detected.push('continue');
}
// vscode
if (existsSync(join(cwd, '.vscode'))) {
detected.push('vscode');
}
return {
detected,
suggested: detected.length > 0 ? detected[0] : null,
};
}
export function getAITypeDescription(type) {
const descriptions = {
claude: 'Claude Code (CLAUDE.md)',
cursor: 'Cursor (.cursor/rules)',
windsurf: 'Windsurf (.windsurf/rules)',
antigravity: 'Antigravity (.agents/rules)',
copilot: 'GitHub Copilot (.github/prompts)',
kiro: 'Kiro (.kiro/rules)',
roocode: 'Roo Code (.roo/rules)',
codex: 'Codex (.codex/rules)',
qoder: 'Qoder (.qoder/rules)',
gemini: 'Gemini CLI (.gemini/rules)',
trae: 'Trae (.trae/rules)',
codebuddy: 'CodeBuddy (.codebuddy/rules)',
opencode: 'OpenCode (.opencode/rules)',
continue: 'Continue (.continue/rules)',
junie: 'Junie (.junie/rules)',
vscode: 'VS Code (.vscode/rules)',
all: 'All Assistants (Install everything)',
};
return descriptions[type] || type;
}
import chalk from 'chalk';
export const logger = {
info: (msg) => console.log(`${chalk.blue('ℹ')} ${msg}`),
success: (msg) => console.log(`${chalk.green('✔')} ${msg}`),
warn: (msg) => console.log(`${chalk.yellow('⚠')} ${msg}`),
error: (msg) => console.log(`${chalk.red('✖')} ${msg}`),
title: (msg) => {
console.log();
console.log(chalk.bold.cyan(msg));
console.log(chalk.cyan('='.repeat(msg.length)));
console.log();
},
};
import { readFile, mkdir, writeFile, cp, access, readdir } from 'node:fs/promises';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const ASSETS_DIR = join(__dirname, '..', '..', 'assets');
const AI_TO_PLATFORM = {
claude: 'claude',
cursor: 'cursor',
windsurf: 'windsurf',
antigravity: 'agent',
copilot: 'copilot',
kiro: 'kiro',
roocode: 'roocode',
codex: 'codex',
qoder: 'qoder',
gemini: 'gemini',
trae: 'trae',
codebuddy: 'codebuddy',
opencode: 'opencode',
continue: 'continue',
junie: 'junie',
vscode: 'vscode',
};
async function exists(path) {
try {
await access(path);
return true;
}
catch {
return false;
}
}
export async function loadPlatformConfig(aiType) {
const platformName = AI_TO_PLATFORM[aiType];
if (!platformName) {
throw new Error(`Unknown AI type: ${aiType}`);
}
const configPath = join(ASSETS_DIR, 'templates', 'platforms', `${platformName}.json`);
const content = await readFile(configPath, 'utf-8');
return JSON.parse(content);
}
async function loadTemplate(templateName) {
const templatePath = join(ASSETS_DIR, 'templates', templateName);
return readFile(templatePath, 'utf-8');
}
function renderFrontmatter(frontmatter) {
if (!frontmatter)
return '';
const lines = ['---'];
for (const [key, value] of Object.entries(frontmatter)) {
if (value.includes(':') || value.includes('"') || value.includes('\n')) {
lines.push(`${key}: "${value.replace(/"/g, '\\"')}"`);
}
else {
lines.push(`${key}: ${value}`);
}
}
lines.push('---', '');
return lines.join('\n');
}
export async function renderSkillFile(config) {
const templateFile = config.template || 'skill-content.md';
let content = await loadTemplate(`base/${templateFile}`);
const scriptDir = config.folderStructure.skillPath.includes('/') ? dirname(config.scriptPath) : config.scriptPath;
let quickReferenceContent = '';
if (config.sections.quickReference) {
quickReferenceContent = await loadTemplate('base/quick-reference.md');
quickReferenceContent = quickReferenceContent.replace(/\{\{SCRIPT_PATH\}\}/g, config.scriptPath);
}
const frontmatter = renderFrontmatter(config.frontmatter);
const quickRefWithNewline = quickReferenceContent ? '\n' + quickReferenceContent : '';
content = content
.replace(/\{\{TITLE\}\}/g, config.title)
.replace(/\{\{DESCRIPTION\}\}/g, config.description)
.replace(/\{\{SCRIPT_PATH\}\}/g, config.scriptPath)
.replace(/\{\{SKILL_OR_WORKFLOW\}\}/g, config.skillOrWorkflow)
.replace(/\{\{QUICK_REFERENCE\}\}/g, quickRefWithNewline);
return frontmatter + content;
}
async function copyDataAndScripts(targetSkillDir) {
const dataSource = join(ASSETS_DIR, 'data');
const scriptsSource = join(ASSETS_DIR, 'scripts');
const dataTarget = join(targetSkillDir, 'data');
const scriptsTarget = join(targetSkillDir, 'scripts');
if (await exists(dataSource)) {
await mkdir(dataTarget, { recursive: true });
await cp(dataSource, dataTarget, { recursive: true });
}
if (await exists(scriptsSource)) {
await mkdir(scriptsTarget, { recursive: true });
await cp(scriptsSource, scriptsTarget, { recursive: true });
}
}
async function ensureSharedExists(targetDir) {
const sharedDir = join(targetDir, '.shared', 'android-pro-max');
if (await exists(sharedDir)) {
return false;
}
await mkdir(sharedDir, { recursive: true });
await copyDataAndScripts(sharedDir);
return true;
}
async function generateRulesFile(targetDir, config) {
if (!config.rulesFile)
return;
const rulesDir = join(ASSETS_DIR, 'templates', 'base', 'rules');
if (!await exists(rulesDir))
return;
const ruleFiles = (await readdir(rulesDir))
.filter(f => f.endsWith('.md'))
.sort();
if (ruleFiles.length === 0)
return;
if (config.rulesFile.mode === 'append') {
const rulesFilePath = join(targetDir, config.rulesFile.path);
const rulesFileDir = dirname(rulesFilePath);
await mkdir(rulesFileDir, { recursive: true });
let existing = '';
if (await exists(rulesFilePath)) {
existing = await readFile(rulesFilePath, 'utf-8');
if (existing.includes('Android Pro Max — Agent Rules')) {
return;
}
existing += '\n\n';
}
const stripFrontmatter = (content) => {
return content.replace(/^---\n[\s\S]*?\n---\n+/, '');
};
const allRules = ['# Android Pro Max — Agent Rules\n'];
for (const file of ruleFiles) {
const content = await readFile(join(rulesDir, file), 'utf-8');
allRules.push(stripFrontmatter(content));
}
await writeFile(rulesFilePath, existing + allRules.join('\n---\n\n'), 'utf-8');
}
else {
const rulesTargetDir = dirname(join(targetDir, config.rulesFile.path));
await mkdir(rulesTargetDir, { recursive: true });
const useMdc = config.rulesFile.path.endsWith('.mdc');
for (const file of ruleFiles) {
const content = await readFile(join(rulesDir, file), 'utf-8');
const targetExt = useMdc ? '.mdc' : '.md';
const targetPath = join(rulesTargetDir, file.replace(/\.md$/, targetExt));
await writeFile(targetPath, content, 'utf-8');
}
}
}
export async function generatePlatformFiles(targetDir, aiType) {
const config = await loadPlatformConfig(aiType);
const createdFolders = [];
const skillDir = join(targetDir, config.folderStructure.root, config.folderStructure.skillPath);
await mkdir(skillDir, { recursive: true });
const skillContent = await renderSkillFile(config);
const skillFilePath = join(skillDir, config.folderStructure.filename);
await writeFile(skillFilePath, skillContent, 'utf-8');
createdFolders.push(config.folderStructure.root);
if (config.installType === 'full') {
await copyDataAndScripts(skillDir);
}
else {
const createdShared = await ensureSharedExists(targetDir);
if (createdShared) {
createdFolders.push('.shared');
}
}
await generateRulesFile(targetDir, config);
return createdFolders;
}
export async function generateAllPlatformFiles(targetDir) {
const allFolders = new Set();
for (const aiType of Object.keys(AI_TO_PLATFORM)) {
try {
const folders = await generatePlatformFiles(targetDir, aiType);
folders.forEach(f => allFolders.add(f));
}
catch {
}
}
return Array.from(allFolders);
}
export function getSupportedAITypes() {
return Object.keys(AI_TO_PLATFORM);
}
+56
-2
#!/usr/bin/env node
"use strict";
console.log('Android Pro Max CLI scaffold');
import { Command } from 'commander';
import { readFileSync } from 'fs';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { initCommand } from './commands/init.js';
import { versionsCommand } from './commands/versions.js';
import { updateCommand } from './commands/update.js';
import { AI_TYPES } from './types/index.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const pkg = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
const program = new Command();
program
.name('android-pro-max')
.description('CLI to install Android Pro Max skill for AI coding assistants')
.version(pkg.version);
program
.command('init')
.description('Install Android Pro Max skill to current project')
.option('-a, --ai <type>', `AI assistant type (${AI_TYPES.join(', ')})`)
.option('-f, --force', 'Overwrite existing files')
.action(async (options) => {
if (options.ai && !AI_TYPES.includes(options.ai)) {
console.error(`Invalid AI type: ${options.ai}`);
console.error(`Valid types: ${AI_TYPES.join(', ')}`);
process.exit(1);
}
await initCommand({
ai: options.ai,
force: options.force,
});
});
program
.command('versions')
.description('List available versions')
.action(versionsCommand);
program
.command('update')
.description('Update Android Pro Max to latest version')
.option('-a, --ai <type>', `AI assistant type (${AI_TYPES.join(', ')})`)
.action(async (options) => {
if (options.ai && !AI_TYPES.includes(options.ai)) {
console.error(`Invalid AI type: ${options.ai}`);
console.error(`Valid types: ${AI_TYPES.join(', ')}`);
process.exit(1);
}
await updateCommand({
ai: options.ai,
});
});
// Default command (when run without subcommand)
program
.action(async () => {
await initCommand({});
});
program.parse();
+16
-4
{
"name": "android-pro-max-cli",
"version": "1.0.1",
"description": "CLI scaffold to install Android Pro Max skill for AI coding assistants",
"version": "1.1.0",
"description": "CLI to install Android Pro Max skill for AI coding assistants",
"type": "module",
"bin": {
"android-pro-max": "./dist/index.js"
},
"files": [
"dist",
"assets",
"LICENSE"

@@ -12,3 +16,4 @@ ],

"build": "tsc",
"dev": "npx ts-node --esm src/index.ts"
"dev": "npx ts-node --esm src/index.ts",
"prepublishOnly": "npm run build"
},

@@ -22,4 +27,11 @@ "keywords": [

"ai",
"skill"
"skill",
"claude",
"cursor",
"windsurf",
"copilot",
"gemini",
"trae"
],
"author": "",
"license": "MIT",

@@ -26,0 +38,0 @@ "dependencies": {