feat: add tile glow, dynamic font sizing, and GitHub Pages deployment (Epic 5, Stories 5.1-5.3)

- Add box-shadow glow effect on tiles with value 128+
- Dynamic font sizing already implemented in Epic 4 responsive work (Story 5.2 = no-op)
- Set Vite base path to /try-bmad/ for GitHub Pages
- Add GitHub Actions workflow for automated deploy on push to main
- Production bundle 22.4KB gzipped (under 50KB target)
This commit is contained in:
2026-04-14 09:43:14 +07:00
parent 0e413e310d
commit 5da48bec47
7 changed files with 265 additions and 4 deletions
+40
View File
@@ -0,0 +1,40 @@
name: Deploy to GitHub Pages
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run build
- uses: actions/upload-pages-artifact@v3
with:
path: dist
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
@@ -0,0 +1,90 @@
# Story 5.1: Tile Glow Effects
Status: done
## Story
As a player,
I want high-value tiles (128+) to glow,
so that I get visual feedback of my progress and milestone tiles feel special.
## Acceptance Criteria
1. Given a tile has a value of 128 or higher, when it renders on the grid, then it displays a glow effect: `box-shadow: 0 0 30px 10px rgba(243, 215, 116, 0.4)` (UX-DR6)
2. Given a tile has a value below 128, when it renders on the grid, then no glow effect is applied
3. Given a tile merges from 64+64 to 128, when the merge completes, then the glow effect appears on the resulting tile
## Tasks / Subtasks
- [x] Task 1: Add conditional glow box-shadow to Tile.svelte (AC: #1, #2, #3)
- [x] Added `$derived` glow: `value >= 128 ? '0 0 30px 10px rgba(243, 215, 116, 0.4)' : 'none'`
- [x] Applied `box-shadow: {glow}` in tile's inline style
- [x] Glow automatically appears on merged tiles via Svelte reactivity (no extra code needed)
- [x] Task 2: Verify no regressions (AC: #1, #2, #3)
- [x] All 90 tests pass, zero regressions
- [x] Production build succeeds
## Dev Notes
### Implementation Details
This is a single-line change in Tile.svelte. Add a derived value for the box-shadow and include it in the inline style.
### Current Tile.svelte (relevant section)
```svelte
<div
class="absolute flex items-center justify-center font-bold rounded-[3px]"
style="
width: var(--cell-size);
height: var(--cell-size);
transform: translate(calc({col} * (var(--cell-size) + var(--grid-gap))), calc({row} * (var(--cell-size) + var(--grid-gap))));
transition: transform 100ms ease-in-out;
animation: {animation};
background: {colors.bg};
color: {colors.text};
font-size: {fontSize};
"
>
```
### Required Change
Add in `<script>`:
```javascript
let glow = $derived(value >= 128 ? '0 0 30px 10px rgba(243, 215, 116, 0.4)' : 'none');
```
Add in style:
```
box-shadow: {glow};
```
### AC #3 (merge glow) — No Extra Code Needed
When 64+64 merges, game-logic returns a new state with the merged tile having value 128. Tile.svelte re-renders with `value=128`, which triggers the glow derived. The merge bounce animation plays simultaneously. No special merge handling needed.
### FRs Covered
- FR29: Tile glow on 128+
### References
- [Source: _bmad-output/planning-artifacts/epics.md — Epic 5, Story 5.1]
- [Source: _bmad-output/planning-artifacts/ux-design-specification.md — UX-DR6]
- [Source: src/components/Tile.svelte — current implementation]
## Dev Agent Record
### Agent Model Used
Claude Opus 4.6 (1M context)
### Debug Log References
### Completion Notes List
- Added `$derived` glow variable and box-shadow to Tile.svelte — 2 lines of code
- Glow triggers automatically for value >= 128 via Svelte reactivity
- All 90 tests pass
### File List
- src/components/Tile.svelte (modified — added glow box-shadow)
@@ -0,0 +1,40 @@
# Story 5.2: Dynamic Tile Font Sizing
Status: done
## Story
As a player,
I want tile numbers to be clearly readable at any value,
so that I can always see tile values regardless of digit count.
## Acceptance Criteria
1. Given a tile with a 1-digit value (2, 4, 8), when it renders, then the font size is 55px bold (desktop) / 30px bold (mobile)
2. Given a tile with a 2-digit value (16, 32, 64), when it renders, then the font size is 45px bold (desktop) / 25px bold (mobile)
3. Given a tile with a 3-digit value (128, 256, 512), when it renders, then the font size is 35px bold (desktop) / 20px bold (mobile)
4. Given a tile with a 4-digit value (1024, 2048, 4096, 8192), when it renders, then the font size is 25px bold (desktop) / 14px bold (mobile)
5. Given a tile with a 5+ digit value (16384, 32768, 65536), when it renders, then the font size is 15px bold (desktop) / proportionally scaled (mobile)
## Tasks / Subtasks
- [x] Task 1: Already implemented in Story 4.3 (Responsive Layout)
- [x] Tile.svelte derives digitCount from String(value).length
- [x] Maps to CSS variables var(--tile-font-1) through var(--tile-font-5)
- [x] Desktop: 55/45/35/25/15px; Mobile: 30/25/20/14/10px via @media (max-width: 520px) override in app.css
## Dev Notes
This story's requirements were fully implemented as part of Story 4.3 (Responsive Layout) since dynamic font sizing was a necessary component of the responsive breakpoint implementation. All ACs are satisfied by the existing code.
### File List
- No additional changes needed — implemented in Story 4.3 commit
## Dev Agent Record
### Agent Model Used
Claude Opus 4.6 (1M context)
### Completion Notes List
- All ACs already satisfied by Story 4.3 implementation
- Tile.svelte has digit-count-based font sizing with responsive CSS variables
@@ -0,0 +1,87 @@
# Story 5.3: GitHub Pages Deployment
Status: done
## Story
As a developer,
I want the game automatically deployed to GitHub Pages on push to main,
so that the game is publicly accessible without manual deployment steps.
## Acceptance Criteria
1. Given the Vite config, when the production build runs, then the `base` option is set to the repository name for correct asset paths on GitHub Pages, and `npm run build` produces a `dist/` directory
2. Given a `.github/workflows/deploy.yml` workflow file, when code is pushed to the main branch, then GitHub Actions runs `npm ci`, `npm run build`, and deploys the `dist/` directory to GitHub Pages
3. Given the deployment completes, when a user visits the GitHub Pages URL, then the game loads and is fully playable with all assets loading correctly
4. Given the production bundle, then it is under 50KB gzipped (NFR4)
## Tasks / Subtasks
- [x] Task 1: Set Vite base path for GitHub Pages (AC: #1)
- [x] Added `base: '/try-bmad/'` to vite.config.js
- [x] Verified dist/ output has correct `/try-bmad/` prefixed asset paths
- [x] Task 2: Create GitHub Actions deploy workflow (AC: #2)
- [x] Created `.github/workflows/deploy.yml` with actions/deploy-pages
- [x] Triggers on push to main, uses Node.js 20, npm ci, npm run build
- [x] Uses upload-pages-artifact + deploy-pages (modern approach, no gh-pages branch)
- [x] Task 3: Verify build and bundle size (AC: #1, #4)
- [x] Build succeeds, dist/ contains index.html + CSS + JS with correct paths
- [x] Gzipped bundle: 22.4KB total (well under 50KB)
- [x] All 90 tests pass
## Dev Notes
### Vite Config Change
Add `base` to vite.config.js:
```javascript
export default defineConfig({
base: '/try-bmad/',
plugins: [svelte(), tailwindcss()],
})
```
### GitHub Actions Workflow
Use the modern `actions/deploy-pages` approach (not gh-pages branch):
```yaml
permissions:
contents: read
pages: write
id-token: write
```
### Current Bundle Size
Last build: 22KB gzipped total (CSS 3.5KB + JS 18.5KB) — well under 50KB limit.
### Font Path Note
Font files in `public/fonts/` use absolute paths (`/fonts/ClearSans-*.woff2`). With `base: '/try-bmad/'`, Vite automatically prefixes static asset URLs, but `@font-face src: url('/fonts/...')` in CSS needs to work correctly. Vite handles this — URLs starting with `/` in CSS are resolved relative to the `base` path in production builds.
### FRs Covered
- FR31: GitHub Pages deployment
### References
- [Source: _bmad-output/planning-artifacts/epics.md — Epic 5, Story 5.3]
- [Source: _bmad-output/planning-artifacts/architecture.md — Infrastructure & Deployment]
- [Source: vite.config.js — current config]
## Dev Agent Record
### Agent Model Used
Claude Opus 4.6 (1M context)
### Debug Log References
### Completion Notes List
- Added `base: '/try-bmad/'` to vite.config.js for correct GitHub Pages asset paths
- Created `.github/workflows/deploy.yml` using modern actions/deploy-pages approach
- Build produces 22.4KB gzipped bundle (well under 50KB NFR4 limit)
- All 90 tests pass
### File List
- vite.config.js (modified — added base path)
- .github/workflows/deploy.yml (created — GitHub Actions deploy workflow)
@@ -76,8 +76,8 @@ development_status:
epic-4-retrospective: optional
# Epic 5: Visual Polish & Deployment
epic-5: backlog
5-1-tile-glow-effects: backlog
5-2-dynamic-tile-font-sizing: backlog
5-3-github-pages-deployment: backlog
epic-5: done
5-1-tile-glow-effects: done
5-2-dynamic-tile-font-sizing: done
5-3-github-pages-deployment: done
epic-5-retrospective: optional
+3
View File
@@ -14,6 +14,8 @@
'var(--tile-font-5)'
);
let glow = $derived(value >= 128 ? '0 0 30px 10px rgba(243, 215, 116, 0.4)' : 'none');
let animation = $derived(
isNew ? 'tile-pop 200ms ease-in-out' :
isMerged ? 'tile-merge 200ms ease-in-out' :
@@ -32,6 +34,7 @@
background: {colors.bg};
color: {colors.text};
font-size: {fontSize};
box-shadow: {glow};
"
role="gridcell"
aria-label="Tile: {value}"
+1
View File
@@ -4,5 +4,6 @@ import tailwindcss from '@tailwindcss/vite'
// https://vite.dev/config/
export default defineConfig({
base: '/try-bmad/',
plugins: [svelte(), tailwindcss()],
})