mirror of
https://github.com/tiennm99/ai-coding-workflow-labs.git
synced 2026-08-13 21:20:37 +00:00
feat: scaffold Svelte + Tailwind + Vite project (Story 1.1)
Initialize project with Svelte 5, Vite 8, Tailwind CSS v4, and Vitest. Set up folder structure (src/lib, src/components, public/fonts), constants module with game values and 12-tier tile colors, Clear Sans font, and page background styling. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -137,3 +137,5 @@ dist
|
||||
# Vite logs files
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
node_modules
|
||||
dist
|
||||
|
||||
+56
-59
@@ -1,6 +1,6 @@
|
||||
# Story 1.1: Project Scaffold & Dev Environment
|
||||
|
||||
Status: ready-for-dev
|
||||
Status: review
|
||||
|
||||
## Story
|
||||
|
||||
@@ -20,53 +20,44 @@ so that all subsequent stories have a solid foundation to build on.
|
||||
|
||||
## Tasks / Subtasks
|
||||
|
||||
- [ ] Task 1: Initialize project (AC: #1)
|
||||
- [ ] Run `npm create vite@latest try-bmad -- --template svelte` (or init in current directory)
|
||||
- [ ] Verify `npm run dev` starts dev server at localhost:5173
|
||||
- [ ] Remove default Svelte demo content (Counter component, default styles, Svelte/Vite logos)
|
||||
- [x] Task 1: Initialize project (AC: #1)
|
||||
- [x] Run `npm create vite@latest try-bmad -- --template svelte` (or init in current directory)
|
||||
- [x] Verify `npm run dev` starts dev server at localhost:5173
|
||||
- [x] Remove default Svelte demo content (Counter component, default styles, Svelte/Vite logos)
|
||||
|
||||
- [ ] Task 2: Install and configure Tailwind CSS v4 (AC: #2)
|
||||
- [ ] Run `npm install tailwindcss @tailwindcss/vite`
|
||||
- [ ] Add `tailwindcss()` plugin to `vite.config.js` plugins array
|
||||
- [ ] Replace content in `src/app.css` with `@import "tailwindcss";`
|
||||
- [ ] Verify Tailwind utilities work in App.svelte (e.g., a `bg-red-500` class renders correctly)
|
||||
- [x] Task 2: Install and configure Tailwind CSS v4 (AC: #2)
|
||||
- [x] Run `npm install tailwindcss @tailwindcss/vite`
|
||||
- [x] Add `tailwindcss()` plugin to `vite.config.js` plugins array
|
||||
- [x] Replace content in `src/app.css` with `@import "tailwindcss";`
|
||||
- [x] Verify Tailwind utilities work in App.svelte (e.g., a `bg-red-500` class renders correctly)
|
||||
|
||||
- [ ] Task 3: Install Vitest (AC: #3)
|
||||
- [ ] Run `npm install -D vitest`
|
||||
- [ ] Add `"test": "vitest"` script to `package.json`
|
||||
- [ ] Create a placeholder test file `src/lib/game-logic.test.js` with a single passing test
|
||||
- [ ] Verify `npx vitest run` passes
|
||||
- [x] Task 3: Install Vitest (AC: #3)
|
||||
- [x] Run `npm install -D vitest`
|
||||
- [x] Add `"test": "vitest"` script to `package.json`
|
||||
- [x] Create a placeholder test file `src/lib/game-logic.test.js` with a single passing test
|
||||
- [x] Verify `npx vitest run` passes
|
||||
|
||||
- [ ] Task 4: Create folder structure (AC: #4)
|
||||
- [ ] Create `src/lib/` directory (for pure JS game logic modules)
|
||||
- [ ] Create `src/components/` directory (for Svelte UI components)
|
||||
- [ ] Create `public/fonts/` directory (for Clear Sans font files)
|
||||
- [x] Task 4: Create folder structure (AC: #4)
|
||||
- [x] Create `src/lib/` directory (for pure JS game logic modules)
|
||||
- [x] Create `src/components/` directory (for Svelte UI components)
|
||||
- [x] Create `public/fonts/` directory (for Clear Sans font files)
|
||||
|
||||
- [ ] Task 5: Create constants module (AC: #5)
|
||||
- [ ] Create `src/lib/constants.js` with all game constants:
|
||||
- [x] Task 5: Create constants module (AC: #5)
|
||||
- [x] Create `src/lib/constants.js` with all game constants:
|
||||
- `GRID_SIZE = 4`
|
||||
- `WIN_VALUE = 2048`
|
||||
- `SPAWN_PROBABILITY = 0.9` (probability of spawning a 2 vs 4)
|
||||
- `DIRECTIONS = { UP: 'up', DOWN: 'down', LEFT: 'left', RIGHT: 'right' }`
|
||||
- `TILE_COLORS` map: `{ 2: { bg: '#eee4da', text: '#776e65' }, 4: { bg: '#ede0c8', text: '#776e65' }, 8: { bg: '#f2b179', text: '#f9f6f2' }, 16: { bg: '#f59563', text: '#f9f6f2' }, 32: { bg: '#f67c5f', text: '#f9f6f2' }, 64: { bg: '#f65e3b', text: '#f9f6f2' }, 128: { bg: '#edcf72', text: '#f9f6f2' }, 256: { bg: '#edcc61', text: '#f9f6f2' }, 512: { bg: '#edc850', text: '#f9f6f2' }, 1024: { bg: '#edc53f', text: '#f9f6f2' }, 2048: { bg: '#edc22e', text: '#f9f6f2' }, super: { bg: '#3c3a32', text: '#f9f6f2' } }`
|
||||
- `TILE_COLORS` map with all 12 tiers
|
||||
|
||||
- [ ] Task 6: Add Clear Sans font (AC: #6)
|
||||
- [ ] Download Clear Sans woff2 from Intel's open-source release or a CDN
|
||||
- [ ] Place `ClearSans-Bold.woff2` (and regular weight if available) in `public/fonts/`
|
||||
- [ ] Add `@font-face` declaration in `src/app.css` after the Tailwind import:
|
||||
```css
|
||||
@font-face {
|
||||
font-family: 'Clear Sans';
|
||||
src: url('/fonts/ClearSans-Bold.woff2') format('woff2');
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
```
|
||||
- [x] Task 6: Add Clear Sans font (AC: #6)
|
||||
- [x] Download Clear Sans woff2 from @fontsource/clear-sans npm package
|
||||
- [x] Place `ClearSans-Bold.woff2` and `ClearSans-Regular.woff2` in `public/fonts/`
|
||||
- [x] Add `@font-face` declarations in `src/app.css` for both bold and regular weights
|
||||
|
||||
- [ ] Task 7: Set page background and base styles (AC: #7)
|
||||
- [ ] In `src/app.css`, add base body style: `body { background: #faf8ef; font-family: 'Clear Sans', 'Helvetica Neue', Arial, sans-serif; margin: 0; }`
|
||||
- [ ] Clean up `App.svelte` to render a minimal placeholder (e.g., "2048" heading) confirming styles work
|
||||
- [x] Task 7: Set page background and base styles (AC: #7)
|
||||
- [x] In `src/app.css`, add base body style with background #faf8ef and Clear Sans font family
|
||||
- [x] Clean up `App.svelte` to render a minimal "2048" heading confirming styles work
|
||||
|
||||
## Dev Notes
|
||||
|
||||
@@ -93,27 +84,6 @@ so that all subsequent stories have a solid foundation to build on.
|
||||
- Functions: `camelCase` (e.g., `initGame`, `moveTiles`)
|
||||
- Constants: `UPPER_SNAKE_CASE` (e.g., `GRID_SIZE`, `WIN_VALUE`)
|
||||
|
||||
### Project Structure After This Story
|
||||
|
||||
```
|
||||
try-bmad/
|
||||
├── index.html
|
||||
├── package.json
|
||||
├── vite.config.js
|
||||
├── .gitignore
|
||||
├── public/
|
||||
│ └── fonts/
|
||||
│ └── ClearSans-Bold.woff2
|
||||
├── src/
|
||||
│ ├── main.js
|
||||
│ ├── App.svelte
|
||||
│ ├── app.css
|
||||
│ ├── components/ (empty, ready for Story 1.3+)
|
||||
│ └── lib/
|
||||
│ ├── constants.js
|
||||
│ └── game-logic.test.js (placeholder)
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- [Source: _bmad-output/planning-artifacts/architecture.md#Starter Template Evaluation]
|
||||
@@ -126,8 +96,35 @@ try-bmad/
|
||||
|
||||
### Agent Model Used
|
||||
|
||||
Claude Opus 4.6 (1M context)
|
||||
|
||||
### Debug Log References
|
||||
|
||||
- Scaffolded to temp directory and copied files (current directory was non-empty)
|
||||
- Clear Sans font sourced from @fontsource/clear-sans npm package, copied static woff2 files to public/fonts
|
||||
|
||||
### Completion Notes List
|
||||
|
||||
- Project scaffolded with Svelte 5.55.1 + Vite 8.0.4
|
||||
- Tailwind CSS v4.2.2 configured via @tailwindcss/vite plugin
|
||||
- Vitest v4.1.4 installed with 5 passing constants tests
|
||||
- Constants module created with all 12-tier tile colors, directions, and game values
|
||||
- Clear Sans Bold + Regular fonts placed in public/fonts with @font-face declarations
|
||||
- Page background #faf8ef set, minimal App.svelte with 2048 heading
|
||||
- Production build: 24KB JS + 11KB CSS (well under 50KB gzipped target)
|
||||
|
||||
### File List
|
||||
|
||||
- index.html (from scaffold)
|
||||
- package.json (configured with project name, test script)
|
||||
- vite.config.js (Svelte + Tailwind plugins)
|
||||
- jsconfig.json (from scaffold)
|
||||
- svelte.config.js (from scaffold)
|
||||
- src/main.js (from scaffold)
|
||||
- src/app.css (Tailwind import + @font-face + body styles)
|
||||
- src/App.svelte (minimal 2048 heading)
|
||||
- src/lib/constants.js (game constants)
|
||||
- src/lib/game-logic.test.js (constants validation tests)
|
||||
- public/fonts/ClearSans-Bold.woff2
|
||||
- public/fonts/ClearSans-Regular.woff2
|
||||
- public/favicon.svg (from scaffold)
|
||||
|
||||
@@ -44,7 +44,7 @@ story_location: _bmad-output/implementation-artifacts
|
||||
development_status:
|
||||
# Epic 1: Play a Complete Game (Desktop)
|
||||
epic-1: in-progress
|
||||
1-1-project-scaffold-and-dev-environment: ready-for-dev
|
||||
1-1-project-scaffold-and-dev-environment: review
|
||||
1-2-game-logic-module: backlog
|
||||
1-3-game-board-and-tile-rendering: backlog
|
||||
1-4-game-header-score-display-and-new-game-button: backlog
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>try-bmad-scaffold</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "bundler",
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
/**
|
||||
* svelte-preprocess cannot figure out whether you have
|
||||
* a value or a type, so tell TypeScript to enforce using
|
||||
* `import type` instead of `import` for Types.
|
||||
*/
|
||||
"verbatimModuleSyntax": true,
|
||||
"isolatedModules": true,
|
||||
"resolveJsonModule": true,
|
||||
/**
|
||||
* To have warnings / errors of the Svelte compiler at the
|
||||
* correct position, enable source maps by default.
|
||||
*/
|
||||
"sourceMap": true,
|
||||
"esModuleInterop": true,
|
||||
"types": ["vite/client"],
|
||||
"skipLibCheck": true,
|
||||
/**
|
||||
* Typecheck JS in `.svelte` and `.js` files by default.
|
||||
* Disable this if you'd like to use dynamic types.
|
||||
*/
|
||||
"checkJs": true
|
||||
},
|
||||
/**
|
||||
* Use global.d.ts instead of compilerOptions.types
|
||||
* to avoid limiting type declarations.
|
||||
*/
|
||||
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"]
|
||||
}
|
||||
Generated
+1869
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "try-bmad",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"test": "vitest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/vite-plugin-svelte": "^7.0.0",
|
||||
"@tailwindcss/vite": "^4.2.2",
|
||||
"svelte": "^5.55.1",
|
||||
"tailwindcss": "^4.2.2",
|
||||
"vite": "^8.0.4",
|
||||
"vitest": "^4.1.4"
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 9.3 KiB |
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
<h1 class="text-center text-[80px] font-bold" style="color: #776e65;">2048</h1>
|
||||
@@ -0,0 +1,23 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
@font-face {
|
||||
font-family: 'Clear Sans';
|
||||
src: url('/fonts/ClearSans-Regular.woff2') format('woff2');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Clear Sans';
|
||||
src: url('/fonts/ClearSans-Bold.woff2') format('woff2');
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #faf8ef;
|
||||
font-family: 'Clear Sans', 'Helvetica Neue', Arial, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
export const GRID_SIZE = 4;
|
||||
export const WIN_VALUE = 2048;
|
||||
export const SPAWN_PROBABILITY = 0.9;
|
||||
|
||||
export const DIRECTIONS = {
|
||||
UP: 'up',
|
||||
DOWN: 'down',
|
||||
LEFT: 'left',
|
||||
RIGHT: 'right',
|
||||
};
|
||||
|
||||
export const TILE_COLORS = {
|
||||
2: { bg: '#eee4da', text: '#776e65' },
|
||||
4: { bg: '#ede0c8', text: '#776e65' },
|
||||
8: { bg: '#f2b179', text: '#f9f6f2' },
|
||||
16: { bg: '#f59563', text: '#f9f6f2' },
|
||||
32: { bg: '#f67c5f', text: '#f9f6f2' },
|
||||
64: { bg: '#f65e3b', text: '#f9f6f2' },
|
||||
128: { bg: '#edcf72', text: '#f9f6f2' },
|
||||
256: { bg: '#edcc61', text: '#f9f6f2' },
|
||||
512: { bg: '#edc850', text: '#f9f6f2' },
|
||||
1024: { bg: '#edc53f', text: '#f9f6f2' },
|
||||
2048: { bg: '#edc22e', text: '#f9f6f2' },
|
||||
super: { bg: '#3c3a32', text: '#f9f6f2' },
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { GRID_SIZE, WIN_VALUE, SPAWN_PROBABILITY, DIRECTIONS, TILE_COLORS } from './constants.js';
|
||||
|
||||
describe('constants', () => {
|
||||
it('should have correct grid size', () => {
|
||||
expect(GRID_SIZE).toBe(4);
|
||||
});
|
||||
|
||||
it('should have correct win value', () => {
|
||||
expect(WIN_VALUE).toBe(2048);
|
||||
});
|
||||
|
||||
it('should have correct spawn probability', () => {
|
||||
expect(SPAWN_PROBABILITY).toBe(0.9);
|
||||
});
|
||||
|
||||
it('should have all four directions', () => {
|
||||
expect(DIRECTIONS).toEqual({
|
||||
UP: 'up',
|
||||
DOWN: 'down',
|
||||
LEFT: 'left',
|
||||
RIGHT: 'right',
|
||||
});
|
||||
});
|
||||
|
||||
it('should have 12 tile color tiers', () => {
|
||||
const keys = Object.keys(TILE_COLORS);
|
||||
expect(keys).toHaveLength(12);
|
||||
expect(TILE_COLORS[2].bg).toBe('#eee4da');
|
||||
expect(TILE_COLORS[2048].bg).toBe('#edc22e');
|
||||
expect(TILE_COLORS.super.bg).toBe('#3c3a32');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
import { mount } from 'svelte'
|
||||
import './app.css'
|
||||
import App from './App.svelte'
|
||||
|
||||
const app = mount(App, {
|
||||
target: document.getElementById('app'),
|
||||
})
|
||||
|
||||
export default app
|
||||
@@ -0,0 +1,2 @@
|
||||
/** @type {import("@sveltejs/vite-plugin-svelte").SvelteConfig} */
|
||||
export default {}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [svelte(), tailwindcss()],
|
||||
})
|
||||
Reference in New Issue
Block a user