DEV Community

Cover image for Forget bundlers: Here is a Full-Stack Todo App in a Single HTML File
ArtyProg
ArtyProg

Posted on

Forget bundlers: Here is a Full-Stack Todo App in a Single HTML File

Every day, we're told we need more. More libraries, more frameworks, more complex build tools just to get started. We're sold a mountain of dependencies—Webpack, Babel, Vite, Node.js—before we've even written a single line of our app's logic.

But what if that's a story we don't have to buy into?

What if I told you that your favorite code editor and a single HTML file are all you need to build a truly complex, high-performance application? I'm not talking about a simple counter. I'm talking about this fully-featured Todo application with:

  • authentication,
  • client-side routing,
  • granular,
  • user-specific persistent storage.

This entire application, all 1,500+ lines of it, lives in one HTML file. There is no npm install, no package.json, no bundler. It just runs.

This is the story of how a different kind of framework—JurisJS—makes this possible by getting out of your way and letting you build.

You can test the demo here : TodoApp

<!DOCTYPE html>
<html lang="fr">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Juris Todo App - Routeur, Auth & Stockage</title>

    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        :root {
            --orange: #ff6b35;
            --orange-light: #ff8c5a;
            --orange-dark: #e55a2b;
            --orange-pale: #fff4f1;
            --primary: #ff6b35;
            --primary-dark: #e55a2b;
            --primary-light: #ff8c5a;
            --success: #10b981;
            --warning: #f59e0b;
            --danger: #ef4444;
            --gray-50: #fafafa;
            --gray-100: #f5f5f5;
            --gray-200: #e5e5e5;
            --gray-300: #d4d4d4;
            --gray-400: #a3a3a3;
            --gray-500: #6b7280;
            --gray-600: #525252;
            --gray-700: #404040;
            --gray-800: #262626;
            --gray-900: #171717;
            --white: #ffffff;
            --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
            --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
            --border-radius: 0.5rem;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Inter', sans-serif;
            line-height: 1.6;
            color: var(--gray-900);
            background: var(--white);
            font-size: 16px;
        }

        /* Layout Components */
        .app-container {
            min-height: 100vh;
            display: flex;
            flex-direction: column;
        }

        .header {
            background: var(--white);
            border-bottom: 1px solid var(--gray-200);
            padding: 1rem 0;
            position: sticky;
            top: 0;
            z-index: 100;
        }

        .header-content {
            max-width: 1200px;
            margin: 0 auto;
            padding: 0 1rem;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .logo {
            font-size: 1.5rem;
            font-weight: 700;
            color: var(--orange);
            text-decoration: none;
        }

        .nav {
            display: flex;
            gap: 1rem;
            align-items: center;
        }

        .nav-link {
            color: var(--gray-600);
            text-decoration: none;
            padding: 0.5rem 1rem;
            border-radius: var(--border-radius);
        }

        .nav-link:hover {
            background: var(--gray-100);
            color: var(--orange);
        }

        .nav-link.active {
            background: var(--orange);
            color: var(--white);
        }

        .main-content {
            flex: 1;
            max-width: 1200px;
            margin: 0 auto;
            padding: 2rem 1rem;
            width: 100%;
        }

        /* Form Components */
        .form-container {
            max-width: 400px;
            margin: 2rem auto;
            background: var(--white);
            padding: 2rem;
            border-radius: var(--border-radius);
            box-shadow: var(--shadow-lg);
        }

        .form-title {
            font-size: 1.5rem;
            font-weight: 600;
            text-align: center;
            margin-bottom: 2rem;
            color: var(--gray-900);
        }

        .form-group {
            margin-bottom: 1rem;
        }

        .form-label {
            display: block;
            margin-bottom: 0.5rem;
            font-weight: 500;
            color: var(--gray-700);
        }

        .form-input {
            width: 100%;
            padding: 0.75rem;
            border: 1px solid var(--gray-300);
            border-radius: var(--border-radius);
            font-size: 1rem;
        }

        .form-input:focus {
            outline: none;
            border-color: var(--orange);
            box-shadow: 0 0 0 3px rgba(255, 107, 53, 0.1);
        }

        .form-input.error {
            border-color: var(--danger);
        }

        .form-error {
            color: var(--danger);
            font-size: 0.875rem;
            margin-top: 0.25rem;
        }

        .btn {
            padding: 0.75rem 1.5rem;
            border: none;
            border-radius: var(--border-radius);
            font-size: 1rem;
            font-weight: 500;
            cursor: pointer;
            text-decoration: none;
            display: inline-block;
            text-align: center;
            touch-action: manipulation;
            user-select: none;
            -webkit-tap-highlight-color: transparent;
        }

        .btn-primary {
            background: var(--orange);
            color: var(--white);
        }

        .btn-primary:hover {
            background: var(--orange-dark);
        }

        .btn-secondary {
            background: var(--gray-200);
            color: var(--gray-800);
        }

        .btn-secondary:hover {
            background: var(--gray-300);
        }

        .btn-danger {
            background: var(--danger);
            color: var(--white);
        }

        .btn-success {
            background: var(--success);
            color: var(--white);
        }

        .btn-full {
            width: 100%;
        }

        /* Todo Components */
        .todo-dashboard {
            display: grid;
            gap: 2rem;
        }

        .todo-lists {
            background: var(--white);
            border-radius: var(--border-radius);
            padding: 1.5rem;
            box-shadow: var(--shadow);
        }

        .section-title {
            font-size: 1.25rem;
            font-weight: 600;
            margin-bottom: 1rem;
            color: var(--gray-900);
        }

        .list-item {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 1rem;
            border: 1px solid var(--gray-200);
            border-radius: var(--border-radius);
            margin-bottom: 0.5rem;
            cursor: pointer;
        }

        .list-item:hover {
            border-color: var(--orange);
            background: var(--gray-50);
        }

        .list-item.active {
            border-color: var(--orange);
            background: var(--orange-pale);
        }

        .list-info {
            flex: 1;
        }

        .list-name {
            font-weight: 500;
            color: var(--gray-900);
        }

        .list-count {
            color: var(--gray-500);
            font-size: 0.875rem;
        }

        .list-actions {
            display: flex;
            gap: 0.5rem;
        }

        .btn-small {
            padding: 0.25rem 0.5rem;
            font-size: 0.75rem;
        }

        .todo-form {
            background: var(--white);
            border-radius: var(--border-radius);
            padding: 1.5rem;
            box-shadow: var(--shadow);
            margin-bottom: 2rem;
        }

        .todo-input {
            display: flex;
            gap: 0.5rem;
        }

        .todo-input input {
            flex: 1;
        }

        .todo-list {
            background: var(--white);
            border-radius: var(--border-radius);
            padding: 1.5rem;
            box-shadow: var(--shadow);
        }

        .todo-item {
            display: flex;
            align-items: center;
            gap: 0.75rem;
            padding: 0.75rem 0;
            border-bottom: 1px solid var(--gray-100);
        }

        .todo-item:last-child {
            border-bottom: none;
        }

        .todo-checkbox {
            width: 1.25rem;
            height: 1.25rem;
            cursor: pointer;
        }

        .todo-text {
            flex: 1;
            color: var(--gray-700);
        }

        .todo-text.completed {
            text-decoration: line-through;
            color: var(--gray-400);
        }

        .todo-actions {
            display: flex;
            gap: 0.5rem;
        }

        .filters {
            display: flex;
            gap: 0.5rem;
            margin-bottom: 1rem;
            flex-wrap: wrap;
        }

        .filter-btn {
            padding: 0.5rem 1rem;
            border: 1px solid var(--gray-300);
            background: var(--white);
            color: var(--gray-600);
            border-radius: var(--border-radius);
            cursor: pointer;
        }

        .filter-btn.active {
            background: var(--orange);
            color: var(--white);
            border-color: var(--orange);
        }

        /* Responsive Design */
        @media (min-width: 768px) {
            .todo-dashboard {
                grid-template-columns: 450px 1fr;
            }

            .main-content {
                padding: 3rem 2rem;
            }
        }

        /* Loading & Empty States */
        .loading {
            text-align: center;
            padding: 2rem;
            color: var(--gray-500);
        }

        .empty-state {
            text-align: center;
            padding: 3rem;
            color: var(--gray-500);
        }

        .empty-state h3 {
            margin-bottom: 1rem;
            color: var(--gray-700);
        }

        /* Utility Classes */
        .text-center {
            text-align: center;
        }

        .text-sm {
            font-size: 0.875rem;
        }

        .text-danger {
            color: var(--danger);
        }

        .text-success {
            color: var(--success);
        }

        .mt-1 {
            margin-top: 0.25rem;
        }

        .mt-2 {
            margin-top: 0.5rem;
        }

        .mb-2 {
            margin-bottom: 0.5rem;
        }

        .hidden {
            display: none;
        }

        /* Toast notifications */
        .toast {
            position: fixed;
            top: 1rem;
            right: 1rem;
            background: var(--white);
            border: 1px solid var(--gray-200);
            border-radius: var(--border-radius);
            padding: 1rem;
            box-shadow: var(--shadow-lg);
            z-index: 1000;
        }

        .toast.success {
            border-left: 4px solid var(--success);
        }

        .toast.error {
            border-left: 4px solid var(--danger);
        }
    </style>
</head>

<body>
    <div id="app"></div>
    <script src="https://unpkg.com/juris"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
    <script>
        // NOTE: The internal logic and console logs of the managers are kept in English
        // for easier debugging by developers, as is common practice. Only user-facing
        // text in UI components and alerts is translated.

        const StatePersistenceManager = (props, context) => {
            const { getState, setState, subscribe } = context;

            // Enhanced configuration with timing controls
            const config = {
                domains: props.domains || [],
                excludeDomains: props.excludeDomains || ['temp', 'cache', 'session', 'geolocation', 'persistence'],
                keyPrefix: props.keyPrefix || 'app_state_',
                debounceMs: props.debounceMs || 1000,
                debug: props.debug || false,
                autoDetectNewDomains: props.autoDetectNewDomains || true,
                watchIntervalMs: props.watchIntervalMs || 5000,

                // Timing controls for layout shift prevention
                aggressiveRestore: props.aggressiveRestore !== false, // Default: true
                restoreDelay: props.restoreDelay || 0,
                priorityDomains: props.priorityDomains || [], // Restore these first
                earlyRestoreTimeout: props.earlyRestoreTimeout || 50,

                // Granular domain timing
                domainRestoreConfig: props.domainRestoreConfig || {},

                // Save timing controls
                immediateSave: props.immediateSave || [], // Save changes immediately
                criticalSave: props.criticalSave || [], // Save with shorter debounce
                criticalDebounceMs: props.criticalDebounceMs || 200,

                // User-specific domains (requires authentication)
                userSpecificDomains: props.userSpecificDomains || [],
                userIdPath: props.userIdPath || 'auth.user.id', // Path to user ID in state
                requireAuth: props.requireAuth || false // Whether user-specific domains require auth
            };

            // Internal state
            let saveTimers = new Map();
            let isRestoring = false;
            let domainSubscriptions = new Map();
            let domainWatcher = null;
            let restoreQueue = [];
            let isProcessingRestoreQueue = false;

            return {
                hooks: {
                    onRegister: () => {
                        console.log('💾 StatePersistenceManager initializing with timing controls...');

                        // Initialize persistence state - DIRECT INJECTION
                        if (context.juris && context.juris.stateManager && context.juris.stateManager.state) {
                            context.juris.stateManager.state.persistence = {
                                isEnabled: true,
                                lastSave: null,
                                lastRestore: null,
                                errors: [],
                                stats: {
                                    domainsTracked: 0,
                                    totalSaves: 0,
                                    totalRestores: 0,
                                    priorityRestores: 0,
                                    delayedRestores: 0
                                }
                            };
                        } else {
                            // Fallback if direct access not available
                            setState('persistence.isEnabled', true);
                            setState('persistence.lastSave', null);
                            setState('persistence.lastRestore', null);
                            setState('persistence.errors', []);
                            setState('persistence.stats', {
                                domainsTracked: 0,
                                totalSaves: 0,
                                totalRestores: 0,
                                priorityRestores: 0,
                                delayedRestores: 0
                            });
                        }

                        // Restore state with timing controls
                        if (config.aggressiveRestore) {
                            restoreAllDomainsWithTiming();
                        } else {
                            setTimeout(() => restoreAllDomainsWithTiming(), config.restoreDelay);
                        }

                        // Setup monitoring after early restore
                        setTimeout(() => {
                            setupDomainMonitoring();

                            if (config.autoDetectNewDomains) {
                                setupDomainWatcher();
                            }
                        }, Math.max(config.earlyRestoreTimeout, 100));

                        // Setup cross-tab sync
                        window.addEventListener('storage', handleStorageEvent);
                        window.addEventListener('beforeunload', saveAllTrackedDomains);

                        console.log('✅ StatePersistenceManager ready with timing controls');
                    },

                    onUnregister: () => {
                        console.log('💾 StatePersistenceManager cleanup');

                        // Save all before cleanup
                        saveAllTrackedDomains();

                        // Clear all timers
                        saveTimers.forEach(timer => clearTimeout(timer));
                        saveTimers.clear();

                        if (domainWatcher) {
                            clearInterval(domainWatcher);
                            domainWatcher = null;
                        }

                        // Unsubscribe from all domains
                        domainSubscriptions.forEach(unsubscribe => unsubscribe());
                        domainSubscriptions.clear();

                        // Remove storage listener
                        window.removeEventListener('storage', handleStorageEvent);
                        window.removeEventListener('beforeunload', saveAllTrackedDomains);

                        console.log('✅ StatePersistenceManager cleaned up');
                    }
                },

                api: {
                    saveDomain: (domain, immediate = false) => saveDomain(domain, immediate),
                    saveAllDomains: () => saveAllTrackedDomains(),
                    restoreDomain: (domain) => restoreDomain(domain),
                    restoreAllDomains: () => restoreAllDomainsWithTiming(),
                    addDomain: (domain) => addDomainTracking(domain),
                    removeDomain: (domain) => removeDomainTracking(domain),
                    clearDomain: (domain) => clearDomainStorage(domain),
                    clearAllStorage: () => clearAllStorage(),
                    getStorageStats: () => getStorageStats(),
                    getTrackedDomains: () => Array.from(domainSubscriptions.keys()),
                    exportState: () => exportState(),
                    importState: (data) => importState(data),
                    refreshDomainDetection: () => setupDomainMonitoring(),
                    forceImmediateSave: (domain) => saveDomain(domain, true),
                    restorePriorityDomains: () => restorePriorityDomains(),
                    getRestoreQueue: () => [...restoreQueue],
                    updateTimingConfig: (newConfig) => Object.assign(config, newConfig),
                    getConfig: () => ({ ...config }) // Get current configuration
                }
            };

            // Enhanced restore with timing controls
            function restoreAllDomainsWithTiming() {
                log('📂 Starting timed restore sequence...');

                // Get all stored domains by scanning localStorage
                const storedDomains = [];
                const keyPrefix = config.keyPrefix;

                for (let i = 0; i < localStorage.length; i++) {
                    const key = localStorage.key(i);
                    if (key && key.startsWith(keyPrefix)) {
                        // Extract domain from key
                        let remainder = key.substring(keyPrefix.length);

                        // Split by underscore and take first part as domain
                        let domain = remainder.split('_')[0];

                        // Only include if it's a valid domain and not already included
                        if (domain && !storedDomains.includes(domain)) {
                            storedDomains.push(domain);
                        }
                    }
                }

                log(`📂 Found stored domains: [${storedDomains.join(', ')}]`);

                if (storedDomains.length === 0) {
                    log('📂 No stored domains found');
                    // DIRECT INJECTION for lastRestore
                    if (context.juris && context.juris.stateManager && context.juris.stateManager.state && context.juris.stateManager.state.persistence) {
                        context.juris.stateManager.state.persistence.lastRestore = Date.now();
                    }
                    return { restored: [], failed: [] };
                }

                // Sort domains by priority and timing configuration
                const sortedDomains = storedDomains.sort((a, b) => {
                    const configA = config.domainRestoreConfig[a] || { priority: 999, delay: 0 };
                    const configB = config.domainRestoreConfig[b] || { priority: 999, delay: 0 };

                    if (configA.priority !== configB.priority) {
                        return configA.priority - configB.priority;
                    }
                    return configA.delay - configB.delay;
                });

                log(`📂 Restore order: [${sortedDomains.join(', ')}]`);

                // Process domains with their configured timing
                let cumulativeDelay = 0;
                const results = { restored: [], failed: [], priority: [], delayed: [] };

                sortedDomains.forEach((domain, index) => {
                    const domainConfig = config.domainRestoreConfig[domain] || { priority: 999, delay: 0, aggressive: false };

                    if (domainConfig.aggressive || config.priorityDomains.includes(domain)) {
                        // Immediate restore for aggressive/priority domains
                        if (restoreDomain(domain)) {
                            results.restored.push(domain);
                            results.priority.push(domain);

                            // DIRECT INJECTION for stats
                            if (context.juris && context.juris.stateManager && context.juris.stateManager.state && context.juris.stateManager.state.persistence) {
                                context.juris.stateManager.state.persistence.stats.priorityRestores =
                                    (context.juris.stateManager.state.persistence.stats.priorityRestores || 0) + 1;
                            }
                        } else {
                            results.failed.push(domain);
                        }

                        log(`⚡ Priority restore completed for ${domain} immediately`);

                    } else {
                        // Delayed restore for non-critical domains
                        const restoreDelay = cumulativeDelay + domainConfig.delay;

                        setTimeout(() => {
                            if (restoreDomain(domain)) {
                                results.restored.push(domain);
                                results.delayed.push(domain);

                                // DIRECT INJECTION for stats
                                if (context.juris && context.juris.stateManager && context.juris.stateManager.state && context.juris.stateManager.state.persistence) {
                                    context.juris.stateManager.state.persistence.stats.delayedRestores =
                                        (context.juris.stateManager.state.persistence.stats.delayedRestores || 0) + 1;
                                }
                            } else {
                                results.failed.push(domain);
                            }
                        }, restoreDelay);

                        log(`⏳ Delayed restore scheduled for ${domain} at ${restoreDelay}ms`);
                        cumulativeDelay += domainConfig.delay;
                    }
                });

                // Update final restore timestamp
                const finalDelay = Math.max(cumulativeDelay, config.earlyRestoreTimeout);
                setTimeout(() => {
                    // DIRECT INJECTION for lastRestore
                    if (context.juris && context.juris.stateManager && context.juris.stateManager.state && context.juris.stateManager.state.persistence) {
                        context.juris.stateManager.state.persistence.lastRestore = Date.now();
                    }
                    log(`📂 Restore sequence completed. Priority: ${results.priority.length}, Delayed: ${results.delayed.length}, Failed: ${results.failed.length}`);
                }, finalDelay);

                return results;
            }

            function restorePriorityDomains() {
                log('⚡ Restoring priority domains only...');

                const priorityResults = { restored: [], failed: [] };

                config.priorityDomains.forEach(domain => {
                    if (restoreDomain(domain)) {
                        priorityResults.restored.push(domain);
                    } else {
                        priorityResults.failed.push(domain);
                    }
                });

                log(`⚡ Priority restore completed: [${priorityResults.restored.join(', ')}]`);
                return priorityResults;
            }

            function setupDomainMonitoring() {
                log('🔍 Setting up domain monitoring...');

                const allState = context.juris.stateManager.state;
                const availableDomains = Object.keys(allState);
                log(`🔍 Available domains in state:`, availableDomains);

                // Clear existing subscriptions
                domainSubscriptions.forEach(unsubscribe => unsubscribe());
                domainSubscriptions.clear();

                // Determine which domains to track
                let domainsToTrack = [];

                if (config.domains.length > 0) {
                    domainsToTrack = config.domains.filter(domain => {
                        const exists = availableDomains.includes(domain);
                        if (!exists) {
                            log(`⚠️ Configured domain '${domain}' not found in state`);
                        }
                        return exists && !config.excludeDomains.includes(domain);
                    });
                } else {
                    domainsToTrack = availableDomains.filter(domain =>
                        !config.excludeDomains.includes(domain)
                    );
                }

                log(`📊 Domains to track: [${domainsToTrack.join(', ')}]`);

                // Track each domain
                domainsToTrack.forEach(domain => {
                    addDomainTracking(domain);
                });

                // Update stats - DIRECT INJECTION
                if (context.juris && context.juris.stateManager && context.juris.stateManager.state && context.juris.stateManager.state.persistence) {
                    context.juris.stateManager.state.persistence.stats.domainsTracked = domainSubscriptions.size;
                }

                log(`✅ Now tracking ${domainSubscriptions.size} domains: [${Array.from(domainSubscriptions.keys()).join(', ')}]`);
            }

            function setupDomainWatcher() {
                domainWatcher = setInterval(() => {
                    const currentDomains = Object.keys(context.juris.stateManager.state);
                    const trackedDomains = Array.from(domainSubscriptions.keys());

                    const newDomains = currentDomains.filter(domain =>
                        !trackedDomains.includes(domain) &&
                        !config.excludeDomains.includes(domain) &&
                        (config.domains.length === 0 || config.domains.includes(domain))
                    );

                    if (newDomains.length > 0) {
                        log(`🆕 Detected new domains: [${newDomains.join(', ')}]`);
                        newDomains.forEach(domain => addDomainTracking(domain));

                        // DIRECT INJECTION for stats
                        if (context.juris && context.juris.stateManager && context.juris.stateManager.state && context.juris.stateManager.state.persistence) {
                            context.juris.stateManager.state.persistence.stats.domainsTracked = domainSubscriptions.size;
                        }
                    }
                }, config.watchIntervalMs);

                log(`👀 Domain watcher started (checking every ${config.watchIntervalMs}ms)`);
            }

            function addDomainTracking(domain) {
                if (domainSubscriptions.has(domain)) {
                    log(`⚠️ Domain ${domain} already being tracked`);
                    return false;
                }

                try {
                    const testValue = getState(domain);
                    log(`🔍 Testing domain '${domain}': ${testValue !== undefined ? 'exists' : 'undefined'}`);

                    // Use internal subscription
                    const unsubscribe = context.juris.stateManager.subscribeInternal(domain, () => {
                        if (!isRestoring) {
                            const currentValue = getState(domain);
                            log(`🔄 State change detected in domain: ${domain}`, { currentValue });
                            debouncedSave(domain, currentValue);
                        }
                    });

                    domainSubscriptions.set(domain, unsubscribe);
                    log(`➕ Added tracking for domain: ${domain}`);
                    return true;

                } catch (error) {
                    logError(`Failed to add tracking for domain ${domain}:`, error);
                    return false;
                }
            }

            function removeDomainTracking(domain) {
                const unsubscribe = domainSubscriptions.get(domain);
                if (unsubscribe) {
                    unsubscribe();
                    domainSubscriptions.delete(domain);
                    log(`➖ Removed tracking for domain: ${domain}`);
                    return true;
                }

                log(`⚠️ Domain ${domain} was not being tracked`);
                return false;
            }

            function debouncedSave(domain, value) {
                // Clear existing timer
                if (saveTimers.has(domain)) {
                    clearTimeout(saveTimers.get(domain));
                }

                // Determine save timing based on domain configuration
                let saveDelay = config.debounceMs;

                if (config.immediateSave.includes(domain)) {
                    // Immediate save for critical domains
                    saveDomain(domain, true);
                    return;
                } else if (config.criticalSave.includes(domain)) {
                    // Faster save for critical domains
                    saveDelay = config.criticalDebounceMs;
                }

                const timer = setTimeout(() => {
                    saveDomain(domain, false);
                    saveTimers.delete(domain);
                }, saveDelay);

                saveTimers.set(domain, timer);

                const saveType = config.criticalSave.includes(domain) ? 'CRITICAL' : 'NORMAL';
                log(`⏰ ${saveType} save scheduled for domain: ${domain} in ${saveDelay}ms`);
            }

            function saveDomain(domain, immediate = false) {
                try {
                    const value = getState(domain);
                    if (value === undefined || value === null) {
                        log(`⚠️ Skipping save for undefined domain: ${domain}`);
                        return false;
                    }

                    const dataPackage = {
                        value: value,
                        timestamp: Date.now(),
                        domain: domain,
                        immediate: immediate
                    };

                    // Check if domain requires user-specific storage
                    const isUserSpecific = config.userSpecificDomains.includes(domain);
                    const currentUserId = getUserId();

                    if (isUserSpecific && config.requireAuth && !currentUserId) {
                        log(`⚠️ Skipping save for user-specific domain '${domain}' - no authenticated user`);
                        return false;
                    }

                    // Build storage key
                    let storageKey = config.keyPrefix + domain;
                    if (isUserSpecific && currentUserId) {
                        storageKey = `${storageKey}_${currentUserId}`;
                    }

                    localStorage.setItem(storageKey, JSON.stringify(dataPackage));

                    // Update statistics - DIRECT INJECTION
                    if (context.juris && context.juris.stateManager && context.juris.stateManager.state && context.juris.stateManager.state.persistence) {
                        const stats = context.juris.stateManager.state.persistence.stats;
                        stats.totalSaves = (stats.totalSaves || 0) + 1;

                        context.juris.stateManager.state.persistence.lastSave = {
                            domain,
                            timestamp: Date.now(),
                            size: JSON.stringify(dataPackage).length,
                            immediate
                        };
                    }

                    const saveType = immediate ? 'IMMEDIATE' : 'DEBOUNCED';
                    log(`💾 ${saveType} saved domain: ${domain} (${JSON.stringify(dataPackage).length} bytes) key: ${storageKey}`);
                    return true;

                } catch (error) {
                    logError(`Failed to save domain ${domain}:`, error);
                    return false;
                }
            }

            function restoreDomain(domain) {
                try {
                    const isUserSpecific = config.userSpecificDomains.includes(domain);
                    const currentUserId = getUserId();

                    // Build storage key
                    let storageKey = config.keyPrefix + domain;
                    if (isUserSpecific && currentUserId) {
                        storageKey = `${storageKey}_${currentUserId}`;
                    }

                    const stored = localStorage.getItem(storageKey);

                    if (!stored) {
                        log(`📂 No stored data for domain: ${domain} (key: ${storageKey})`);
                        return false;
                    }

                    const data = JSON.parse(stored);

                    // DIRECT INJECTION - Restore directly to state without triggering subscriptions
                    isRestoring = true;

                    // Direct injection into the state manager's internal state
                    if (context.juris && context.juris.stateManager && context.juris.stateManager.state) {
                        context.juris.stateManager.state[domain] = data.value;
                        log(`📂 DIRECT INJECT: ${domain} directly injected into state`);
                    } else {
                        // Fallback to setState if direct access not available
                        setState(domain, data.value);
                        log(`📂 FALLBACK: ${domain} restored via setState`);
                    }

                    isRestoring = false;

                    // Update statistics - DIRECT INJECTION
                    if (context.juris && context.juris.stateManager && context.juris.stateManager.state && context.juris.stateManager.state.persistence) {
                        const stats = context.juris.stateManager.state.persistence.stats;
                        stats.totalRestores = (stats.totalRestores || 0) + 1;

                        context.juris.stateManager.state.persistence.lastRestore = {
                            domain,
                            timestamp: Date.now(),
                            dataTimestamp: data.timestamp
                        };
                    }

                    log(`📂 Restored domain: ${domain} (saved ${new Date(data.timestamp).toLocaleString()})`);
                    return true;

                } catch (error) {
                    logError(`Failed to restore domain ${domain}:`, error);
                    return false;
                }
            }

            function saveAllTrackedDomains() {
                log('💾 Saving all tracked domains...');

                const savedDomains = [];
                const failedDomains = [];

                domainSubscriptions.forEach((unsubscribe, domain) => {
                    if (saveDomain(domain, true)) {
                        savedDomains.push(domain);
                    } else {
                        failedDomains.push(domain);
                    }
                });

                log(`💾 Saved ${savedDomains.length} domains: [${savedDomains.join(', ')}]`);

                if (failedDomains.length > 0) {
                    logError(`❌ Failed to save ${failedDomains.length} domains: [${failedDomains.join(', ')}]`);
                }

                return { saved: savedDomains, failed: failedDomains };
            }

            function handleStorageEvent(event) {
                if (!event.key || !event.key.startsWith(config.keyPrefix)) {
                    return;
                }

                // Extract domain from key
                let remainder = event.key.substring(config.keyPrefix.length);
                let domain = remainder.split('_')[0];

                if (domainSubscriptions.has(domain)) {
                    log(`🔄 Storage changed externally for domain: ${domain}`);

                    if (event.newValue) {
                        // Parse and directly inject the new value
                        try {
                            const data = JSON.parse(event.newValue);
                            isRestoring = true;

                            // DIRECT INJECTION for cross-tab sync
                            if (context.juris && context.juris.stateManager && context.juris.stateManager.state) {
                                context.juris.stateManager.state[domain] = data.value;
                                log(`🔄 DIRECT INJECT: ${domain} synced from external tab`);
                            } else {
                                setState(domain, data.value);
                                log(`🔄 FALLBACK: ${domain} synced via setState`);
                            }

                            isRestoring = false;
                        } catch (error) {
                            logError(`Failed to parse external change for ${domain}:`, error);
                        }
                    } else {
                        // Value was deleted externally
                        isRestoring = true;
                        if (context.juris && context.juris.stateManager && context.juris.stateManager.state) {
                            delete context.juris.stateManager.state[domain];
                            log(`🔄 DIRECT DELETE: ${domain} removed from state`);
                        } else {
                            setState(domain, undefined);
                            log(`🔄 FALLBACK DELETE: ${domain} removed via setState`);
                        }
                        isRestoring = false;
                    }
                }
            }

            function clearDomainStorage(domain) {
                try {
                    const isUserSpecific = config.userSpecificDomains.includes(domain);
                    const currentUserId = getUserId();

                    let storageKey = config.keyPrefix + domain;
                    if (isUserSpecific && currentUserId) {
                        storageKey = `${storageKey}_${currentUserId}`;
                    }

                    localStorage.removeItem(storageKey);
                    log(`🗑️ Cleared storage for domain: ${domain} (key: ${storageKey})`);
                    return true;
                } catch (error) {
                    logError(`Failed to clear storage for domain ${domain}:`, error);
                    return false;
                }
            }

            function clearAllStorage() {
                try {
                    const keysToRemove = [];

                    for (let i = 0; i < localStorage.length; i++) {
                        const key = localStorage.key(i);
                        if (key && key.startsWith(config.keyPrefix)) {
                            keysToRemove.push(key);
                        }
                    }

                    keysToRemove.forEach(key => localStorage.removeItem(key));

                    log(`🗑️ Cleared ${keysToRemove.length} storage entries`);
                    return true;
                } catch (error) {
                    logError('Failed to clear all storage:', error);
                    return false;
                }
            }

            function getStorageStats() {
                let totalSize = 0;
                let entryCount = 0;
                const domains = [];

                for (let i = 0; i < localStorage.length; i++) {
                    const key = localStorage.key(i);
                    if (key && key.startsWith(config.keyPrefix)) {
                        const value = localStorage.getItem(key);
                        totalSize += key.length + (value ? value.length : 0);
                        entryCount++;

                        // Extract domain from key
                        let remainder = key.substring(config.keyPrefix.length);
                        let domain = remainder.split('_')[0];
                        domains.push(domain);
                    }
                }

                return {
                    totalSize,
                    entryCount,
                    domains: [...new Set(domains)], // Remove duplicates
                    trackedDomains: Array.from(domainSubscriptions.keys()),
                    config: {
                        aggressiveRestore: config.aggressiveRestore,
                        priorityDomains: config.priorityDomains,
                        immediateSave: config.immediateSave,
                        criticalSave: config.criticalSave,
                        keyPrefix: config.keyPrefix,
                        userSpecificDomains: config.userSpecificDomains
                    }
                };
            }

            function exportState() {
                const exportData = {
                    timestamp: Date.now(),
                    domains: {}
                };

                domainSubscriptions.forEach((unsubscribe, domain) => {
                    exportData.domains[domain] = getState(domain);
                });

                return exportData;
            }

            function importState(data) {
                try {
                    if (!data.domains) {
                        throw new Error('Invalid import data format');
                    }

                    isRestoring = true;

                    Object.entries(data.domains).forEach(([domain, value]) => {
                        // DIRECT INJECTION for import as well
                        if (context.juris && context.juris.stateManager && context.juris.stateManager.state) {
                            context.juris.stateManager.state[domain] = value;
                            log(`📥 DIRECT INJECT: ${domain} imported directly into state`);
                        } else {
                            setState(domain, value);
                            log(`📥 FALLBACK: ${domain} imported via setState`);
                        }
                        saveDomain(domain, true);
                    });

                    isRestoring = false;

                    log(`📥 Imported ${Object.keys(data.domains).length} domains`);
                    return true;
                } catch (error) {
                    isRestoring = false;
                    logError('Import failed:', error);
                    return false;
                }
            }

            // Helper function to get user ID from configurable path
            function getUserId() {
                try {
                    const pathParts = config.userIdPath.split('.');
                    let value = context.juris.stateManager.state;

                    for (const part of pathParts) {
                        if (value && typeof value === 'object') {
                            value = value[part];
                        } else {
                            return null;
                        }
                    }

                    return value;
                } catch (error) {
                    log(`⚠️ Failed to get user ID from path: ${config.userIdPath}`, error);
                    return null;
                }
            }

            function log(message, ...args) {
                if (config.debug) {
                    console.log(`💾 [StatePersistence] ${message}`, ...args);
                }
            }

            function logError(message, error = null) {
                console.error(`💾 [StatePersistence] ${message}`, error);

                // DIRECT INJECTION for errors
                if (context.juris && context.juris.stateManager && context.juris.stateManager.state && context.juris.stateManager.state.persistence) {
                    const errors = context.juris.stateManager.state.persistence.errors;
                    errors.push({
                        message,
                        error: error ? error.message : null,
                        timestamp: Date.now()
                    });

                    if (errors.length > 10) {
                        errors.splice(0, errors.length - 10);
                    }
                }
            }
        };

        // URL State Sync with Route Guards
        const UrlStateSync = (props, context) => {
            const { getState, setState } = context;

            const routeGuards = {
                '/': ['authenticated'],
                '/lists': ['authenticated'],
                '/profile': ['authenticated'],
                '/settings': ['authenticated']
            };

            return {
                hooks: {
                    onRegister: () => {
                        console.log('🧭 UrlStateSync initializing...');
                        handleUrlChange();
                        window.addEventListener('hashchange', handleUrlChange);
                        window.addEventListener('popstate', handleUrlChange);
                    }
                }
            };

            async function handleUrlChange() {
                const hash = window.location.hash.substring(1) || '/';
                const segments = parseSegments(hash);

                // Check route guards
                const guardResult = await checkRouteAccess(hash);

                if (guardResult.allowed) {
                    setState('url.path', hash);
                    setState('url.segments', segments);
                    console.log('🧭 URL updated:', hash);
                } else {
                    console.log('🚫 Route access denied, redirecting to:', guardResult.redirect);
                    window.location.hash = guardResult.redirect;
                }
            }

            async function checkRouteAccess(path) {
                const guards = getRouteGuards(path);
                const isAuthenticated = getState('auth.isLoggedIn', false);

                if (guards.includes('authenticated') && !isAuthenticated) {
                    return { allowed: false, redirect: '/login' };
                }

                return { allowed: true };
            }

            function getRouteGuards(path) {
                if (routeGuards[path]) return routeGuards[path];

                const segments = path.split('/').filter(Boolean);
                for (let i = segments.length - 1; i > 0; i--) {
                    const parentPath = '/' + segments.slice(0, i).join('/');
                    if (routeGuards[parentPath]) return routeGuards[parentPath];
                }

                return [];
            }

            function parseSegments(path) {
                const parts = path.split('/').filter(Boolean);
                return {
                    full: path,
                    parts: parts,
                    base: parts[0] || '',
                    sub: parts[1] || '',
                    id: parts[2] || ''
                };
            }
        };

        // Authentication Manager
        const AuthManager = (props, context) => {
            const { getState, setState } = context;

            return {
                hooks: {
                    onRegister: () => {
                        console.log('🔐 AuthManager initializing...');
                        checkExistingAuth();
                    }
                },

                api: {
                    login: async (email, password) => {
                        setState('auth.loading', true);
                        setState('auth.error', null);

                        try {
                            await new Promise(resolve => setTimeout(resolve, 1000));

                            const users = getState('storage.users', []);
                            const user = users.find(u => u.email === email && u.password === hashPassword(password));

                            if (!user) {
                                throw new Error('Email ou mot de passe invalide');
                            }

                            const token = generateToken();

                            setState('auth.user', user);
                            setState('auth.token', token);
                            setState('auth.isLoggedIn', true);

                            // Store in localStorage
                            localStorage.setItem('todo_auth_token', token);
                            localStorage.setItem('todo_auth_user', JSON.stringify(user));

                            console.log('✅ Login successful');

                            // Trigger user-specific data restore after login
                            setTimeout(() => {
                                context.headless.StatePersistenceManager.restoreAllDomains();
                            }, 100);

                            return { success: true };

                        } catch (error) {
                            setState('auth.error', error.message);
                            console.error('❌ Login failed:', error.message);
                            return { success: false, error: error.message };
                        } finally {
                            setState('auth.loading', false);
                        }
                    },

                    register: async (email, password, name) => {
                        setState('auth.loading', true);
                        setState('auth.error', null);

                        try {
                            await new Promise(resolve => setTimeout(resolve, 1000));

                            const users = getState('storage.users', []);

                            if (users.find(u => u.email === email)) {
                                throw new Error('Cet email existe déjà');
                            }

                            const newUser = {
                                id: Date.now().toString(),
                                email,
                                password: hashPassword(password),
                                name,
                                createdAt: new Date().toISOString()
                            };

                            const updatedUsers = [...users, newUser];
                            setState('storage.users', updatedUsers);

                            console.log('✅ Registration successful');
                            return { success: true };

                        } catch (error) {
                            setState('auth.error', error.message);
                            console.error('❌ Registration failed:', error.message);
                            return { success: false, error: error.message };
                        } finally {
                            setState('auth.loading', false);
                        }
                    },

                    logout: () => {
                        // Save current state before logout
                        context.headless.StatePersistenceManager.saveAllDomains();

                        setState('auth.user', null);
                        setState('auth.token', null);
                        setState('auth.isLoggedIn', false);

                        // Clear user-specific state
                        setState('ui.selectedListId', null);
                        setState('todos.lists', []);
                        setState('todos.items', {});
                        setState('todos.filter', 'all');

                        localStorage.removeItem('todo_auth_token');
                        localStorage.removeItem('todo_auth_user');

                        window.location.hash = '/login';
                        console.log('👋 Logged out');
                    }
                }
            };

            function checkExistingAuth() {
                const token = localStorage.getItem('todo_auth_token');
                const userStr = localStorage.getItem('todo_auth_user');

                if (token && userStr) {
                    try {
                        const user = JSON.parse(userStr);
                        setState('auth.user', user);
                        setState('auth.token', token);
                        setState('auth.isLoggedIn', true);
                        console.log('🔄 Restored authentication');

                        // Trigger user-specific data restore after auth restore
                        setTimeout(() => {
                            context.headless.StatePersistenceManager.restoreAllDomains();
                        }, 100);
                    } catch (error) {
                        console.error('❌ Failed to restore auth:', error);
                        localStorage.removeItem('todo_auth_token');
                        localStorage.removeItem('todo_auth_user');
                    }
                }
            }

            function hashPassword(password) {
                return CryptoJS.SHA256(password).toString();
            }

            function generateToken() {
                return CryptoJS.lib.WordArray.random(32).toString();
            }
        };

        // Enhanced Todo Manager
        const TodoManager = (props, context) => {
            const { getState, setState, subscribe } = context;

            return {
                hooks: {
                    onRegister: () => {
                        console.log('📝 TodoManager initializing...');
                        loadUserTodos();

                        // Subscribe to auth changes
                        subscribe('auth.user', (user) => {
                            if (user) {
                                loadUserTodos();
                            } else {
                                setState('todos', { lists: [], items: {}, filters: {} });
                                setState('ui.selectedListId', null);
                            }
                        });
                    }
                },

                api: {
                    createList: (name) => {
                        const user = getState('auth.user');
                        if (!user) return;

                        const newList = {
                            id: Date.now().toString(),
                            name,
                            userId: user.id,
                            createdAt: new Date().toISOString()
                        };

                        const lists = getState('todos.lists', []);
                        setState('todos.lists', [...lists, newList]);

                        // Auto-select the new list
                        setState('ui.selectedListId', newList.id);

                        saveTodos();
                        console.log('✅ List created:', name);
                    },

                    deleteList: (listId) => {
                        const lists = getState('todos.lists', []);
                        const items = getState('todos.items', {});

                        // Remove list
                        const updatedLists = lists.filter(list => list.id !== listId);
                        setState('todos.lists', updatedLists);

                        // Remove all items in this list
                        const updatedItems = { ...items };
                        delete updatedItems[listId];
                        setState('todos.items', updatedItems);

                        // Clear selection if this list was selected
                        const selectedId = getState('ui.selectedListId');
                        if (selectedId === listId) {
                            // Auto-select the first remaining list or null
                            const newSelectedId = updatedLists.length > 0 ? updatedLists[0].id : null;
                            setState('ui.selectedListId', newSelectedId);
                        }

                        saveTodos();
                        console.log('🗑️ List deleted:', listId);
                    },

                    createTodo: (listId, text) => {
                        const newTodo = {
                            id: Date.now().toString(),
                            text,
                            completed: false,
                            createdAt: new Date().toISOString()
                        };

                        const items = getState('todos.items', {});
                        const listItems = items[listId] || [];

                        setState(`todos.items.${listId}`, [...listItems, newTodo]);
                        saveTodos();
                        console.log('✅ Todo created:', text);
                    },

                    toggleTodo: (listId, todoId) => {
                        const items = getState(`todos.items.${listId}`, []);
                        const updatedItems = items.map(item =>
                            item.id === todoId ? { ...item, completed: !item.completed } : item
                        );

                        setState(`todos.items.${listId}`, updatedItems);
                        saveTodos();
                    },

                    deleteTodo: (listId, todoId) => {
                        const items = getState(`todos.items.${listId}`, []);
                        const updatedItems = items.filter(item => item.id !== todoId);

                        setState(`todos.items.${listId}`, updatedItems);
                        saveTodos();
                    },

                    setFilter: (filter) => {
                        setState('todos.filter', filter);
                    },

                    selectList: (listId) => {
                        setState('ui.selectedListId', listId);
                        console.log('📋 Selected list:', listId);
                    }
                }
            };

            function loadUserTodos() {
                const user = getState('auth.user');
                if (!user) return;

                const stored = localStorage.getItem(`todo_data_${user.id}`);
                if (stored) {
                    try {
                        const data = JSON.parse(stored);
                        setState('todos.lists', data.lists || []);
                        setState('todos.items', data.items || {});
                        console.log('📚 Todos loaded for user:', user.email);
                    } catch (error) {
                        console.error('❌ Failed to load todos:', error);
                    }
                }
            }

            function saveTodos() {
                const user = getState('auth.user');
                if (!user) return;

                const data = {
                    lists: getState('todos.lists', []),
                    items: getState('todos.items', {}),
                    lastSaved: new Date().toISOString()
                };

                localStorage.setItem(`todo_data_${user.id}`, JSON.stringify(data));
                console.log('💾 Todos saved');
            }
        };

        // ==================== UI COMPONENTS (with French translations) ====================

        // App Layout
        const AppLayout = (props, context) => {
            const { getState } = context;

            return {
                render: () => ({
                    div: {
                        className: 'app-container',
                        children: () => {
                            const isLoggedIn = getState('auth.isLoggedIn', false);
                            const currentPath = getState('url.path', '/');

                            if (!isLoggedIn && !['/login', '/register'].includes(currentPath)) {
                                return [{ AuthLayout: {} }];
                            }

                            if (['/login', '/register'].includes(currentPath)) {
                                return [{ AuthLayout: {} }];
                            }

                            return [
                                { AppHeader: {} },
                                { MainContent: {} }
                            ];
                        }
                    }
                })
            };
        };

        // App Header
        const AppHeader = (props, context) => {
            const { getState } = context;

            return {
                render: () => ({
                    header: {
                        className: 'header',
                        children: [{
                            div: {
                                className: 'header-content',
                                children: [
                                    {
                                        a: {
                                            className: 'logo',
                                            href: '#/',
                                            text: '📝 Todo App ',
                                            onclick: (e) => {
                                                e.preventDefault();
                                                window.location.hash = '/';
                                            }
                                        }
                                    },
                                    {
                                        nav: {
                                            className: 'nav',
                                            children: [
                                                {
                                                    a: {
                                                        className: () => {
                                                            const path = getState('url.path', '/');
                                                            return path === '/' ? 'nav-link active' : 'nav-link';
                                                        },
                                                        href: '#/',
                                                        text: 'Tableau de bord',
                                                        onclick: (e) => {
                                                            e.preventDefault();
                                                            window.location.hash = '/';
                                                        }
                                                    }
                                                },
                                                {
                                                    a: {
                                                        className: () => {
                                                            const path = getState('url.path', '/');
                                                            return path === '/profile' ? 'nav-link active' : 'nav-link';
                                                        },
                                                        href: '#/profile',
                                                        text: 'Profil',
                                                        onclick: (e) => {
                                                            e.preventDefault();
                                                            window.location.hash = '/profile';
                                                        }
                                                    }
                                                },
                                                {
                                                    button: {
                                                        className: 'btn btn-secondary btn-small',
                                                        text: 'Déconnexion',
                                                        onclick: () => context.headless.AuthManager.logout()
                                                    }
                                                }
                                            ]
                                        }
                                    }
                                ]
                            }
                        }]
                    }
                })
            };
        };

        // Auth Layout
        const AuthLayout = (props, context) => {
            const { getState } = context;

            return {
                render: () => ({
                    div: {
                        className: 'app-container',
                        children: [{
                            main: {
                                className: 'main-content',
                                children: () => {
                                    const path = getState('url.path', '/');

                                    if (path === '/register') {
                                        return [{ RegisterForm: {} }];
                                    }

                                    return [{ LoginForm: {} }];
                                }
                            }
                        }]
                    }
                })
            };
        };

        // Login Form
        const LoginForm = (props, context) => {
            const { getState, setState, headless } = context;

            return {
                render: () => ({
                    div: {
                        className: 'form-container fade-in',
                        children: [
                            {
                                h2: {
                                    className: 'form-title',
                                    text: 'Bon retour !'
                                }
                            },
                            {
                                form: {
                                    onsubmit: async (e) => {
                                        e.preventDefault();
                                        const email = getState('auth.form.email', '');
                                        const password = getState('auth.form.password', '');

                                        const result = await headless.AuthManager.login(email, password);
                                        if (result.success) {
                                            window.location.hash = '/';
                                        }
                                    },
                                    children: [
                                        {
                                            div: {
                                                className: 'form-group',
                                                children: [
                                                    {
                                                        label: {
                                                            className: 'form-label',
                                                            text: 'Email'
                                                        }
                                                    },
                                                    {
                                                        input: {
                                                            type: 'email',
                                                            className: 'form-input',
                                                            placeholder: 'Saisissez votre email',
                                                            value: () => getState('auth.form.email', ''),
                                                            oninput: (e) => setState('auth.form.email', e.target.value),
                                                            required: true
                                                        }
                                                    }
                                                ]
                                            }
                                        },
                                        {
                                            div: {
                                                className: 'form-group',
                                                children: [
                                                    {
                                                        label: {
                                                            className: 'form-label',
                                                            text: 'Mot de passe'
                                                        }
                                                    },
                                                    {
                                                        input: {
                                                            type: 'password',
                                                            className: 'form-input',
                                                            placeholder: 'Saisissez votre mot de passe',
                                                            value: () => getState('auth.form.password', ''),
                                                            oninput: (e) => setState('auth.form.password', e.target.value),
                                                            required: true
                                                        }
                                                    }
                                                ]
                                            }
                                        },
                                        {
                                            div: {
                                                className: () => getState('auth.error') ? 'form-error' : 'hidden',
                                                text: () => getState('auth.error', '')
                                            }
                                        },
                                        {
                                            button: {
                                                type: 'submit',
                                                className: 'btn btn-primary btn-full',
                                                disabled: () => getState('auth.loading', false),
                                                text: () => getState('auth.loading') ? 'Connexion...' : 'Se connecter'
                                            }
                                        },
                                        {
                                            div: {
                                                className: 'text-center mt-2',
                                                children: [
                                                    {
                                                        span: {
                                                            text: "Pas encore de compte ? "
                                                        }
                                                    },
                                                    {
                                                        a: {
                                                            href: '#/register',
                                                            text: 'Inscrivez-vous',
                                                            onclick: (e) => {
                                                                e.preventDefault();
                                                                window.location.hash = '/register';
                                                            }
                                                        }
                                                    }
                                                ]
                                            }
                                        }
                                    ]
                                }
                            }
                        ]
                    }
                })
            };
        };

        // Register Form
        const RegisterForm = (props, context) => {
            const { getState, setState, headless } = context;

            return {
                render: () => ({
                    div: {
                        className: 'form-container fade-in',
                        children: [
                            {
                                h2: {
                                    className: 'form-title',
                                    text: 'Créer un compte'
                                }
                            },
                            {
                                form: {
                                    onsubmit: async (e) => {
                                        e.preventDefault();
                                        const name = getState('auth.form.name', '');
                                        const email = getState('auth.form.email', '');
                                        const password = getState('auth.form.password', '');

                                        const result = await headless.AuthManager.register(email, password, name);
                                        if (result.success) {
                                            setState('auth.form', {});
                                            window.location.hash = '/login';
                                        }
                                    },
                                    children: [
                                        {
                                            div: {
                                                className: 'form-group',
                                                children: [
                                                    {
                                                        label: {
                                                            className: 'form-label',
                                                            text: 'Nom complet'
                                                        }
                                                    },
                                                    {
                                                        input: {
                                                            type: 'text',
                                                            className: 'form-input',
                                                            placeholder: 'Saisissez votre nom complet',
                                                            value: () => getState('auth.form.name', ''),
                                                            oninput: (e) => setState('auth.form.name', e.target.value),
                                                            required: true
                                                        }
                                                    }
                                                ]
                                            }
                                        },
                                        {
                                            div: {
                                                className: 'form-group',
                                                children: [
                                                    {
                                                        label: {
                                                            className: 'form-label',
                                                            text: 'Email'
                                                        }
                                                    },
                                                    {
                                                        input: {
                                                            type: 'email',
                                                            className: 'form-input',
                                                            placeholder: 'Saisissez votre email',
                                                            value: () => getState('auth.form.email', ''),
                                                            oninput: (e) => setState('auth.form.email', e.target.value),
                                                            required: true
                                                        }
                                                    }
                                                ]
                                            }
                                        },
                                        {
                                            div: {
                                                className: 'form-group',
                                                children: [
                                                    {
                                                        label: {
                                                            className: 'form-label',
                                                            text: 'Mot de passe'
                                                        }
                                                    },
                                                    {
                                                        input: {
                                                            type: 'password',
                                                            className: 'form-input',
                                                            placeholder: 'Créez un mot de passe',
                                                            value: () => getState('auth.form.password', ''),
                                                            oninput: (e) => setState('auth.form.password', e.target.value),
                                                            required: true
                                                        }
                                                    }
                                                ]
                                            }
                                        },
                                        {
                                            div: {
                                                className: () => getState('auth.error') ? 'form-error' : 'hidden',
                                                text: () => getState('auth.error', '')
                                            }
                                        },
                                        {
                                            button: {
                                                type: 'submit',
                                                className: 'btn btn-primary btn-full',
                                                disabled: () => getState('auth.loading', false),
                                                text: () => getState('auth.loading') ? 'Création du compte...' : 'Créer un compte'
                                            }
                                        },
                                        {
                                            div: {
                                                className: 'text-center mt-2',
                                                children: [
                                                    {
                                                        span: {
                                                            text: "Vous avez déjà un compte ? "
                                                        }
                                                    },
                                                    {
                                                        a: {
                                                            href: '#/login',
                                                            text: 'Connectez-vous',
                                                            onclick: (e) => {
                                                                e.preventDefault();
                                                                window.location.hash = '/login';
                                                            }
                                                        }
                                                    }
                                                ]
                                            }
                                        }
                                    ]
                                }
                            }
                        ]
                    }
                })
            };
        };

        // Main Content
        const MainContent = (props, context) => {
            const { getState } = context;

            return {
                render: () => ({
                    main: {
                        className: 'main-content',
                        children: () => {
                            const segments = getState('url.segments', { base: '' });

                            switch (segments.base) {
                                case '':
                                    return [{ TodoDashboard: {} }];
                                case 'lists':
                                    if (segments.sub) {
                                        return [{ TodoListDetail: { listId: segments.sub } }];
                                    }
                                    return [{ TodoDashboard: {} }];
                                case 'profile':
                                    return [{ UserProfile: {} }];
                                case 'settings':
                                    return [{ AppSettings: {} }];
                                default:
                                    return [{ NotFound: {} }];
                            }
                        }
                    }
                })
            };
        };

        // Todo Dashboard
        const TodoDashboard = (props, context) => {
            const { getState, setState, headless } = context;

            return {
                render: () => ({
                    div: {
                        className: 'todo-dashboard fade-in',
                        children: [
                            {
                                div: {
                                    className: 'todo-lists',
                                    children: [
                                        {
                                            div: {
                                                className: 'section-title',
                                                text: 'Vos listes de tâches'
                                            }
                                        },
                                        {
                                            div: {
                                                className: 'todo-form',
                                                children: [{
                                                    form: {
                                                        onsubmit: (e) => {
                                                            e.preventDefault();
                                                            const name = getState('ui.newListName', '').trim();
                                                            if (name) {
                                                                headless.TodoManager.createList(name);
                                                                setState('ui.newListName', '');
                                                            }
                                                        },
                                                        children: [{
                                                            div: {
                                                                className: 'todo-input',

                                                                children: [
                                                                    {
                                                                        input: {
                                                                            type: 'text',
                                                                            style: { flex: '0.75' },
                                                                            className: 'form-input',
                                                                            placeholder: 'Saisir le nom de la liste',
                                                                            value: () => getState('ui.newListName', ''),
                                                                            oninput: (e) => setState('ui.newListName', e.target.value)
                                                                        }
                                                                    },
                                                                    {
                                                                        button: {
                                                                          style: { flex: 0.25 },
                                                                            type: 'submit',
                                                                            className: 'btn btn-primary',
                                                                            text: 'Ajouter'
                                                                        }
                                                                    }
                                                                ]
                                                            }
                                                        }]
                                                    }
                                                }]
                                            }
                                        },
                                        {
                                            div: {
                                                children: () => {
                                                    const lists = getState('todos.lists', []);

                                                    if (lists.length === 0) {
                                                        return [{
                                                            div: {
                                                                className: 'empty-state',
                                                                children: [
                                                                    {
                                                                        h3: {
                                                                            text: 'Aucune liste pour le moment'
                                                                        }
                                                                    },
                                                                    {
                                                                        p: {
                                                                            text: 'Créez votre première liste de tâches pour commencer !'
                                                                        }
                                                                    }
                                                                ]
                                                            }
                                                        }];
                                                    }

                                                    return lists.map(list => ({
                                                        TodoListItem: { list, key: list.id }
                                                    }));
                                                }
                                            }
                                        }
                                    ]
                                }
                            },
                            {
                                div: {
                                    className: 'todo-list',
                                    children: () => {
                                        const selectedListId = getState('ui.selectedListId');
                                        const lists = getState('todos.lists', []);
                                        const selectedList = lists.find(l => l.id === selectedListId);

                                        if (!selectedList) {
                                            return [{
                                                div: {
                                                    className: 'empty-state',
                                                    children: [
                                                        {
                                                            h3: {
                                                                text: 'Sélectionnez une liste'
                                                            }
                                                        },
                                                        {
                                                            p: {
                                                                text: 'Choisissez une liste dans la barre latérale pour voir et gérer vos tâches.'
                                                            }
                                                        }
                                                    ]
                                                }
                                            }];
                                        }

                                        return [{ TodoListDetail: { listId: selectedListId } }];
                                    }
                                }
                            }
                        ]
                    }
                })
            };
        };

        // Todo List Item
        const TodoListItem = (props, context) => {
            const { getState, setState, headless } = context;
            const { list } = props;

            return {
                render: () => ({
                    div: {
                        className: () => {
                            const selectedId = getState('ui.selectedListId');
                            return selectedId === list.id ? 'list-item active' : 'list-item';
                        },
                        onclick: () => headless.TodoManager.selectList(list.id),
                        children: [
                            {
                                div: {
                                    className: 'list-info',
                                    children: [
                                        {
                                            div: {
                                                className: 'list-name',
                                                text: list.name
                                            }
                                        },
                                        {
                                            div: {
                                                className: 'list-count',
                                                text: () => {
                                                    const items = getState(`todos.items.${list.id}`, []);
                                                    const completed = items.filter(item => item.completed).length;
                                                    return `${completed}/${items.length} terminées`;
                                                }
                                            }
                                        }
                                    ]
                                }
                            },
                            {
                                div: {
                                    className: 'list-actions',
                                    children: [{
                                        button: {
                                            className: 'btn btn-danger btn-small',
                                            text: '🗑️',
                                            onclick: (e) => {
                                                e.stopPropagation();
                                                if (confirm(`Supprimer "${list.name}" ?`)) {
                                                    headless.TodoManager.deleteList(list.id);
                                                }
                                            }
                                        }
                                    }]
                                }
                            }
                        ]
                    }
                })
            };
        };

        // Todo List Detail
        const TodoListDetail = (props, context) => {
            const { getState, setState, headless } = context;
            const { listId } = props;

            return {
                render: () => ({
                    div: {
                        className: 'fade-in',
                        children: [
                            {
                                div: {
                                    className: 'section-title',
                                    text: () => {
                                        const lists = getState('todos.lists', []);
                                        const list = lists.find(l => l.id === listId);
                                        return list ? list.name : 'Liste de tâches';
                                    }
                                }
                            },
                            {
                                div: {
                                    className: 'todo-form',
                                    children: [{
                                        form: {
                                            onsubmit: (e) => {
                                                e.preventDefault();
                                                const text = getState('ui.newTodoText', '').trim();
                                                if (text) {
                                                    headless.TodoManager.createTodo(listId, text);
                                                    setState('ui.newTodoText', '');
                                                }
                                            },
                                            children: [{
                                                div: {
                                                    className: 'todo-input',
                                                    children: [
                                                        {
                                                            input: {
                                                                type: 'text',
                                                                className: 'form-input',
                                                                placeholder: 'Ajouter une nouvelle tâche...',
                                                                value: () => getState('ui.newTodoText', ''),
                                                                oninput: (e) => setState('ui.newTodoText', e.target.value)
                                                            }
                                                        },
                                                        {
                                                            button: {
                                                                type: 'submit',
                                                                className: 'btn btn-primary',
                                                                text: 'Ajouter'
                                                            }
                                                        }
                                                    ]
                                                }
                                            }]
                                        }
                                    }]
                                }
                            },
                            {
                                div: {
                                    className: 'filters',
                                    children: [
                                        {
                                            button: {
                                                className: () => {
                                                    const filter = getState('todos.filter', 'all');
                                                    return filter === 'all' ? 'filter-btn active' : 'filter-btn';
                                                },
                                                text: 'Toutes',
                                                onclick: () => headless.TodoManager.setFilter('all')
                                            }
                                        },
                                        {
                                            button: {
                                                className: () => {
                                                    const filter = getState('todos.filter', 'all');
                                                    return filter === 'active' ? 'filter-btn active' : 'filter-btn';
                                                },
                                                text: 'Actives',
                                                onclick: () => headless.TodoManager.setFilter('active')
                                            }
                                        },
                                        {
                                            button: {
                                                className: () => {
                                                    const filter = getState('todos.filter', 'all');
                                                    return filter === 'completed' ? 'filter-btn active' : 'filter-btn';
                                                },
                                                text: 'Terminées',
                                                onclick: () => headless.TodoManager.setFilter('completed')
                                            }
                                        }
                                    ]
                                }
                            },
                            {
                                div: {
                                    children: () => {
                                        const items = getState(`todos.items.${listId}`, []);
                                        const filter = getState('todos.filter', 'all');

                                        let filteredItems = items;
                                        if (filter === 'active') {
                                            filteredItems = items.filter(item => !item.completed);
                                        } else if (filter === 'completed') {
                                            filteredItems = items.filter(item => item.completed);
                                        }

                                        if (filteredItems.length === 0) {
                                            return [{
                                                div: {
                                                    className: 'empty-state',
                                                    children: [
                                                        {
                                                            h3: {
                                                                text: () => {
                                                                    const filter = getState('todos.filter', 'all');
                                                                    if (filter === 'active') return 'Aucune tâche active';
                                                                    if (filter === 'completed') return 'Aucune tâche terminée';
                                                                    return 'Aucune tâche pour le moment';
                                                                }
                                                            }
                                                        },
                                                        {
                                                            p: {
                                                                text: 'Ajoutez votre première tâche ci-dessus !'
                                                            }
                                                        }
                                                    ]
                                                }
                                            }];
                                        }

                                        return filteredItems.map(item => ({
                                            TodoItem: { listId, item, key: item.id }
                                        }));
                                    }
                                }
                            }
                        ]
                    }
                })
            };
        };

        // Todo Item
        const TodoItem = (props, context) => {
            const { headless } = context;
            const { listId, item } = props;

            return {
                render: () => ({
                    div: {
                        className: 'todo-item',
                        children: [
                            {
                                input: {
                                    type: 'checkbox',
                                    className: 'todo-checkbox',
                                    checked: item.completed,
                                    onchange: () => headless.TodoManager.toggleTodo(listId, item.id)
                                }
                            },
                            {
                                span: {
                                    className: item.completed ? 'todo-text completed' : 'todo-text',
                                    text: item.text
                                }
                            },
                            {
                                div: {
                                    className: 'todo-actions',
                                    children: [{
                                        button: {
                                            className: 'btn btn-danger btn-small',
                                            text: '🗑️',
                                            onclick: () => {
                                                if (confirm('Supprimer cette tâche ?')) {
                                                    headless.TodoManager.deleteTodo(listId, item.id);
                                                }
                                            }
                                        }
                                    }]
                                }
                            }
                        ]
                    }
                })
            };
        };

        // User Profile
        const UserProfile = (props, context) => {
            const { getState } = context;

            return {
                render: () => ({
                    div: {
                        className: 'fade-in',
                        children: [{
                            div: {
                                className: 'form-container',
                                children: [
                                    {
                                        h2: {
                                            className: 'form-title',
                                            text: 'Profil'
                                        }
                                    },
                                    {
                                        div: {
                                            className: 'form-group',
                                            children: [
                                                {
                                                    label: {
                                                        className: 'form-label',
                                                        text: 'Nom'
                                                    }
                                                },
                                                {
                                                    div: {
                                                        className: 'form-input',
                                                        style: {
                                                            background: 'var(--gray-100)',
                                                            border: 'none',
                                                            color: 'var(--gray-700)'
                                                        },
                                                        text: () => getState('auth.user.name', 'Non disponible')
                                                    }
                                                }
                                            ]
                                        }
                                    },
                                    {
                                        div: {
                                            className: 'form-group',
                                            children: [
                                                {
                                                    label: {
                                                        className: 'form-label',
                                                        text: 'Membre depuis'
                                                    }
                                                },
                                                {
                                                    div: {
                                                        className: 'form-input',
                                                        style: {
                                                            background: 'var(--gray-100)',
                                                            border: 'none',
                                                            color: 'var(--gray-700)'
                                                        },
                                                        text: () => {
                                                            const createdAt = getState('auth.user.createdAt');
                                                            return createdAt ? new Date(createdAt).toLocaleDateString() : 'Non disponible';
                                                        }
                                                    }
                                                }
                                            ]
                                        }
                                    },
                                    {
                                        div: {
                                            className: 'form-group',
                                            children: [
                                                {
                                                    label: {
                                                        className: 'form-label',
                                                        text: 'Statistiques'
                                                    }
                                                },
                                                {
                                                    div: {
                                                        style: {
                                                            background: 'var(--gray-50)',
                                                            padding: '1rem',
                                                            borderRadius: 'var(--border-radius)',
                                                            border: '1px solid var(--gray-200)'
                                                        },
                                                        children: [
                                                            {
                                                                div: {
                                                                    style: { marginBottom: '0.5rem' },
                                                                    children: [
                                                                        {
                                                                            span: {
                                                                                style: { fontWeight: '500' },
                                                                                text: 'Total des listes : '
                                                                            }
                                                                        },
                                                                        {
                                                                            span: {
                                                                                text: () => getState('todos.lists', []).length.toString()
                                                                            }
                                                                        }
                                                                    ]
                                                                }
                                                            },
                                                            {
                                                                div: {
                                                                    style: { marginBottom: '0.5rem' },
                                                                    children: [
                                                                        {
                                                                            span: {
                                                                                style: { fontWeight: '500' },
                                                                                text: 'Total des tâches : '
                                                                            }
                                                                        },
                                                                        {
                                                                            span: {
                                                                                text: () => {
                                                                                    const items = getState('todos.items', {});
                                                                                    const total = Object.values(items).reduce((sum, list) => sum + list.length, 0);
                                                                                    return total.toString();
                                                                                }
                                                                            }
                                                                        }
                                                                    ]
                                                                }
                                                            },
                                                            {
                                                                div: {
                                                                    children: [
                                                                        {
                                                                            span: {
                                                                                style: { fontWeight: '500' },
                                                                                text: 'Terminées : '
                                                                            }
                                                                        },
                                                                        {
                                                                            span: {
                                                                                text: () => {
                                                                                    const items = getState('todos.items', {});
                                                                                    const completed = Object.values(items)
                                                                                        .flat()
                                                                                        .filter(item => item.completed).length;
                                                                                    return completed.toString();
                                                                                }
                                                                            }
                                                                        }
                                                                    ]
                                                                }
                                                            }
                                                        ]
                                                    }
                                                }
                                            ]
                                        }
                                    }
                                ]
                            }
                        }]
                    }
                })
            };
        };

        // App Settings
        const AppSettings = (props, context) => {
            const { getState, setState, headless } = context;

            return {
                render: () => ({
                    div: {
                        className: 'fade-in',
                        children: [{
                            div: {
                                className: 'form-container',
                                children: [
                                    {
                                        h2: {
                                            className: 'form-title',
                                            text: 'Paramètres'
                                        }
                                    },
                                    {
                                        div: {
                                            className: 'form-group',
                                            children: [
                                                {
                                                    label: {
                                                        className: 'form-label',
                                                        text: 'Filtre par défaut'
                                                    }
                                                },
                                                {
                                                    select: {
                                                        className: 'form-input',
                                                        value: () => getState('settings.defaultFilter', 'all'),
                                                        onchange: (e) => setState('settings.defaultFilter', e.target.value),
                                                        children: [
                                                            {
                                                                option: {
                                                                    value: 'all',
                                                                    text: 'Toutes les tâches'
                                                                }
                                                            },
                                                            {
                                                                option: {
                                                                    value: 'active',
                                                                    text: 'Tâches actives'
                                                                }
                                                            },
                                                            {
                                                                option: {
                                                                    value: 'completed',
                                                                    text: 'Tâches terminées'
                                                                }
                                                            }
                                                        ]
                                                    }
                                                }
                                            ]
                                        }
                                    },
                                    {
                                        div: {
                                            className: 'form-group',
                                            children: [
                                                {
                                                    label: {
                                                        className: 'form-label',
                                                        children: [
                                                            {
                                                                input: {
                                                                    type: 'checkbox',
                                                                    checked: () => getState('settings.autoSave', true),
                                                                    onchange: (e) => setState('settings.autoSave', e.target.checked),
                                                                    style: { marginRight: '0.5rem' }
                                                                }
                                                            },
                                                            {
                                                                span: {
                                                                    text: 'Sauvegarde automatique'
                                                                }
                                                            }
                                                        ]
                                                    }
                                                }
                                            ]
                                        }
                                    },
                                    {
                                        div: {
                                            className: 'form-group',
                                            children: [
                                                {
                                                    label: {
                                                        className: 'form-label',
                                                        text: 'Statistiques de Persistance'
                                                    }
                                                },
                                                {
                                                    div: {
                                                        style: {
                                                            background: 'var(--gray-50)',
                                                            padding: '1rem',
                                                            borderRadius: 'var(--border-radius)',
                                                            border: '1px solid var(--gray-200)'
                                                        },
                                                        children: () => {
                                                            const stats = getState('persistence.stats', {});
                                                            return [
                                                                {
                                                                    div: {
                                                                        style: { marginBottom: '0.5rem' },
                                                                        children: [
                                                                            {
                                                                                span: {
                                                                                    style: { fontWeight: '500' },
                                                                                    text: 'Domaines Suivis : '
                                                                                }
                                                                            },
                                                                            {
                                                                                span: {
                                                                                    text: (stats.domainsTracked || 0).toString()
                                                                                }
                                                                            }
                                                                        ]
                                                                    }
                                                                },
                                                                {
                                                                    div: {
                                                                        style: { marginBottom: '0.5rem' },
                                                                        children: [
                                                                            {
                                                                                span: {
                                                                                    style: { fontWeight: '500' },
                                                                                    text: 'Total Sauvegardes : '
                                                                                }
                                                                            },
                                                                            {
                                                                                span: {
                                                                                    text: (stats.totalSaves || 0).toString()
                                                                                }
                                                                            }
                                                                        ]
                                                                    }
                                                                },
                                                                {
                                                                    div: {
                                                                        children: [
                                                                            {
                                                                                span: {
                                                                                    style: { fontWeight: '500' },
                                                                                    text: 'Total Restaurations : '
                                                                                }
                                                                            },
                                                                            {
                                                                                span: {
                                                                                    text: (stats.totalRestores || 0).toString()
                                                                                }
                                                                            }
                                                                        ]
                                                                    }
                                                                }
                                                            ];
                                                        }
                                                    }
                                                }
                                            ]
                                        }
                                    },
                                    {
                                        div: {
                                            className: 'form-group',
                                            children: [
                                                {
                                                    button: {
                                                        className: 'btn btn-secondary btn-full',
                                                        style: { marginBottom: '0.5rem' },
                                                        text: 'Exporter toutes les données',
                                                        onclick: () => {
                                                            try {
                                                                const exportData = headless.StatePersistenceManager.exportState();
                                                                const blob = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' });
                                                                const url = URL.createObjectURL(blob);
                                                                const a = document.createElement('a');
                                                                a.href = url;
                                                                a.download = `todo-app-sauvegarde-${new Date().toISOString().split('T')[0]}.json`;
                                                                document.body.appendChild(a);
                                                                a.click();
                                                                document.body.removeChild(a);
                                                                URL.revokeObjectURL(url);
                                                                alert('Données exportées avec succès !');
                                                            } catch (error) {
                                                                alert("L'exportation a échoué : " + error.message);
                                                            }
                                                        }
                                                    }
                                                }
                                            ]
                                        }
                                    },
                                    {
                                        div: {
                                            className: 'form-group',
                                            children: [
                                                {
                                                    button: {
                                                        className: 'btn btn-danger btn-full',
                                                        text: 'Effacer toutes les données',
                                                        onclick: () => {
                                                            if (confirm('Ceci supprimera toutes vos listes et données. Cette action est irréversible. Êtes-vous sûr(e) ?')) {
                                                                const user = getState('auth.user');
                                                                if (user) {
                                                                    // Clear old todo data
                                                                    localStorage.removeItem(`todo_data_${user.id}`);

                                                                    // Clear new persistence data
                                                                    headless.StatePersistenceManager.clearAllStorage();

                                                                    // Reset state
                                                                    setState('todos.lists', []);
                                                                    setState('todos.items', {});
                                                                    setState('ui.selectedListId', null);

                                                                    alert('Toutes les données ont été effacées.');
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            ]
                                        }
                                    }
                                ]
                            }
                        }]
                    }
                })
            };
        };

        // Not Found Page
        const NotFound = (props, context) => {
            return {
                render: () => ({
                    div: {
                        className: 'empty-state fade-in',
                        children: [
                            {
                                h3: {
                                    text: '404 - Page non trouvée'
                                }
                            },
                            {
                                p: {
                                    text: "La page que vous cherchez n'existe pas."
                                }
                            },
                            {
                                a: {
                                    href: '#/',
                                    className: 'btn btn-primary',
                                    text: 'Aller au Tableau de bord',
                                    onclick: (e) => {
                                        e.preventDefault();
                                        window.location.hash = '/';
                                    }
                                }
                            }
                        ]
                    }
                })
            };
        };

        // ==================== APPLICATION INITIALIZATION ====================

        const juris = new Juris({
            components: {
                AppLayout,
                AppHeader,
                AuthLayout,
                LoginForm,
                RegisterForm,
                MainContent,
                TodoDashboard,
                TodoListItem,
                TodoListDetail,
                TodoItem,
                UserProfile,
                AppSettings,
                NotFound
            },

            headlessComponents: {
                AuthManager: { fn: AuthManager, options: { autoInit: true } },
                UrlStateSync: { fn: UrlStateSync, options: { autoInit: true } },
                TodoManager: { fn: TodoManager, options: { autoInit: true } },
                StatePersistenceManager: {
                    fn: StatePersistenceManager,
                    options: {
                        autoInit: true,
                        debug: true, // Enable debug logging
                        domains: ['ui', 'todos', 'settings', 'storage'], // Specify domains to track
                        priorityDomains: ['ui'], // UI gets priority restore for selected list
                        immediateSave: ['ui'], // Save UI changes immediately (like selected list)
                        criticalSave: ['todos'], // Save todos with faster debounce
                        aggressiveRestore: true, // Restore immediately on startup
                        keyPrefix: 'todo_app_state_',
                        // User-specific domains will have user ID appended automatically
                        domainRestoreConfig: {
                            ui: { priority: 1, delay: 0, aggressive: true }, // Restore selected list first
                            todos: { priority: 2, delay: 0, aggressive: true },
                            settings: { priority: 3, delay: 100, aggressive: false },
                            storage: { priority: 4, delay: 200, aggressive: false }
                        }
                    }
                }
            },

            layout: {
                div: {
                    children: [{ AppLayout: {} }]
                }
            },

            states: {
                url: {
                    path: '/',
                    segments: { full: '/', parts: [], base: '', sub: '', id: '' }
                },
                auth: {
                    user: null,
                    token: null,
                    isLoggedIn: false,
                    loading: false,
                    error: null,
                    form: {}
                },
                todos: {
                    lists: [],
                    items: {},
                    filter: 'all'
                },
                ui: {
                    selectedListId: '', // This will now be persisted!
                    newListName: '',
                    newTodoText: ''
                },
                storage: {
                    users: [],
                    settings: {}
                },
                settings: {
                    defaultFilter: 'all',
                    autoSave: true
                }
            }
        });

        // Start the application
        juris.render('#app');

        // Auto-navigate to login if no hash
        if (!window.location.hash) {
            // Don't force login redirect, let auth check handle it
        }

        // Global access for debugging
        window.juris = juris;

        console.log('🚀 Todo App est prête !');
        console.log('📱 Routes disponibles :');
        console.log('  - #/login (public)');
        console.log('  - #/register (public)');
        console.log('  - #/ (protégé - tableau de bord)');
        console.log('  - #/profile (protégé)');
        console.log('  - #/settings (protégé)');
        console.log('💾 Les données persistent dans localStorage');
        console.log('🔐 Authentification avec gardes de route');
        console.log('🧭 Routage basé sur l\'état');
    </script>
</body>

</html>
Enter fullscreen mode Exit fullscreen mode

Top comments (0)