AI-powered study platform. Chat with your notes, fork topics, track progress — all local, all yours.
What StudyOS Does
Upload your PDFs, talk to an LLM that reads them, split conversations into topic-focused forks, do exercises, track your progress, review with flashcards, generate exams — all in one polished dark-UI interface. No cloud accounts, no data leaving your machine.
┌─────────────┐ ┌──────────────┐ ┌────────────────┐
│ React 18 │────▶│ Express API │────▶│ SQLite (WASM) │
│ + Vite │◀────│ :3001 │ │ sql.js │
└─────────────┘ SSE └──────┬───────┘ └────────────────┘
│
┌─────────┼─────────┐
▼ ▼ ▼
┌────────┐ ┌──────┐ ┌──────────────┐
│ glm │ │ VLM │ │ Transformers │
│ 4.5-air│ │glm4.6v│ │ .js (local) │
└────────┘ └──────┘ └──────────────┘
Features
Chat & AI
- Streaming chat (SSE) — tokens appear in real time, dual adapter (Anthropic + OpenAI-compatible)
- Multi-model — configure any OpenAI-compatible endpoint, switch on the fly
- Syntax highlighting —
prismjswith auto-language detection from code fences - LaTeX rendering —
KaTeXfor all inline and block math - Graph rendering — inline SVG coordinate planes via
```graphblocks - Voice input — Web Speech API microphone to text
- LaTeX editor — real-time preview while typing
PDF Processing
- Upload & extract — VLM extraction first (
glm-4.6v),pdfjs-distfallback - RAG search — local embeddings via
@xenova/transformers(ONNX Runtime + DirectML GPU), cosine similarity retrieval over chunks - Multi-PDF compare — side-by-side view of two PDFs
- Sidebar search — FTS5 full-text search across all PDFs and messages, with LIKE fallback
Study System
- Conversations — organized chat threads with file attachments
- Forks — branch any topic into a focused sub-chat, merge back when done
- Auto-fork suggestion — model detects when you're struggling and suggests a practice fork
- Exercises — model generates exercises, auto-detects correctness, logs to progress
- Progress tracking — per-topic stats (exercises done, correct, accuracy, difficulty)
- Difficulty auto-adjust — lowers difficulty after consecutive failures
- Calendar heatmap — GitHub-style study activity visualization
- Pomodoro timer — 25/5 minute cycles with browser notifications
Exams & Flashcards
- Exam generator — AI generates exams from your progress data
- Timed exams — countdown timer, auto-submit on expiry, instant grading
- Exam PDF export — download any exam as printable PDF via
pdfkit - Flashcard generator — LLM creates Q&A cards from your PDFs and exercises
- SM-2 spaced repetition — science-backed review scheduling with ease factor
- Review queue — sidebar badge shows due cards
Collaboration
- Study buddy mode — share a conversation via token, two users chat with AI referee
- WebSocket real-time — progress and buddy message push across tabs
UI & UX
- Dark/light theme — toggle with CSS variables, persisted to localStorage, zero flash
- Glassmorphism — indigo/purple gradients, backdrop blur, micro-interactions
- Sidebar — collapsible sections, PDF reorder via drag-and-drop, search bar
- Fork panel — resizeable right panel, own chat context
- Toasts — context-based notification system for success/error feedback
- Skeleton loading — animated placeholders while data loads
- Scroll-to-bottom FAB — appears when scrolled up in chat
- Keyboard shortcuts —
Ctrl+Nnew chat,Ctrl+Ksearch,Escapeclose panels,Ctrl+Entersend - PWA — install as native app via
vite-plugin-pwa - Responsive — sidebar auto-collapses on mobile with hamburger overlay
- Message copy — hover to reveal copy button on any message
Infrastructure
- Zero native deps —
sql.jsWASM for SQLite,@xenova/transformersWASM for embeddings - Tests —
vitest(jsdom) on client,node:teston server - DB backup/restore — download/upload SQLite file from Settings
- Rate limiting — client-side guard blocks concurrent sends
Quick Start
# 1. Install
cd studyos/server && npm install
cd studyos/client && npm install
# 2. Run backend (terminal 1)
cd studyos/server && node index.js
# 3. Run frontend (terminal 2)
cd studyos/client && npm run dev
# 4. Open http://localhost:5173
First launch: the embeddings model (~118 MB) downloads automatically to server/node_modules/.cache/transformers/. Chat works immediately — embeddings are ready after the warmup completes (check server logs).
Production
cd studyos/client && npm run build
cd studyos/server && node index.js
# Everything served from http://localhost:3001
Configuration
Everything lives in the Settings page. No .env file needed.
| Setting | Default | Purpose |
|---|---|---|
| Main model | None | LLM for chat (OpenAI-compatible endpoint) |
| Fork model | None | LLM used inside forks (falls back to main) |
| VLM endpoint | None | Vision model for PDF extraction |
| VLM API key | None | Key for the vision endpoint |
| Admin key | None | Required for DB backup/restore |
Recommended: Z.ai
| Role | Model | Endpoint |
|---|---|---|
| Chat | glm-4.5-air |
https://api.z.ai/api/coding/paas/v4 |
| Vision | glm-4.6v |
https://api.z.ai/api/coding/paas/v4 |
StudyOS is provider-agnostic — any OpenAI-compatible endpoint works.
Architecture
Backend (server/)
server/
├── index.js # Express + WebSocket server, async DB init
├── db.js # sql.js schema, migrations, seed
├── systemPromptBuilder.js # Context-aware prompt: PDFs, progress, RAG, difficulty
├── lib/
│ ├── llm.js # Dual SSE adapter (Anthropic SDK + OpenAI SDK)
│ ├── embeddings.js # @xenova/transformers pipeline (webgpu → wasm)
│ ├── rag.js # chunkText, cosineSimilarity, searchRelevant
│ ├── broadcast.js # WebSocket broadcast with buddy support
│ └── sm2.js # SM-2 spaced repetition algorithm
└── routes/
├── chat.js # SSE streaming, RAG pipeline, auto-fork, difficulty
├── conversations.js # CRUD, fork, merge, study buddy share/join
├── pdfs.js # Upload, VLM extraction, embedding generation
├── progress.js # Topic stats, study sessions, heatmap, exam PDF
├── exams.js # Generate, start, submit timed exams
├── flashcards.js # SSE generation, SM-2 reviews, due queue
├── search.js # FTS5 full-text search with LIKE fallback
├── models.js # LLM model CRUD, default exclusivity
├── config.js # Key-value config, VLM test, DB backup/restore
└── notes.js # Simple notes CRUD
Frontend (client/)
client/src/
├── components/
│ ├── Sidebar.jsx # Conv list, PDFs, search, theme toggle, nav
│ ├── MainChat.jsx # Chat area, graph panel, rename, scroll FAB
│ ├── MessageBubble.jsx # Markdown, KaTeX, Prism, reactions, copy
│ ├── ForkPanel.jsx # Resizeable fork chat panel
│ ├── ChatInput.jsx # Text area, voice input, LaTeX toggle, send
│ ├── SearchBar.jsx # FTS5 modal overlay with results
│ ├── ThemeToggle.jsx # Dark/light switch
│ ├── [17 more components] # All features listed above
├── hooks/
│ ├── useChat.js # SSE stream, send, fork/difficulty events
│ ├── useExam.js # Timer, auto-submit, navigation
│ ├── useFlashcards.js # Queue, review, due count
│ ├── usePdfs.js # Upload, reorder, delete, refresh
│ ├── useProgress.js # Stats, WebSocket subscription
│ ├── useSearch.js # Debounced FTS5 queries
│ ├── useStudyBuddy.js # Token join, WebSocket sync
│ └── [6 more hooks]
├── lib/
│ ├── api.js # All endpoint functions
│ └── sm2.js # Client-side SM-2 mirror
├── context/
│ └── ReactionsContext.jsx # 👍/👎 session-local state
├── pages/
│ └── Settings.jsx # Models, VLM, backup/restore, exam export, theme
└── data/
└── roadmap.json # Topic relationship graph
Database
SQLite via sql.js (WASM). Tables include conversations, messages, pdfs, models, progress, exams, flashcards, flashcard_reviews, study_sessions, embeddings, shared_conversations, conversation_participants, topic_relationships, plus FTS5 virtual tables for full-text search.
API Overview
| Method | Path | Purpose |
|---|---|---|
POST |
/api/chat/:id/stream |
SSE chat streaming |
GET/POST |
/api/conversations |
List / create conversations |
POST |
/api/conversations/:id/fork |
Create topic fork |
POST |
/api/conversations/:id/merge |
Merge fork back |
POST |
/api/conversations/:id/share |
Generate buddy token |
POST |
/api/conversations/join |
Join buddy conversation |
POST |
/api/pdfs/upload |
Upload PDF + extract + embed |
GET |
/api/progress?main_id=:id |
Topic-level progress |
GET |
/api/progress/heatmap?days=365 |
Study activity data |
GET |
/api/progress/exam/pdf |
Download exam as PDF |
POST |
/api/exams/generate |
AI-generated exam |
POST |
/api/exams/:id/submit |
Submit exam answers |
POST |
/api/flashcards/generate |
SSE flashcard generation |
PUT |
/api/flashcards/:id/review |
SM-2 review (quality 0-5) |
GET |
/api/flashcards/reviews/due |
Due review queue |
GET |
/api/search?q=term |
FTS5 search messages + PDFs |
GET |
/api/config/backup |
Download DB (auth required) |
POST |
/api/config/restore |
Upload DB (auth required) |
GET |
/api/models |
Available chat models |
WS |
ws://localhost:3001 |
Progress push, buddy messages |
Testing
# Client (vitest + jsdom)
cd studyos/client && npm test
# Server (node:test)
cd studyos/server && npm test
Tech Stack
| Layer | Technology |
|---|---|
| Runtime | Node.js 18+ |
| Backend | Express 4, ws |
| Database | SQLite via sql.js (WASM — zero native) |
| Frontend | React 18, Vite 5 |
| Routing | react-router-dom v6 |
| Markdown | react-markdown v9 |
| Math | KaTeX 0.17 |
| Syntax | Prism.js 1.30 |
| Charts | Recharts |
| Drag & drop | @dnd-kit |
| Icons | Lucide React |
| PWA | vite-plugin-pwa |
| Tests | Vitest + @testing-library/react (client), node:test (server) |
| LLM client | Anthropic SDK + OpenAI SDK |
| Embeddings | @xenova/transformers (local, WASM + DirectML) |
| PDF export | pdfkit |
| PDF extraction | pdfjs-dist |
License
MIT