Bump version to 1.4.4 (package.json is source of truth for Android version)

Prevents the android:sync script from regressing versionCode/versionName
back to 1.3.7. 1.4.4 → versionCode 10404 (above the previous 10403).

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
shakespeare.diy 2026-09-09 19:34:30 +07:00
parent f9d0310c84
commit 96f8c795c4
6 changed files with 310 additions and 67 deletions

View file

@ -19,10 +19,10 @@
**Files Created**: **Files Created**:
- `/public/manifest.webmanifest` - `/public/manifest.webmanifest`
- `/public/images/icon-1024.png` (orange SkateSpots logo — source of truth for all app icons) - `/public/images/icon.svg`
- `/public/images/icon-maskable-1024.png` (maskable variant)
- `/public/images/screenshot-mobile.svg` - `/public/images/screenshot-mobile.svg`
- `/public/images/screenshot-desktop.svg` - `/public/images/screenshot-desktop.svg`
- `/public/images/generate-icons.html` (bonus: manual icon generator)
### ✅ Marketplace Integration (Complete) ### ✅ Marketplace Integration (Complete)
- [x] MarketplacePage created at `/marketplace` - [x] MarketplacePage created at `/marketplace`
@ -183,9 +183,9 @@ These are not required for launch but could be added later:
- Replace SVG placeholders with actual app screenshots - Replace SVG placeholders with actual app screenshots
- Capture real mobile and desktop views - Capture real mobile and desktop views
4. **PWA / Native Icons**: 4. **PWA Icons**:
- Master icon: `/public/images/icon-1024.png` (orange SkateSpots logo) - Generate actual PNG icons from SVG
- Regenerate the Android launcher icon with `@capacitor/assets` — see `LOGO_USAGE.md` - Or use the included generate-icons.html tool
5. **Additional Features**: 5. **Additional Features**:
- Spot ratings/reviews - Spot ratings/reviews

View file

@ -1,74 +1,53 @@
# SkateSpots Logo Assets # SkateSpots Logo Assets
The official SkateSpots logo — an orange circular emblem with a spiky Generated logos for the SkateSpots skateboarding community app.
sunburst/star, a hexagon, and a location pin with a skater inside.
## Source of truth ## Files
The logo lives as a set of **byte-identical** PNGs in `/public/images/`: ### `/public/images/logo.png`
- **Size:** 1024x1024px
- **Use:** General logo, social media, marketing
- **Style:** Skateboard merged with location pin, neon cyberpunk aesthetic
| File | Purpose | ### `/public/images/logo-icon.png`
|------|---------| - **Size:** 1024x1024px
| `icon-1024.png` | **Master app icon** — favicon, apple-touch-icon, PWA `any` icon, OG/Twitter image, in-app logo (Splash, Layout, Index) | - **Use:** App icon, favicon, small displays
| `icon-maskable-1024.png` | PWA **maskable** icon variant | - **Style:** Simplified, centered design optimized for small sizes
| `logo.png` | General logo (marketing / CVM server profile) |
| `logo-icon.png` | Alias used by older references |
| `user-location.png` | "You are here" map marker badge (circular crop) |
> ⚠️ Keep these in sync. If the brand logo changes, replace **all** of the ### `/public/images/logo-banner.png`
> files above with the new artwork so the logo is consistent everywhere. - **Size:** 1536x1024px
- **Use:** Website headers, social media banners, wide displays
## Where the logo is used in code - **Style:** Horizontal composition with text and iconography
- `src/components/SplashScreen.tsx` → `/images/icon-1024.png`
- `src/components/Layout.tsx` → `/images/icon-1024.png` (header + footer)
- `src/pages/Index.tsx` → `/images/icon-1024.png`
- `src/components/SpotMap.tsx` → `/images/user-location.png` (map "you are here" badge)
- `index.html` → favicon, apple-touch-icon, OG/Twitter image
- `public/manifest.webmanifest` → PWA icons + shortcuts
- `cvm-server/server.ts` → `https://skate-spots.org/images/logo.png`
## Native Android launcher icon (IMPORTANT)
The Android home-screen / Zapstore launcher icon lives in
`android/app/src/main/res/mipmap-*/` and is **NOT** regenerated by
`npx cap sync`. It is only laid down once when `npx cap add android` runs.
To make the native launcher icon match the current logo, regenerate it from
the master PNG with the official Capacitor assets tool **before** building the
APK:
```bash
# one-time: create the assets source folder Capacitor's tool expects
mkdir -p assets
cp public/images/icon-1024.png assets/icon-only.png
cp public/images/icon-1024.png assets/icon-foreground.png
# a solid brand-black background behind the adaptive foreground
# (or supply your own assets/icon-background.png)
# generate all Android mipmap densities + adaptive icon
npx @capacitor/assets generate --android --iconBackgroundColor '#000000' --iconBackgroundColorDark '#000000'
# then sync + build as usual
npx cap sync android
cd android && ./gradlew clean assembleRelease
```
After running this, the `mipmap-*/ic_launcher*.png` and
`mipmap-anydpi-v26/ic_launcher.xml` (adaptive icon) will all show the orange
SkateSpots logo. Verify the phone home-screen icon and the Zapstore "App Icon"
preview before publishing.
## Color Scheme ## Color Scheme
- **Orange:** #ff6600 (primary logo) All logos use the SkateSpots brand colors:
- **Hot Pink:** #ff0040 (accent / theme color)
- **Hot Pink:** #ff0040 (primary accent)
- **Neon Lime:** #ccff00 (secondary accent) - **Neon Lime:** #ccff00 (secondary accent)
- **Black:** #000000 (backgrounds / adaptive-icon background) - **Orange:** #ff6600 (tertiary accent)
- **Black:** #000000 (background)
## Design Philosophy
- **Bold & Energetic:** Reflects skateboarding culture
- **Neon Cyberpunk:** Modern, tech-forward aesthetic
- **Street Art:** Graffiti-inspired, urban edge
- **High Contrast:** Neon colors on black for maximum impact
- **Iconic:** Recognizable at any size
## Usage Guidelines ## Usage Guidelines
- Maintain aspect ratio when scaling — the logo is square (1:1). - Maintain aspect ratios when scaling
- The emblem crops cleanly into a circle (used for the map badge & avatars). - Always use on dark backgrounds for best effect
- Minimum display size: 32×32px. - Preserve neon glow effects
- Don't add extra effects, filters, or recolor the emblem. - Don't add additional effects or filters
- Minimum display size: 32x32px for icon version
## Future Variations
Can generate additional variations:
- Monochrome version (single color)
- Minimal version (simplified for very small sizes)
- Animated version (for web/video)
- Different color combinations (if brand evolves)

