The live room now behaves like a game screen instead of a scrolling page: adaptive 100dvh layout, split Excel question workspace, compact host controls and a mobile leaderboard drawer. v20 also adds Team Battle and a shared-HP Boss Workbook multiplayer mode. See docs/v20-live-room-team-boss.md.
- 10 Excel lessons covering text, logic, lookup, and conditional aggregation functions.
- 125 practice questions and 24 Quick Exam questions.
- 12 interaction types, including formula input, cell selection, ordering, matching, and error diagnosis.
- Excel-first Formula Arena with speed, debugging, cell-reading, reference-lock and Boss Workbook modes.
- Local-first progress and preferences; personal learning requires no account.
- Community question sets and reusable creator-owned sets.
- Live multiplayer rooms with reconnect support, automatic round flow, host moderation, four game presets, pause/resume, SFX, and durable leaderboards.
- Vietnamese and English interface powered by i18next.
The learning content is currently authored in Vietnamese. Application navigation, landing, settings, set discovery, and shared interface controls support Vietnamese and English.
Room setup now starts with a question set and one of four presets instead of exposing every switch at once:
- Classic — balanced timing, speed points, live leaderboard.
- Lightning — 12-second rounds for fast reaction play.
- Focus — longer rounds with the leaderboard hidden during play.
- Streak Rush — larger combo bonuses for consecutive correct answers.
The server owns round progression. When every active player has answered, Fomuli keeps the result visible for the configured reveal time and then advances automatically. If time expires, it advances without requiring a host click. Hosts can play as a scored participant or stay in control-only mode, and can pause/resume, skip, kick players, or end the game.
The Set Builder also supports creating common custom question types inline. Custom questions stay creator-owned/private, but a public or unlisted set can securely use them without exposing its answer key or making the question globally discoverable.
Learn a concept
↓
Practise in multiple formats
↓
Incorrect ─────→ return later in the session
│ ↓
└────────────→ schedule an earlier review
Correct → 1 day → 3 days → 7 days → 14 days → ...
The /review route prioritizes questions that are actually due instead of replaying the entire course.
- Single choice
- True or false
- Multiple choice
- Formula input
- Fill in the missing segment
- Predict a result
- Repair a broken formula
- Build a formula from blocks
- Put blocks in the correct order
- Match related items
- Select a spreadsheet cell
- Diagnose the formula segment causing an error
Personal learning, public sets, and entering a room code do not require a permanent account. Fomuli creates an anonymous Appwrite session in the background when a room player needs a reconnectable identity.
Creators use a permanent account to:
- create and edit question sets;
- publish public or unlisted sets;
- create rooms;
- control live rounds.
| Role | Learn | Play public sets | Join rooms | Manage own sets | Host rooms | Official content |
|---|---|---|---|---|---|---|
| Guest | ✓ | ✓ | ✓ | — | — | — |
| Room player | ✓ | ✓ | ✓ | — | — | — |
| Creator | ✓ | ✓ | ✓ | ✓ | ✓ | — |
| Administrator | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
See Access control for the complete policy.
Scores and host privileges are never trusted from the browser.
player answer
↓
Appwrite Function
↓
verify identity, membership, current question, and deadline
↓
compare against the private answer key
↓
commit answer and score in one database transaction
↓
publish the updated documents through Realtime
The question_answers collection is not readable by browser roles. Clients cannot directly update score, streak, is_host, room state, or submitted answers.
Fomuli uses i18next and react-i18next with bundled resources, so changing language does not require a network request.
- Configuration and translations:
src/i18n.ts - Language preference:
AppSettings.language - Selector:
/settings - Supported interface languages:
vi,en - Fallback language: Vietnamese
The selected language is persisted in localStorage, updates the root <html lang> attribute, and changes the document title.
/ Landing page
/dashboard Personal dashboard
/lab Workbook Lab missions
/arena Formula Arena game engine
/learn Learning path
/learn/:lessonId Lesson details
/practice/:lessonId Practice session
/practice/:lessonId/:questionId Open a specific review question
/review Spaced review queue
/challenges Challenges
/exam Quick Exam
/progress Progress
/settings Preferences and language
/sets Public set library
/sets/:slug Play a set
/join Enter a room code
/room/:code Live room
/host Creator login and room setup
/studio Creator Studio
/studio/new Create a set
/studio/:setId Edit a set
Cloud data is stored in these collections:
courses
lessons
question_bank
question_answers
question_sets
rooms
room_players
room_answers
All privileged operations go through the gateway at appwrite/functions/fomuli-api. The frontend subscribes to rooms and room_players document events, with heartbeat and polling as reconnect fallbacks.
Copy .env.example to .env and provide your Appwrite values:
VITE_APPWRITE_ENDPOINT... # See .env.example for the complete listNever expose APPWRITE_API_KEY through a VITE_* variable. Vite variables are included in the browser bundle.
Create a temporary server API key with database, collection, attribute, index, and document read/write scopes, then run:
npm run appwrite:setupThe idempotent setup creates the database schema and seeds:
- 10 lessons;
- 125 public question documents;
- 125 private answer documents;
- 6 official sets.
The setup script retries transient network errors and can safely be run again.
Replace YOUR_PROJECT_ID in appwrite.json, authenticate the Appwrite CLI, and run:
appwrite deploy function --function-id fomuli-apiSet APPWRITE_DATABASE_ID=fomuli in the Function settings. Grant its dynamic API key document read/write and user read scopes. Detailed instructions are available in Appwrite setup.
bun install
bun devThe app falls back to bundled official learning content when Appwrite is not configured.
bun run qa
bun run buildThe QA suite covers syntax, types, content integrity, room-state behavior, Appwrite boundaries, access control, product copy, responsive CSS, and Formula Arena invariants.
For the complete history, see CHANGELOG.md.
Formula evaluation uses HyperFormula. Review its licensing terms before distributing Fomuli under a commercial or closed-source model.