- app.html: add format-detection=telephone=no so mobile browsers stop auto-linking 2-digit bingo numbers as tel: links. - app.html: rewrite description to mention Bingo 90, Vietnamese voice, offline play; add application-name + apple-mobile-web-app-title. - app.html: add Open Graph (og:type, locale, site_name, title, description, url, image) + Twitter summary card. URLs hardcoded to https://tiennm99.github.io/loto/ to match the GH Pages target. - app.html: add explicit <link rel="icon"> alongside apple-touch-icon. - manifest.webmanifest: add stable id "/loto/", expanded description, and categories ["games", "entertainment"].
Lô tô
Bàn số của trò chơi "Lô tô" — SvelteKit app.
Single page (/). The host enables "Chế độ quản trò" in settings to
reveal the master panel inline below their player card; called numbers
get spoken aloud in Vietnamese using bundled MP3 clips (no runtime TTS).
See docs/ for architecture, code standards, and deployment.
Development
npm install
npm run dev
Inside code-server (reverse proxy)
cp .env.example .env.local
# edit .env.local: set CODESERVER_HOST and CODESERVER_PORT
npm run dev:codeserver
Open https://<CODESERVER_HOST>/absproxy/<CODESERVER_PORT>/.
Use /absproxy/{port}/, not /proxy/{port}/ — the latter strips the
path prefix and breaks the SvelteKit base path.
Build
npm run build # root basePath (local preview / generic static host)
npm run build:gh # /loto basePath, for tiennm99.github.io/loto
Static export to build/. Deployed to GitHub Pages from main via
.github/workflows/deploy-github-pages.yml — see
docs/deployment-guide.md.
Regenerating audio
Vietnamese voice clips live in static/audio/{voiceId}/. Generated
once with edge-tts (free, no API
key) — runtime never calls TTS. To regenerate (e.g., to add a new voice
that Microsoft ships, or to change wording):
pip install edge-tts
python3 scripts/generate-audio.py
The script auto-discovers every vi-* voice and writes a manifest the
app reads on next reload.