SkateSpots/package.json
shakespeare.diy 92f317f5e5 fix: Amber login for GrapheneOS — clipboard + paste flow
GrapheneOS Vanadium browser blocks intent: URLs from web pages as a
security hardening measure. This is why every URL format we tried
caused "malformed request" — Vanadium was blocking the intent before
Amber ever saw it.

New flow that works on ALL Android browsers including GrapheneOS:
1. Tap "Open Amber" → navigates to nostrsigner: URL with no callbackUrl
   (Amber copies pubkey to clipboard when no callbackUrl is given)
2. User approves in Amber, comes back to app
3. App tries navigator.clipboard.readText() automatically on visibilitychange
4. If clipboard permission denied → shows paste input for hex pubkey
5. User pastes pubkey → logged in

No intent: scheme, no callback URL, no redirect loop. Simple and bulletproof.

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-07-08 11:43:59 +07:00

133 lines
5 KiB
JSON

{
"name": "skate-spots",
"private": true,
"version": "1.0.31",
"type": "module",
"homepage": "https://skate-spots.com",
"scripts": {
"dev": "npm i --silent && vite",
"build": "npm i --silent && vite build -l error && cp dist/index.html dist/404.html && echo 'Project built successfully!'",
"test": "npm i --silent && tsc --noEmit && eslint && vitest run --reporter=dot --silent && vite build -l error && cp dist/index.html dist/404.html && echo 'All tests passed!'",
"deploy": "npm i --silent && npm run build && npx -y nostr-deploy-cli deploy --skip-setup",
"android:init": "npm run android:build:apk && npx cap add android && npx cap sync android",
"android:sync": "npm run android:build:apk && npx cap sync android",
"android:open": "npx cap open android",
"android:build": "npm run android:build:apk && npx cap sync android && cd android && ./gradlew assembleRelease",
"android:build:apk": "CAPACITOR_BUILD=1 vite build && sed -i 's|<script type=\"module\" src=\"/shakespeare_tailwind[^\"]*\\.js\"></script>||g' dist/index.html && sed -i 's|<style type=\"text/tailwindcss\">|<style>|g' dist/index.html && cp dist/index.html dist/404.html"
},
"dependencies": {
"@bitcoinerlab/secp256k1": "^1.2.0",
"@cashu/cashu-ts": "2.8.1",
"@contextvm/sdk": "^0.12.0",
"@fontsource-variable/inter": "^5.2.6",
"@fontsource-variable/outfit": "^5.2.8",
"@fontsource/barlow-condensed": "^5.2.8",
"@fontsource/bebas-neue": "^5.2.7",
"@getalby/sdk": "^5.1.1",
"@hookform/resolvers": "^3.9.0",
"@modelcontextprotocol/sdk": "^1.29.0",
"@noble/curves": "^2.0.1",
"@noble/hashes": "^2.0.1",
"@nostrify/nostrify": "^0.47.1",
"@nostrify/react": "^0.2.17",
"@radix-ui/react-accordion": "^1.2.0",
"@radix-ui/react-alert-dialog": "^1.1.1",
"@radix-ui/react-aspect-ratio": "^1.1.0",
"@radix-ui/react-avatar": "^1.1.0",
"@radix-ui/react-checkbox": "^1.1.1",
"@radix-ui/react-collapsible": "^1.1.0",
"@radix-ui/react-context-menu": "^2.2.1",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-hover-card": "^1.1.1",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-menubar": "^1.1.1",
"@radix-ui/react-navigation-menu": "^1.2.0",
"@radix-ui/react-popover": "^1.1.1",
"@radix-ui/react-progress": "^1.1.0",
"@radix-ui/react-radio-group": "^1.2.0",
"@radix-ui/react-scroll-area": "^1.1.0",
"@radix-ui/react-select": "^2.1.1",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slider": "^1.2.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-switch": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.0",
"@radix-ui/react-toast": "^1.2.1",
"@radix-ui/react-toggle": "^1.1.0",
"@radix-ui/react-toggle-group": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.4",
"@scure/bip32": "^2.0.1",
"@scure/bip39": "1.6.0",
"@tanstack/react-query": "^5.56.2",
"@unhead/addons": "^2.0.10",
"@unhead/react": "^2.0.10",
"bitcoinjs-lib": "^7.0.0",
"buffer": "^6.0.3",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
"coco-cashu-core": "1.1.2-rc.30",
"coco-cashu-indexeddb": "1.1.2-rc.30",
"date-fns": "^4.1.0",
"dexie": "^4.0.8",
"dotenv": "^17.4.2",
"ecpair": "^3.0.0",
"embla-carousel-react": "^8.3.0",
"hls.js": "^1.6.15",
"html2canvas": "^1.4.1",
"html5-qrcode": "^2.3.8",
"idb": "^8.0.3",
"input-otp": "^1.2.4",
"leaflet": "^1.9.4",
"leaflet.markercluster": "^1.5.3",
"lucide-react": "^0.462.0",
"ngeohash": "^0.6.3",
"nostr-tools": "^2.13.0",
"npubcash-sdk": "^0.2.0",
"qrcode": "^1.5.4",
"react": "^18.3.1",
"react-day-picker": "^8.10.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.53.0",
"react-intersection-observer": "^9.16.0",
"react-resizable-panels": "^2.1.3",
"react-router-dom": "^6.26.2",
"recharts": "^2.12.7",
"tailwind-merge": "^2.5.2",
"tailwindcss-animate": "^1.0.7",
"vaul": "^0.9.3",
"zod": "^3.25.71"
},
"devDependencies": {
"@eslint/js": "^9.9.0",
"@html-eslint/eslint-plugin": "^0.41.0",
"@html-eslint/parser": "^0.41.0",
"@tailwindcss/typography": "^0.5.15",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@types/leaflet": "^1.9.21",
"@types/leaflet.markercluster": "^1.5.6",
"@types/ngeohash": "^0.6.8",
"@types/node": "^22.5.5",
"@types/qrcode": "^1.5.5",
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react-swc": "^3.5.0",
"@webbtc/webln-types": "^3.0.0",
"autoprefixer": "^10.4.20",
"eslint": "^9.9.0",
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
"eslint-plugin-react-refresh": "^0.4.9",
"globals": "^15.9.0",
"jsdom": "^26.1.0",
"postcss": "^8.4.47",
"tailwindcss": "^3.4.11",
"tsx": "^4.22.4",
"typescript": "^5.5.3",
"typescript-eslint": "^8.0.1",
"vite": "^6.3.5",
"vitest": "^3.1.4"
}
}