Architecture Blueprint · v2.1 · live in production

A system that holds four years of grad school.

Every module, every data shape, every safety layer, every design decision, and an honest audit of what's still off. This is the technical truth of Study OS as it exists today — live at uxdesignlab.us.

Owner
Nabil Rouissi
Degree
IIT MDes + MPA · Fall 2026
Version
2.1 · Apr 27 2026
Modules
14 live
File size
408 KB index
Status
Live · SW v1.1.6
01
Overview

Four layers. One truth.

The system separates concerns so each layer has one job. When one fails, the others hold.

Layer 01 · UI
The App

Single-page web app. 13 modules, hash-routed. Origin v2 design language with warm paper cards on cool canvas. Installable as PWA on iPhone.

File: index.html

Layer 02 · Data
The Vault

9 JSON files in School/StudyOS/data/. localStorage is a cache, vault is the source of truth. File System Access API writes every change.

Persistence: IndexedDB for directory handle, vault for data.

Layer 03 · AI
The Claude Bridge

Two paths: web paste-round-trip (universal) and Cowork study-intake skill (desktop fast-path). Strict JSON schemas for every prompt.

Flows: Intake · Weekly · Layla · Flashcard gen · Exam plan · Annotation.

Layer 04 · Safety
The Net

Three layers prevent data loss: auto-sync to vault, backup nudge when sync is off, version history with undo stack for every destructive action.

New in v2.

14
Live modules
9
JSON schema files
7,885
Lines of code
217
JS functions
29
Media query breakpoints
0
External JS deps at runtime

The app loads PDF.js and Tesseract.js lazily on-demand (only when needed for Intake). Fonts via Google Fonts CDN. Otherwise 100% vanilla.

02
Module Map · 13 live

Every view and what it's for.

01
Dashboard
Command Center
Anchor + Pomodoro instrument · unified Timechart (days + months) · Vital Signs (5 tiles with per-metric viz) · Program Balance · Quick Tools dock · 3-column queues · Mind (intention + prompts).
anchortimechartvital-signsmotion
02
Intake
AI Capture
Drop zone (PDF · image · text · MD). PDF.js extraction. Tesseract.js OCR (lazy-loaded). Memo loader. Generate structured prompt. Paste JSON back · merge with diff preview.
pdf.jstesseractround-trip
03
Overwhelm Protocol
Crisis Rescue
6-step flow with breathing banner. Data-aware: reads actual pending items, auto-triages by due-today / soon / overdue, suggests smallest next action with one-click "send to focus."
adhddata-driven
04
Readings
Knowledge Queue
Filterable queue by program / status. Annotation modal (summary · concepts · connections · quote). Auto-flashcard generator from annotation context.
queueannotationsauto-cards
05
Assignments
Task Tracker
Urgency tiers + due dates + program tags + course link. Auto grade modal on completion. Drives the Agenda preview, Radar dots, Vital Signs Tasks-Pending tile.
deadlinesgradescourse-link
06
Writing
Authoring
Full writing workspace: outline + draft textareas · live word count · auto-save 500ms · 8 Layla coach shortcuts with project-aware prompts.
workspacelaylaautosave
07
Planner
Weekly Generator
4 input tiles → Claude-generated 7-day schedule → preview → accept. Color-coded calendar with day pulse strips. Legend below.
generatorcalendarlegend
08
Flashcards
Drill
3D flip cards. Program filters. Paste-from-Claude import. Keyboard shortcuts (space / ← / →). Cards source-tagged to readings.
spaced-revkeyboard
09
Exam Prep
Countdown + Plan
Pick any upcoming deliverable → adaptive phase plan (14d / 7-14d / 3-6d / 1-2d / 0d) · live countdown · filtered flashcards + readings for the target.
countdownprogressive
10
Progress
Evidence + Daily Bridge
Daily stats · streak · session log with quality tags · Daily Note bridge (auto markdown summary for Obsidian Daily Notes).
streakbridge
11
Courses
Structure
Full course records (code · name · program · professor · schedule · grading · syllabus URL). Running average grade per course. Assignments / readings / writing link by courseId.
gradesstructuretranscript
12
Concept Map
Knowledge Graph
Force-directed SVG graph of concepts from reading annotations. Nodes sized by frequency. Edges = co-occurrence. Click node → readings + related concepts + flashcards touching it.
svgforce-simvanilla
13
IIT Guide
Reference
Origin v1 standalone course guide for IIT MDes + MPA, embedded as iframe inside Study OS so it stays one tap away. Pop-out via Open ↗ button.
referenceiframev1
14
Settings
System
Vault Auto-Sync toggle. Manual export / import. Version History (last 20 snapshots). Semester config. About panel.
synchistoryimport
03
Data Layer

