Update README to reflect current feature set and project structure
- Add Morning Routine, strike event logging, block timer remaining, and single-click block switching to features - Remove /schedules as a separate route (schedule management is in /admin) - Remove docker-compose.override.yml and alembic/ references (neither exists) - Replace Database Migrations section with accurate description of the create_all + idempotent ALTER TABLE startup approach - Update project structure to show new model/router files - Update setup steps and URL table to match current routes - Add block_elapsed_seconds to WebSocket events table Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
110
README.md
110
README.md
@@ -6,11 +6,13 @@ A self-hosted web app for managing homeschool schedules, tracking daily learning
|
|||||||
|
|
||||||
## Features
|
## 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.
|
- **TV Dashboard** — Full-screen display for the living room TV. Shows the current subject, countdown timer, day progress, activity options, and the upcoming block list. Updates live without page refresh via WebSocket.
|
||||||
- **Schedule Builder** — Create named schedule templates with time blocks assigned to subjects. Assign templates per-child or share across all children.
|
- **Morning Routine** — Define a list of morning routine items in Admin. They appear in the TV dashboard Activities panel during the "Good Morning" countdown before the first block starts, then switch to subject-specific activities once a block begins.
|
||||||
- **Daily Sessions** — Start a school day against a schedule template. Track which blocks are active, paused, or complete. Timer state (including paused) is preserved when navigating between pages. Switching to a different block auto-pauses the current one; returning to it resumes from where it left off.
|
- **Schedule Builder** — Create named schedule templates with time blocks assigned to subjects. Set optional school day start/end hours for a day-progress bar. Assign templates per-child or share across all children. Managed inside the Admin page.
|
||||||
- **Activity Log** — Automatically records every timer event (day started, block start/pause/resume/complete/skip) as a timeline, including which schedule template was used. Supports manual notes with subject, duration, and free text. Browse and filter history by child and date.
|
- **Daily Sessions** — Start a school day against a schedule template. Track which blocks are active, paused, or complete. Click any block in the list to switch to it instantly — the current block is auto-paused and the new one starts in a single click. Elapsed time per block is remembered, so returning to a block resumes the timer from where it left off.
|
||||||
- **Behavior Tracking (Strikes)** — Issue up to 3 strikes per child from the Dashboard. Strike count is shown on the TV dashboard and resets automatically when a new school day begins.
|
- **Block Timer Remaining** — Each block in the schedule list shows how much time is left on that block's timer (allocated duration minus elapsed time already spent), counting down live on both the parent dashboard and the TV sidebar.
|
||||||
|
- **Activity Log** — Automatically records every timer event (day started, block start/pause/resume/complete/skip) and every strike change as a timestamped timeline. Includes which schedule template was used. Supports manual notes with free text. Browse and filter history by child and date.
|
||||||
|
- **Behavior Tracking (Strikes)** — Issue up to 3 strikes per child from the Dashboard. Strike additions and removals are logged in the activity log with a timestamp. Strike count is shown on the TV dashboard and resets automatically when a new school day begins.
|
||||||
- **Timezone Support** — Set your local timezone in Admin → Settings. All activity log timestamps display in your timezone, including the TV dashboard clock.
|
- **Timezone Support** — Set your local timezone in Admin → Settings. All activity log timestamps display in your timezone, including the TV dashboard clock.
|
||||||
- **Multi-Child Support** — Manage multiple students under one parent account, each with their own color, schedule, and history.
|
- **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).
|
- **JWT Authentication** — Secure parent login with access tokens and httpOnly refresh cookies. TV dashboard is public (no login required).
|
||||||
@@ -27,7 +29,6 @@ A self-hosted web app for managing homeschool schedules, tracking daily learning
|
|||||||
| Real-time | WebSockets via FastAPI |
|
| Real-time | WebSockets via FastAPI |
|
||||||
| Database | MySQL 8 |
|
| Database | MySQL 8 |
|
||||||
| ORM | SQLAlchemy 2.0 (async) |
|
| ORM | SQLAlchemy 2.0 (async) |
|
||||||
| Migrations | Alembic |
|
|
||||||
| Auth | JWT — python-jose + passlib/bcrypt |
|
| Auth | JWT — python-jose + passlib/bcrypt |
|
||||||
| Orchestration | Docker Compose |
|
| Orchestration | Docker Compose |
|
||||||
|
|
||||||
@@ -37,23 +38,37 @@ A self-hosted web app for managing homeschool schedules, tracking daily learning
|
|||||||
|
|
||||||
```
|
```
|
||||||
homeschool/
|
homeschool/
|
||||||
├── docker-compose.yml # Production stack (3 services)
|
├── docker-compose.yml # Stack definition (3 services: db, backend, frontend)
|
||||||
├── docker-compose.override.yml # Dev overrides (hot reload)
|
|
||||||
├── .env.example # Environment variable template
|
├── .env.example # Environment variable template
|
||||||
│
|
│
|
||||||
├── backend/
|
├── backend/
|
||||||
│ ├── Dockerfile
|
│ ├── Dockerfile
|
||||||
│ ├── requirements.txt
|
│ ├── requirements.txt
|
||||||
│ ├── alembic/ # Database migrations
|
|
||||||
│ └── app/
|
│ └── app/
|
||||||
│ ├── main.py # FastAPI app entry point
|
│ ├── main.py # FastAPI app entry point + table auto-creation
|
||||||
│ ├── config.py # Settings (reads from .env)
|
│ ├── config.py # Settings (reads from .env)
|
||||||
│ ├── database.py # Async SQLAlchemy engine
|
│ ├── database.py # Async SQLAlchemy engine
|
||||||
│ ├── dependencies.py # Auth dependencies (get_current_user)
|
│ ├── dependencies.py # Auth dependencies (get_current_user)
|
||||||
│ ├── auth/jwt.py # Token creation, password hashing
|
│ ├── auth/jwt.py # Token creation, password hashing
|
||||||
│ ├── models/ # SQLAlchemy ORM models
|
│ ├── models/ # SQLAlchemy ORM models
|
||||||
|
│ │ ├── child.py
|
||||||
|
│ │ ├── subject.py # Subject + SubjectOption
|
||||||
|
│ │ ├── schedule.py # ScheduleTemplate + ScheduleBlock
|
||||||
|
│ │ ├── session.py # DailySession + TimerEvent
|
||||||
|
│ │ ├── activity.py # ActivityLog (manual notes)
|
||||||
|
│ │ ├── morning_routine.py# MorningRoutineItem
|
||||||
|
│ │ └── strike.py # StrikeEvent (strike history)
|
||||||
│ ├── schemas/ # Pydantic request/response schemas
|
│ ├── schemas/ # Pydantic request/response schemas
|
||||||
│ ├── routers/ # API route handlers
|
│ ├── routers/ # API route handlers
|
||||||
|
│ │ ├── auth.py
|
||||||
|
│ │ ├── children.py
|
||||||
|
│ │ ├── subjects.py
|
||||||
|
│ │ ├── schedules.py
|
||||||
|
│ │ ├── sessions.py # Timer actions + block switching
|
||||||
|
│ │ ├── logs.py # Timeline + strike events
|
||||||
|
│ │ ├── morning_routine.py
|
||||||
|
│ │ ├── dashboard.py # Public snapshot endpoint (TV)
|
||||||
|
│ │ └── users.py
|
||||||
│ └── websocket/manager.py # WebSocket connection manager
|
│ └── websocket/manager.py # WebSocket connection manager
|
||||||
│
|
│
|
||||||
└── frontend/
|
└── frontend/
|
||||||
@@ -64,7 +79,7 @@ homeschool/
|
|||||||
│ ├── useApi.js # Axios with auto token-refresh
|
│ ├── useApi.js # Axios with auto token-refresh
|
||||||
│ └── useWebSocket.js # Auto-reconnecting WebSocket
|
│ └── useWebSocket.js # Auto-reconnecting WebSocket
|
||||||
├── stores/ # Pinia: auth, children, schedule
|
├── stores/ # Pinia: auth, children, schedule
|
||||||
├── views/ # LoginView, TVView, DashboardView, etc.
|
├── views/ # LoginView, TVView, DashboardView, LogView, AdminView
|
||||||
└── components/ # TimerDisplay, ScheduleBlock, NavBar, etc.
|
└── components/ # TimerDisplay, ScheduleBlock, NavBar, etc.
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -75,7 +90,7 @@ homeschool/
|
|||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
- [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/) installed
|
- [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/) installed
|
||||||
- Port `8054` available on the host
|
- Port `8054` available on the host (or change it in `docker-compose.yml`)
|
||||||
|
|
||||||
### 1. Clone the repo
|
### 1. Clone the repo
|
||||||
|
|
||||||
@@ -124,11 +139,12 @@ Open **http://localhost:8054/login** and register. This creates your admin accou
|
|||||||
### 5. Set up your data (in order)
|
### 5. Set up your data (in order)
|
||||||
|
|
||||||
1. **Admin** (`/admin`) → Add each child, pick a color
|
1. **Admin** (`/admin`) → Add each child, pick a color
|
||||||
2. **Admin** → Add subjects (Math, Reading, Science, etc.) with emoji icons and colors
|
2. **Admin** → Add subjects (Math, Reading, Science, etc.) with emoji icons and colors. Add activity options to each subject — they appear on the TV dashboard during that block.
|
||||||
3. **Admin** → Scroll to **Settings** and select your local timezone — this ensures activity log times and the TV clock display correctly
|
3. **Admin** → Add **Morning Routine** items — these show on the TV during the countdown before the first block starts.
|
||||||
4. **Schedules** (`/schedules`) → Create a schedule template, add time blocks assigned to subjects
|
4. **Admin** → Scroll to **Settings** and select your local timezone
|
||||||
5. **Dashboard** (`/dashboard`) → Click "Start Day", choose a template
|
5. **Admin** → Scroll to **Schedules** → Create a schedule template, set school day hours, add time blocks assigned to subjects
|
||||||
6. **TV** → Open `http://your-lan-ip:8054/tv/1` on the living room TV (replace `1` with the child's ID)
|
6. **Dashboard** (`/dashboard`) → Click "Start Day", choose a template
|
||||||
|
7. **TV** → Open `http://your-lan-ip:8054/tv/1` on the living room TV (replace `1` with the child's ID)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -138,16 +154,15 @@ Open **http://localhost:8054/login** and register. This creates your admin accou
|
|||||||
|
|
||||||
| URL | Description |
|
| URL | Description |
|
||||||
|-----|-------------|
|
|-----|-------------|
|
||||||
| `/dashboard` | Overview, start/stop sessions, timer controls, issue behavior strikes |
|
| `/dashboard` | Overview, start/stop sessions, switch blocks, timer controls, issue behavior strikes |
|
||||||
| `/schedules` | Create and edit schedule templates and time blocks |
|
| `/logs` | Browse timer and strike event history and manual notes; filter by child and date |
|
||||||
| `/logs` | Browse timer event history and manual activity notes; filter by child and date |
|
| `/admin` | Manage children, subjects (with activity options), morning routine, schedule templates, and account settings |
|
||||||
| `/admin` | Manage children, subjects, schedule templates, and account settings (timezone) |
|
|
||||||
|
|
||||||
### TV Dashboard (no login)
|
### TV Dashboard (no login)
|
||||||
|
|
||||||
| URL | Description |
|
| URL | Description |
|
||||||
|-----|-------------|
|
|-----|-------------|
|
||||||
| `/tv/:childId` | Full-screen display — current block, countdown timer, day progress |
|
| `/tv/:childId` | Full-screen display — greeting + morning routine, current block timer, activity options, day progress, schedule sidebar |
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
@@ -160,41 +175,16 @@ FastAPI auto-generates interactive API docs:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Development Mode
|
## Schema Migrations
|
||||||
|
|
||||||
The `docker-compose.override.yml` file enables hot reload automatically when running locally:
|
The app automatically creates all database tables on startup via SQLAlchemy's `create_all`. Additive column changes are applied with idempotent `ALTER TABLE` statements in the startup lifespan, so upgrading to a new version is safe — just rebuild and restart:
|
||||||
|
|
||||||
- **Backend** — uvicorn `--reload` watches `backend/app/` for changes
|
|
||||||
- **Frontend** — Vite HMR on port `5173` (mapped to `8054` in dev mode)
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose up --build # override is applied automatically in dev
|
docker compose build
|
||||||
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
To run production mode explicitly (no hot reload):
|
No separate migration tool or manual steps are required.
|
||||||
|
|
||||||
```bash
|
|
||||||
docker compose -f docker-compose.yml up --build
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Database Migrations
|
|
||||||
|
|
||||||
Alembic is configured for async SQLAlchemy migrations.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -202,15 +192,17 @@ docker compose exec backend alembic downgrade -1
|
|||||||
|
|
||||||
The TV dashboard connects to `ws://host/ws/{child_id}` and receives JSON events:
|
The TV dashboard connects to `ws://host/ws/{child_id}` and receives JSON events:
|
||||||
|
|
||||||
| Event | Triggered by | Payload |
|
| Event | Triggered by | Key payload fields |
|
||||||
|-------|-------------|---------|
|
|-------|-------------|---------|
|
||||||
| `session_update` | Session start/end | Full session snapshot |
|
| `session_update` | Session start/end | Full session snapshot |
|
||||||
| `start` | Timer started | `session_id`, `block_id`, `current_block_id` |
|
| `start` | Block started | `block_id`, `current_block_id`, `block_elapsed_seconds` |
|
||||||
| `pause` | Timer paused | `session_id`, `block_id` |
|
| `pause` | Block paused | `block_id`, `current_block_id` |
|
||||||
| `resume` | Timer resumed | `session_id`, `block_id` |
|
| `resume` | Block resumed | `block_id`, `current_block_id` |
|
||||||
| `complete` | Block completed | `session_id`, `block_id` |
|
| `complete` | Block completed | `block_id` |
|
||||||
| `skip` | Block skipped | `session_id`, `block_id` |
|
| `skip` | Block skipped | `block_id` |
|
||||||
| `strikes_update` | Strike issued/cleared | `child_id`, `strikes` |
|
| `strikes_update` | Strike issued/cleared | `strikes` |
|
||||||
|
|
||||||
|
`block_elapsed_seconds` on the `start` event carries the authoritative elapsed time for that block (including all previous intervals), so every client — including the TV — can restore the correct timer offset without a local cache.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user