Skip to content

davidmarek/easter

Repository files navigation

🐰 Velikonoční honba za pokladem (Easter Treasure Hunt)

An outdoor QR-code treasure hunt for kids. Players scan QR codes at physical stations, answer Easter-themed questions (in Czech) read aloud by a bunny voice, and follow clues to the next station until they find the treasure.

How It Works

  1. Edit game.json with your questions, answers, and clues
  2. Build the static site → one HTML page per station + a start page
  3. Print QR codes and hide them around a garden / house / park
  4. Kids scan a QR code → a question appears on their phone with audio
  5. Answer correctly → get a clue to the next station
  6. Repeat until the final station triggers confetti and reveals the treasure 🎁

Each station is a standalone HTML page — no backend, no app install, just a phone camera.

Quick Start

npm install
npm run build          # generates static HTML in dist/
npm run generate-qr    # generates QR code PNGs in qr-output/

Print the QR codes, hide them, and you're ready to go.

To also generate bunny-voice audio (requires Azure Speech credentials):

export AZURE_SPEECH_KEY=<your-key>
export AZURE_SPEECH_REGION=westeurope
npm run generate-audio   # generates MP3s in dist/audio/
npm run build            # build again to pick up audio files

game.json Format

{
  "title": "Velikonoční honba za pokladem",
  "description": "Najdi všechny stanoviště a získej poklad!",
  "baseUrl": "https://your-site.azurestaticapps.net",
  "firstHint": "První QR kód najdeš na zahradě u vchodových dveří! 🚪",
  "stations": [
    {
      "id": "1",
      "question": "Z čeho se plete pomlázka?",
      "answers": [
        { "text": "Z provázku", "correct": false },
        { "text": "Z vrbového proutí", "correct": true },
        { "text": "Z drátku", "correct": false }
      ],
      "nextClue": "Další QR kód hledej u jabloně! 🌳"
    }
    // ... more stations — last station omits nextClue
  ],
  "finalMessage": "🎉 Výborně! Našli jste poklad! Běžte do kuchyně! 🎁"
}
Field Description
title Game title shown on every page
description Subtitle on the start page
baseUrl Where the site is hosted (used for QR code URLs)
firstHint Clue revealed on the start page when the player clicks "Začít hledání!"
stations[] Array of stations, each with a question and answers
stations[].id Unique station identifier (used in filenames: station-{id}.html)
stations[].question The question text shown to the player
stations[].answers[] Array of { text, correct } — exactly one should be correct: true
stations[].nextClue Clue pointing to the next station's physical QR code location
finalMessage Shown after the last station is completed (with confetti!)

The last station does not need a nextCluefinalMessage takes over.

Available Scripts

Command What it does
npm run build Generate static site in dist/ from templates + game.json
npm run generate-qr Generate QR code PNGs in qr-output/
npm run generate-audio Generate bunny-voice MP3s in dist/audio/ via Azure TTS
npm run create-game Interactive CLI wizard to create/edit game.json
npm run preview Local preview with Azure SWA CLI
npm run deploy Deploy dist/ to Azure Static Web Apps
npm run clean Delete the dist/ directory

The QR generator accepts --base-url to override the URL in game.json:

node tools/generate-qr.js --base-url https://easter.example.com

Audio Generation (Bunny Voice)

npm run generate-audio uses Azure Cognitive Services Speech SDK to produce MP3 files read by a pitched-up Czech female voice (cs-CZ-VlastaNeural) — the "bunny" effect.

SSML settings: rate 50%, pitch +25%.

What gets generated

File Content
welcome.mp3 Game title + description (played on the start page)
station-{id}.mp3 Question read aloud, then each answer option ("Možnost jedna: …", "Možnost dva: …")
station-{id}-correct.mp3 "Správně! Výborně!" + the nextClue text (or finalMessage for the last station)

Environment variables

Variable Description
AZURE_SPEECH_KEY Azure Speech service subscription key
AZURE_SPEECH_REGION Azure region (e.g. westeurope)

If credentials are missing, the script exits silently with a warning — the site works fine without audio.

Audio in the UI

  • Audio autoplays when a station page loads
  • On mobile (where autoplay is blocked), a hint appears: "👆 Klepni na 🔊 pro přehrání"
  • A 🔊 replay button is always available
  • On correct answer, question audio stops and celebration audio plays

Easter-Themed UI

All UI text is in Czech. The design is mobile-first with pastel spring colors:

  • Bouncing bunny 🐰 header animation on every page
  • Floating eggs 🥚🐣🌷 drifting in the background
  • Grass footer gradient at the bottom of the viewport
  • Progress dots showing completed / current / remaining stations
  • Start page — "Začít hledání!" button triggers a clue-reveal animation showing firstHint
  • Station pages — answer buttons with egg icons, shake animation on wrong answer, pop animation on correct
  • Final station — triggers a 5-second confetti canvas animation + rainbow-pulse celebration box
  • Responsive — landscape layout for answer grid, font scaling on small screens (< 350px)

Answer Verification

Correct answers are not stored as plaintext in the generated HTML. The build script SHA-256 hashes the correct answer's index (0, 1, 2, …). At runtime, the player's selected index is hashed via the Web Crypto API and compared to the stored hash — so viewing the page source doesn't reveal the answer.

Deployment

The site deploys to Azure Static Web Apps. See DEPLOY.md for full instructions.

GitHub Actions CI/CD

The workflow (.github/workflows/azure-static-web-apps.yml) runs on every push to main:

  1. npm ci
  2. npm run generate-audio (using AZURE_SPEECH_KEY secret)
  3. npm run build
  4. Deploy dist/ to Azure Static Web Apps

Security hardening:

  • Push-to-main only (no PR deploys — prevents fork-based attacks)
  • All actions pinned to full commit SHAs (supply chain protection)
  • permissions: contents: read (least privilege)
  • Named production environment for audit trail

Required GitHub Secrets

Secret Purpose
AZURE_STATIC_WEB_APPS_API_TOKEN SWA deployment token
AZURE_SPEECH_KEY Azure Speech TTS key (for audio generation)

QR Codes

npm run generate-qr reads game.json and creates one PNG per station plus a start-page QR code in qr-output/:

  • qr-start.png{baseUrl}/index.html
  • qr-station-{id}.png{baseUrl}/station-{id}.html

Settings: error correction H (high), 400×400 px, 2 px margin.

Interactive Game Creator

npm run create-game walks you through building game.json interactively in the terminal (Czech prompts). It can load an existing game.json and add stations or start fresh.

Tech Stack

  • Frontend: Vanilla HTML, CSS, JavaScript — no frameworks, no bundler
  • Build: Node.js scripts (tools/build.js) using HTML templates with {{placeholder}} substitution
  • TTS: microsoft-cognitiveservices-speech-sdk for Azure Speech
  • QR codes: qrcode npm package
  • Hosting: Azure Static Web Apps (free tier)
  • CI/CD: GitHub Actions with pinned action SHAs
  • Security: SHA-256 answer hashing, least-privilege permissions, no plaintext answers in source

About

🐰 Easter treasure hunt game for kids — QR-code stations with Czech questions, bunny voice audio, and confetti celebrations. Deployed on Azure Static Web Apps.

Topics

Resources

Stars

Watchers

Forks

Contributors