Initialize Black 7 PWA with React, Vite, and app icons
Sets up Vite + React + TypeScript with vite-plugin-pwa for offline support. Adds app icon (line-drawn 7 on black) in all required sizes with a generation script. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+12
@@ -0,0 +1,12 @@
|
||||
/tmp
|
||||
/out-tsc
|
||||
/dist
|
||||
|
||||
/node_modules
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
.vscode/*
|
||||
Generated
+10
@@ -0,0 +1,10 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Ignored default folder with query files
|
||||
/queries/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
@@ -0,0 +1,36 @@
|
||||
# Black 7
|
||||
|
||||
Scoring app for the card game **Last Panther**, hosted at black7.org.
|
||||
|
||||
## What this is
|
||||
|
||||
A mobile-first progressive web app (PWA) built with React and TypeScript. No backend — everything runs in the browser. Players use it to track scores during a game of Last Panther.
|
||||
|
||||
## Tech stack
|
||||
|
||||
- React (UI)
|
||||
- TypeScript (strict mode)
|
||||
- PWA (installable, offline-capable)
|
||||
- No server, no API — browser-only
|
||||
|
||||
## Key constraints
|
||||
|
||||
- **Mobile-first**: design and test for phone-sized screens first; desktop is secondary
|
||||
- **No backend**: all state lives in the browser (localStorage, sessionStorage, or in-memory)
|
||||
- **Installable**: must meet PWA requirements (manifest, service worker, HTTPS)
|
||||
|
||||
## Running the app
|
||||
|
||||
```
|
||||
npm install
|
||||
npm run dev # start dev server
|
||||
npm run build # production build
|
||||
```
|
||||
|
||||
## Project conventions
|
||||
|
||||
- Components live in `src/components/`
|
||||
- Game logic (scoring rules, state) lives in `src/game/`
|
||||
- Types shared across the app live in `src/types.ts`
|
||||
- Prefer small, focused components; keep game logic out of UI components
|
||||
- No unnecessary comments — name things clearly instead
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
||||
<title>Black 7</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
Generated
+6240
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "black7",
|
||||
"version": "1.0.0",
|
||||
"description": "Scoring app for Last Panther card game",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^19.2.6",
|
||||
"react-dom": "^19.2.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^19.2.15",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^6.0.2",
|
||||
"typescript": "^5.9.3",
|
||||
"vite": "^8.0.14",
|
||||
"vite-plugin-pwa": "^1.3.0"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<rect width="512" height="512" fill="#0a0a0a"/>
|
||||
<g fill="none" stroke="#f0ede6" stroke-linecap="round" stroke-linejoin="round">
|
||||
<!-- horizontal top bar + diagonal leg of the 7 -->
|
||||
<path d="M 90 120 L 408 112 L 206 450" stroke-width="30"/>
|
||||
<!-- European crossbar -->
|
||||
<path d="M 248 268 L 354 262" stroke-width="23"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 413 B |
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/../public"
|
||||
|
||||
rsvg-convert -w 512 -h 512 icon.svg -o pwa-512x512.png
|
||||
rsvg-convert -w 192 -h 192 icon.svg -o pwa-192x192.png
|
||||
rsvg-convert -w 180 -h 180 icon.svg -o apple-touch-icon.png
|
||||
rsvg-convert -w 32 -h 32 icon.svg -o favicon-32.png
|
||||
magick favicon-32.png favicon.ico
|
||||
rm favicon-32.png
|
||||
|
||||
echo "Icons generated."
|
||||
@@ -0,0 +1,7 @@
|
||||
export default function App() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Black 7</h1>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { StrictMode } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import App from './App'
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>
|
||||
)
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"jsx": "react-jsx",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
import { VitePWA } from 'vite-plugin-pwa'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
react(),
|
||||
VitePWA({
|
||||
registerType: 'autoUpdate',
|
||||
includeAssets: ['favicon.ico', 'apple-touch-icon.png'],
|
||||
manifest: {
|
||||
name: 'Black 7',
|
||||
short_name: 'Black 7',
|
||||
description: 'Scoring app for Last Panther',
|
||||
theme_color: '#000000',
|
||||
background_color: '#000000',
|
||||
display: 'standalone',
|
||||
icons: [
|
||||
{
|
||||
src: 'pwa-192x192.png',
|
||||
sizes: '192x192',
|
||||
type: 'image/png',
|
||||
},
|
||||
{
|
||||
src: 'pwa-512x512.png',
|
||||
sizes: '512x512',
|
||||
type: 'image/png',
|
||||
},
|
||||
{
|
||||
src: 'pwa-512x512.png',
|
||||
sizes: '512x512',
|
||||
type: 'image/png',
|
||||
purpose: 'any maskable',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
],
|
||||
})
|
||||
Reference in New Issue
Block a user