Skip to content

Repository files navigation

Fomuli Community

v20 highlight

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.

Highlights

  • 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.

Live game v16

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.

Learning loop

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.

Interaction types

  1. Single choice
  2. True or false
  3. Multiple choice
  4. Formula input
  5. Fill in the missing segment
  6. Predict a result
  7. Repair a broken formula
  8. Build a formula from blocks
  9. Put blocks in the correct order
  10. Match related items
  11. Select a spreadsheet cell
  12. Diagnose the formula segment causing an error

Accounts and permissions

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.

Multiplayer security

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.

Internationalization

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.

Routes

/                                  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

Appwrite backend

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.

Environment configuration

Copy .env.example to .env and provide your Appwrite values:

VITE_APPWRITE_ENDPOINT... # See .env.example for the complete list

Never expose APPWRITE_API_KEY through a VITE_* variable. Vite variables are included in the browser bundle.

Create the schema and seed content

Create a temporary server API key with database, collection, attribute, index, and document read/write scopes, then run:

npm run appwrite:setup

The 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.

Deploy the Function

Replace YOUR_PROJECT_ID in appwrite.json, authenticate the Appwrite CLI, and run:

appwrite deploy function --function-id fomuli-api

Set 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.

Local development

bun install
bun dev

The app falls back to bundled official learning content when Appwrite is not configured.

Quality checks

bun run qa
bun run build

The 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 runtime

Formula evaluation uses HyperFormula. Review its licensing terms before distributing Fomuli under a commercial or closed-source model.

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages