Skip to content

Commit 561ba8d

Browse files
author
hatim
committed
2.0: brutalist treatment + meta polish + CI
No app behavior changed. Brings the repo in line with the rest of my portfolio's house style and adds the missing-but-expected meta: Meta polish (index.html) ------------------------ - Open Graph (og:type, og:title, og:description) - Twitter Card (summary variant) - theme-color matching the pink brand accent - Inline SVG favicon (no asset round-trip; gradient L-mark) - Pinned FontAwesome 6.4.0 (was already at 6.4.0 but now explicit in the comment) Brand ----- - assets-readme/ hero banner SVGs (light + dark via <picture> + prefers-color-scheme) - README rewritten in brutalist house style with an ASCII layout diagram of the toolbar/content/sidebar tri-pane, "why it exists" framing, customisation notes, and explicit project layout CI -- - .github/workflows/ci.yml runs `npm run build` and sanity-checks that dist/index.html + dist/assets/ exist + reports bundle size - artifact upload (14-day retention) Topics ------ - Added: teacher, language-learning, offline-first, teaching, rich-text-editor, undo-redo, vanilla-js (now 13 total)
1 parent f622092 commit 561ba8d

5 files changed

Lines changed: 239 additions & 111 deletions

File tree

.github/workflows/ci.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
workflow_dispatch:
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
build:
15+
name: Vite build
16+
runs-on: ubuntu-latest
17+
timeout-minutes: 5
18+
19+
steps:
20+
- uses: actions/checkout@v5
21+
22+
- uses: actions/setup-node@v4
23+
with:
24+
node-version: "20"
25+
cache: npm
26+
27+
- name: Install
28+
run: npm ci
29+
30+
- name: Build
31+
run: npm run build
32+
33+
- name: Sanity-check dist
34+
run: |
35+
test -f dist/index.html
36+
test -d dist/assets
37+
echo "Bundle size: $(du -sh dist | cut -f1)"
38+
39+
- uses: actions/upload-artifact@v4
40+
with:
41+
name: dist
42+
path: dist/
43+
retention-days: 14

README.md