Vault as truth. localStorage as cache.

Every state mutation triggers two writes: immediate to localStorage (cache), debounced 1.2s to the vault JSON files (truth). Vault survives browser wipes, travels via Obsidian Sync / iCloud Drive, and is readable by any tool that speaks JSON.

File
Contents
Shape
assignments.json
Every assignment with courseId link, status, grade, weight, feedback, source tag
items: Assignment[]
readings.json
Reading queue with summary, concepts[], connections, quote, annotatedAt
items: Reading[]
writing.json
Writing projects with outline, draft, wordCount, grade, lastEdited
items: WritingProject[]
flashcards.json
Cards with sourceReadingId link, status (todo · done · review)
items: Card[]
sessions.json
Every Pomodoro: duration, mode, focus text, quality rating, linkedItem
items: Session[]
intentions.json
Weekly intention text + ISO week tag
week, text
milestones.json
Fixed semester dates (orientation, finals, breaks)
items: Milestone[]
schedule.json
Accepted weekly Pomodoro blocks with date, time, task, rationale
items: Block[]
settings.json
startDate, semester, autoSync config, lastSyncAt, focus state, theme
Object

Not in vault: Version history (stored inside the state object itself for portability). Interruption buffer items (cleared at session end). Tesseract language models (cached in browser).

State shape · top-level keys of the single S object

S = { version: "1.0.0", settings: { startDate, semester, autoSyncEnabled, vaultDirName, lastSyncAt, lastExportAt, backupNudgeDismissedAt, pomoFocus, pomoBreak, ... }, focus: { text, program, urgency, date, linkedItem }, intention: string, intentionWeek: "2026-W17", assignments: Assignment[], readings: Reading[], writing: WritingProject[], flashcards: Card[], sessions: Session[], milestones: Milestone[], schedule: Block[], courses: Course[], interruptions: Interruption[], weeklyReviews: Review[], history: Snapshot[20], examPrepRef: "type:id" | null, protocol: { step, done }, lastUsed: ISO }
04
Intake Pipeline

Anything in, structure out.

01
Drop
Drag PDFs, images, text files. Or click Load Note for .md / .txt. Or paste text directly.
02
Extract
PDFs → PDF.js text extraction. Images → Tesseract.js OCR (lazy-loaded, ~2MB). Text files → direct read.
text = await extract(files) // PDF → pdfjsLib.getDocument().getTextContent() // PNG → Tesseract.recognize(blob) // TXT → file.text()
03
Prompt
App builds a structured prompt with current state + existing courses + extracted text. Category decision rules embedded. Strict JSON schema in response spec.
04
Round-trip
Copy Prompt → paste Claude → JSON response → paste back. Or (desktop) use the Cowork study-intake skill for one-click execution.
05
Parse + merge
5 category arrays merged into state: assignments, readings, writing, milestones, flashcards. Automatic snapshot before apply so ⌘Z undoes if wrong.
06
Toast · breakdown
Shows per-category count: "Applied · 3 assignments · 2 readings · 1 writing · 1 milestone."
05
Weekly Generator

Sunday planning · one button.

Inputs · what feeds the prompt
Your week, packaged

Deadlines — assignments + writing due next 14 days, sorted by proximity, with urgency tags.

Reading queue — top 15 active readings with hours estimate.

Writing projects — active with status + due date.

Weekly intention — current text.

Focus pattern — aggregated Pomodoro minutes per day-of-week from last 80 sessions. Surfaces your peak focus days.

Output · what comes back
A 7-day schedule

Blocks per day with date, time, duration, task, program, rationale.

Rules baked in: max 4h focus/day · no 3-in-a-row without break · Sunday light · demanding work on peak days · 25m standard / 45m deep.

Overflow warnings for anything that couldn't fit.

Strategy note — 1-2 sentences of overall approach.

Preview → Accept flow

The preview shows the full schedule grouped by day, with program-colored left borders and rationale lines. Accept writes to S.schedule (auto-snapshot first). This Week view populates with target-icon click-to-focus buttons. Calendar cells update with colored block chips.

06
Safety Layers

Three ways the system refuses to lose your data.

