derekc 7346159745 Sort schedule blocks by start time instead of order_index
Backend queries and model relationship now order by time_start.
Frontend also sorts blocks client-side for reliability across all views.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 16:22:17 -08:00
2026-02-27 22:56:56 -08:00
2026-02-27 22:56:56 -08:00
2026-02-27 23:04:41 -08:00

Homeschool Dashboard

A self-hosted web app for managing homeschool schedules, tracking daily learning sessions, and logging activities. Features a full-screen TV dashboard with live timers and real-time updates via WebSockets.


Features

  • TV Dashboard — Full-screen display for the living room TV. Shows the current subject, countdown timer, day progress, and upcoming schedule blocks. Updates live without page refresh.
  • Schedule Builder — Create named schedule templates with time blocks assigned to subjects. Assign templates per-child or share across all children.
  • Daily Sessions — Start a school day against a schedule template. Track which blocks are active, paused, or complete.
  • Activity Log — Manually log school activities with subject, duration, and notes. Browse and filter history by date.
  • Multi-Child Support — Manage multiple students under one parent account, each with their own color, schedule, and history.
  • JWT Authentication — Secure parent login with access tokens and httpOnly refresh cookies. TV dashboard is public (no login required).

Tech Stack

Layer Technology
Frontend Vue 3 + Vite + Pinia + Vue Router
Frontend server nginx (Docker)
Backend API FastAPI (Python 3.12)
Real-time WebSockets via FastAPI
Database MySQL 8
ORM SQLAlchemy 2.0 (async)
Migrations Alembic
Auth JWT — python-jose + passlib/bcrypt
Orchestration Docker Compose

Project Structure

homeschool/
├── docker-compose.yml            # Production stack (3 services)
├── docker-compose.override.yml   # Dev overrides (hot reload)
├── .env.example                  # Environment variable template
│
├── backend/
│   ├── Dockerfile
│   ├── requirements.txt
│   ├── alembic/                  # Database migrations
│   └── app/
│       ├── main.py               # FastAPI app entry point
│       ├── config.py             # Settings (reads from .env)
│       ├── database.py           # Async SQLAlchemy engine
│       ├── dependencies.py       # Auth dependencies (get_current_user)
│       ├── auth/jwt.py           # Token creation, password hashing
│       ├── models/               # SQLAlchemy ORM models
│       ├── schemas/              # Pydantic request/response schemas
│       ├── routers/              # API route handlers
│       └── websocket/manager.py  # WebSocket connection manager
│
└── frontend/
    ├── Dockerfile                # Multi-stage: Node build → nginx serve
    ├── nginx.conf                # Proxy /api/ and /ws/ to backend
    └── src/
        ├── composables/
        │   ├── useApi.js         # Axios with auto token-refresh
        │   └── useWebSocket.js   # Auto-reconnecting WebSocket
        ├── stores/               # Pinia: auth, children, schedule
        ├── views/                # LoginView, TVView, DashboardView, etc.
        └── components/           # TimerDisplay, ScheduleBlock, NavBar, etc.

Getting Started

Prerequisites

1. Clone the repo

git clone https://git.chns.tech/CooperandGoodman/homeschool.git
cd homeschool

2. Create your .env file

cp .env.example .env

Open .env and fill in the values:

MYSQL_ROOT_PASSWORD=your_secure_root_password
MYSQL_DATABASE=homeschool
MYSQL_USER=homeschool
MYSQL_PASSWORD=your_secure_db_password

# Generate with: openssl rand -hex 32
SECRET_KEY=your_generated_secret_key

ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30
REFRESH_TOKEN_EXPIRE_DAYS=30

# Your host IP or domain (no trailing slash)
CORS_ORIGINS=http://localhost:8054

3. Build and start

docker compose up --build

The first build takes a few minutes (npm install + pip install). On subsequent starts it's fast.

4. Register your parent account

Open http://localhost:8054/login and register. This creates your admin account.

5. Set up your data (in order)

  1. Admin (/admin) → Add each child, pick a color
  2. Admin → Add subjects (Math, Reading, Science, etc.) with emoji icons and colors
  3. Schedules (/schedules) → Create a schedule template, add time blocks assigned to subjects
  4. Dashboard (/dashboard) → Click "Start Day", choose a template
  5. TV → Open http://your-lan-ip:8054/tv/1 on the living room TV (replace 1 with the child's ID)

Usage

Parent Views (require login)

URL Description
/dashboard Overview, start/stop sessions, timer controls, link to TV view
/schedules Create and edit schedule templates and time blocks
/logs Browse and add activity log entries
/admin Manage children and subjects

TV Dashboard (no login)

URL Description
/tv/:childId Full-screen display — current block, countdown timer, day progress

Point a browser on the living room TV at http://your-lan-ip:8054/tv/1. The page connects via WebSocket and updates automatically when a parent starts/stops/advances the timer from the Dashboard.

API Documentation

FastAPI auto-generates interactive API docs:

  • Swagger UIhttp://localhost:8054/api/docs
  • ReDochttp://localhost:8054/api/redoc

Development Mode

The docker-compose.override.yml file enables hot reload automatically when running locally:

  • Backend — uvicorn --reload watches backend/app/ for changes
  • Frontend — Vite HMR on port 5173 (mapped to 8054 in dev mode)
docker compose up --build   # override is applied automatically in dev

To run production mode explicitly (no hot reload):

docker compose -f docker-compose.yml up --build

Database Migrations

Alembic is configured for async SQLAlchemy migrations.

# Generate a new migration after changing models
docker compose exec backend alembic revision --autogenerate -m "description"

# Apply pending migrations
docker compose exec backend alembic upgrade head

# Roll back one migration
docker compose exec backend alembic downgrade -1

Note: On first startup the app auto-creates all tables via SQLAlchemy's create_all. Alembic is used for schema changes after the initial setup.


WebSocket Events

The TV dashboard connects to ws://host/ws/{child_id} and receives JSON events:

Event Triggered by Payload
session_update Session start/end Full session snapshot
start Timer started session_id, block_id, current_block_id
pause Timer paused session_id, block_id
resume Timer resumed session_id, block_id
complete Block completed session_id, block_id
skip Block skipped session_id, block_id

Environment Variables Reference

Variable Required Description
MYSQL_ROOT_PASSWORD Yes MySQL root password
MYSQL_DATABASE Yes Database name (default: homeschool)
MYSQL_USER Yes App database user
MYSQL_PASSWORD Yes App database password
SECRET_KEY Yes JWT signing key — generate with openssl rand -hex 32
ALGORITHM No JWT algorithm (default: HS256)
ACCESS_TOKEN_EXPIRE_MINUTES No Access token lifetime (default: 30)
REFRESH_TOKEN_EXPIRE_DAYS No Refresh token lifetime (default: 30)
CORS_ORIGINS No Comma-separated allowed origins (default: http://localhost:8054)

Stopping and Restarting

# Stop containers (data preserved in Docker volume)
docker compose down

# Stop and wipe the database volume (full reset)
docker compose down -v

# Restart without rebuilding
docker compose up
Description
A self-hosted web app for managing homeschool schedules, tracking daily learning sessions, and logging activities. Features a full-screen TV dashboard with live timers and real-time updates via WebSockets.
Readme 708 KiB
Languages
Vue 50.3%
Python 35.9%
JavaScript 13.2%
Dockerfile 0.2%
Mako 0.2%
Other 0.2%