- Student section: new hero gradient header, fixed bottom nav bar with
icon+label pills (Today/Courses/Spelling/Inbox/Docs)
- Today rows: card style with left accent stripe, lift on hover
- Course cards: grid layout with top color bar per course
- Docs tab: list view with doc cards, OnlyOffice editor embedded via
iframe using server-signed JWT config
- Server: documents table, CRUD routes, OnlyOffice callback endpoint
for auto-save, /api/docs/:id/editor-config returns signed config
- Blank DOCX template embedded as base64 for new document creation
- OnlyOffice server: https://onlyoffice.necloud.us (set ONLYOFFICE_JWT_SECRET
env var to match your Document Server JWT secret)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace horizontal top-nav with a dark sidebar (grouped: People / Academics / Tools)
- Add Dashboard landing page with kid stat cards, today's schedule, and recent scores
- Add /api/admin/schedule and /api/admin/recent-scores endpoints for dashboard data
- Add Lock button and mobile sidebar toggle in top bar
- Redesign planner toolbar: two-section layout (nav left, actions right)
- Elevate auto-schedule out of hidden accordion into always-visible inline bar
- Richer planner task cards: course color stripe, course name label, completion counter per day
- Dashed "+ Add task" empty state instead of plain dash
- Fix nav-pill CSS conflict: student tabs (light bg) now use dark text; admin sidebar keeps white text
- Add seed.js demo data script for two students (Emma and Liam)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Spelling: "Blank test" print button per word list (numbered lines, no words shown) for dictated paper tests
- Spelling: "Record Paper Test" form in admin to log a paper test score to the gradebook
- Gradebook: "Record Paper Score" form to log a paper quiz/assignment score for any course item
- Flashcards: "Print" button per deck generates a cut-and-fold card sheet (fronts page + backs page)
- Crossword: print now includes a second page with a filled answer key
- Lessons + Assignments: 🖨 Print button in student view generates a clean printable page
- Word lists: new "CSV file" import tab — upload a .csv with word, sentence, definition columns
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Polls every 30s for unread messages on both kid and admin sides.
Kid app shows a tappable in-page toast and fires a browser OS
notification when a parent message arrives while the tab is open.
Admin app shows a toast and OS notification when a student replies.
Clicking the OS notification focuses the tab and opens the messages view.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaced db.transaction() wrapper (unreliable in node:sqlite at this
version) with a plain loop. Added try/catch in the JS save handler so
any server error surfaces as a visible toast instead of failing silently.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a "Correct" button to each test in the Spelling Test History table.
Clicking it opens a modal showing each word, what the student typed, and a
checkbox to mark it correct or incorrect. Saving PATCHes the server, which
updates test_answers, recalculates the test score, and keeps any linked
course submission in sync.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove cross-list review words (Leitner spaced repetition) from practice
sessions so only the currently assigned list's words are shown. Also remove
the now-unused dueReviews count from the state endpoint and student UI.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace reply-by-message-ID endpoint with POST /api/admin/messages/:studentId so parent can send without a prior message existing
- Switch GET /api/admin/messages to LEFT JOIN so all students appear in the thread list, not just those who have sent messages
- Remove guard that blocked sending when no messages existed in the thread
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Grading queue now shows short-answer questions and student responses inline so the parent can read answers before scoring
- Student inbox tab shows all graded items with score, percentage, and parent feedback; unread badge appears on login
- Parent-student messaging: students send messages from the Inbox tab; Messages panel in admin shows threads with unread count badge, full conversation history, and reply compose
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each time a student completes a pass through a spelling_practice course
item — initial round, missed-words drill, or a retry — a row is now
written to submission_history so the parent sees individual attempts
instead of a single day-grouped entry.
- app.js: send sessionAttempted/sessionCorrect with /complete calls
- server.js: write to submission_history on each spelling_practice
completion; add GET /api/spelling-sessions endpoint
- admin.html/js: new "Practice Sessions" table shows one row per pass
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Shows per-student, per-day practice history in the Spelling panel: date,
time range, word list(s), and first-try correct rate. Clicking a row opens
a detail modal with every word attempted, what the student typed, and
whether it was a first try or retype.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- School name now appears on the student home screen and updates the page title
- Logo can be uploaded in Settings (PNG/JPG/GIF/WebP/SVG, max 2 MB); stored in the data volume so it persists across container restarts
- When a logo is uploaded the text school name is hidden in favour of the logo
- Admin header shows the school name instead of hardcoded "Homeschool", updates live when saved
- New server endpoints: GET /api/logo, POST /api/admin/upload-logo, DELETE /api/admin/logo
- /api/public-settings now includes school_name and has_logo
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Parents can set a birthday (MM-DD) per student in the Kids panel. During the student's birthday week (Mon–Sun), a festive overlay appears on login with balloons, birthday cake, confetti, and a personalized message — shown once per day via sessionStorage. Summer birthdays (June–Aug) show a note in admin suggesting the parent set an alternate school-week date to celebrate early.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Show full word list before practice starts so students can study words first
- Add per-student young learner mode (set in admin): word stays visible while typing
- Center all practice card content (speak button, prompt, feedback, check button)
- Remove 10-word-per-session cap so large lists (25-30 words) practice all words
- Double the misspelled-word study countdown from 4s to 8s
- Fix word list preview numbering for 10+ items (inline numbers, no clipping)
- Add young_learner column to students table with admin toggle
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Parent can turn the floating school emoji on/off from Settings > Student home screen. Setting persists in the DB and is read via a public /api/public-settings endpoint on the student home page.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Grading: add student filter dropdown, Enter-to-save, and point max always defaults to 100
- Student side: show next-item/back-to-course actions after completing a lesson or assignment
- Lesson body: apply prose typography styles (headings, lists, blockquotes, links, hr)
- Gradebook: fix % display when points_possible is 0 (default to 100 on grade save)
- Auto-schedule: skip items that already have a submission
- Item editor: default new/existing item point values to 100 instead of 10
- Planner: friendly week date header, per-day short date, today highlight, course color on task pills, done toggle, within-day drag reorder, Today button
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Today button jumps planner to current week; today column highlighted with accent outline
- Week label now shows friendly format (Aug 3–7, 2026) instead of ISO dates
- Course color shown as left border on scheduled course items
- Parent-side done toggle on every planner task (works for offline + course items)
- Within-day drag-to-reorder tasks via new /api/schedule/reorder endpoint
- Grading queue shows visible "/ N pts" max-points label (defaults to 100 when unset)
- New item default points changed from 10 to 100
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- School/family name: saved to DB, appears in printed week/month report headers
- Passing grade threshold: replaces hardcoded 80% in all gradebook/history views
- Week start day (Mon vs Sun): shifts the planner 5-day grid and month view accordingly
- Settings are loaded at unlock time so they apply before any panel opens
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes the scan-a-page workflow (photo → lesson/quiz content), all
Ollama/cloud provider code, the scan settings panel, and the related
DB seed values.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New `worksheet` item type: admin pastes raw worksheet text, parser auto-detects fill-in-the-blank (___), true/false (T F ...), section headers (Part N —), and short-answer questions
- Admin editor shows each parsed question with inputs to set correct answers for FITB and T/F; short answers are marked parent-grades
- Kid view renders FITB as inline underline inputs, T/F as tap-to-toggle T/F buttons, and short answer as a textarea; Name/Date header auto-populated
- Auto-grades T/F (exact) and FITB (case-insensitive); worksheets with short answers go to grading queue as status=done
- Print blank button opens a formatted print window with underlines, circled T/F, and ruled lines for short answers
- "I handed in my paper copy" button lets kids mark a printed worksheet as turned in without digital submission, queuing it for parent grading
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- requirePin: prepare pin-lookup statement once at module level instead of per-request
- Gradebook: replace O(students × items × 3) per-item queries with 2 bulk INs + in-memory Maps
- List/deck PUT: wrap DELETE + re-INSERT in a transaction to prevent partial-write corruption
- Print views: detect HTML vs plain-text lesson bodies before escaping, fixing rich-text output
- Planner add-task: parallelize course detail fetches with Promise.all
- Planner save-all: parallelize schedule inserts with Promise.all
- HOMESCHOOL_DIR: read from env var with existing path as fallback
- Remove unused isDown function in crossword-submit handler
- Remove dead empty-if stub in docx import change handler
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
mammoth outputs week/quiz headings as <h2>/<h1>, not <p><strong>. The
block-element regex only matched <p>, so all headings were skipped and no
lessons were ever created. Expand regex to h[1-6]|p|ul|ol and treat any
h-tag as a heading unconditionally.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Export any course as a .json bundle (GET /api/admin/courses/:id/export)
- Import a .json bundle as a new course (POST /api/admin/import-course)
- Import one or more unit .docx files directly in the browser — server
parses each file with mammoth, extracts Week N: headings as lesson
items and the Unit Quiz section as a graded quiz with answer key
(POST /api/admin/import-course-docx, multer memory storage)
- Admin UI: Export button on course detail; Import card with JSON and
Word docs tabs; multi-file picker for docx uploads
- scripts/import-kitchen-course.js: one-time converter that produced
the Kitchen, Tools & Electrical Skills course JSON bundle (already
imported as course id 3: 8 units, 44 items)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Admin enters Across/Down words and clues; server auto-generates the grid
using a backtracking placement algorithm (longest-first, intersection-based).
Students fill in the interactive grid with click-to-select, direction toggle,
arrow-key navigation, and Tab-to-next-word. Auto-graded per word on submit,
with correct/wrong color highlighting on the results view. Includes a print
worksheet option for blank paper practice.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Instead of embedding an iframe, mammoth HTML is inserted straight into
the contenteditable body so the admin can edit it like any other content.
A download link to the original .docx sits above the content.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Switch to Georgia to better match Word's serif rendering
- Explicit font-weight:normal on body/p so mammoth's <strong> wrapping
doesn't bleed into paragraph text
- Tighter heading/paragraph spacing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Removed narrow max-width/margin from generated HTML page
- iframe now spans full card width (100%)
- onload JS auto-sizes iframe height to content so nothing is cut off
- Falls back to 500px if cross-origin restriction ever applies
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the <iframe> with an inline <div> containing the mammoth HTML.
Content now flows full-width with the page instead of being cramped in
a fixed-height scrolling box. Download link still available below.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On upload, mammoth converts the doc to a styled HTML page saved alongside
the .docx. The item body gets an <iframe> pointing to the HTML so students
see the document inline. A download link below gives access to the original.
Falls back to a plain download link if HTML conversion fails.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Instead of parsing .docx content via mammoth and inserting raw text/HTML,
the import flow now saves the file to data/attachments/ (UUID filename) and
inserts an <a> link into the item body so students can open/download the doc.
- Added GET /api/attachments/:filename (no PIN — students access directly)
- Added POST /api/admin/upload-attachment (PIN required)
- Removed mammoth dependency from server
- Updated admin.js import handler to POST to new endpoint and set link HTML
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove all AI processing from the import-docx endpoint. Instead:
- Convert the .docx to HTML with mammoth.convertToHtml (preserves
bold, headings, lists, etc.) — the result goes straight into the
item body and renders in the lesson viewer
- Extract raw text in parallel to pick the document title from the
first non-empty line
- No external services, no AI, works on the deployed server
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The import-docx endpoint was hardcoded to local Ollama, which fails
on the deployed server where Ollama isn't running. Now mirrors the
image scan logic: tries local first, falls back to Ollama Cloud if
configured, using the same scan_primary setting.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The old import scanned a hardcoded Seafile CloudStorage path that only
worked on one specific machine. Replaced with a standard <input type=file>
browser picker that reads the .docx as base64 and uploads it directly, so
the feature works everywhere. Server endpoint now accepts either a base64
payload or the legacy path. Also fixed a crash where resetImportSection()
still referenced the removed select element, which was breaking the item
editor for all item types.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Gradebook now groups items by unit with collapsible cards (same card
style as course detail) and a Course overall summary table at the bottom
- server.js: add unit_id/unit_name to gradebook API so items can be grouped
- Course detail: preserve which units are open and scroll position across
any in-place re-render (add unit, delete unit, save meta, return from
item editor) — no more jumping to the top with everything reset
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Gradebook: period dropdown (all time / 30 / 90 days) and CSV export for
Spelling Test History section
- Student portal spelling tab: shows last 10 tests as a Recent Tests list
- Planner: completed standalone spelling tests appear as read-only ⭐ badges
on the day they were taken (week and month views)
- Removed dead s.tests query from /api/overview (now served by dedicated endpoints)
- New endpoints: GET /api/spelling-tests/csv, GET /api/students/:id/tests,
GET /api/admin/students/:id/tests-range
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a GET /api/spelling-tests endpoint that returns all standalone test
results grouped by student. The Gradebook panel now shows a "Spelling Test
History" section below the course gradebook table. Removed the "Test results"
section from the Spelling panel left column.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Assign → button on each list row opens a popup to pick a kid directly
without scrolling up to the assignment dropdowns
- Hide/Unhide button on built-in lists (stored in localStorage) keeps
UNGROUPED clean; Show hidden toggle reveals them dimmed when needed
- Mastery progress bar on each kid showing X/Y words mastered for their
current assigned list (server now returns listProgress in /api/overview)
- Filter-lists / filter-decks search input for fast lookup by name
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- group_name column added to lists and decks tables
- GET/POST/PUT endpoints for both include group_name
- Admin Spelling and Flashcards panels render items grouped under
labeled section headers (e.g. Bible 6, Bible 8) with ungrouped
items shown last
- Group input in each form has datalist autocomplete from existing groups
- Edit/copy populates the group field; Clear resets it
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- POST /api/courses/:id/duplicate deep-copies a course with all units,
items, and quiz questions; opens the copy immediately for renaming
- Roster changed from broken vertical stack to horizontal chip-pills
(fixes admin-card label override that was collapsing inline-flex)
- item-row padding reduced for tighter lists throughout admin
- Courses and Kids admin panels now use a 2-column auto-fill grid
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Week print: tasks grouped by day, each showing course name, type,
and full assignment body text. Month print: course name in calendar
cells + an Assignment Detail section below the calendar with body text.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Course detail API now returns item body text and quiz questions.
Print course renders body paragraphs and numbered quiz questions
with lettered choices (correct answers marked with ✓).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Month view toggle in planner (Mon-Fri calendar grid, 4-5 weeks)
- Prev/Next navigate by month when in month mode
- Print month report (landscape calendar layout)
- Print course button on course detail (all units + items)
- New GET /api/schedule-range endpoint for arbitrary date spans
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Streak tracker: server-side streak counting per kid, celebration overlay
when all today's tasks are done for the first time that day
- Kid themes: 5 colour palettes (blue/green/purple/orange/pink), picked via
colour dots on the kid home screen; parents can set it from the Kids panel
- Grading badge: Grading nav pill turns red and shows a pending count
- Print worksheets: 🖨 Worksheet button per word list in admin Spelling panel;
kids also get "Print my words" on the Spelling tab
- Parent feedback: gold 💬 badge on Today rows with unread comments; more
prominent callout styling inside the assignment view
- Planner drag-and-drop: tasks can be dragged between days; PATCH
/api/schedule/:id moves the task, drop zones highlight on hover
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Practice: fire streak badge, first-letter hint on wrong answers, missed-words drill session after practice completes.
Test: audio-only mode with listening state before input appears, larger re-read button.
Words: definition field (DB migration + admin editor + TTS playback).
TTS: replace speechSynthesis with local Piper via /api/tts, WAV cached in data/tts-cache, falls back to browser voice when Piper is not installed.
Dockerfile: switched to node:26-slim, installs Piper binary + en_US-lessac-medium voice.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New "Auto-schedule a course" section in the Weekly Planner lets you pick
a course, start date, and items-per-day, then fills the planner in order
skipping weekends. POST /api/schedule/auto handles the logic server-side.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Evidence on assignments: photo upload + notes + student self-note (needs help / not sure)
- Evidence required/optional/none flag per item; grading queue shows evidence with lightbox thumbnail
- Parent comment field when grading; shown to student on graded items
- Offline tasks: 3-state status (not started → in progress → done) with inline evidence form
- Retake policy per item: latest / highest / average — gradebook computes effective score accordingly
- Grading queue expanded to include lessons and practices (not just assignments) when evidence present
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>