Layer 1
Vault Auto-Sync

File System Access API. Grant once, writes every change within 1.2s debounce.

Chrome · Edge · Opera. HTTPS or localhost required.

Directory handle persisted via IndexedDB, auto-resumes across sessions.

Layer 2
Backup Nudge

For Safari / Firefox or when sync is off: escalating banner on Dashboard.

7d: gentle gray · 14d: amber caution · 30d: urgent red pulsing.

One-click Export All when ready.

Layer 3
Version History

Auto-snapshots before every destructive action (reset · weekly accept · intake apply · import · vault import · course delete).

Rolling last 20. Restore any with one click. ⌘Z undoes the most recent.

07
Signal Collection

What the system learns from you.

Every Pomodoro you run, every item you complete, every thought you capture becomes data that feeds back into the system. Over weeks, the system knows your patterns.

Session quality
🎯 · 🟡 · 🔴

After every focus session, 3-button rating. Feeds Weekly Generator (demanding work on high-quality hours), Overwhelm Protocol (burnout detection), Friday Review (trend bar).

Focus pattern
Day-of-week aggregation

Rolling sum of focus minutes per day-of-week from last 80 sessions. Reveals whether you're a Tuesday-morning person or a Friday-night crammer. Weekly Generator places demanding work on high-density days.

Interruption buffer
Stray thoughts captured

During Pomodoro, a floating field captures distractions without breaking focus. At session end, thoughts route to Intake as pending items.

Friday Review carry
Week-to-week continuity

Answering "what carries into next week" saves to next week's Intention and feeds the next Weekly Generator run. Creates a compounding reflection loop.

08
Design Tokens

Origin v2 hybrid · warm paper on cool canvas.

