ระบบการสอนแบบอินเทอร์แอคทีฟสำหรับหลักสูตรออนไซต์ ที่มาพร้อมกับแบบทดสอบเรียลไทม์และการมีส่วนร่วมของนักเรียน พร้อมระบบจัดการคอร์สแบบอิสระผ่าน mkdocs
- ✅ Checkbox Questions: Multiple-selection questions with array-based answers
- ✅ Markdown Support: Full markdown rendering in questions and options (code blocks, formatting, etc.)
- ✅ Syntax Highlighting: Automatic code highlighting for C++, Python, JavaScript, Arduino, and more
- ✅ Interactive Quiz Creation: Preview and select correct answers directly in the form
- ✅ Quiz Export/Import:
- Export as JSON for backup and migration
- Export as Markdown for documentation and Google Forms conversion
- Import from JSON files
- ✅ Persistent Quiz Monitor: Reusable popup window that updates with each quiz (perfect for dual monitors)
- ✅ Enhanced Answer Display: Clean, human-readable answer formatting
- ✅ Quiz Categories: Organize quizzes into folders
- ✅ Scoring System: Configurable points with automatic grading
- ✅ Quiz Queue System: Per-student queue management with position tracking
- 🔒 Security enhancements: Comprehensive input validation, XSS protection, rate limiting, and stronger password requirements (see SECURITY.md)
- Syntax highlighting for code blocks in quiz questions and options
- Fixed checkbox question type database constraint
- Enhanced quiz validation and error handling
- Improved modal dialogs with proper overlay positioning
- Better export/import error messages
- Environment variable support for database path (
DB_PATH) - Migration scripts with
.envfile support
- Multiple Question Types:
- Text answers (free-form input)
- Multiple choice (single selection)
- Checkbox questions (multiple selection) - NEW!
- Markdown Support: Questions and options support markdown formatting including code blocks
- Interactive Preview: Teachers can preview and select correct answers directly in the creation form
- Quiz Categories: Organize quizzes into folders/categories
- Scoring System: Configurable points per quiz with automatic grading
- Export/Import:
- Export quizzes as JSON for backup and migration
- Export quizzes as Markdown for viewing and Google Forms conversion
- Import quizzes from JSON files
- Teacher Dashboard: Create and push quizzes, see online students, track responses
- Student Interface: Course content with real-time quiz notifications
- WebSocket-based Communication: Instant push notifications and response tracking
- Quiz Monitor Window: Persistent popup window that updates with each new quiz (perfect for dual monitors)
- Response Tracking: Monitor student engagement, answer times, and completion rates
- Timeout Handling: Configurable quiz timeouts with automatic status updates
- Course Enrollment: Students enroll with course-specific passkeys
- Attendance Tracking: Monitor which students are actively viewing course content
- Performance Analytics: Track quiz scores, response rates, and time taken
- Quiz Queue System: Students see upcoming quizzes in their personal queue
- CSV Export: Export student data (basic and full modes) with course and teacher information
- Show Answers: Push quiz results to students showing correct/incorrect answers with color-coded display
- Student Scores: View comprehensive scoring dashboard with filtering and sorting
- Quiz History: Complete history of all quiz pushes and student responses
- Teacher Profile Management: Edit display name and change password through UI
- Multiple Teachers: Support for multiple teacher accounts with separate quiz libraries
- Student Registration: Self-service registration with course enrollment
- Node.js 16+
- npm or yarn
- Python 3.7+ (for course documentation)
- Git
Run the automated setup script:
./setup.shOr manually:
- Install dependencies:
npm install- Initialize and update course submodules:
git submodule update --init --recursive- Setup Python virtual environment and build documentation:
python3 -m venv courses/venv
source courses/venv/bin/activate
pip install mkdocs mkdocs-material
# Build each course
cd courses/your_course && mkdocs build && cd ../..
deactivate- Bootstrap the demo database:
npm run bootstrapNote: This script removes any existing
database.sqlitebefore recreating demo data.
- Start the server:
npm start- Open your browser to
http://localhost:3030(orhttps://localhost:3030if HTTPS is configured)
| Script | Command | Purpose | Used By |
|---|---|---|---|
| setup.sh | npm run setup |
First-time installation: dependencies, submodules, venv, docs build | Developers, new deployments |
| start.sh | npm start |
Development startup: updates submodules, builds docs, starts server | Local development (foreground) |
| startByService.sh | (systemd only) | Production service startup: loads env, starts server only | systemd service (background) |
| auto-update.sh | (timer) | Auto-update: git pull, submodule update, docs build, service restart | systemd timer (every 5 min) |
| test-service.sh | ./test-service.sh |
Check service status and configuration | Testing/debugging production |
Important Notes:
⚠️ Never runbash startByService.shmanually - it will block your terminal. Usesudo systemctl start tutoriazinstead.- For local development: use
npm start(runs in foreground, easy to stop with Ctrl+C) - For production: use
sudo systemctl start tutoriaz(runs in background, managed by systemd)
You can run the Express + Socket.IO server over TLS without a reverse proxy.
- Generate a certificate (use
mkcertoropenssl):mkdir -p certs mkcert -key-file certs/local-key.pem -cert-file certs/local-cert.pem localhost 127.0.0.1 ::1 # or openssl req -x509 -newkey rsa:2048 -nodes -keyout certs/local-key.pem -out certs/local-cert.pem -days 365 - Export the certificate paths before starting the server:
export HTTPS_KEY_PATH=certs/local-key.pem export HTTPS_CERT_PATH=certs/local-cert.pem # optional extras # export HTTPS_CA_PATH=certs/rootCA.pem # single file or comma-separated list # export HTTPS_PASSPHRASE="your-passphrase" npm start
If the key/cert cannot be loaded the server falls back to HTTP automatically. In production you can continue to terminate TLS at a reverse proxy (e.g., Nginx + Let's Encrypt) as described below.
- Teacher: username=
teacher, password=admin123 - Students:
student1-student50, password=student123 - Course Passkey:
JOIN-ESP32(generated by the bootstrap script)
Use the provided script to create additional teacher accounts:
node scripts/createTeacher.js --username=john --password=secure123 --display="John Doe"Options:
--username- Username for login (required)--password- Password for the account (required, min 6 characters)--display- Display name shown in UI (optional, defaults to username)
Example:
# Create a teacher with default display name
node scripts/createTeacher.js --username=teacher2 --password=mypassword
# Create a teacher with custom display name
node scripts/createTeacher.js --username=jane.smith --password=secure456 --display="Dr. Jane Smith"The script will:
- Check if the username already exists
- Hash the password securely using bcrypt
- Create the teacher account in the database
- Display the new user ID
Teachers can update their own profile through the web interface:
- Log in to the teacher dashboard
- Click the "⚙️ Profile" button in the header (next to Logout)
- Update display name and/or password:
- Display Name: Change how your name appears to students
- Password: Enter current password, then new password (min 6 characters)
- Click "💾 Save Changes"
Security Notes:
- Changing password requires entering your current password
- Passwords are validated for minimum length (6 characters)
- All passwords are hashed using bcrypt before storage
- Login with teacher credentials
- Edit Your Profile: Click "⚙️ Profile" button to update display name or change password
- Create Quizzes:
- Choose question type (text, multiple choice, or checkbox)
- Use markdown for formatting (code blocks, bold, italic, etc.)
- Preview options with interactive answer selection
- Organize with categories
- Set time limits and point values
- Push Quizzes: Send quizzes to all online students or specific courses
- Monitor Responses: Watch real-time responses in a persistent popup window
- Export Quizzes:
- JSON format: For backup and importing to other courses
- Markdown format: For documentation or converting to Google Forms
- Import Quizzes: Upload JSON files to reuse quizzes across courses
- Export Student Data: Click "📥 Export CSV" to download student performance data
- Show Quiz Results: Click "📋 Show Answers to Students" to push quiz results with correct answers
- Undo quiz pushes if needed
- Login with student credentials or register with course passkey
- View course content on the main page
- Receive Quiz Notifications:
- Quizzes appear as overlay notifications
- See your position in the queue
- Markdown-formatted questions and options
- Answer Quizzes:
- Text input for free-form answers
- Radio buttons for single-choice questions
- Checkboxes for multiple-selection questions
- Submit answers within the time limit
- See confirmation when answers are submitted
- View Quiz Results: When teacher pushes answers, see your results with correct answers highlighted
- Track your quiz history and scores
Course materials are maintained in separate repositories and included as Git submodules under the courses/ directory. Each course uses MkDocs with Material theme for documentation.
Follow these steps to create and add a new course to the platform:
Create a new folder for your course content:
mkdir my_new_course
cd my_new_course
git initSet up the MkDocs structure:
# Create MkDocs configuration
cat > mkdocs.yml << 'EOF'
site_name: My New Course
theme:
name: material
palette:
primary: indigo
accent: indigo
features:
- navigation.sections
- navigation.expand
- navigation.top
nav:
- Home: index.md
- Getting Started: getting-started.md
- Module 1: modules/module-01.md
- Module 2: modules/module-02.md
- Reference: appendix/reference.md
EOF
# Create documentation structure
mkdir -p docs/{modules,appendix,assets/{images,snippets}}
# Write your course content
cat > docs/index.md << 'EOF'
# Welcome to My New Course
Course overview and introduction...
EOF
# Create module files
echo "# Module 1: Introduction" > docs/modules/module-01.md
echo "# Module 2: Advanced Topics" > docs/modules/module-02.md
echo "# Getting Started" > docs/getting-started.md
echo "# Reference Materials" > docs/appendix/reference.mdInstall MkDocs and preview your course locally:
# Create virtual environment (recommended)
python3 -m venv venv
source venv/bin/activate
# Install MkDocs
pip install mkdocs mkdocs-material
# Serve locally (live preview)
mkdocs serve
# Visit http://127.0.0.1:8000
# Build static site
mkdocs build
# Output will be in site/ directoryVerify that:
- All pages load correctly
- Navigation works as expected
- Images and assets display properly
- Mobile view renders correctly
Push your course to GitHub (or your Git hosting):
# Add a .gitignore
cat > .gitignore << 'EOF'
site/
venv/
__pycache__/
*.pyc
.DS_Store
EOF
# Commit and push
git add .
git commit -m "Initial course content"
git remote add origin https://github.com/yourusername/my_new_course.git
git push -u origin mainIn the main tutoriaz repository, add your course as a submodule:
cd /path/to/tutoriaz
# Add the course as a submodule
git submodule add https://github.com/yourusername/my_new_course.git courses/my_new_course
# Initialize and update submodules
git submodule update --init --recursive
# Commit the submodule addition
git add .gitmodules courses/my_new_course
git commit -m "Add my_new_course submodule"
git pushAdd the course to the database through the teacher dashboard:
- Login as teacher
- Click "New Course" button
- Fill in course details:
- Title: My New Course
- Description: Brief description of the course
- Documentation URL:
https://github.com/yourusername/my_new_course.git - Documentation Branch:
main - Access Code: Generate a passkey (e.g.,
JOIN-MYNEWCOURSE)
- Click "Create Course"
The platform will automatically:
- Pull the submodule when updates are available
- Build documentation using MkDocs in a virtual environment
- Serve the static site at
/docs/my_new_course/
To update an existing course:
# Navigate to the course submodule
cd courses/my_new_course
# Make your changes
vim docs/modules/module-01.md
# Test locally
source venv/bin/activate
mkdocs serve
# Commit and push
git add .
git commit -m "Update module 1 content"
git pushThe auto-update script on the production server will:
- Detect new commits every 5 minutes
- Pull the latest changes
- Rebuild the documentation
- Restart the service
Each course should follow this structure:
my_new_course/
├── mkdocs.yml # MkDocs configuration
├── docs/
│ ├── index.md # Course homepage
│ ├── getting-started.md
│ ├── modules/ # Course modules
│ │ ├── module-01.md
│ │ └── module-02.md
│ ├── appendix/ # Reference materials
│ │ └── reference.md
│ └── assets/ # Images, code snippets
│ ├── images/
│ └── snippets/
├── venv/ # Python virtual environment (gitignored)
├── site/ # Built documentation (gitignored)
└── .gitignore
- Backend: Node.js + Express + Socket.IO + SQLite
- Frontend: Vanilla HTML/CSS/JavaScript with Socket.IO client
- Database: SQLite for demo (easily switchable to PostgreSQL)
- Real-time: WebSocket connections for live quiz distribution
POST /api/login- User authenticationPOST /api/register- Student registrationGET /api/me- Get current user infoPUT /api/profile- Update user profile (display name and password)
GET /api/courses- List courses (context-aware for teachers/students)POST /api/courses- Create new course (teacher only)POST /api/courses/:courseId/enroll- Enroll in course (student only)GET /api/courses/:courseId/export-csv- Export student data as CSV (teacher only)POST /api/courses/:courseId/push-answers- Push quiz results to students (teacher only)
GET /api/quizzes- List teacher's quizzesPOST /api/quizzes- Create new quizPUT /api/quizzes/:quizId- Update existing quizDELETE /api/quizzes/:quizId- Delete quizGET /api/quizzes/:quizId/responses- Get quiz responsesPOST /api/quizzes/export- Export quizzes as JSON or MarkdownPOST /api/quizzes/import- Import quizzes from JSONPOST /api/pushes- Push quiz to studentsPOST /api/pushes/:id/undo- Undo quiz push
GET /api/categories- List quiz categoriesPOST /api/categories- Create new categoryPUT /api/categories/:id- Update categoryDELETE /api/categories/:id- Delete category
GET /api/students/online- List online students (teacher only)
auth- Authenticate with JWT tokenauth_ok/auth_error- Authentication responses
quiz_push- Server pushes quiz to studentsquiz_queue_updated- Server updates student's quiz queueshow_next_quiz- Server tells student to display next quizqueue_empty- Notify student queue is emptyquiz_answer- Student submits answerquiz_response- Server notifies teachers of responsesquiz_undo- Server cancels active quizquiz_timeout- Quiz timeout notificationshow_answers- Server pushes quiz results to students with correct answers
online_students- Updates list of connected students
The platform implements comprehensive security measures to protect against common vulnerabilities:
- 🔒 Authentication: Bcrypt password hashing with configurable rounds
- 🛡️ Rate Limiting: Protection against brute force attacks (15 requests per 15 minutes)
- 🔐 Input Validation: Strict username and password requirements
- ✨ XSS Protection: All user-generated content sanitized using the
xsslibrary - 💉 SQL Injection: All database queries use parameterized statements
- 🔑 JWT Tokens: Secure token-based authentication with 24-hour expiry
- 🚫 Reserved Usernames: System usernames blocked (admin, root, etc.)
- 📏 Body Size Limits: Request payload size capped at 8KB
- Minimum 8 characters
- Maximum 128 characters
- Must contain at least one letter
- Must contain at least one number or symbol
- 3-30 characters
- Letters, numbers, and underscore only
- Must start with a letter
- Case-insensitive
For detailed security information, see SECURITY.md
Run the security test suite:
node test-security.jsThe platform includes database migrations for schema updates. To run a migration:
# Run specific migration (automatically loads .env)
node scripts/migrate-011.js
# Or with explicit DB_PATH
DB_PATH=/var/lib/tutoriaz/database.sqlite node scripts/migrate-011.jsCheck Quiz Data:
node scripts/checkQuizData.jsShows detailed information about quizzes and their options, useful for debugging.
Fix Checkbox Quizzes:
node scripts/fixCheckboxQuiz.jsRepairs checkbox quizzes that were created without options (before the fix).
The platform supports these environment variables:
DB_PATH- Path to SQLite database (default:./database.sqlite)PORT- Server port (default:3030)HOST- Server host (default:0.0.0.0)NODE_ENV- Environment mode (developmentorproduction)JWT_SECRET- Secret for JWT tokensHTTPS_KEY_PATH- Path to HTTPS private keyHTTPS_CERT_PATH- Path to HTTPS certificateHTTPS_CA_PATH- Path to CA certificate(s)HTTPS_PASSPHRASE- Passphrase for HTTPS key
Create a .env file in the project root:
DB_PATH=/var/lib/tutoriaz/database.sqlite
PORT=3030
NODE_ENV=production
JWT_SECRET=your-secret-hereThe platform uses these main tables:
users- User accounts (teachers/students) with profile informationcourses- Course definitions with access codes and documentation settingscourse_enrollments- Student course enrollment trackingcourse_attendance_sessions- Student viewing/attendance trackingquiz_categories- Quiz organization foldersquizzes- Quiz definitions with scoring and timeout settingsquiz_pushes- Quiz distribution instances with targetingquiz_responses- Student answers and engagement data with correctness trackingstudent_quiz_queue- Per-student quiz queue management
├── server.js # Main server application
├── schema.sql # Database schema
├── migrations/ # Database migrations
│ ├── 011_add_checkbox_question_type.sql
│ └── ...
├── courses/ # Course documentation (Git submodules)
│ └── esp32_basic/
│ ├── mkdocs.yml
│ └── docs/
├── scripts/
│ ├── bootstrapDemo.js # Combined wipe + seed helper
│ ├── createTeacher.js # Standalone teacher seeding utility
│ ├── createStudents.js # Standalone student batch creator
│ ├── seedQuizzes.js # Standalone quiz seeding utility
│ ├── testPushUndo.js # Integration test for push/undo flow
│ ├── migrate-011.js # Migration script for checkbox support
│ ├── checkQuizData.js # Database inspection tool
│ └── fixCheckboxQuiz.js # Quiz data repair utility
├── public/
│ ├── index.html # Login page
│ ├── register.html # Student registration
│ ├── teacher.html # Teacher dashboard
│ ├── student.html # Student interface
│ └── quiz-monitor.html # Quiz monitoring popup
├── example_quiz_export.json # Example JSON export
├── example_quiz_export.md # Example Markdown export
├── QUIZ_EXPORT_IMPORT.md # Export/Import documentation
├── MARKDOWN_EXPORT_GUIDE.md # Markdown export guide
└── package.json # Dependencies and scripts
- Install Node.js:
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs- Create application user:
sudo useradd -m -s /bin/bash esp32course
sudo su - esp32course- Clone and setup:
git clone <your-repo> esp32-course-platform
cd esp32-course-platform
git submodule update --init --recursive # Initialize docs submodule
npm install --production
npm run init-dbCreate /etc/systemd/system/esp32course.service:
[Unit]
Description=Tutoriaz - Real-time Quiz Platform
After=network.target
[Service]
Type=simple
User=esp32course
WorkingDirectory=/home/esp32course/esp32-course-platform
ExecStart=/usr/bin/node server.js
Restart=always
RestartSec=10
Environment=NODE_ENV=production
Environment=PORT=3000
[Install]
WantedBy=multi-user.targetStart service:
sudo systemctl enable esp32course
sudo systemctl start esp32courseInstall nginx:
sudo apt update
sudo apt install nginxCreate /etc/nginx/sites-available/esp32course:
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:3030;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}Enable site:
sudo ln -s /etc/nginx/sites-available/esp32course /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginxsudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.com- Change JWT_SECRET in production
- Use environment variables for sensitive config
- Enable HTTPS/SSL
- Implement rate limiting
- Add input validation and sanitization
- Switch to PostgreSQL for better concurrency:
sudo apt install postgresql postgresql-contrib
sudo -u postgres createdb esp32course- Update connection in
server.jsto usepgpackage
- Add logging with winston
- Monitor with PM2 or systemd
- Set up health checks
- Monitor WebSocket connections
- Use Redis for WebSocket session storage
- Load balance with multiple Node.js instances
- Separate database server
- CDN for static assets
- Port already in use: Change PORT in environment or stop conflicting process
- Database locked: Ensure SQLite file permissions are correct
- WebSocket connection fails: Check firewall and proxy settings
- Students don't receive quizzes: Verify authentication and WebSocket connection
Check application logs:
sudo journalctl -u esp32course -fView database content:
sqlite3 database.sqlite
.tables
SELECT * FROM users;Modulemore Co., Ltd.
MIT License - see LICENSE file for details.