Skip to content

tot0p/MotMystere

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mot Mystère

A modern, elegant French word game inspired by Motus and Wordle. Built with Eleventy (11ty) and vanilla JavaScript.

Features

Game Modes

  1. Mot du jour (Daily Mode)

    • One shared daily word for all players
    • Deterministic word selection based on Europe/Paris timezone
    • Streak tracking for consecutive daily wins
    • Share your results with emoji grid
    • Progress persists across sessions
  2. Mode Aléatoire (Random Mode)

    • Play unlimited random words
    • New puzzle on demand
    • Perfect for practice

Gameplay

  • Variable word length: 4-10 letters (grid adapts automatically)
  • Smart attempts: 6 attempts (7 for words > 7 letters)
  • Color feedback:
    • 🟩 Green = correct letter, correct position
    • 🟨 Yellow = correct letter, wrong position
    • ⬜ Gray = letter not in word
  • Duplicate letter handling: Follows standard Wordle rules
  • Dictionary validation: Only accept valid French words
  • Accent-insensitive: Compare by normalized form (works with or without accents)
  • Definition hints: See word definitions after completing the puzzle

User Interface

  • Clean, modern design with smooth animations
  • Responsive layout (mobile-first approach)
  • Light/Dark mode toggle with persistent preference
  • Dual input methods: On-screen keyboard + physical keyboard
  • Accessibility features: ARIA labels, good contrast, focus management
  • French AZERTY keyboard layout

Project Structure

MotMystere/
├── package.json           # Dependencies and scripts
├── .eleventy.js          # Eleventy configuration
├── scripts/
│   └── generate-data.js  # CSV parser and JSON generator
├── src/
│   ├── _includes/
│   │   └── layout.njk    # Base layout template
│   ├── index.njk         # Landing page
│   ├── daily.njk         # Daily mode page
│   ├── random.njk        # Random mode page
│   ├── data/
│   │   └── dictionary.csv # French word dictionary
│   └── assets/
│       ├── css/
│       │   └── main.css  # Styles with theme support
│       ├── js/
│       │   ├── game.js   # Core game engine
│       │   ├── dict.js   # Dictionary loader
│       │   ├── storage.js # LocalStorage manager
│       │   ├── utils.js  # Utility functions
│       │   ├── daily.js  # Daily mode logic
│       │   └── random.js # Random mode logic
│       └── data/         # Generated JSON (output)
│           ├── words.json
│           └── defs.json
├── tests/
│   └── game.test.js      # Unit tests
└── _site/                # Generated static site (output)

Setup and Installation

Prerequisites

  • Node.js (v18 or higher recommended)
  • npm

Installation

  1. Clone or download this repository

  2. Install dependencies:

    npm install
  3. Ensure your dictionary CSV is at src/data/dictionary.csv with this format:

    Mot,Définitions
    Accueil,"[""Definition 1"", ""Definition 2""]"

Usage

Development Mode

Run the development server with live reload:

npm run dev

The site will be available at http://localhost:8080

Build for Production

Generate the static site:

npm run build

The output will be in the _site/ directory, ready to deploy to any static hosting service.

Run Tests

Execute the unit tests:

npm test

How It Works

Daily Word Selection

The daily word is selected deterministically using a simple hash function:

  1. Get current date in Europe/Paris timezone (YYYY-MM-DD format)
  2. Hash the date string to generate a seed
  3. Use seed to select index: index = hash(dateString) % wordsCount
  4. All users see the same word for the same date

This approach ensures:

  • No server required
  • Same word for all users on a given day
  • Predictable but pseudo-random selection
  • Works offline after initial load

Streak Tracking

The streak system tracks consecutive daily wins:

  • Increment: Streak increases when you solve the daily puzzle
  • Continue: Solving today after solving yesterday maintains the streak
  • Reset: Streak resets when you:
    • Fail to solve the daily puzzle, OR
    • Skip a day (didn't solve yesterday's puzzle)

Streak data is stored locally with the last solved date for continuity verification.

Dictionary Processing

At build time, the generate-data.js script:

  1. Reads src/data/dictionary.csv
  2. Parses each word and its definitions
  3. Handles mixed quotes in definition strings:
    • Attempts JSON.parse first
    • Sanitizes quotes if needed
    • Falls back to heuristic splitting
  4. Normalizes words (removes accents) for comparison
  5. Generates two JSON files:
    • words.json: Array of {word, normalized} objects
    • defs.json: Map of normalized word → definitions array

Duplicate Letter Handling

The evaluation algorithm correctly handles duplicate letters:

  1. First pass: Mark all correct positions (green) and decrement letter counts
  2. Second pass: For remaining letters:
    • If letter count > 0: mark as present (yellow) and decrement
    • Otherwise: mark as absent (gray)

Example: If the solution has one "E" and guess has two "E"s, only the first "E" (if present) gets marked yellow/green; the second gets gray.

Local Storage

The game uses different localStorage keys for each mode:

  • motmystere_daily_state: Current daily game state + date
  • motmystere_daily_streak: Streak count + last solved date
  • motmystere_random_state: Current random game state
  • theme: User's theme preference (light/dark)

Customization

Changing Word Length Limits

Edit the range in dict.js:

export function getRandomWord(minLength = 4, maxLength = 10)
export function getDailyWord(date, minLength = 4, maxLength = 10)

Adjusting Attempts

Modify in mode files (daily.js, random.js):

const maxAttempts = todayWord.length > 7 ? 7 : 6;

Keyboard Layout

Change the layout in mode files:

const KEYBOARD_LAYOUT = [
  ['A', 'Z', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
  ['Q', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M'],
  ['ENTER', 'W', 'X', 'C', 'V', 'B', 'N', '⌫']
];

Theme Colors

Edit CSS variables in main.css:

:root {
  --color-correct: #6aaa64;
  --color-present: #c9b458;
  --color-absent: #787c7e;
  /* ... */
}

Browser Compatibility

  • Modern browsers with ES6 module support
  • LocalStorage API
  • Clipboard API (for share feature)
  • CSS custom properties

Tested on:

  • Chrome/Edge 90+
  • Firefox 88+
  • Safari 14+

Technologies Used

  • Eleventy (11ty): Static site generator
  • Vanilla JavaScript: ES6 modules, no frameworks
  • CSS: Custom properties, flexbox, grid
  • Node.js: Build scripts and data processing
  • Node test runner: Built-in test framework

License

MIT License - Feel free to use and modify for your own projects.

Credits

Inspired by:

  • Wordle by Josh Wardle
  • Motus (French TV game show)

Enjoy playing Mot Mystère! 🎮

About

Resources

Stars

Watchers

Forks

Contributors