Typography is strictly Origin v2 (Space Grotesk + Space Mono). Background is cool off-white (#FBFAF7). Card surfaces are warm cream paper (#F4ECD9) for contrast. Program coding is red / indigo / green inherited from IIT Course Guide lineage.

canvas
#FBFAF7
paper
#F4ECD9
ink
#1A1714
red · MDes
#D91E18
indigo · MPA
#4A4A9A
green · AI
#5A8A5A
amber · caution
#B89020
g6 · borders
#E5E5E5

Terminal aesthetic layer

Pomodoro instrument panel uses a dark (#0A0A0A) inset with ticks, orbit dot, crosshair reticle, blinking colon, block-char progress bar, terminal status line with cursor. Explicit inspiration: mission-control panels + oscilloscopes + mechanical clock faces.

Motion tokens

--ease-out · cubic-bezier(.22,.61,.36,1) for exits and resolutions. --ease-spring · cubic-bezier(.16,1,.3,1) for entries and actions. Durations: --dur-fast (150ms) for hovers, --dur-med (350ms) for state changes, --dur-slow (550ms) for view transitions. Respects prefers-reduced-motion.

09
Keyboard Layer

Move without clicking.

Command palette
⌘K

Opens anywhere. Indexes every view, every action, every assignment / reading / writing / course. Fuzzy-scored, keyboard-first (↑↓ / enter / esc).

g-prefix navigation
g letter

Gmail-style two-stroke jumps. Tap g, see hint banner with valid second keys, tap letter to jump: d · i · p · r · a · w · l · f · e · c · m · s.

Global actions
⌘↵ · ⌘Z · ⌘⇧F · ?

Start/pause Pomodoro from anywhere · Undo last big change · Set Focus · Show shortcuts help.

Module shortcuts
Flashcards

Space / F to flip · → / G for "got it" · ← / R for "needs review." Only active on Flashcards view.

10
PWA · iPhone-ready

Installable. Offline. Full-screen.

manifest.json
Install manifest

name · short_name · icons (180 · 192 · 512) · start_url · scope · display:standalone · theme_color #0A0A0A. Shortcuts: Set Focus · Intake · Overwhelm (long-press iPhone icon to use).

service-worker.js
Offline caching

Precaches app shell on install. Navigation requests: network-first + cached fallback. Same-origin assets: cache-first. Google Fonts / cdnjs: stale-while-revalidate.

icons
Red corner brackets + cursor

SVG master (512×512) + PNG 180 / 192 / 512 generated via cairosvg. iPhone uses 180×180 apple-touch-icon.

11
Honest audit · v2.0

What's off, what's weak, what's missing.

This system has been built iteratively over one session. It's structurally complete, but honesty matters — here's the real state.

Critical

Critical · untested
Zero real-world usage
Every feature is code-complete but no actual syllabus has been round-tripped, no real Pomodoro has been run end-to-end, no real Friday Review has been generated. Expect 5-15 small bugs to surface in the first two weeks of actual use. Mitigation: test before deploy.
Critical · platform
Not yet deployed
T19 is the only pending task. Without deploy, no iPhone install, no cross-device, no Netlify HTTPS. PWA features (service worker, FSA API) require HTTPS or localhost — running from file:// disables them. Mitigation: deploy to study.nabilrouissi.com.
Critical · stale
Cowork SKILL.md is slightly out of date
The study-intake SKILL.md was written before Courses module existed. It doesn't mention courseId linking and doesn't know about the latest intake writing vs. assignment rules. Mitigation: update the skill file.

Medium

Medium · performance
Single-file ~400KB
index.html is ~400KB uncompressed, ~80KB gzipped. Acceptable for desktop but slow on cellular iPhone on first visit. Mitigation: service worker caches on first load → subsequent loads instant. Future: split CSS and JS into separate files for HTTP/2 multiplexing.
Medium · silent failure
No global error boundary
If any render function throws (bad data, browser API missing), the view silently breaks with a blank section. The user has no indication anything failed. Mitigation: wrap render functions in try/catch with a visible error toast.
Medium · first-use
No onboarding
A first-time user opens the app to a nearly-empty Dashboard with no guidance on what to do first. The GUIDE exists but the app doesn't walk through it. Mitigation: first-launch detection + a 3-step wizard (enable sync · add term date · add first course).
Medium · daily notes
Daily Note bridge writes to StudyOS/daily-notes/ not vault-root Daily/
FSA API can only write inside the granted directory (StudyOS/). Real Daily Notes live at vault root. User must symlink or manually move files. Mitigation: add a second directory grant for the Daily folder, or provide a bash script that symlinks.
Medium · concept map
Force sim may bog down at 100+ nodes
O(n²) repulsion in tickMap(). Untested above ~30 concepts. At 100+ nodes, each tick is 10,000 pair comparisons. Mitigation: Barnes-Hut optimization when node count exceeds 50.
Medium · mobile
Writing workspace cramped on iPhone
The 2-column outline + draft layout collapses to single-column on mobile, which works but the textareas are small. Writing on a phone isn't the primary use case but should be acceptable. Mitigation: tested needed.

Minor

Minor · dead code
Legacy .sem CSS + renderSemTimeline unused
Kept for safety during the timechart merge but no longer referenced. Can be deleted on cleanup pass.
Minor · first-week UX
Weekly Generator has no focus-pattern data week 1
The pattern needs ~2 weeks of sessions to be useful. First-time generator runs without it and says "no history yet." Mitigation: seed with reasonable defaults for first 2 weeks.
Minor · search
No flashcard search
Command Palette doesn't index individual flashcards (would be noisy). Flashcards module has no filter by text. Acceptable for now — cards are organized by program and source reading.
Minor · bulk ops
No multi-select
Can't bulk-delete 5 assignments or bulk-tag 10 readings. One-by-one only. Low priority but noteworthy.
Serious · accessibility
Partial WCAG 2.1 AA conformance — 62/100
Per the full a11y audit (Apr 27): 1 critical, 6 serious, 7 moderate, 4 minor. Top issue: 11 click-only divs (Pomodoro ring, Anchor card, Intake drop, Overwhelm steps) are unreachable by keyboard. Dark-mode g2/g3 text contrast 1.31:1–2.47:1. Modal/toast missing role=dialog and aria-live. Quick wins lift the score 62 → 88 in ~90 minutes.
Minor · interop
No Anki export for flashcards
Cards are locked in Study OS JSON format. Users can't easily export to Anki or other SRS tools. Low priority since Study OS is the primary drill tool, but lock-in risk noted.

Working well

Ok · tight
Dashboard hierarchy + unified timechart
Anchor → Time (days + months) → Vital Signs → Balance → Tools → Queues → Mind reads cleanly. Information density per scroll inch is high without feeling cluttered. Time zoom from days to months is visually coherent.
Ok · safety
Three-layer data protection
Auto-sync + backup nudge + version history create genuinely robust data protection. Accidental reset is recoverable. Browser wipe is recoverable. Brain fart is recoverable.
Ok · keyboard
Command palette + g-prefix
⌘K plus gd/gi/gp/gr covers 90% of navigation. Fuzzy search finds anything. This is the fastest UI in the app once learned.
Ok · philosophy
Signal collection is real
Session quality · focus pattern · interruptions · Friday Review carry · reading annotations · grades — the system is genuinely collecting compounding signal that will make year 2 materially better than year 1.
12
Roadmap

Where we are · where we're going.

Phase 1-7 · foundation
Shipped
Core system + integrations + compounding
Single-page shell, 13 modules, unified data layer, Intake with PDF + OCR, Weekly Routine Generator, Cowork skill, PWA manifest + SW + icons, all T1-T18 improvements.
T1 · vault auto-sync
T2 · backup nudge
T3 · version history
T4 · vault folder import
T5 · session quality
T6 · interruption buffer
T7 · ambient focus
T8 · daily note bridge
T9 · friday review
T10 · smart overwhelm
T11 · reading annotations
T12 · writing workspace
T13 · courses module
T14 · grade tracking
T15 · exam prep mode
T16 · concept map
T17 · auto flashcards
T18 · keyboard + command palette
Timechart unification
Dark mode fixes
Guide expansion
Phase 8 · ship
Shipped
Deploy + supporting docs
Live on Cloudflare Pages at uxdesignlab.us. PWA installable on iPhone. Service Worker v1.1.6 caches the app shell. Origin v2 mobile redesign of the Dashboard (vital signs as icon rows, time as accordion, queues as tap-to-expand). New How-To visual quickstart (12 sections, annotated SVG mockups). New IIT Course Guide tab (iframe-embedded). Empty data/ + intake/ folders staged for vault sync.
Cloudflare Pages deploy
uxdesignlab.us domain
PWA installed on iPhone
Service Worker v1.1.6
Mobile dashboard redesign
Visual How-To guide
IIT Course Guide tab
Phase 9 · harden
In Flight
Address audit findings before grad school starts
Per the Apr 27 system audit (7.0/10) and the a11y audit (62/100, partial AA): lock the URL down, validate the data path, and clean up the accessibility findings before September.
Cloudflare Access on uxdesignlab.us
Test vault sync end-to-end with real data
Convert 11 click-divs → buttons (a11y critical)
Fix dark-mode contrast on g2 / g3 text
Add aria-live to toast + role=dialog to modals
Connect Cloudflare → GitHub for push-to-deploy
Phase 10 · native iOS
Planned
Capacitor wrapper + iCloud sync + native widgets
Wrap the existing HTML/CSS/JS in a native iOS shell via Capacitor. Replace localStorage with the iOS Filesystem API pointed at an iCloud Drive ubiquity container — automatic cross-device sync (iPhone ↔ iPad ↔ Mac) at zero cost, no backend. Then add native extensions one per week: Today widget (Lock Screen + Home Screen), Pomodoro Live Activity (Dynamic Island countdown), Siri Shortcuts ("What's due this week"), Share Sheet ("Send to Study OS Intake"), VisionKit OCR replacement for Tesseract.js. Vault stays the source of truth — vault folder is the meeting point between web (uxdesignlab.us) and native (iOS app), so everything stays in sync via the existing T1 sync architecture.
Capacitor scaffold in School/StudyOS-iOS/
iCloud filesystem bridge plugin (Swift)
Today widget · WidgetKit
Pomodoro Live Activity · ActivityKit
Siri Shortcuts · AppIntents
Share Sheet · UIActivityViewController
VisionKit · native OCR
Phase 11 · Google bridges
Planned
Calendar push · Drive intake · NotebookLM nudge
Google Calendar — write deadlines + Pomodoro sessions as events when you save. Google Drive — pull syllabi from a watched intake folder; periodic backup snapshots. NotebookLM — manual workflow (no API exists): "Send to NotebookLM Sources" button bundles content into a Drive folder + opens NotebookLM in a tab. All three flow through the vault as the single source of truth — never bidirectional sync between non-vault clouds.
Google Calendar API (push events)
Google Drive intake folder
Google Drive backup target
NotebookLM nudge buttons
Phase 12 · future
Someday
Next-generation ideas
Spaced repetition (SM-2 algorithm) for flashcards. Voice-note → intake pipeline via Whisper. Direct Claude API integration (one-click processing instead of paste round-trip). Multi-user mode if Nabil ever shares Study OS with classmates. Apple Intelligence integration for on-device summarization once iOS 18+ is everywhere.