Professional speedcubing timer and analytics platform.
- Auth — email/password signup with email verification, WCA ID linking
- Sessions — persistent solve sessions stored in SQLite
- Timer — WCA-compliant inspection, spacebar/touch controls, no-scroll layout
- Scrambles — official WCA scramble algorithm via cubing.net (same as competitions)
- Segmented Solves — mark Cross / F2L / OLL / PLL splits during a solve (CFOP, Roux, custom)
- WCA Integration — full PR table for all 17 events with world and national ranks
- Competition Comparison — statistical analysis of home vs official results
- Speed-Tiered Coaching — tips calibrated to your current average
- CV Analysis — local MediaPipe hand detection, TPS estimation, regrip & pause detection
- Color Themes — built-in presets + full custom color picker
- Import/Export — native backup format + csTimer import (times, penalties, scrambles)
npm installcp .env.example .env
# Edit .env with your settingsWithout SMTP, email verification is skipped automatically in development.
Gmail: Enable 2FA → Security → App Passwords → generate one for "Mail".
Set in .env:
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=you@gmail.com
SMTP_PASS=your_app_password
SMTP_FROM=noreply@yourdomain.com
npm start
# or for development with auto-restart:
npm run devSQLite database (cublytics.db) is created automatically on first run.
Tables:
users— accounts, hashed passwords, WCA IDs, color schemessessions— named practice sessions per usersolves— individual solves with time, display, scramble, segments
Click "Continue as Guest" to use the app without an account. Data is stored in localStorage and can be exported/imported as JSON.
In csTimer: File → Export → Export to file → upload the .json here.
Transfers: all sessions, times, +2/DNF penalties, scrambles, timestamps.
| Variable | Value |
|---|---|
BASE_URL |
https://cublytics.onrender.com |
JWT_SECRET |
Any long random string |
SMTP_HOST |
smtp.gmail.com |
SMTP_PORT |
587 |
SMTP_USER |
Your Gmail address |
SMTP_PASS |
Your Gmail App Password |
SMTP_FROM |
noreply@cublytics.app (or your address) |
Render's free tier has an ephemeral filesystem — the SQLite database (cublytics.db) is wiped on every redeploy or restart.
Options to persist data:
- Render Disk (paid, $1/month) — add a persistent disk at
/var/data, then setDB_PATH=/var/data/cublytics.db - Free alternative — users can export their data (Account → Export) before redeploying and reimport afterward
- Upgrade to Render paid tier and mount a persistent volume
-
Enable 2-Factor Authentication on your Google account
-
Go to Google Account → Security → App Passwords
-
Create a new app password for "Mail"
-
Paste it as
SMTP_PASSin Render -
Set
JWT_SECRETto a long random string -
Set
BASE_URLto your domain -
Use a reverse proxy (nginx/caddy) in front of the Node server
-
Consider using a process manager (PM2, systemd)