diff --git a/.Jules/changelog.md b/.Jules/changelog.md
index 11fc864..29838df 100644
--- a/.Jules/changelog.md
+++ b/.Jules/changelog.md
@@ -55,6 +55,13 @@
- Captures errors in `AppRoutes` and displays a user-friendly message instead of a white screen.
- **Technical:** Created `web/components/ErrorBoundary.tsx` using a hybrid Class+Functional approach to support Hooks in the fallback UI. Integrated into `web/App.tsx`.
+- **Mobile Skeleton Loading:** Replaced generic ActivityIndicator with `GroupListSkeleton` for smoother and more professional loading state.
+ - **Features:**
+ - Custom animated `Skeleton` primitive utilizing `Animated.loop` to mimic content layout.
+ - Added comprehensive skeleton list container component mirroring actual data appearance.
+ - Ensured screen reader compatibility with appropriate progressbar ARIA equivalents (`accessible=true`, `accessibilityRole=progressbar`, `accessibilityLabel="Loading groups"`).
+ - **Technical:** Created `mobile/components/ui/Skeleton.js` and `mobile/components/skeletons/GroupListSkeleton.js`. Integrated into `mobile/screens/HomeScreen.js`.
+
- Inline form validation in Auth page with real-time feedback and proper ARIA accessibility support (`aria-invalid`, `aria-describedby`, `role="alert"`).
- Dashboard skeleton loading state (`DashboardSkeleton`) to improve perceived performance during data fetch.
- Comprehensive `EmptyState` component for Groups and Friends pages to better guide new users.
diff --git a/.Jules/todo.md b/.Jules/todo.md
index ebb0c7a..5f12324 100644
--- a/.Jules/todo.md
+++ b/.Jules/todo.md
@@ -57,8 +57,9 @@
- Impact: Native feel, users can easily refresh data
- Size: ~150 lines
-- [ ] **[ux]** Complete skeleton loading for HomeScreen groups
- - File: `mobile/screens/HomeScreen.js`
+- [x] **[ux]** Complete skeleton loading for HomeScreen groups
+ - Completed: 2026-02-14
+ - Files: `mobile/screens/HomeScreen.js`, `mobile/components/ui/Skeleton.js`, `mobile/components/skeletons/GroupListSkeleton.js`
- Context: Replace ActivityIndicator with skeleton group cards
- Impact: Better loading experience, less jarring
- Size: ~40 lines
diff --git a/mobile/components/skeletons/GroupListSkeleton.js b/mobile/components/skeletons/GroupListSkeleton.js
new file mode 100644
index 0000000..c63c849
--- /dev/null
+++ b/mobile/components/skeletons/GroupListSkeleton.js
@@ -0,0 +1,47 @@
+import React from 'react';
+import { View, StyleSheet } from 'react-native';
+import { Card } from 'react-native-paper';
+import Skeleton from '../ui/Skeleton';
+
+const GroupListSkeletonItem = () => {
+ return (
+
+ }
+ left={(props) => }
+ />
+
+
+
+
+ );
+};
+
+const GroupListSkeleton = ({ count = 3 }) => {
+ return (
+
+ {Array.from({ length: count }).map((_, index) => (
+
+ ))}
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ padding: 16,
+ },
+ card: {
+ marginBottom: 16,
+ },
+ subtitle: {
+ marginTop: 4,
+ },
+});
+
+export default GroupListSkeleton;
diff --git a/mobile/components/ui/Skeleton.js b/mobile/components/ui/Skeleton.js
new file mode 100644
index 0000000..0f2b642
--- /dev/null
+++ b/mobile/components/ui/Skeleton.js
@@ -0,0 +1,51 @@
+import React, { useEffect, useRef } from 'react';
+import { Animated, View, StyleSheet } from 'react-native';
+import { useTheme } from 'react-native-paper';
+
+const Skeleton = ({ width, height, borderRadius = 4, style }) => {
+ const theme = useTheme();
+ const opacity = useRef(new Animated.Value(0.3)).current;
+
+ useEffect(() => {
+ const loop = Animated.loop(
+ Animated.sequence([
+ Animated.timing(opacity, {
+ toValue: 0.7,
+ duration: 800,
+ useNativeDriver: true,
+ }),
+ Animated.timing(opacity, {
+ toValue: 0.3,
+ duration: 800,
+ useNativeDriver: true,
+ }),
+ ])
+ );
+ loop.start();
+ return () => loop.stop();
+ }, [opacity]);
+
+ return (
+
+ );
+};
+
+const styles = StyleSheet.create({
+ skeleton: {
+ overflow: 'hidden',
+ },
+});
+
+export default Skeleton;
diff --git a/mobile/screens/HomeScreen.js b/mobile/screens/HomeScreen.js
index d2f3c38..e8c2320 100644
--- a/mobile/screens/HomeScreen.js
+++ b/mobile/screens/HomeScreen.js
@@ -13,6 +13,7 @@ import {
import HapticButton from '../components/ui/HapticButton';
import HapticCard from '../components/ui/HapticCard';
import { HapticAppbarAction } from '../components/ui/HapticAppbar';
+import GroupListSkeleton from '../components/skeletons/GroupListSkeleton';
import * as Haptics from "expo-haptics";
import { createGroup, getGroups, getOptimizedSettlements } from "../api/groups";
import { AuthContext } from "../context/AuthContext";
@@ -257,9 +258,7 @@ const HomeScreen = ({ navigation }) => {
{isLoading ? (
-
-
-
+
) : (