Files
gupi-osint-board/package.json
gitprovandClaude Opus 4.8 1893bf23af Add 3D clamshell phone dialer spike + persistent-board design
A diegetic 90s handset rendered as a small three.js scene in a fixed 1:2
portrait stage (visual spike at /?phone=1, three.js lazy-loaded so the
board bundle is unchanged). Blocky flat-shaded clamshell with glowing
keys, a flip-open animation with an intro camera orbit that settles
head-on before the DOM screen appears, a hinge barrel on the pivot axis,
and a chubby antenna. Pressable 3D keypad (raycast + keyboard) with DTMF
tones drives a dialer: connect / voicemail / SIT "unobtainable", against
a stub number->node directory with flag-gated node enablement.

The screen UI is real DOM positioned in percent of the stage, kept
pixel-exact by the head-on ortho camera.

Also documents the persistent-board flow model (docs/persistent-boards.md):
board_key reuse across level nodes, present-but-hidden flag-gated exhibits
with live arrival reveals, reset/new-game semantics, and A/B/M citation codes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-22 12:14:11 +02:00

56 lines
1.8 KiB
JSON

{
"name": "gupi-osint-board",
"private": true,
"version": "0.1.0",
"type": "module",
"scripts": {
"dev": "concurrently -k \"npm:dev:server\" \"npm:dev:web\"",
"dev:web": "vite",
"dev:server": "tsx watch server/index.ts",
"build": "tsc -b && vite build",
"e2e:serve": "TEST_DATABASE_URL=${TEST_DATABASE_URL:-postgres://osint:osint_secret@localhost:5433/osint_dev} tsx server/e2eHarness.ts",
"start": "NODE_ENV=production tsx server/index.ts",
"migrate:up": "tsx server/migrate.ts",
"mystery:import": "tsx scripts/importMysteryTemplate.ts",
"test": "vitest run --exclude '**/*.integration.test.ts' --exclude 'e2e/**'",
"test:integration": "TEST_DATABASE_URL=${TEST_DATABASE_URL:-postgres://osint:osint_secret@localhost:5433/osint_dev} vitest run server/*.integration.test.ts",
"test:e2e": "npm run build && playwright test"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.1111.0",
"cookie-parser": "^1.4.7",
"cors": "2.8.5",
"dotenv": "16.5.0",
"express": "5.1.0",
"jsonwebtoken": "^9.0.2",
"lucide-react": "0.468.0",
"multer": "^2.2.0",
"pg": "8.16.3",
"react": "19.1.0",
"react-dom": "19.1.0",
"three": "^0.185.1",
"tsx": "4.20.3"
},
"devDependencies": {
"@playwright/test": "^1.62.1",
"@types/cookie-parser": "^1.4.9",
"@types/cors": "2.8.18",
"@types/express": "5.0.3",
"@types/jsonwebtoken": "^9.0.10",
"@types/multer": "2.0.0",
"@types/node": "22.15.30",
"@types/pg": "8.15.4",
"@types/react": "19.1.8",
"@types/react-dom": "19.1.6",
"@types/three": "^0.185.4",
"@vitejs/plugin-react": "4.5.2",
"concurrently": "9.1.2",
"typescript": "5.8.3",
"vite": "^6.4.3",
"vitest": "^3.2.7"
},
"engines": {
"node": "^20.0.0 || >=22.0.0"
}
}