mobile-design by davila7/claude-code-templates
npx skills add https://github.com/davila7/claude-code-templates --skill mobile-design设计理念: 触控优先。关注电量。尊重平台。支持离线。核心原则: 移动端不是缩小的桌面端。思考移动端的限制,询问平台选择。
执行以下脚本进行验证(不要阅读,直接运行):
| 脚本 | 目的 | 用法 |
|---|---|---|
scripts/mobile_audit.py | 移动端用户体验与触控审计 | python scripts/mobile_audit.py <project_path> |
⛔ 在阅读相关文件之前,请勿开始开发:
| 文件 | 内容 | 状态 |
|---|
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| mobile-design-thinking.md | ⚠️ 反记忆化:强制思考,防止 AI 使用默认模式 | ⬜ 首要关键 |
| touch-psychology.md | 费茨定律、手势、触觉反馈、拇指热区 | ⬜ 关键 |
| mobile-performance.md | RN/Flutter 性能、60fps、内存 | ⬜ 关键 |
| mobile-backend.md | 推送通知、离线同步、移动端 API | ⬜ 关键 |
| mobile-testing.md | 测试金字塔、端到端测试、平台特定测试 | ⬜ 关键 |
| mobile-debugging.md | 原生与 JS 调试、Flipper、Logcat | ⬜ 关键 |
| mobile-navigation.md | 标签栏/堆栈/抽屉导航、深度链接 | ⬜ 阅读 |
| mobile-typography.md | 系统字体、动态类型、无障碍访问 | ⬜ 阅读 |
| mobile-color-system.md | OLED 优化、深色模式、电量感知 | ⬜ 阅读 |
| decision-trees.md | 框架/状态/存储选择 | ⬜ 阅读 |
🧠 mobile-design-thinking.md 是首要文件! 此文件确保 AI 进行思考,而不是使用记忆中的模式。
| 平台 | 文件 | 内容 | 何时阅读 |
|---|---|---|---|
| iOS | platform-ios.md | 人机界面指南、SF Pro 字体、SwiftUI 模式 | 为 iPhone/iPad 构建时 |
| Android | platform-android.md | Material Design 3、Roboto 字体、Compose 模式 | 为 Android 构建时 |
| 跨平台 | 以上两者 | 平台差异点 | React Native / Flutter |
🔴 如果为 iOS 构建 → 首先阅读 platform-ios.md! 🔴 如果为 Android 构建 → 首先阅读 platform-android.md! 🔴 如果跨平台 → 阅读两者并应用条件性平台逻辑!
停!如果用户的请求是开放式的,不要默认使用你偏好的方案。
| 方面 | 询问内容 | 原因 |
|---|---|---|
| 平台 | "iOS、Android 还是两者都要?" | 影响每一个设计决策 |
| 框架 | "React Native、Flutter 还是原生?" | 决定模式和工具 |
| 导航 | "标签栏、抽屉还是基于堆栈?" | 核心用户体验决策 |
| 状态管理 | "使用什么状态管理?(Zustand/Redux/Riverpod/BLoC?)" | 架构基础 |
| 离线 | "是否需要离线工作?" | 影响数据策略 |
| 目标设备 | "仅手机,还是支持平板?" | 布局复杂度 |
🚫 这些是 AI 的默认倾向,必须避免!
| ❌ 永远不要做 | 错误原因 | ✅ 应该总是做 |
|---|---|---|
| 对长列表使用 ScrollView | 渲染所有项,内存爆炸 | 使用 FlatList / FlashList / ListView.builder |
| 内联 renderItem 函数 | 每次渲染都创建新函数,所有项重新渲染 | useCallback + React.memo |
| 缺少 keyExtractor | 基于索引的键在重新排序时会导致错误 | 使用数据中唯一、稳定的 ID |
| 跳过 getItemLayout | 异步布局导致滚动卡顿 | 当项有固定高度时提供 |
| 到处使用 setState() | 不必要的部件重建 | 有针对性的状态、const 构造函数 |
| 原生驱动:false | 动画被 JS 线程阻塞 | 总是使用 useNativeDriver: true |
| 生产环境中使用 console.log | 严重阻塞 JS 线程 | 发布构建前移除 |
| 跳过 React.memo/const | 任何更改都会导致所有项重新渲染 | 总是记忆化列表项 |
| ❌ 永远不要做 | 错误原因 | ✅ 应该总是做 |
|---|---|---|
| 触控目标 < 44px | 无法准确点击,令人沮丧 | 最小 44pt (iOS) / 48dp (Android) |
| 目标间距 < 8px | 容易误触相邻目标 | 最小 8-12px 间距 |
| 仅手势交互 | 排除了运动障碍用户 | 总是提供按钮替代方案 |
| 无加载状态 | 用户以为应用崩溃 | 总是显示加载反馈 |
| 无错误状态 | 用户卡住,无法恢复 | 显示错误并提供重试选项 |
| 无离线处理 | 网络丢失时崩溃/阻塞 | 优雅降级,使用缓存数据 |
| 忽略平台惯例 | 用户困惑,肌肉记忆被破坏 | iOS 感觉像 iOS,Android 感觉像 Android |
| ❌ 永远不要做 | 错误原因 | ✅ 应该总是做 |
|---|---|---|
| 令牌存储在 AsyncStorage | 易被访问,在已 root 设备上被盗 | 使用 SecureStore / Keychain / EncryptedSharedPreferences |
| 硬编码 API 密钥 | 可从 APK/IPA 逆向工程 | 环境变量,安全存储 |
| 跳过 SSL 证书锁定 | 可能遭受中间人攻击 | 在生产环境中锁定证书 |
| 记录敏感数据 | 日志可能被提取 | 永不记录令牌、密码、个人身份信息 |
| ❌ 永远不要做 | 错误原因 | ✅ 应该总是做 |
|---|---|---|
| 业务逻辑放在 UI 中 | 不可测试,难以维护 | 服务层分离 |
| 全局状态用于所有内容 | 不必要的重新渲染,复杂度高 | 默认使用本地状态,需要时提升 |
| 深度链接作为事后考虑 | 通知、分享功能损坏 | 从第一天就规划深度链接 |
| 跳过 dispose/cleanup | 内存泄漏,僵尸监听器 | 清理订阅、定时器 |
统一(两者相同) 区分(平台特定)
─────────────────── ──────────────────────────
业务逻辑 ✅ 总是 -
数据层 ✅ 总是 -
核心功能 ✅ 总是 -
导航 - ✅ iOS:边缘滑动,Android:返回按钮
手势 - ✅ 平台原生感觉
图标 - ✅ SF Symbols vs Material Icons
日期选择器 - ✅ 原生选择器感觉正确
模态框/底部动作面板 - ✅ iOS:底部动作面板 vs Android:对话框
排版 - ✅ SF Pro vs Roboto(或自定义)
错误对话框 - ✅ 平台惯例的警告框
| 元素 | iOS | Android |
|---|---|---|
| 主要字体 | SF Pro / SF Compact | Roboto |
| 最小触控目标 | 44pt × 44pt | 48dp × 48dp |
| 返回导航 | 左侧边缘滑动 | 系统返回按钮/手势 |
| 底部标签栏图标 | SF Symbols | Material Symbols |
| 动作面板 | 从底部弹出的 UIActionSheet | 底部动作面板 / 对话框 |
| 进度指示器 | 旋转指示器 | 线性进度条 (Material) |
| 下拉刷新 | 原生 UIRefreshControl | SwipeRefreshLayout |
桌面端:光标是精确的 (1px)
移动端:手指是不精确的 (~7mm 接触面积)
→ 触控目标必须至少 44-48px
→ 重要操作放在拇指热区(屏幕底部)
→ 破坏性操作远离容易触及的区域
┌─────────────────────────────┐
│ 难以触及区域 │ ← 导航、菜单、返回
│ (伸展) │
├─────────────────────────────┤
│ 可以触及区域 │ ← 次要操作
│ (自然) │
├─────────────────────────────┤
│ 容易触及区域 │ ← 主要操作按钮、标签栏
│ (拇指自然弧度区域) │ ← 主要内容交互
└─────────────────────────────┘
[ 主页 ]
| 桌面端 | 移动端差异 |
|---|---|
| 多窗口 | 一次一个任务 |
| 键盘快捷键 | 触摸手势 |
| 悬停状态 | 无悬停(点击或无) |
| 大视口 | 空间有限,垂直滚动 |
| 注意力稳定 | 经常被打断 |
深入了解:touch-psychology.md
// ✅ 正确:记忆化的 renderItem + React.memo 包装器
const ListItem = React.memo(({ item }: { item: Item }) => (
<View style={styles.item}>
<Text>{item.title}</Text>
</View>
));
const renderItem = useCallback(
({ item }: { item: Item }) => <ListItem item={item} />,
[]
);
// ✅ 正确:具有所有优化的 FlatList
<FlatList
data={items}
renderItem={renderItem}
keyExtractor={(item) => item.id} // 稳定 ID,不是索引
getItemLayout={(data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
})}
removeClippedSubviews={true}
maxToRenderPerBatch={10}
windowSize={5}
/>
// ✅ 正确:const 构造函数防止重建
class MyWidget extends StatelessWidget {
const MyWidget({super.key}); // 常量!
@override
Widget build(BuildContext context) {
return const Column( // 常量!
children: [
Text('静态内容'),
MyConstantWidget(),
],
);
}
}
// ✅ 正确:使用 ValueListenableBuilder 的有针对性的状态
ValueListenableBuilder<int>(
valueListenable: counter,
builder: (context, value, child) => Text('$value'),
child: const ExpensiveWidget(), // 不会重建!
)
GPU 加速(快): CPU 绑定(慢):
├── 变换 ├── 宽度,高度
├── 透明度 ├── 顶部,左侧,右侧,底部
└── (仅使用这些) ├── 外边距,内边距
└── (避免动画化这些)
在编写任何移动端代码之前,你必须完成此检查点:
🧠 检查点:
平台: [ iOS / Android / 两者 ]
框架: [ React Native / Flutter / SwiftUI / Kotlin ]
已读文件: [ 列出你已阅读的技能文件 ]
我将应用的 3 个原则:
1. _______________
2. _______________
3. _______________
我将避免的反模式:
1. _______________
2. _______________
示例:
🧠 检查点:
平台: iOS + Android (跨平台)
框架: React Native + Expo
已读文件: touch-psychology.md, mobile-performance.md, platform-ios.md, platform-android.md
我将应用的 3 个原则:
1. 对所有列表使用 FlatList 配合 React.memo + useCallback
2. 48px 触控目标,主要操作按钮放在拇指热区
3. 平台特定导航(iOS 边缘滑动,Android 返回按钮)
我将避免的反模式:
1. 对列表使用 ScrollView → 使用 FlatList
2. 内联 renderItem → 记忆化
3. 使用 AsyncStorage 存储令牌 → 使用 SecureStore
🔴 无法填写检查点? → 返回并阅读技能文件。
你要构建什么?
│
├── 需要 OTA 更新 + 快速迭代 + 有 Web 团队
│ └── ✅ React Native + Expo
│
├── 需要像素级完美自定义 UI + 性能关键
│ └── ✅ Flutter
│
├── 深度原生功能 + 单一平台专注
│ ├── 仅 iOS → SwiftUI
│ └── 仅 Android → Kotlin + Jetpack Compose
│
├── 现有 RN 代码库 + 新功能
│ └── ✅ React Native (bare workflow)
│
└── 企业级 + 现有 Flutter 代码库
└── ✅ Flutter
完整决策树:decision-trees.md
针对特定领域的深入指导:
| 文件 | 何时使用 |
|---|---|
| mobile-design-thinking.md | 首要!反记忆化,强制基于上下文的思考 |
| touch-psychology.md | 理解触控交互、费茨定律、手势设计 |
| mobile-performance.md | 优化 RN/Flutter、60fps、内存/电量 |
| platform-ios.md | iOS 特定设计、HIG 合规性 |
| platform-android.md | Android 特定设计、Material Design 3 |
| mobile-navigation.md | 导航模式、深度链接 |
| mobile-typography.md | 字体比例、系统字体、无障碍访问 |
| mobile-color-system.md | OLED 优化、深色模式、电量 |
| decision-trees.md | 框架、状态、存储决策 |
记住: 移动端用户不耐烦、易被打断,并且在小屏幕上使用不精确的手指。为最差条件设计:网络差、单手操作、阳光刺眼、电量低。如果在这种情况下能工作,那么在任何地方都能工作。
每周安装量
688
仓库
GitHub 星标
22.6K
首次出现
2026年1月25日
安全审计
安装于
opencode626
gemini-cli602
codex597
github-copilot569
cursor492
kimi-cli485
Philosophy: Touch-first. Battery-conscious. Platform-respectful. Offline-capable. Core Principle: Mobile is NOT a small desktop. THINK mobile constraints, ASK platform choice.
Execute these for validation (don't read, just run):
| Script | Purpose | Usage |
|---|---|---|
scripts/mobile_audit.py | Mobile UX & Touch Audit | python scripts/mobile_audit.py <project_path> |
⛔ DO NOT start development until you read the relevant files:
| File | Content | Status |
|---|---|---|
| mobile-design-thinking.md | ⚠️ ANTI-MEMORIZATION: Forces thinking, prevents AI defaults | ⬜ CRITICAL FIRST |
| touch-psychology.md | Fitts' Law, gestures, haptics, thumb zone | ⬜ CRITICAL |
| mobile-performance.md | RN/Flutter performance, 60fps, memory | ⬜ CRITICAL |
| mobile-backend.md | Push notifications, offline sync, mobile API | ⬜ CRITICAL |
| mobile-testing.md |
🧠 mobile-design-thinking.md is PRIORITY! This file ensures AI thinks instead of using memorized patterns.
| Platform | File | Content | When to Read |
|---|---|---|---|
| iOS | platform-ios.md | Human Interface Guidelines, SF Pro, SwiftUI patterns | Building for iPhone/iPad |
| Android | platform-android.md | Material Design 3, Roboto, Compose patterns | Building for Android |
| Cross-Platform | Both above | Platform divergence points | React Native / Flutter |
🔴 If building for iOS → Read platform-ios.md FIRST! 🔴 If building for Android → Read platform-android.md FIRST! 🔴 If cross-platform → Read BOTH and apply conditional platform logic!
STOP! If the user's request is open-ended, DO NOT default to your favorites.
| Aspect | Ask | Why |
|---|---|---|
| Platform | "iOS, Android, or both?" | Affects EVERY design decision |
| Framework | "React Native, Flutter, or native?" | Determines patterns and tools |
| Navigation | "Tab bar, drawer, or stack-based?" | Core UX decision |
| State | "What state management? (Zustand/Redux/Riverpod/BLoC?)" | Architecture foundation |
| Offline | "Does this need to work offline?" | Affects data strategy |
| Target devices | "Phone only, or tablet support?" | Layout complexity |
🚫 These are AI default tendencies that MUST be avoided!
| ❌ NEVER DO | Why It's Wrong | ✅ ALWAYS DO |
|---|---|---|
| ScrollView for long lists | Renders ALL items, memory explodes | Use FlatList / FlashList / ListView.builder |
| Inline renderItem function | New function every render, all items re-render | useCallback + React.memo |
| Missing keyExtractor | Index-based keys cause bugs on reorder | Unique, stable ID from data |
| Skip getItemLayout |
| ❌ NEVER DO | Why It's Wrong | ✅ ALWAYS DO |
|---|---|---|
| Touch target < 44px | Impossible to tap accurately, frustrating | Minimum 44pt (iOS) / 48dp (Android) |
| Spacing < 8px between targets | Accidental taps on neighbors | Minimum 8-12px gap |
| Gesture-only interactions | Motor impaired users excluded | Always provide button alternative |
| No loading state | User thinks app crashed | ALWAYS show loading feedback |
| No error state | User stuck, no recovery path | Show error with retry option |
| No offline handling | Crash/block when network lost | Graceful degradation, cached data |
| Ignore platform conventions | Users confused, muscle memory broken | iOS feels iOS, Android feels Android |
| ❌ NEVER DO | Why It's Wrong | ✅ ALWAYS DO |
|---|---|---|
| Token in AsyncStorage | Easily accessible, stolen on rooted device | SecureStore / Keychain / EncryptedSharedPreferences |
| Hardcode API keys | Reverse engineered from APK/IPA | Environment variables, secure storage |
| Skip SSL pinning | MITM attacks possible | Pin certificates in production |
| Log sensitive data | Logs can be extracted | Never log tokens, passwords, PII |
| ❌ NEVER DO | Why It's Wrong | ✅ ALWAYS DO |
|---|---|---|
| Business logic in UI | Untestable, unmaintainable | Service layer separation |
| Global state for everything | Unnecessary re-renders, complexity | Local state default, lift when needed |
| Deep linking as afterthought | Notifications, shares broken | Plan deep links from day one |
| Skip dispose/cleanup | Memory leaks, zombie listeners | Clean up subscriptions, timers |
UNIFY (same on both) DIVERGE (platform-specific)
─────────────────── ──────────────────────────
Business Logic ✅ Always -
Data Layer ✅ Always -
Core Features ✅ Always -
Navigation - ✅ iOS: edge swipe, Android: back button
Gestures - ✅ Platform-native feel
Icons - ✅ SF Symbols vs Material Icons
Date Pickers - ✅ Native pickers feel right
Modals/Sheets - ✅ iOS: bottom sheet vs Android: dialog
Typography - ✅ SF Pro vs Roboto (or custom)
Error Dialogs - ✅ Platform conventions for alerts
| Element | iOS | Android |
|---|---|---|
| Primary Font | SF Pro / SF Compact | Roboto |
| Min Touch Target | 44pt × 44pt | 48dp × 48dp |
| Back Navigation | Edge swipe left | System back button/gesture |
| Bottom Tab Icons | SF Symbols | Material Symbols |
| Action Sheet | UIActionSheet from bottom | Bottom Sheet / Dialog |
| Progress | Spinner | Linear progress (Material) |
| Pull to Refresh | Native UIRefreshControl | SwipeRefreshLayout |
Desktop: Cursor is precise (1px)
Mobile: Finger is imprecise (~7mm contact area)
→ Touch targets MUST be 44-48px minimum
→ Important actions in THUMB ZONE (bottom of screen)
→ Destructive actions AWAY from easy reach
┌─────────────────────────────┐
│ HARD TO REACH │ ← Navigation, menu, back
│ (stretch) │
├─────────────────────────────┤
│ OK TO REACH │ ← Secondary actions
│ (natural) │
├─────────────────────────────┤
│ EASY TO REACH │ ← PRIMARY CTAs, tab bar
│ (thumb's natural arc) │ ← Main content interaction
└─────────────────────────────┘
[ HOME ]
| Desktop | Mobile Difference |
|---|---|
| Multiple windows | ONE task at a time |
| Keyboard shortcuts | Touch gestures |
| Hover states | NO hover (tap or nothing) |
| Large viewport | Limited space, scroll vertical |
| Stable attention | Interrupted constantly |
For deep dive: touch-psychology.md
// ✅ CORRECT: Memoized renderItem + React.memo wrapper
const ListItem = React.memo(({ item }: { item: Item }) => (
<View style={styles.item}>
<Text>{item.title}</Text>
</View>
));
const renderItem = useCallback(
({ item }: { item: Item }) => <ListItem item={item} />,
[]
);
// ✅ CORRECT: FlatList with all optimizations
<FlatList
data={items}
renderItem={renderItem}
keyExtractor={(item) => item.id} // Stable ID, NOT index
getItemLayout={(data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
})}
removeClippedSubviews={true}
maxToRenderPerBatch={10}
windowSize={5}
/>
// ✅ CORRECT: const constructors prevent rebuilds
class MyWidget extends StatelessWidget {
const MyWidget({super.key}); // CONST!
@override
Widget build(BuildContext context) {
return const Column( // CONST!
children: [
Text('Static content'),
MyConstantWidget(),
],
);
}
}
// ✅ CORRECT: Targeted state with ValueListenableBuilder
ValueListenableBuilder<int>(
valueListenable: counter,
builder: (context, value, child) => Text('$value'),
child: const ExpensiveWidget(), // Won't rebuild!
)
GPU-accelerated (FAST): CPU-bound (SLOW):
├── transform ├── width, height
├── opacity ├── top, left, right, bottom
└── (use these ONLY) ├── margin, padding
└── (AVOID animating these)
For complete guide: mobile-performance.md
Before writing ANY mobile code, you MUST complete this checkpoint:
🧠 CHECKPOINT:
Platform: [ iOS / Android / Both ]
Framework: [ React Native / Flutter / SwiftUI / Kotlin ]
Files Read: [ List the skill files you've read ]
3 Principles I Will Apply:
1. _______________
2. _______________
3. _______________
Anti-Patterns I Will Avoid:
1. _______________
2. _______________
Example:
🧠 CHECKPOINT:
Platform: iOS + Android (Cross-platform)
Framework: React Native + Expo
Files Read: touch-psychology.md, mobile-performance.md, platform-ios.md, platform-android.md
3 Principles I Will Apply:
1. FlatList with React.memo + useCallback for all lists
2. 48px touch targets, thumb zone for primary CTAs
3. Platform-specific navigation (edge swipe iOS, back button Android)
Anti-Patterns I Will Avoid:
1. ScrollView for lists → FlatList
2. Inline renderItem → Memoized
3. AsyncStorage for tokens → SecureStore
🔴 Can't fill the checkpoint? → GO BACK AND READ THE SKILL FILES.
WHAT ARE YOU BUILDING?
│
├── Need OTA updates + rapid iteration + web team
│ └── ✅ React Native + Expo
│
├── Need pixel-perfect custom UI + performance critical
│ └── ✅ Flutter
│
├── Deep native features + single platform focus
│ ├── iOS only → SwiftUI
│ └── Android only → Kotlin + Jetpack Compose
│
├── Existing RN codebase + new features
│ └── ✅ React Native (bare workflow)
│
└── Enterprise + existing Flutter codebase
└── ✅ Flutter
For complete decision trees: decision-trees.md
For deeper guidance on specific areas:
| File | When to Use |
|---|---|
| mobile-design-thinking.md | FIRST! Anti-memorization, forces context-based thinking |
| touch-psychology.md | Understanding touch interaction, Fitts' Law, gesture design |
| mobile-performance.md | Optimizing RN/Flutter, 60fps, memory/battery |
| platform-ios.md | iOS-specific design, HIG compliance |
| platform-android.md | Android-specific design, Material Design 3 |
| mobile-navigation.md | Navigation patterns, deep linking |
Remember: Mobile users are impatient, interrupted, and using imprecise fingers on small screens. Design for the WORST conditions: bad network, one hand, bright sun, low battery. If it works there, it works everywhere.
Weekly Installs
688
Repository
GitHub Stars
22.6K
First Seen
Jan 25, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode626
gemini-cli602
codex597
github-copilot569
cursor492
kimi-cli485
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
102,200 周安装
Gemini Interactions API 指南:统一接口、智能体交互与服务器端状态管理
833 周安装
Apollo MCP 服务器:让AI代理通过GraphQL API交互的完整指南
834 周安装
智能体记忆系统构建指南:分块策略、向量存储与检索优化
835 周安装
Scrapling官方网络爬虫框架 - 自适应解析、绕过Cloudflare、Python爬虫库
836 周安装
抽奖赢家选取器 - 随机选择工具,支持CSV、Excel、Google Sheets,公平透明
838 周安装
Medusa 前端开发指南:使用 SDK、React Query 构建电商商店
839 周安装
| Testing pyramid, E2E, platform-specific |
| ⬜ CRITICAL |
| mobile-debugging.md | Native vs JS debugging, Flipper, Logcat | ⬜ CRITICAL |
| mobile-navigation.md | Tab/Stack/Drawer, deep linking | ⬜ Read |
| mobile-typography.md | System fonts, Dynamic Type, a11y | ⬜ Read |
| mobile-color-system.md | OLED, dark mode, battery-aware | ⬜ Read |
| decision-trees.md | Framework/state/storage selection | ⬜ Read |
| Async layout = janky scroll |
| Provide when items have fixed height |
| setState() everywhere | Unnecessary widget rebuilds | Targeted state, const constructors |
| Native driver: false | Animations blocked by JS thread | useNativeDriver: true always |
| console.log in production | Blocks JS thread severely | Remove before release build |
| Skip React.memo/const | Every item re-renders on any change | Memoize list items ALWAYS |
| mobile-typography.md | Type scale, system fonts, accessibility |
| mobile-color-system.md | OLED optimization, dark mode, battery |
| decision-trees.md | Framework, state, storage decisions |