Lines changed: 118 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,142 +1,150 @@
1-
<div align="center">
2-
<img src="https://img.shields.io/badge/LessonForge-Teaching%20Dashboard-E11D6B?style=for-the-badge&logo=bookstack&logoColor=white" alt="LessonForge">
3-
4-
<h1>🎓 LessonForge</h1>
5-
<p><strong>Open-source lesson management terminal for language teachers</strong></p>
6-
<p>A beautiful, offline-capable dashboard to organize lessons, track class time, manage student profiles, and store teaching resources — all in your browser.</p>
7-
8-
<br>
9-
10-
![Vite](https://img.shields.io/badge/Vite-6.0-646CFF?logo=vite&logoColor=white)
11-
![JavaScript](https://img.shields.io/badge/JavaScript-ES2024-F7DF1E?logo=javascript&logoColor=black)
12-
![CSS](https://img.shields.io/badge/CSS-Custom%20Properties-1572B6?logo=css3&logoColor=white)
13-
![License](https://img.shields.io/badge/License-MIT-green)
14-
</div>
15-
16-
---
17-
18-
## ✨ Features
19-
20-
### 📖 Lesson Management
21-
- **Multi-page lessons** — Organize content into separate pages (Warm-Up, Vocabulary, Grammar, etc.)
22-
- **Rich-text editing** — Bold, italic, underline, colored highlights, lists
23-
- **Drag-and-drop reordering** — Rearrange lesson pages by dragging
24-
- **Import/Export** — Share lesson plans as JSON files with colleagues
25-
26-
### 🧰 Toolkit
27-
- **Resource cards** — Quick-reference grammar rules, vocabulary, pronunciation tips
28-
- **Categorized & filterable** — Filter cards by type (Grammar, Vocabulary, Connectors, etc.)
29-
- **Custom categories** — Add your own card categories
30-
- **Fully editable** — Add, edit, and delete cards in edit mode
31-
32-
### ⏱️ Timer
33-
- **Stopwatch mode** — Count up during class
34-
- **Countdown mode** — Set a timer (e.g. 25 minutes) with visual warnings at 60s and expiry alert
35-
- **Keyboard shortcut** — Press `0` to start/stop
36-
37-
### 👩‍🎓 Student Profiles
38-
- Save student **name, level, and notes**
39-
- Quick-switch between students from the toolbar dropdown
40-
- Stored in localStorage — persists across sessions
41-
42-
### 🎨 Design
43-
- **Sakura theme** — Soft pink/rose palette in light mode, deep rose in dark mode
44-
- **Dark mode toggle** — One-click switch
45-
- **Print stylesheet**`Ctrl+P` prints just the lesson content, no UI chrome
46-
- **Keyboard-first** — Number keys to switch pages, `E` to edit, `?` for shortcuts
47-
48-
### 💾 Data
49-
- **LocalStorage persistence** — All data auto-saved
50-
- **Undo/Redo** — Up to 50 history snapshots
51-
- **JSON import/export** — Portable lesson plans
1+
<p align="center">
2+
<picture>
3+
<source media="(prefers-color-scheme: dark)" srcset="assets-readme/hero-banner-dark.svg" />
4+
<img src="assets-readme/hero-banner.svg" alt="LessonForge" width="100%" />
5+
</picture>
6+
</p>
7+
8+
<p align="center">
9+
<a href="https://github.com/hatimhtm/LessonForge/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/hatimhtm/LessonForge/ci.yml?branch=main&style=for-the-badge&label=CI&labelColor=1A1A1A&color=CCFF00" alt="CI" /></a>
10+
<img src="https://img.shields.io/badge/Vite-6-1A1A1A?style=for-the-badge&logo=vite&logoColor=CCFF00" alt="Vite 6" />
11+
<img src="https://img.shields.io/badge/Vanilla_JS-1A1A1A?style=for-the-badge&logo=javascript&logoColor=CCFF00" alt="Vanilla JS" />
12+
<img src="https://img.shields.io/badge/Offline_First-1A1A1A?style=for-the-badge&logo=html5&logoColor=CCFF00" alt="Offline-first" />
13+
<a href="LICENSE"><img src="https://img.shields.io/badge/LICENSE-MIT-1A1A1A?style=for-the-badge&labelColor=1A1A1A&color=CCFF00" alt="MIT" /></a>
14+
</p>
15+
16+
<p align="center">
17+
<em>A teaching dashboard for language tutors. Multi-page lessons, a built-in timer, student profiles, drag-and-drop reordering, a categorised toolkit of grammar / vocab / pronunciation cards, undo/redo history, and JSON import/export — all running in a browser tab with zero backend and full offline persistence via <code>localStorage</code>. ~2,500 LOC of vanilla JS on Vite, no framework, no dependencies in the wheel.</em>
18+
</p>
5219

5320
---
5421

55-
## 🚀 Quick Start
22+
### `/// WHAT IT IS`
5623

57-
```bash
58-
# Clone the repo
59-
git clone https://github.com/hatimhtm/LessonForge.git
60-
cd LessonForge
24+
```
25+
┌─────────────────────────────────────────────────────────────────┐
26+
│ TOOLBAR │
27+
│ ▸ Page tabs (drag to reorder in edit mode) │
28+
│ ▸ Toolkit filters · Timer (stopwatch / countdown) │
29+
│ ▸ Edit mode · Undo / Redo · Reset session · Print │
30+
│ ▸ Import / Export JSON · Theme toggle │
31+
├──────────────────┬──────────────────────────────────────────────┤
32+
│ CONTENT │ TOOLKIT (right rail) │
33+
│ ▸ Rich-text page │ ▸ Categorised reference cards │
34+
│ (B / I / U / │ ▸ Filter by category │
35+
│ highlights / │ ▸ Custom categories │
36+
│ lists) │ ▸ Add / edit / delete in edit mode │
37+
│ ▸ Auto-saves to │ │
38+
│ localStorage │ STUDENT PANEL │
39+
│ on every edit │ ▸ Per-student profile + notes │
40+
│ │ ▸ Active-student indicator │
41+
│ │ │
42+
│ │ CHECKLIST │
43+
│ │ ▸ Per-session checkbox state │
44+
│ │ ▸ Cleared on "Reset session" │
45+
└──────────────────┴──────────────────────────────────────────────┘
46+
```
6147

62-
# Install dependencies
63-
npm install
48+
---
6449

65-
# Start dev server
66-
npm run dev
67-
```
50+
### `/// WHY IT EXISTS`
6851

69-
Open [http://localhost:5173](http://localhost:5173) in your browser.
52+
Most lesson-prep tools either lock you into a SaaS subscription or expect you to live inside Google Docs / Notion. LessonForge fits the actual tutoring workflow: open a tab between Zoom calls, swipe through the lesson plan, click "next page" mid-class, hit space to start the timer, scribble in the rich-text editor while the student is talking, undo a wrong edit, export the whole plan as JSON when the lesson's done.
7053

71-
### Production Build
72-
```bash
73-
npm run build
74-
npm run preview
75-
```
54+
Built for **one teacher**, **one device**, **no signups, no sync, no servers** — just `localStorage` and a print stylesheet for when you need a paper copy.
7655

7756
---
7857

79-
## ⌨️ Keyboard Shortcuts
58+
### `/// HIGHLIGHTS`
8059

81-
| Key | Action |
60+
| | |
8261
|---|---|
83-
| `1``9` | Switch lesson page |
84-
| `0` | Start/stop timer |
85-
| `E` | Toggle edit mode |
86-
| `?` | Show shortcuts modal |
87-
| `⌘Z` / `Ctrl+Z` | Undo |
88-
| `⌘⇧Z` / `Ctrl+Shift+Z` | Redo |
89-
| `⌘S` / `Ctrl+S` | Export lesson |
90-
| `Esc` | Close modals |
62+
| **Multi-page lessons** | Tabs for Warm-Up / Vocab / Grammar / Practice / Wrap-Up. Drag the tab order in edit mode. Per-page rich-text content survives reloads. |
63+
| **Rich-text editor** | `contenteditable` body with bold / italic / underline / highlight / lists. No external editor lib — just `document.execCommand` for the basics. |
64+
| **Toolkit cards** | Categorised reference cards (grammar rules, vocab, connectors, pronunciation tips, conjugations). Filter by category. Add custom categories. |
65+
| **Built-in timer** | Stopwatch + countdown modes. Survives tab switches via `setInterval`. |
66+
| **Student profiles** | Per-student name, level, notes. Active-student indicator at the top of the right rail. |
67+
| **Session checklist** | Per-session todos (warm-up done, homework collected, etc.). One-click "Reset session" clears boxes + timer + temporary notes — but not your lesson plan. |
68+
| **Undo / Redo history** | 50-step ring buffer in `state.js`. Every meaningful change snapshots. Keyboard shortcuts `Ctrl/⌘+Z` and `Ctrl/⌘+Shift+Z`. |
69+
| **Import / Export JSON** | One button: download the entire workspace as `lessonforge-export.json`. Share lesson plans with colleagues, back up before a redesign, restore on a new machine. |
70+
| **Offline-first** | Once the tab loads, no network. All state in `localStorage`. Yes, the Google Fonts + FontAwesome CDN need a first online load; everything else is cached. |
71+
| **Print stylesheet** | Dedicated `print.css` strips the chrome and prints the active lesson page cleanly for in-class handouts. |
72+
| **Keyboard shortcuts** | `Ctrl/⌘+Z` undo · `Ctrl/⌘+Shift+Z` redo · `Ctrl/⌘+E` toggle edit mode · `Ctrl/⌘+S` save / export · `Ctrl/⌘+P` print. |
9173

9274
---
9375

94-
## 📁 Project Structure
76+
### `/// PROJECT LAYOUT`
9577

9678
```
9779
LessonForge/
98-
├── index.html # App entry point
99-
├── package.json # Dependencies & scripts
100-
├── vite.config.js # Build config
101-
└── src/
102-
├── main.js # App controller
103-
├── state.js # State manager (localStorage, undo/redo)
104-
├── data.js # Demo content & defaults
105-
└── styles/
106-
├── variables.css # Design tokens & themes
107-
├── layout.css # Grid layout & modals
108-
├── toolbar.css # Toolbar & buttons
109-
├── content.css # Lesson content typography
110-
├── toolkit.css # Resource cards & filters
111-
├── sidebar.css # Navigation & checklist
112-
├── shortcuts.css # Shortcuts modal
113-
└── print.css # Print stylesheet
80+
├── index.html single-page shell — toolbar + content + sidebar
81+
├── package.json vite only — zero runtime deps
82+
├── vite.config.js
83+
├── src/
84+
│ ├── main.js app controller — render · events · drag · timer
85+
│ ├── state.js StateManager — localStorage · undo/redo · snapshots
86+
│ ├── data.js default lessons + cards + categories + checklist
87+
│ └── styles/
88+
│ ├── variables.css tokens — colors, fonts, spacing, radii, shadows
89+
│ ├── layout.css page grid + toolbar layout
90+
│ ├── toolbar.css action buttons, dropdowns, timer chip
91+
│ ├── content.css rich-text editor + page tabs
92+
│ ├── toolkit.css right-rail cards + filter chips
93+
│ ├── sidebar.css student panel + session checklist
94+
│ ├── shortcuts.css keyboard-shortcut hint chip
95+
│ └── print.css print-only stylesheet (strips chrome)
96+
└── assets-readme/ brutalist banner SVGs (light + dark)
11497
```
11598

11699
---
117100

118-
## 🔧 Customization
101+
### `/// LOCAL DEV`
119102

120-
### Adding Your Own Lessons
121-
1. Click **Edit** in the toolbar
122-
2. Create pages, add toolkit cards, customize the checklist
123-
3. Click **Export** to save your lesson as a JSON file
124-
4. Share the JSON with colleagues — they can click **Import** to load it
103+
```bash
104+
git clone https://github.com/hatimhtm/LessonForge.git
105+
cd LessonForge
106+
npm install
107+
npm run dev # vite dev server → http://localhost:5173
108+
npm run build # production bundle → dist/
109+
npm run preview # serve dist/ → http://localhost:4173
110+
```
111+
112+
Static output — drop `dist/` on any host (Vercel, Netlify, GitHub Pages, S3, your own teacher portal).
113+
114+
---
115+
116+
### `/// CUSTOMISATION`
125117

126-
### Changing the Theme
127-
Edit `src/styles/variables.css` to customize colors, fonts, spacing, and border radius tokens.
118+
- **Theme:** edit `src/styles/variables.css`. CSS custom properties drive every color, radius, shadow, font stack.
119+
- **Default lessons:** edit `src/data.js`. `defaultPages` / `defaultTools` / `defaultCategories` / `defaultChecklist` populate the first run; subsequent sessions load from `localStorage`.
120+
- **Add a category:** in edit mode, click the "+" next to the category chips. State persists automatically.
121+
- **Replace the icons:** the FontAwesome CDN load can be swapped for Lucide / Phosphor / Heroicons by editing two lines in `index.html` and the icon classes throughout.
128122

129123
---
130124

131-
## 📄 License
125+
### `/// 2.0 — POLISH`
132126

133-
MIT — free for personal and commercial use.
127+
- **Brutalist house-style README** + light/dark hero banners.
128+
- **Open Graph + Twitter Card** meta for social sharing.
129+
- **`theme-color`** meta so the browser chrome matches the pink accent on mobile.
130+
- **Inline SVG favicon** (no asset round-trip).
131+
- **CI workflow** (`vite build` + dist sanity check) so every push verifies the bundle still ships.
134132

135133
---
136134

137-
<div align="center">
138-
<p><sub>Built with ❤️ for teachers everywhere</sub></p>
139-
140-
[![Portfolio](https://img.shields.io/badge/Portfolio-hatimelhassak.is--a.dev-E11D6B?style=flat-square&logo=safari&logoColor=white)](https://hatimelhassak.is-a.dev)
141-
[![LinkedIn](https://img.shields.io/badge/LinkedIn-Hatim%20El%20Hassak-0A66C2?style=flat-square&logo=linkedin&logoColor=white)](https://linkedin.com/in/hatimelhassak)
142-
</div>
135+
### `/// LICENSE`
136+
137+
[MIT](LICENSE). Fork it, ship your own teacher dashboard, change the colour palette, re-skin it for any subject (it's hardcoded for languages but the bones are general). Just keep the copyright line.
138+
139+
---
140+
141+
<p align="center">
142+
<a href="https://hatimelhassak.is-a.dev"><img src="https://img.shields.io/badge/PORTFOLIO-1A1A1A?style=for-the-badge&logo=vercel&logoColor=CCFF00" alt="Portfolio" /></a>
143+
<a href="https://cal.com/hatimelhassak/engineering-discovery"><img src="https://img.shields.io/badge/BOOK_A_CALL-CCFF00?style=for-the-badge&logo=googlecalendar&logoColor=1A1A1A" alt="Book a call" /></a>
144+
<a href="https://www.linkedin.com/in/hatim-elhassak/"><img src="https://img.shields.io/badge/LINKEDIN-1A1A1A?style=for-the-badge&logo=linkedin&logoColor=CCFF00" alt="LinkedIn" /></a>
145+
<a href="mailto:hatimelhassak.official@gmail.com"><img src="https://img.shields.io/badge/EMAIL-1A1A1A?style=for-the-badge&logo=gmail&logoColor=CCFF00" alt="Email" /></a>
146+
</p>
147+
148+
<p align="center">
149+
<code>///&nbsp;&nbsp;OPEN FOR NEW WORK&nbsp;&nbsp;///&nbsp;&nbsp;CONTRACT &amp; FREELANCE&nbsp;&nbsp;///&nbsp;&nbsp;REMOTE WORLDWIDE&nbsp;&nbsp;///</code>
150+
</p>

assets-readme/hero-banner-dark.svg

Lines changed: 32 additions & 0 deletions
Loading

assets-readme/hero-banner.svg

Lines changed: 32 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)