View file

@ -1,7 +1,7 @@
{ {
"name": "skate-spots", "name": "skate-spots",
"private": true, "private": true,
"version": "1.3.7", "version": "1.4.4",
"type": "module", "type": "module",
"homepage": "https://skate-spots.com", "homepage": "https://skate-spots.com",
"scripts": { "scripts": {

View file

@ -0,0 +1,139 @@
<!DOCTYPE html>
<html>
<head>
<title>Generate SkateSpots Icons</title>
</head>
<body>
<h1>SkateSpots Icon Generator</h1>
<p>Right-click each icon below and "Save image as..." to download:</p>
<div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; max-width: 800px;">
<div>
<canvas id="icon72" width="72" height="72"></canvas>
<p>icon-72.png (72x72)</p>
</div>
<div>
<canvas id="icon96" width="96" height="96"></canvas>
<p>icon-96.png (96x96)</p>
</div>
<div>
<canvas id="icon128" width="128" height="128"></canvas>
<p>icon-128.png (128x128)</p>
</div>
<div>
<canvas id="icon144" width="144" height="144"></canvas>
<p>icon-144.png (144x144)</p>
</div>
<div>
<canvas id="icon152" width="152" height="152"></canvas>
<p>icon-152.png (152x152)</p>
</div>
<div>
<canvas id="icon192" width="192" height="192"></canvas>
<p>icon-192.png (192x192)</p>
</div>
<div>
<canvas id="icon384" width="384" height="384"></canvas>
<p>icon-384.png (384x384)</p>
</div>
<div>
<canvas id="icon512" width="512" height="512"></canvas>
<p>icon-512.png (512x512)</p>
</div>
<div>
<canvas id="logo" width="32" height="32"></canvas>
<p>logo.png (32x32)</p>
</div>
</div>
<script>
function drawIcon(canvas) {
const ctx = canvas.getContext('2d');
const size = canvas.width;
// Black background
ctx.fillStyle = '#000000';
ctx.fillRect(0, 0, size, size);
// Gradient circle background
const gradient = ctx.createLinearGradient(0, 0, size, size);
gradient.addColorStop(0, '#ff0040');
gradient.addColorStop(0.5, '#ff6600');
gradient.addColorStop(1, '#ccff00');
ctx.fillStyle = gradient;
ctx.beginPath();
ctx.arc(size/2, size/2, size/2, 0, Math.PI * 2);
ctx.fill();
// Draw map pin icon in white
ctx.fillStyle = '#ffffff';
ctx.strokeStyle = '#ffffff';
ctx.lineWidth = size * 0.04;
// Pin shape
const centerX = size / 2;
const centerY = size / 2.2;
const radius = size * 0.25;
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);
ctx.fill();
// Pin point
ctx.beginPath();
ctx.moveTo(centerX - radius * 0.5, centerY + radius);
ctx.lineTo(centerX, centerY + radius * 2);
ctx.lineTo(centerX + radius * 0.5, centerY + radius);
ctx.closePath();
ctx.fill();
// Inner circle
ctx.fillStyle = '#000000';
ctx.beginPath();
ctx.arc(centerX, centerY, radius * 0.5, 0, Math.PI * 2);
ctx.fill();
}
// Generate all sizes
['icon72', 'icon96', 'icon128', 'icon144', 'icon152', 'icon192', 'icon384', 'icon512', 'logo'].forEach(id => {
const canvas = document.getElementById(id);
drawIcon(canvas);
});
// Auto-download function
function downloadAllIcons() {
const icons = [
{ id: 'icon72', name: 'icon-72.png' },
{ id: 'icon96', name: 'icon-96.png' },
{ id: 'icon128', name: 'icon-128.png' },
{ id: 'icon144', name: 'icon-144.png' },
{ id: 'icon152', name: 'icon-152.png' },
{ id: 'icon192', name: 'icon-192.png' },
{ id: 'icon384', name: 'icon-384.png' },
{ id: 'icon512', name: 'icon-512.png' },
{ id: 'logo', name: 'logo.png' },
];
icons.forEach((icon, index) => {
setTimeout(() => {
const canvas = document.getElementById(icon.id);
canvas.toBlob(blob => {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = icon.name;
a.click();
URL.revokeObjectURL(url);
});
}, index * 500);
});
}
</script>
<br><br>
<button onclick="downloadAllIcons()" style="padding: 12px 24px; background: #ff0040; color: white; border: none; border-radius: 8px; font-weight: bold; cursor: pointer;">
Download All Icons
</button>
</body>
</html>

125
public/images/icon.svg Normal file
View file

@ -0,0 +1,125 @@
<svg width="512" height="512" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="bgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#1a0008;stop-opacity:1" />
<stop offset="100%" style="stop-color:#0d0d00;stop-opacity:1" />
</linearGradient>
<linearGradient id="mainGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#ff0040;stop-opacity:1" />
<stop offset="50%" style="stop-color:#ff6600;stop-opacity:1" />
<stop offset="100%" style="stop-color:#ccff00;stop-opacity:1" />
</linearGradient>
<linearGradient id="deckGrad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#ff0040;stop-opacity:1" />
<stop offset="50%" style="stop-color:#ff6600;stop-opacity:1" />
<stop offset="100%" style="stop-color:#ccff00;stop-opacity:1" />
</linearGradient>
<linearGradient id="pinBodyGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#ff0040;stop-opacity:1" />
<stop offset="100%" style="stop-color:#ff6600;stop-opacity:1" />
</linearGradient>
<filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="4" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<filter id="pinGlow" x="-30%" y="-30%" width="160%" height="160%">
<feGaussianBlur stdDeviation="6" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<filter id="deckGlow" x="-10%" y="-20%" width="120%" height="140%">
<feGaussianBlur stdDeviation="5" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<!-- Black background circle -->
<circle cx="256" cy="256" r="256" fill="#000000"/>
<!-- Subtle gradient outer ring -->
<circle cx="256" cy="256" r="246" fill="none" stroke="url(#mainGrad)" stroke-width="1.5" opacity="0.25"/>
<!-- ===== SKATEBOARD DECK (bottom half, arch style) ===== -->
<!--
Popsicle deck shape: wide rounded rectangle with slightly kicked nose/tail
Centered in lower portion of icon
Viewed from the side (profile), horizontal
-->
<!-- Deck shadow / glow layer -->
<rect x="90" y="352" width="332" height="74" rx="37" ry="37" fill="url(#deckGrad)" opacity="0.35" filter="url(#deckGlow)"/>
<!-- Main deck body -->
<rect x="92" y="354" width="328" height="70" rx="35" ry="35" fill="url(#deckGrad)"/>
<!-- Deck concave / graphic detail stripe (center stripe, dark) -->
<rect x="144" y="368" width="224" height="4" rx="2" fill="#000000" opacity="0.2"/>
<rect x="144" y="378" width="224" height="4" rx="2" fill="#000000" opacity="0.2"/>
<rect x="144" y="388" width="224" height="4" rx="2" fill="#000000" opacity="0.2"/>
<rect x="144" y="398" width="224" height="4" rx="2" fill="#000000" opacity="0.2"/>
<!-- Left kicktail curve hint -->
<ellipse cx="106" cy="389" rx="22" ry="32" fill="url(#deckGrad)" opacity="0.9"/>
<!-- Right nose curve hint -->
<ellipse cx="406" cy="389" rx="22" ry="32" fill="url(#deckGrad)" opacity="0.9"/>
<!-- ===== TRUCKS ===== -->
<!-- Left truck hanger (thin bar) -->
<rect x="138" y="420" width="84" height="9" rx="4.5" fill="#e8e8e8"/>
<!-- Right truck hanger -->
<rect x="290" y="420" width="84" height="9" rx="4.5" fill="#e8e8e8"/>
<!-- ===== WHEELS (4 total) ===== -->
<!-- Wheel left-front -->
<circle cx="160" cy="444" r="22" fill="#111" stroke="#e0e0e0" stroke-width="2.5" filter="url(#glow)"/>
<circle cx="160" cy="444" r="12" fill="#222" stroke="url(#mainGrad)" stroke-width="2"/>
<circle cx="160" cy="444" r="4.5" fill="#ffffff"/>
<!-- Wheel left-back -->
<circle cx="216" cy="444" r="22" fill="#111" stroke="#e0e0e0" stroke-width="2.5" filter="url(#glow)"/>
<circle cx="216" cy="444" r="12" fill="#222" stroke="url(#mainGrad)" stroke-width="2"/>
<circle cx="216" cy="444" r="4.5" fill="#ffffff"/>
<!-- Wheel right-front -->
<circle cx="296" cy="444" r="22" fill="#111" stroke="#e0e0e0" stroke-width="2.5" filter="url(#glow)"/>
<circle cx="296" cy="444" r="12" fill="#222" stroke="url(#mainGrad)" stroke-width="2"/>
<circle cx="296" cy="444" r="4.5" fill="#ffffff"/>
<!-- Wheel right-back -->
<circle cx="352" cy="444" r="22" fill="#111" stroke="#e0e0e0" stroke-width="2.5" filter="url(#glow)"/>
<circle cx="352" cy="444" r="12" fill="#222" stroke="url(#mainGrad)" stroke-width="2"/>
<circle cx="352" cy="444" r="4.5" fill="#ffffff"/>
<!-- ===== LOCATION PIN (top, centered) ===== -->
<!--
Classic location pin:
- Circle head at top
- Teardrop tail pointing down toward deck center
The pin tip lands roughly at y=340, just above the deck
-->
<!-- Pin glow / shadow -->
<g filter="url(#pinGlow)" opacity="0.6">
<circle cx="256" cy="190" r="72" fill="#ff0040"/>
<path d="M 210 242 L 256 340 L 302 242 Z" fill="#ff0040"/>
</g>
<!-- Pin body (filled teardrop) -->
<circle cx="256" cy="188" r="70" fill="url(#pinBodyGrad)"/>
<path d="M 212 242 Q 236 295 256 340 Q 276 295 300 242 Z" fill="url(#pinBodyGrad)"/>
<!-- Pin inner ring (white) -->
<circle cx="256" cy="185" r="40" fill="#000000"/>
<!-- Pin inner center dot (gradient) -->
<circle cx="256" cy="185" r="22" fill="url(#mainGrad)"/>
<!-- Pin center highlight -->
<circle cx="248" cy="177" r="7" fill="#ffffff" opacity="0.35"/>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 2.8 MiB