A personal, evidence-backed university learning cockpit.
See what changed, choose one meaningful next action, read the source, and ask focused questions without losing provenance.
The interface is intentionally serious and information-first. It is built for one learner working across university course trees, official course material, prior exams, personal notes, and community discussion. Activity, generated guidance, and system metadata stay distinguishable from learning itself.
- Activity — triage course announcements, file changes, assignments, and history.
- Courses — browse synchronized course trees, study levels, indexed material, and recent context.
- Study — select one next action using course evidence, exam plans, and adaptive guidance.
- Session — read deeply in the document workspace with highlights, notes, recall, and reading history.
- Ask — have a focused conversation grounded in course material, with consulted sources shown beside the answer.
- Settings — configure courses, synchronization, preferences, knowledge indexing, and the available chat provider.
Evidence keeps its origin: official material, past exams, community-authored content, and learner-created notes do not silently become interchangeable.
docker compose
├── tree-eclass FastAPI JSON API (:8000 inside the network)
│ ├── backend/api routers, shared state, cache warmers
│ ├── backend/services course persistence and learner history
│ ├── backend/knowledge rebuildable document index and grounded chat
│ └── backend/messages optional Discord archive index
└── tree-eclass-ssr Node SSR entry (:8000 on the host)
├── React 19 + Vite client bundle
├── streamed SSR pages and hydration data
├── /api, /files, and /mcp proxying
└── /ask and /study/session client islands
The application uses three independent SQLite stores:
eclass.db— courses, files, learner history, study plans, and Ask conversations.knowledge.db— rebuildable documents, chunks, embeddings, enrichment, and blueprints.discord_knowledge.db— optional Discord archive data.
The Docker deployment mounts ./data for these stores. Keep the API and SSR services on a private network; the application deliberately has no authentication or authorization layer.
Requirements: Docker with Compose support and a private Docker network named apps-net.
docker network create apps-net 2>/dev/null || true
cp .env.example .env
# Add provider credentials only if you want live indexing or Ask answers.
docker compose up --buildOpen http://127.0.0.1:8000. The SSR service is the public entry point; FastAPI is intended to remain reachable only over the Docker network.
Provider credentials are optional for browsing synchronized data. Never commit .env, database files, Discord exports, WebDAV credentials, SMTP settings, webhook URLs, or provider cookies.
Install Python dependencies and the frontend dependencies:
python3 -m pip install -r requirements.txt -r requirements-dev.txt
cd frontend && bun install --frozen-lockfileBuild the client and SSR bundles:
cd frontend
bun run build
bun run build:ssrRun the API and SSR entry in separate terminals. Use database paths outside the repository when possible:
DB_FILE=/absolute/path/eclass.db \
KNOWLEDGE_DB_FILE=/absolute/path/knowledge.db \
python3 run.pycd frontend
API_TARGET=http://127.0.0.1:8000 PORT=5173 node dist/server/server.jsVisit http://127.0.0.1:5173.
The screenshot workflow builds the frontend, creates a temporary secret-free SQLite fixture, starts the API and SSR services, drives Chromium, and writes screenshots for dark, light, and e-ink themes:
python3 -m pip install -r requirements-dev.txt
playwright install chromium
python3 scripts/capture_screenshots.pyBy default, output goes to docs/screenshots/. Use a disposable CI directory with --output artifacts/screenshots. If the bundles are already built, use --skip-build.
Each generated PNG is exactly 1920×1080; captures use the browser viewport rather than full-page output.
The workflow covers Activity, Courses, a course detail page, Study, Exercises, Settings, and Ask for every theme. It also submits a question through a deterministic local SSE fixture and captures ask-interaction-dark.png. The route checks fail on 4xx/5xx resource responses, page errors, console errors, rendered error states, missing headings, or a broken Ask response.
The fixture is synthetic and lives only in a temporary directory. It contains fictional course names, crawled-data-shaped file metadata, deterministic study context, and demo links under demo.invalid. It does not read data/, copy production databases, or require provider credentials. The intercepted Ask stream keeps visual testing offline and reproducible; live Ask behavior still depends on a configured provider.
The same workflow runs in CI through Visual screenshots. Pull requests that touch the app, frontend, or fixture fail with an uploaded screenshot artifact when a route or visual smoke check breaks.
The shell supports system, light, dark, and eink. Theme preference is stored in localStorage under treeEclass.theme; e-ink intentionally removes shadows and motion and uses a high-contrast paper palette. The screenshot workflow captures the three explicit visual modes so regressions are visible instead of being hidden behind the system preference.
Run the repository gates before submitting changes:
python3 scripts/quality/audit_limits.py
(cd frontend && bun run lint)
frontend/node_modules/.bin/prettier --check .
ruff check . && ruff format --check .
python3 -m pytest -qThe tests are offline. Avoid importing backend.api.app in ad-hoc checks against the live databases; set explicit temporary database paths as the screenshot workflow does.
backend/ FastAPI application, persistence, knowledge, and messages
frontend/src/ React pages, Ask, study workspace, shell, and styles
frontend/ssr/ Node SSR route table, shell, and proxy server
scripts/ Deterministic screenshot fixture and browser workflow
docs/ System design notes and committed marketing screenshots
tests/ Offline Python contract and behavior tests
data/ Runtime databases and crawled exports; never commit
This is a single-user, trusted-network application. It has no login, session, API-key gate, or per-route authorization. Do not expose either service directly to an untrusted network. Keep data/ and all provider credentials outside version control, and review any crawled or community content before treating it as evidence.


