diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx
new file mode 100644
index 0000000..00da53f
--- /dev/null
+++ b/app/(tabs)/_layout.tsx
@@ -0,0 +1,44 @@
+import { Tabs } from "expo-router";
+import { GlassTabBar } from "@/components/glass";
+import { House, Compass, UserCircle } from "phosphor-react-native";
+import type { ColorValue } from "react-native";
+
+export default function TabLayout() {
+ return (
+ }
+ screenOptions={{
+ headerShown: false,
+ tabBarStyle: { display: "none" },
+ }}
+ >
+ (
+
+ ),
+ }}
+ />
+ (
+
+ ),
+ }}
+ />
+ (
+
+ ),
+ }}
+ />
+
+ );
+}
diff --git a/app/(tabs)/explore.tsx b/app/(tabs)/explore.tsx
new file mode 100644
index 0000000..612fec1
--- /dev/null
+++ b/app/(tabs)/explore.tsx
@@ -0,0 +1,60 @@
+import { StyleSheet, Text, View } from "react-native";
+import { useSafeAreaInsets } from "react-native-safe-area-context";
+import Animated, { FadeInDown } from "react-native-reanimated";
+import { GlassCard } from "@/components/glass";
+import { colors, typography, spacing, layout } from "@/theme";
+
+export default function ExploreScreen() {
+ const insets = useSafeAreaInsets();
+
+ return (
+
+
+
+ Explorer
+
+ Découvrez la communauté
+
+
+
+
+
+
+
+
+ Bientôt disponible
+
+
+ Partagez vos créations et découvrez{"\n"}
+ celles de la communauté — V1.5
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: colors.background,
+ paddingHorizontal: layout.screenPadding,
+ },
+ placeholder: {
+ flex: 1,
+ justifyContent: "center",
+ paddingHorizontal: spacing.md,
+ },
+ content: {
+ alignItems: "center",
+ },
+});
diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx
new file mode 100644
index 0000000..502cff4
--- /dev/null
+++ b/app/(tabs)/index.tsx
@@ -0,0 +1,232 @@
+import { useCallback } from "react";
+import {
+ Dimensions,
+ FlatList,
+ Image,
+ Pressable,
+ StyleSheet,
+ Text,
+ View,
+} from "react-native";
+import { useSafeAreaInsets } from "react-native-safe-area-context";
+import { useRouter } from "expo-router";
+import Animated, { FadeInDown } from "react-native-reanimated";
+import { Plus, ImageSquare } from "phosphor-react-native";
+import { GlassCard, GlassButton } from "@/components/glass";
+import { useWallpaperStore } from "@/stores/wallpaper.store";
+import { colors, typography, spacing, layout } from "@/theme";
+import { ANIMATION_META, type WallpaperConfig } from "@/types/wallpaper";
+
+const { width: SCREEN_WIDTH } = Dimensions.get("window");
+const CARD_SIZE = (SCREEN_WIDTH - layout.screenPadding * 2 - spacing.md) / 2;
+
+export default function HomeScreen() {
+ const insets = useSafeAreaInsets();
+ const router = useRouter();
+ const savedWallpapers = useWallpaperStore((s) => s.savedWallpapers);
+
+ const handleNewWallpaper = useCallback(() => {
+ router.push("/picker");
+ }, [router]);
+
+ const handleOpenWallpaper = useCallback(
+ (config: WallpaperConfig) => {
+ const store = useWallpaperStore.getState();
+ store.setSourceImage(config.sourceUri);
+ store.setAnimation(config.animation);
+ Object.entries(config.uniforms).forEach(([key, value]) => {
+ store.setUniform(key, value);
+ });
+ router.push(`/editor/${config.id}`);
+ },
+ [router]
+ );
+
+ return (
+
+ {/* Header */}
+
+
+
+
+ Lively
+
+ Vos fonds d'écran animés
+
+
+
+
+
+
+ {/* Content */}
+ {savedWallpapers.length === 0 ? (
+
+ ) : (
+ item.id}
+ contentContainerStyle={styles.grid}
+ columnWrapperStyle={styles.row}
+ showsVerticalScrollIndicator={false}
+ ListHeaderComponent={
+
+ Récentes
+
+ {savedWallpapers.length} création{savedWallpapers.length > 1 ? "s" : ""}
+
+
+ }
+ renderItem={({ item, index }) => (
+ handleOpenWallpaper(item)}
+ />
+ )}
+ />
+ )}
+
+ {/* Floating CTA */}
+ {savedWallpapers.length > 0 && (
+
+
+
+ )}
+
+ );
+}
+
+function EmptyState({ onPress }: { onPress: () => void }) {
+ return (
+
+
+
+
+ Donnez vie à vos photos
+
+
+ Choisissez une image et appliquez{"\n"}une animation en quelques taps
+
+
+
+
+
+ );
+}
+
+function WallpaperCard({
+ config,
+ index,
+ onPress,
+}: {
+ config: WallpaperConfig;
+ index: number;
+ onPress: () => void;
+}) {
+ const meta = ANIMATION_META[config.animation];
+
+ return (
+
+
+
+
+
+ {meta.label}
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: colors.background,
+ paddingHorizontal: layout.screenPadding,
+ },
+ header: {
+ marginBottom: spacing.lg,
+ },
+ headerRow: {
+ flexDirection: "row",
+ justifyContent: "space-between",
+ alignItems: "center",
+ },
+ sectionHeader: {
+ flexDirection: "row",
+ justifyContent: "space-between",
+ alignItems: "center",
+ marginBottom: spacing.md,
+ },
+ grid: {
+ paddingBottom: 160,
+ },
+ row: {
+ gap: spacing.md,
+ },
+ emptyContainer: {
+ flex: 1,
+ justifyContent: "center",
+ paddingHorizontal: spacing.md,
+ },
+ emptyContent: {
+ alignItems: "center",
+ },
+ cardImage: {
+ width: CARD_SIZE,
+ height: CARD_SIZE * 1.4,
+ borderRadius: 24,
+ },
+ cardOverlay: {
+ position: "absolute",
+ bottom: 0,
+ left: 0,
+ right: 0,
+ padding: 12,
+ borderBottomLeftRadius: 24,
+ borderBottomRightRadius: 24,
+ backgroundColor: "rgba(0, 0, 0, 0.4)",
+ },
+ cardLabel: {
+ ...typography.caption,
+ color: colors.text.primary,
+ fontWeight: "600",
+ },
+ fabContainer: {
+ position: "absolute",
+ left: layout.screenPadding,
+ right: layout.screenPadding,
+ },
+});
diff --git a/app/(tabs)/profile.tsx b/app/(tabs)/profile.tsx
new file mode 100644
index 0000000..ea18f1b
--- /dev/null
+++ b/app/(tabs)/profile.tsx
@@ -0,0 +1,242 @@
+import { ScrollView, StyleSheet, Switch, Text, View } from "react-native";
+import { useSafeAreaInsets } from "react-native-safe-area-context";
+import Animated, { FadeInDown } from "react-native-reanimated";
+import { GlassCard } from "@/components/glass";
+import { useSettingsStore } from "@/stores/settings.store";
+import { useWallpaperStore } from "@/stores/wallpaper.store";
+import { colors, typography, spacing, layout } from "@/theme";
+
+export default function ProfileScreen() {
+ const insets = useSafeAreaInsets();
+ const settings = useSettingsStore();
+ const wallpaperCount = useWallpaperStore((s) => s.savedWallpapers.length);
+
+ return (
+
+
+
+ Profil
+
+ Préférences & réglages
+
+
+
+
+ {/* Stats */}
+
+
+ Statistiques
+
+
+ {wallpaperCount}
+ Créations
+
+
+
+ 5
+ Animations
+
+
+
+
+
+ {/* Settings */}
+
+
+ Réglages
+
+
+
+
+
+
+
+ {/* Export Quality */}
+
+
+
+ Qualité d'export
+
+ {(["low", "medium", "high"] as const).map((q) => (
+ settings.setExportQuality(q)}
+ />
+ ))}
+
+
+
+ {/* About */}
+
+
+ À propos
+
+ Lively v1.0.0
+
+
+ Fonds d'écran animés depuis votre galerie
+
+
+
+
+
+
+ );
+}
+
+function SettingRow({
+ label,
+ description,
+ value,
+ onToggle,
+}: {
+ label: string;
+ description: string;
+ value: boolean;
+ onToggle: (v: boolean) => void;
+}) {
+ return (
+
+
+ {label}
+ {description}
+
+
+
+ );
+}
+
+function QualityOption({
+ label,
+ description,
+ selected,
+ onPress,
+}: {
+ label: string;
+ description: string;
+ selected: boolean;
+ onPress: () => void;
+}) {
+ return (
+
+
+
+ {label}
+
+ {description}
+
+
+ {selected && }
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: colors.background,
+ paddingHorizontal: layout.screenPadding,
+ },
+ content: {
+ paddingBottom: 40,
+ },
+ section: {
+ marginTop: spacing.md,
+ },
+ statsRow: {
+ flexDirection: "row",
+ marginTop: 16,
+ alignItems: "center",
+ },
+ stat: {
+ flex: 1,
+ alignItems: "center",
+ },
+ statDivider: {
+ width: 1,
+ height: 40,
+ backgroundColor: colors.glass.border,
+ },
+ settingRow: {
+ flexDirection: "row",
+ justifyContent: "space-between",
+ alignItems: "center",
+ paddingVertical: 12,
+ borderBottomWidth: 1,
+ borderBottomColor: colors.glass.highlight,
+ },
+ settingText: {
+ flex: 1,
+ marginRight: 16,
+ },
+ qualityRow: {
+ flexDirection: "row",
+ justifyContent: "space-between",
+ alignItems: "center",
+ paddingVertical: 12,
+ paddingHorizontal: 12,
+ borderRadius: 12,
+ marginBottom: 4,
+ },
+ qualitySelected: {
+ backgroundColor: "rgba(255, 255, 255, 0.06)",
+ },
+ radio: {
+ width: 20,
+ height: 20,
+ borderRadius: 10,
+ borderWidth: 1.5,
+ borderColor: colors.text.tertiary,
+ alignItems: "center",
+ justifyContent: "center",
+ },
+ radioSelected: {
+ borderColor: colors.text.primary,
+ },
+ radioDot: {
+ width: 10,
+ height: 10,
+ borderRadius: 5,
+ backgroundColor: colors.text.primary,
+ },
+});
diff --git a/app/_layout.tsx b/app/_layout.tsx
new file mode 100644
index 0000000..2cad593
--- /dev/null
+++ b/app/_layout.tsx
@@ -0,0 +1,48 @@
+import { useEffect } from "react";
+import { StatusBar } from "expo-status-bar";
+import { Stack } from "expo-router";
+import { GestureHandlerRootView } from "react-native-gesture-handler";
+import { StyleSheet } from "react-native";
+import { useWallpaperStore } from "@/stores/wallpaper.store";
+import { useSettingsStore } from "@/stores/settings.store";
+import { colors } from "@/theme";
+
+export default function RootLayout() {
+ const loadWallpapers = useWallpaperStore((s) => s.loadSavedWallpapers);
+ const loadSettings = useSettingsStore((s) => s.loadSettings);
+
+ useEffect(() => {
+ loadWallpapers();
+ loadSettings();
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ root: {
+ flex: 1,
+ backgroundColor: colors.background,
+ },
+});