Overview
Estudo Organizado uses a centralized global state pattern similar to Redux, but implemented in pure Vanilla JavaScript. All application data lives in a singlestate object managed by store.js.
The state object is the single source of truth for all application data.
The State Object
The global state is defined insrc/js/store.js:36:
src/js/store.js
State Schema Breakdown
ciclo - Study Cycle Configuration
ciclo - Study Cycle Configuration
Manages the active study cycle with rotating subjects:
ativo: Boolean indicating if cycle is enabledciclosCompletos: Counter for completed cyclesdisciplinas: Array of subjects with time allocations
planejamento - Study Planning System
planejamento - Study Planning System
Advanced study planning with automated scheduling:
ativo: Whether planning is activetipo: Planning type (relevance-based, time-based, etc.)disciplinas: Selected subjects for planningrelevancia: Subject relevance scoreshorarios: Time slot allocationssequencia: Study sequence order
editais - Exam Syllabi
editais - Exam Syllabi
Array of exam syllabi (editais), each containing:
id: Unique identifiernome: Exam namecor: Color code for UIdisciplinas: Array of subjects with topics and lessons
eventos - Study Events
eventos - Study Events
All study sessions (scheduled, in-progress, completed, or late):
id: Event IDtitulo: Event titledata: Scheduled datestatus: ‘agendado’, ‘estudando’, ‘concluido’, ‘atrasado’tempoEstudado: Minutes studied_timerStart: Timestamp when timer started (transient)
arquivo - Archived Events
arquivo - Archived Events
Events older than 90 days that have been archived for performance.
habitos - Study Habits Tracking
habitos - Study Habits Tracking
Daily habit logs categorized by type:
questoes: Practice questionsrevisao: Review sessionsdiscursiva: Essay practicesimulado: Mock examsleitura: Readinginformativo: News/updatessumula: Legal summariesvideoaula: Video lessons
revisoes - Spaced Repetition
revisoes - Spaced Repetition
Review items scheduled according to spaced repetition intervals.
config - User Configuration
config - User Configuration
visualizacao: Calendar view mode (‘mes’, ‘semana’)primeirodiaSemana: First day of week (0=Sunday, 1=Monday)frequenciaRevisao: Spaced repetition intervals in days [1, 7, 30, 90]tema: Theme (‘light’, ‘dark’, ‘matrix’, etc.)dataProva: Exam date for countdownmetas: Weekly goals (hours, questions)
bancaRelevance - Exam Board Intelligence
bancaRelevance - Exam Board Intelligence
Machine learning data for exam board analysis:
hotTopics: Most frequent topics from past examsuserMappings: User corrections to auto-matchinglessonMappings: Lesson-to-topic relationships
State Mutations with setState()
All state changes go through thesetState() function (store.js:14):
src/js/store.js
setState() ensures all required properties exist with proper defaults, preventing undefined errors.Why Mutate Instead of Replace?
Notice the critical pattern at the end:- Other modules import
stateas a reference - Replacing the reference would break those imports
- Mutating preserves reactivity across modules
Scheduled Persistence with scheduleSave()
To prevent excessive writes to IndexedDB, state changes are debounced usingscheduleSave() (store.js:182):
src/js/store.js
The Save Flow
- User modifies data (e.g., completes a study session)
- Module calls
scheduleSave() - Timer starts (or resets if already running)
- After 2 seconds of inactivity, data is persisted
- UI updates immediately via events (optimistic updates)
The 2-second debounce prevents database thrashing during rapid user interactions like typing or dragging.
Immediate Persistence with saveStateToDB()
For critical operations (app close, manual sync), usesaveStateToDB() directly (store.js:195):
src/js/store.js
Sync Cascade
After successful local save:- Dispatch
stateSavedevent - If Cloudflare sync enabled, queue cloud push
- Cloud push happens asynchronously via
SyncQueue
The SyncQueue Pattern
To prevent concurrent sync operations, a queue ensures sequential execution (store.js:151):
src/js/store.js
- No race conditions between sync operations
- Ordered execution of cloud pushes
- Error isolation (one failure doesn’t block queue)
Reactive Updates with Events
Modules communicate state changes via custom events:Example: Adding a Study Event
Here’s how a typical state mutation flows:This pattern keeps components decoupled - the function doesn’t need to know about the UI, only state and events.
State Clearing
To reset the app (used by “Clear All Data” in settings):src/js/store.js
Best Practices
- Always use
scheduleSave()after mutations (unless immediate save required) - Import state as reference, never reassign:
import { state } from './store.js' - Dispatch events for cross-module communication
- Use
setState()for bulk updates or initialization - Validate data before mutating state
- Keep business logic separate from state mutations