Files
loto/docs/deployment-guide.md
tiennm99 574c22ddc1 refactor: rewrite from Next.js + React to SvelteKit + Svelte 5
Full stack swap to enable future extension (more pages / load functions /
backend) while keeping JSDoc-only code style.

Stack:
- SvelteKit 2 + adapter-static
- Svelte 5 runes ($state, $derived, $effect, $props)
- Vite 7 + @sveltejs/vite-plugin-svelte 6
- Tailwind 4 (Vite plugin)
- ESLint 9 (flat) + eslint-plugin-svelte
- Pure JS + JSDoc, no TypeScript

Source moves:
- app/page.jsx              → src/routes/+page.svelte
- app/master/page.jsx       → src/routes/master/+page.svelte
- app/layout.jsx            → src/routes/+layout.svelte (+ +layout.js)
- components/player-board.jsx → src/lib/PlayerBoard.svelte
- lib/game-logic.js         → src/lib/game-logic.js (verbatim)
- next.config.mjs           → svelte.config.js + vite.config.js
- app/globals.css           → src/app.css
- (new)                     → src/app.html

Behavior preserved: PlayerBoard with bingo "Kinh!" popup + waiting "Chờ X"
toast, master 9x10 tracking board with shuffled draw, host's own player
card via storagePrefix="loto_master_card", localStorage prefix model
(loto_*, loto_master, loto_master_card_*), basePath dual mode (CF default
empty, BUILD_PROFILE=gh → /loto, codeserver dev → /absproxy/{port}).

A11y kept from prior hardening: role-correct buttons, aria-pressed on
cells, role=dialog modal with Escape, role=status toast.

Plans: ts-to-jsdoc plan marked completed; sveltekit-refactor plan tracks
the work above. Docs under ./docs/ rewritten by docs-manager subagent to
match the SvelteKit terminology.
2026-04-26 21:03:41 +07:00

5.1 KiB

Deployment Guide

Build Profiles

Script basePath Target
npm run build "" (root) Cloudflare Pages → https://loto.miti99.com
npm run build:gh /loto GitHub Pages → https://tiennm99.github.io/loto (manual fallback)

Implementation: svelte.config.js reads BUILD_PROFILE env. Default is empty basePath; BUILD_PROFILE=gh npm run build switches to /loto.

Internal links use import { base } from '$app/paths' so they survive either profile without code changes.

Production Deployment — Cloudflare Pages

Primary deploy. Set up via the Cloudflare dashboard once; subsequent pushes to master trigger automatic builds + deploys.

  1. dash.cloudflare.com → Workers & Pages → Create → Pages → Connect to Git → pick the repo
  2. Build settings:
    • Framework preset: SvelteKit
    • Build command: npm run build
    • Build output directory: build
    • Production branch: master
  3. After first deploy, add the custom domain: Project → Custom domains → loto.miti99.com. Cloudflare gives DNS records to add at your registrar (or auto-configures if miti99.com is on Cloudflare DNS).

No GitHub Actions involved; no repo secrets needed.

Manual GH Pages Deploy (optional)

If you ever want to push a build to GitHub Pages by hand:

npm run build:gh
# upload build/ to the GH Pages target

The repo no longer auto-deploys to GH Pages — there's no GitHub Actions workflow. CF Pages is the only auto-deploy target.

Development Environment

Local Dev

npm install
npm run dev

Access at http://localhost:3000 (no basePath).

HMR works automatically.

Code-Server Dev

For browser-based development (VS Code in browser):

1. Start code-server with Node.js environment:

code-server --no-auth

2. Create .env.local in project root:

VITE_DEV_PROFILE=codeserver
CODESERVER_HOST=your-machine.example.com
CODESERVER_PORT=3000

Replace your-machine.example.com with your actual hostname/IP (must match the proxy URL you'll access).

3. Run dev server:

npm run dev:codeserver

This reads vite.config.js codeserver config (basePath /absproxy/{PORT}, HMR proxy).

4. Access via browser: Navigate to:

https://your-codeserver-host/absproxy/3000/

Key Points:

  • /absproxy/{port} (NOT /proxy/{port}) preserves basePath through the proxy.
  • HMR socket connects to CODESERVER_HOST for live reload.
  • If HMR fails, manually refresh the page (Vite HMR still compiles server-side).

Manual Refresh Workaround

If HMR over proxy is unreliable:

  1. Make code changes
  2. Manually refresh browser (F5)
  3. Dev server has already compiled the changes

This is normal in proxy environments.

Build & Output

Build Command

npm run build

Generates:

  • build/ — Complete static HTML + JS export
  • .svelte-kit/ — Build cache (not needed for deployment)

Export Settings

  • adapter-static in svelte.config.js
  • No server-side rendering (SSR disabled via ssr: false)
  • All pages pre-rendered to HTML + JS bundles

Asset Hosting

  • base path matches deployment target (prod: "", GH: /loto, codeserver: /absproxy/{port})
  • CSS, JS, fonts all prefixed correctly
  • GitHub Pages serves from repository root, so /loto paths resolve correctly

Environment Variables

Development (code-server only)

  • VITE_DEV_PROFILE — set to "codeserver" to enable proxy mode
  • CODESERVER_HOST — hostname for HMR proxy
  • CODESERVER_PORT — port (default 3000)

Build-Time

  • BUILD_PROFILE — set to "gh" for GitHub Pages build (basePath /loto). Default empty (Cloudflare).

Not Used at Runtime

  • No database URL, API keys, or secrets (all client-side, localStorage)
  • .env.local is .gitignored and safe for local config

Troubleshooting

Issue Cause Fix
404 on subpages after deploy basePath mismatch Verify BUILD_PROFILE=gh for GitHub Pages; default for Cloudflare
HMR not connecting (code-server) CODESERVER_HOST not set Add CODESERVER_HOST=... to .env.local
Assets 404 (code-server) Wrong proxy URL Use /absproxy/{port}, not /proxy/{port}
Page blank after refresh State not persisted Check browser localStorage is enabled
Stale CSS (code-server) HMR failed Manually refresh page (F5)

CI/CD Pipeline

Cloudflare Pages handles CI/CD automatically:

  • GitHub Pages deployment removed (Cloudflare is primary).
  • Manual fallback: npm run build:gh && git push (if needed).
  • No GitHub Actions workflow for automatic GH Pages deploy.

Performance Checklist

  • Static export via adapter-static (no server overhead)
  • Tailwind 4 purged for production size
  • localStorage reduces bundle—no API calls
  • Images minimal (mostly CSS gradients + emojis)
  • Fonts: Geist via Google Fonts CDN

Bundle analysis: Run npm run build && ls -lh build/ to inspect file sizes.

Security Considerations

  • No sensitive data in code (no API keys, secrets)
  • .env.local is local-only, not committed
  • localStorage scoped to origin
  • No external API calls (offline-capable)
  • GitHub Pages HTTPS by default

Last reviewed: 2026-04-26