🧹 Spot owners can delete from the card menu - Owner/admin members now get a **Delete** action in the three-dot menu on spot and shop cards, opening the existing confirmation dialog. - Added a mobile **Back** arrow on every non-map screen, with history fallback to the map. The bottom Spots tab remains the home shortcut. - Trimmed the avatar account menu to purpose-built actions: status, profile, settings, account switching and logout. The larger navigation stays in the burger menu. - Brand wordmark hides on sub-pages so the Back arrow and header controls fit on narrow phones without truncation. --- 🧭 Brand logo opens your profile - The top-left SkateSpots lockup now opens your public profile when signed in (both mobile and desktop). Signed out, it still goes to the map. - The bottom Spots tab / desktop Map tab remains the home shortcut, so map access is unchanged. - The green avatar still opens your profile too; its chevron opens the account menu. --- 👤 Avatar opens your profile - The green user avatar in the mobile header now opens your public profile. - The small chevron beside it opens the account menu (status, add account, wallet, settings, logout) — the avatar itself is no longer a menu trigger. - Removed the redundant “IN” label so the brand and header controls fit on narrow phones. - The SkateSpots brand mark still goes to the map. --- 🧭 Simpler mobile navigation - The bottom bar is now exactly five intents: Spots, The Lab, Events, Crews and More. Profile/login moved to the header avatar, where it already lived. - Mints and every other secondary section stay in the More menu — nothing was removed, only moved out of the way. - The nav customiser now edits three middle slots and previews the fixed More button. Existing four-slot layouts are normalised to three on read. - Desktop defaults now show Community instead of Mints as a primary tab. --- 🔐 Private operator status + transport hardening - New admin-only `/ops` page shows relay/coordinator health, Cordn 429s, services, disk/memory, media usage and TLS expiry. - The status endpoint requires a NIP-98 signature from one of the two relay admin npubs. Nothing is public; the page has no restart/config actions. - The host health timer now writes an aggregate status snapshot for that endpoint every five minutes. - Added HSTS to `relay.skate-spots.org` and `blossom.skate-spots.org`. - Added CAA records restricting certificate issuance for those two hosts to Let's Encrypt. --- 🖼️ Image uploads are now bounded by npub, not just IP - Blossom uploads are image-only: JPEG, PNG, WebP, AVIF, HEIC or GIF, max 10 MB. No video uploads were added. - A signed quota proxy now verifies the BUD-11 upload token, then enforces: • 50 images / 250 MB per npub per day • 3× that budget for the two relay admins • a generous 100 images / 500 MB per IP per hour backstop • a 20 GB relay-wide media budget with health alerts - Uploads go through our own Blossom only. Public mirrors remain read-side fallbacks for existing images, but can no longer silently bypass the quota. - Clear size/type/daily-limit errors replace raw Blossom responses. - Newlay’s own per-object cap is now 10 MB as a second line of defence. The private read-only admin dashboard is next; this release is the quota layer. --- 🛰️ Cordn / Staircase reliability pass - Raised the embedded coordinator’s request budget (120/min → 300/min, burst 30 → 120) and concurrency (32 → 64) after finding 3,767 rate-limit rejections in one day. - Cordn polling now backs off exponentially with jitter after failures, polls hidden tabs half as often, and clears stale error state on recovery. - The relay health check now alerts on Cordn rate-limit bursts, a missing coordinator announcement, and TLS expiry — not just a dead relay. - Settings → Coordinator shows live health dots for each configured relay. - Crew coordination card adds a scan-to-add QR for Staircase/Cordn clients. --- 🛹 Support page: compact, tabbed, easier to scan - The supporters page is now split into four tabs — Support, Supporters, Community, Grants — instead of one very long scroll. - The three funding rails are a compact selector: only the chosen rail opens, while “what your support pays for” stays visible underneath. - Hero, section headers, impact stats, cards and spacing are tighter on mobile while keeping all grantmaker transparency and everyone’s credit. - `/support` now redirects to `/supporters`, so the page is easy to find. - Donate page keeps its focused single-page layout and still uses the same rail cards. --- 💸 Profile payments: CLINK + Lightning, properly separated - The profile tip card no longer appears as an empty box when a skater has no payment method. Both can now coexist cleanly: • Lightning address (`you@yourdomain.com`) powers Zaps and direct sats. • CLINK (`noffer1…`) powers the self-custodial “Tip in Bitcoin” handoff. - Lightning addresses are normalised (accept a pasted `lightning:` prefix) and the profile Lightning row is now tap-to-copy. - CLINK codes are normalised on save everywhere (profile, shops, crews, Lab), so a pasted `nostr:noffer1…` is stored as the canonical raw code. - Marketplace listing detail now surfaces the seller’s CLINK tip button when their profile has a valid CLINK offer. - CLINK remains an explicit handoff to a CLINK-compatible wallet; it is not presented as an in-app payment rail. Lightning remains the in-app rail. --- ⚡ Faster shell, smoother menus, safer Amber - The web entry bundle is ~25% smaller after moving the map to a web-only lazy route and loading the Cashu/Zap dialog on first tap. Android keeps the map eager (static) so the native boot path is unchanged. - Page navigation keeps the header and bottom nav mounted. A short delayed skeleton fades in under the chrome instead of a full-screen black spinner, and primary menu destinations prefetch on hover/touch. - The mobile burger menu now closes on any route change (back, notifications, global search), and nav links expose aria-current. - Amber native calls are serialized and coalesced by request. Identical concurrent decrypts/signs share one result, decrypts are memory-cached, and overlapping intents can no longer race the 60s native timeout. - Production dependency audit: 0 vulnerabilities. No risky major upgrades. --- 🔐 Community chat setup: no overlapping Amber requests - Cordn setup now runs one coordinator operation at a time. A double-tap on “Set up” can no longer start two publish/join flows and leave one Amber request orphaned. - The setup panel now shows the two real steps for Amber users: Set up this device → Request join. Those are two separate coordinator signatures, so seeing two prompts is expected; the first publishes this device’s key package, the second asks the room to approve it. --- 🛑 Amber: no more popups after you navigate away - The DM inbox and Cordn notification readers decrypt message-by-message. When you left the screen while Amber was open, the query was cancelled but the loop kept launching Amber for every remaining message — the app looked possessed. - Every decrypt loop now checks the query's abort signal before the next message and stops immediately. Closing the notification bell also stops its decrypt loop. - The first half of a two-step DM decrypt is cached, so if you leave mid-request the next visit only asks once for that message instead of asking twice again. - Cordn's crew-message fetch now honours the same cancellation rule. --- ⚡ Faster open, no spinning logo - The cold-start splash now clears in about 0.7s instead of ~1.7s: no artificial hold, no long relay wait, and a hard 0.9s cap. - The wheel mark no longer spins. It drops in once, throws a single short spark burst, then stays still. - The exit is an aperture-style iris that closes into the logo, revealing the app from the edges without moving the map. Content stays visible through the transition, so there is no dead black frame. - Reduced-motion users get the same faster timing with a plain fade. --- ✨ Smoother app-open transition - The logo now starts near the native splash’s centred position and settles into the wordmark/progress column, so the native → web handoff has no jump. - On exit the splash content lifts and softens while the app revealed beneath stays still; no map nudge or zoom flash. --- 🚨 Native boot: eager map + safe cleanup - The home map is now imported eagerly instead of through a lazy Suspense boundary. A slow/hung native chunk import could leave the app on the black PageLoader forever; the header and map now start immediately. - Native service-worker cleanup is feature-checked and can no longer throw before React mounts. --- 🚨 Critical native boot fix - Native service-worker cleanup is now fully feature-checked and wrapped. Some Android WebViews expose a partial Service Worker API; the cleanup could throw before React mounted, leaving the splash/logo then a black screen. - Boot now continues even when that cleanup is unsupported. The cleanup remains best-effort. --- 🚨 Boot-loop breaker - If the app reloads three times within a minute, the boot guard now clears the old app-shell worker/caches once and reloads into a clean shell before the error panel can be trapped. Normal opens and reloads are unaffected. --- 🩹 Remove the white flash from native boot - The document background is black before CSS loads, so a native launch can no longer flash white between the splash and the app shell. - `boot-guard.js` uses a cache-busting query and is never cached by the app-shell worker, so the old-worker cleanup is always the new code. --- 🩹 Stronger native boot recovery - Bumped the app-shell worker cache to v3; old shell caches are deleted on activate. - `boot-guard.js` is no longer cached by the service worker, so a stale worker can never trap the app in its own cleanup path. - Native WebViews unregister old app-shell workers and clear their caches before the bundle runs. Web registrations use updateViaCache: none. --- 🩹 Fix native white/black reload loop - Native installs now clear any old app-shell service worker and `skate-spots-shell-*` cache from `https://localhost` before the bundle runs. A stale worker could serve an old index.html whose hashed chunks no longer existed, causing the white/black reload loop after an upgrade. - Web installs are unchanged; the app-shell worker still updates normally. --- 🧪 Zero known production vulnerabilities + profile services - Replaced the write-only SheetJS xlsx package with a small local OOXML writer. `npm audit --omit=dev` is now **0 vulnerabilities**. - Personal profiles now show a **Lab services** strip linking to their Transport, coaching, design, building and other Lab profiles. - Added tests for the Transport parser and XLSX writer (156 tests total). --- 🔍 Audit pass: counts, forms, dependencies - Followers now query up to 500 follow lists instead of 100, so profile and sponsor counts are less likely to undercount. - Clothing designers were missing from /stats and Supporters impact; they now have their own count and card (15 Lab crafts total). - The floating Sasquatch bubble is hidden on /become forms, create/edit forms and /supporters so it can't cover inputs or the grantmaker form. - protobufjs override moved to 7.6.5, clearing the moderate ONNX-path advisory. The only remaining production advisory is xlsx (write-only export, no fix published). --- 🛠 Cordn empty-response fix - The coordinator client now accepts both structuredContent and JSON text responses, and treats an empty list response as an empty list. This fixes the “expected object, received undefined” error when a coordinator omits the structured field on an empty join-request/welcome/message result. --- 🚐 Transport / Driver profiles in The Lab - New Transport craft for skaters who move people, gear or cargo: cars, taxis, vans, motorcycles, helicopters, planes and boats. - Services: people, goods/cargo, skate gear, airport and venue transfers, tours and event logistics. - Capabilities, capacity and coverage filters on /lab: cargo, bike/board rack, wheelchair access, pets, cross-border, night driving, covered, group size, local/regional/national/international. - Capacity, cargo, coverage, availability, base area and accessibility fields. - WoT badge, crew link, vouches, reviews and the normal report/hide flow. - Explicitly self-attested: SkateSpots does not verify licences, insurance, vehicle roadworthiness or operator permits. A visible notice says so. - Transport counts on /stats and Supporters impact. - All Transport copy is in all 24 languages at 100%. --- 🗺 Cleaner map footer + follower stat fit - The grey floating “Links” pill between Events and Crews is gone. The map footer is now a slim, always-visible strip above the bottom nav. - Profile stats use 2/3/6 responsive columns; the Followers label and caveat no longer overflow or open an edge tooltip. - The Bitcoin grantmaker section now states its ethos and privacy boundaries: no KYC of SkateSpots, no tracking/CRM, private NIP-17 DM, and only grants that keep the project open source, self-hosted and analytics-free. --- 🧾 Grantmaker transparency + stat fit - The Followers stat no longer overflows its card: stats use 2/3/6 columns, and the relay-reported caveat is a proper footnote instead of an edge tooltip. - The Bitcoin grantmaker section now spells out the ethos and the boundaries: no KYC of SkateSpots, no tracking/CRM, private NIP-17 DM, and only grants that keep the project open source, self-hosted and analytics-free. --- 💸 Sponsorship opt-in + Bitcoin grantmakers - Profiles have an explicit “Open to sponsorships” switch and optional note; the badge and sponsor card only claim it after the skater opts in. - The Supporters page now has a Bitcoin grantmaker inquiry form. It opens a private DM to the owner and stores nothing: not to KYC us — to KYC YOU. It is only for grantmakers that KYC/KYB their grantees. - The Followers stat carries an info tooltip: relay-reported, not audited analytics. --- 👤 Sponsor-ready profiles - Profiles now have Follow/Unfollow, Followers and Following counts, and an Events hosted section. - New sponsor/collab card shows followers, events, spots and zaps received, with a prefilled collab DM and a direct link to the skater's Rider Card. - Stats strip is a balanced six cells: Spots, Shops, Crews, Events, Gear and Followers. - NIP-05 now shows a real verifying state instead of briefly looking unverified. - Public stash images use the same resilient image fallback as the rest of the app. --- 🛹 Rolling logo, Cordn inbox, safer sends - The app now opens on the orange SkateSpots wheel: it rolls in, keeps spinning and throws sparks. Reduced-motion users get the clean static mark. - Android's launch screen is regenerated from the same source instead of the stock placeholder, so the first frame is on-brand too. - Messages gains Private Rooms: Community plus every crew MLS room, with Open/Set up state and local unread dots. - Cordn rooms now have per-room mute, in-room message search, Chat vs Private chat guidance and a last-checked coordinator status. - Approving or removing a device asks for confirmation. - Failed Cordn sends are kept in a device-local outbox, retried a few times when online, and can be retried or discarded later. - The mobile wordmark no longer truncates in the logged-in header. --- 🔒 Community join hardening - /cordn now opens the in-app Community room too; the raw Cordn link is copy-only from Advanced, so no browser short link lands in the stalled Cordn web client. - Approving a device now asks for confirmation before adding it to the encrypted room. - Corrected the second-device hint: use Link device for a direct handoff, or ask to join again with the new device. - The community bot enforces an hourly approval brake (30/hour) on top of the 250-member and 5-devices-per-account caps. - Daily encrypted state backups now run via a user timer: 30 local snapshots plus restic when configured. ops-health reports the backup timer. --- 🧵 Community polish + host tooling - The Advanced Cordn web link now warns that Cordn web may stall after sign-in; the in-app join remains the reliable path. - Admins get a “Request handled” confirmation after clearing a join request. - Added scripts/deploy-community-bot.sh: builds, backs up, uploads, restarts skatespots-community and refreshes the local 0600 state backup. - ops-health now reports whether the community Cordn bot is active. --- 💬 Community joins that actually finish - skate-spots.org/c now opens the in-app Community room instead of Cordn web, which currently stalls after NIP-42. /cordn remains the raw Cordn reference for Staircase/Cordn clients. - Join requests now say the community bot or an admin approves them, with a Request again action and an admin banner when requests are waiting. - Second-device users are told to use Link device; the bot cannot add a second MLS key for the same account. - The community bot now retires handled and stale requests (fixing requests stuck on “Join request sent”), prefers the exact key package, logs pending queues, and stops automatic approval at 250 members or 5 devices per account. - The room warns when the bot is missing, so admins know to review manually. --- ♿ Accessibility and clearer crew-chat aggregation - The mobile map Local Chat button now has a screen-reader name and title. - The first-run tip's close and “Find a crew” controls get a visible keyboard focus ring. - The bell's message row is now “Messages & crew chats”, making it clear that crew-chat envelopes are part of that single encrypted unread count (still envelope-only, still no background decryption). --- 💬 Per-thread mute, event passes, and unmute - 1:1 and group DM threads have a mute toggle in the thread header; muted threads stop showing unread dots on the inbox. Your choice is device-local. - Card Mute actions can now be undone: muted accounts show “Unmute”. - Event pages get an Event Pass shortcut when you’re the organiser or RSVP’d going/interested; it opens the card studio with that event preselected. - The mobile header wordmark truncates at 200% text instead of colliding with search/profile controls. - The frictionless first-run tip keeps one quiet “Find a crew” link. --- 🗓 Small clarity and recovery wins - Event pages now show the viewer's timezone under the local start/end time, so a shared event can't silently mean another city's clock. - The Gear Swap error state has a real Retry button instead of only an apology. --- 🛒 A smarter, safer Gear Swap - Save the current search/filters under a name and restore them with one tap. - Offer dialog gained quick note templates (discount, swap, pickup, shipping). - A collapsed safety guide now sits above the marketplace: meet in public, inspect the gear, keep deals in chat, never share keys, and read escrow terms before shipping. - Saved searches are device-local; no new server or tracking. --- 🧭 First run is one tap, not a to-do list - Removed the Add Spot / Join Crew / Wallet / Community CTAs from the first-run tip. A new skater now sees one optional "Near Me" button and "Got it"; the map is already populated and nothing needs setting up. - The fresh-signup checklist no longer fires a crew query, so it also costs less. 🛡 Inline safety actions - Report already lives on cards; Mute now sits beside it on spot, event, tour and gear cards, using the same NIP-51 mute list as the rest of the app. - Hidden content still explains itself to its author on the detail page. --- 🗺 The map remembers your view - The map restores the last center/zoom on return, so you don't re-find your neighbourhood every time. - The Events/Crews layer choices and the new global search already persist. - The first-run checklist now includes the Community room alongside Add Spot, Crew and Wallet. --- 💬 DMs now reach the notification bell — without decrypting - A Messages row appears when new NIP-17 gift-wrap envelopes are waiting. The count uses envelope IDs only, so Amber is never prompted; opening Messages acknowledges the envelope. Your own sent copies are tracked and excluded. - 1:1 and group DM unread dots remain on the inbox and clear when the thread is opened. This is the first slice of the unified inbox; per-thread mute and crew-chat aggregation are next. --- 💬 Group DMs now show unread state - NIP-17 group conversations get the same unread dot and red-tinted card as 1:1 DMs; opening the group marks it read. One less blind spot in the inbox. - No decrypt-on-background change: Amber users still refresh manually. --- 🔎 Global search, and the app remembers where you were - New command palette: Cmd/Ctrl+K or the header search button. Search spots, crews, shops, events, gear, skaters and app pages from one place; recent searches are kept locally. - Search only queries the datasets while the palette is open, so it does not add to cold-start relay load. - Browser Back/Forward restores the scroll position for that history entry; query and tab changes on the same page do not jump you to the top. - The opt-in Events and Crews map layers are remembered across visits. - No new vendor, analytics, or server; all state is local. --- 🧠 Amber now tells you its prompt budget - The Signers page shows an Amber-only card explaining exactly what prompts: high-value signed actions do, reads/background decrypts do not; group DMs cost one approval per recipient and Cordn may ask per coordinator request. - It suggests a bunker or local key for long private/crew chats while keeping Amber for high-value signing. - Service-worker update headers were tightened: no long browser cache for `push-sw.js`, and App Links assetlinks is served with a short cache. --- 📱 Android Back, deep links, and faster repeat web loads - Hardware Back now closes the open menu/sheet first, then walks history, then minimises at the map instead of killing the app. - `https://skate-spots.org` links can open the installed app (verified Android App Links), and `org.skatespots.app://` links are routed correctly through the HashRouter. Uses the official @capacitor/app plugin; no new vendor. - The web app now has a small service worker shell: hashed assets cache-first, navigations network-first, old shell caches cleaned up. Push handlers are unchanged; API and model requests are never cached. - `public/.well-known/assetlinks.json` pins the release certificate for App Links. --- 🛍 Zapstore now shows the current app - Replaced the empty marketplace listing image with the current community room and refreshed the map/spot screenshots. - Listing images are compressed; no app code changed. Version bumped only so the new Zapstore metadata/media can be published. --- 🔔 Amber gets fewer surprise prompts - Cordn join-request bell notices are encrypted, so reading them costs a signer prompt on Amber. They now wait until you actually open the bell. Passive signers (nsec/bunker/extension) still preload them quietly, and the NIP-17 DM push path is unchanged. - The capability check uses the safe signer probe, so an extension that has not injected yet cannot crash the bell. 🛍 Zapstore listing refreshed - Added map, spot and marketplace screenshots; updated copy for crews, private chat, the Lab, translation, community and notifications; expanded supported NIPs and added a publisher-key guard. - No behaviour change outside the listing. --- 🧹 Leaner repo, same features - Removed 1,295 stale Gradle build files that were accidentally tracked under the NFC plugin; Gradle regenerates them locally and they were already ignored. - Dropped the unused sticker-design source and recompressed the large logo, newsletter cover and Sasquatch guide images. No app image paths changed. - The on-device translation worker runs ONNX Runtime single-threaded, so the unused threaded WASM variants were removed. The SIMD and non-SIMD fallbacks remain, so every browser/device path is unchanged. - README rewritten to match the current app; the tracked tree is ~47 MB instead of ~66 MB. Git history is untouched (no rewritten hashes). --- 🖼 Load images and crews only where they matter - Content images now default to lazy loading + async decode. Long spot, gear, event and crew lists no longer pull every off-screen photo up front. - Crew notifications no longer fetch every crew: the bell asks only for crews that actually list you as a member. The full crew directory is loaded only when an admin has an incoming join request to resolve. - These are local rendering/query changes — no CDN, no analytics, no new server. --- 🔔 The notification bell is off the critical path - The whole notification center is now code-split and deferred until the app has painted (or until you tap the bell). The bell icon is still there immediately; its five data sources no longer compete with the map/profile queries on a cold start. - The map and route chunks get the first network slots; the bell chunk and its feeds arrive after first paint. If you tap the bell before that, it loads and opens immediately. - Still local-first: no analytics, no new vendor, no notification server. The existing push path is unchanged. --- ⚡ Faster cold starts, same ethos - Profile lookups are batched: one relay round-trip per 100 authors instead of three per card. Avatars and names on the map, crews and lists stop stampeding the relays. - The map only asks for layers that are actually on. Events and Crews are opt-in and no longer fetch until you toggle them; Shops, Gear and Tours follow the same rule. - The local public cache now rehydrates crews, tours, the shop directory and newsletter issues on a cold start, so those screens render from disk before the relay answers. - No analytics, no new vendor, no server-side shortcut: this is batching, gating and local-first caching. Next targets are the notification bell's cold-start query storm, map pagination, a no-vendor app-shell service worker, and a smaller translation model. --- 🧭 The map footer is back - DIY, Newsletter, License and Privacy are always visible on the desktop map again, plus the OpenSats note. We removed the hide toggle that could bury the only footer on the map forever. Mobile keeps the compact Links chip. 🔔 Cordn private-chat join requests now push - A background watcher checks the coordinator every minute and turns each new request into a NIP-17 DM (so the phone can wake with the app closed) and an encrypted notification-bell card. - The bell shows "Private chat request" with Review and Dismiss; the in-app request dot still works. The watcher uses its own key — never an admin key. 🛡 Inline crew roles + private-chat controls - The founder can promote/demote a member directly from the Private chat member row (it republishes the crew event with the updated admin tag). - Private chat now has reactions, delete-for-everyone and read receipts. These ride as encrypted MLS control messages; the coordinator still sees ciphertext only. Delete is a tombstone, not a relay hard-delete. Automatic read receipts are silent-signer only (Amber users aren't prompted behind their back). 📊 Translation matrix runner (and a real finding) - Added `npm run translation:matrix` to drive the actual built worker in a browser. First runs: en↔es ~54s, en↔ca ~21s; the Basque model downloads did not finish in 25 minutes. The 617 MB M2M100 is too slow for low-end phones — this needs a smaller model or native ONNX, not another checkbox. All-language APK/low-end verification is still open. --- 📰 The weekly newsletter builds itself (almost) - The newsletter now assembles a complete weekly draft: four shipped highlights, three rotating South Park-style roasts, current tech headlines, and a fresh cover built from the same Drop #006 foundation. - Admins get a "Weekly draft ready" banner. The composer loads every field, previews the Markdown safely, and publishes. Subscribers still get issues in the notification bell's News tab, and the archive no longer duplicates a backfilled live issue. - A weekly timer generates the draft every Monday at 08:00. The first one is ready now. Auto-publish is opt-in after review (NEWSLETTER_AUTOPUBLISH=1), so the roast gets a second pair of eyes before it goes out under the founder key. - The generator runs locally with the admin signer; no subscriber list or key leaves the box. Covers are uploaded to our own Blossom. --- 🧑‍🤝‍🧑 Private chat: devices + members - Link a new phone or device with a QR code. An existing member scans it, and the new device joins without another founder approval round trip. - Remove a member/device from the member list. Founders also get an Edit Crew link for admin roles. - Copy or reply to any private-chat message. - The Private chat tab keeps its unread and join-request dots. 🔐 Dependency hardening - Patched the critical protobufjs advisory used by the on-device translation runtime and updated sharp. Only the write-only xlsx advisory remains. --- 💬 Private chat badges + remembered joins - The Private chat tab now shows a dot when new messages arrive while you’re reading Events or Chat; opening the tab clears it. - Founders/admins get a red dot when someone is waiting to join. - A pending join request survives a reload; the auto-check resumes when you come back. - Background checks run only for silent nsec/bunker signers. Amber and browser extension users are never prompted behind their back. --- 🔐 Sign up from anywhere, without losing the flow - The sign-in/sign-up dialog now lives above the app, not inside cards, sheets or menus. Creating an account from Spot Chat, Settings, alerts or a profile card no longer closes the profile/backup steps when you log in. - The language search clears when the menu closes, and the compact sign-in icons have proper screen-reader labels. 🔗 Safer trip links - Links in AI-generated trip itineraries are sanitized before they render. --- 🔐 Sign-in from the menu, fixed - Logging in or creating an account from the burger menu no longer opens behind the menu; the menu closes first and the auth dialog is always on top. - Welcome → sign up/log in and Log In ↔ Create Account now keep exactly one dialog open. - The desktop welcome prompt no longer pops over an in-progress sign-in. - Choosing a language in the menu returns you to the menu. --- 💬 SkateSpots Community room - New Community chat for questions and feedback — end-to-end encrypted. - A community bot approves new devices automatically; admins can still approve. - Find it in the menu or About, share the link/QR, or open it from Cordn. - Menus: the language picker now has its own view, crew tabs fit long labels, and touch targets are roomier. --- 📱 Invite QR fixed on Android - Invite QR codes now use the public skate-spots.org link instead of the app's local address, so another phone can scan them. The link opens the crew's Private chat tab. --- 🔐 Basque translation, repaired - Basque ↔ English now gives real translations and stops cleanly instead of repeating a word. No new download of the large model is needed. 💬 Private crew chat polish - After "Ask to join", the app checks for the invite automatically, so you can leave the page open. - Three plain steps explain how to start or join; Cordn, group links and key packages now live under Advanced. - Connection trouble shows a plain message and Retry; a new device can be set up again without losing access. - See who's in the chat with avatars and founder/member roles, plus Sending… / Sent / Failed — Retry on messages. - Invite links open the Private chat tab and have a QR code; the promo banner is dismissible. --- 🌍 Hindi, Català, Euskara and Galego - The app is now fully available in Hindi (हिन्दी), Catalan, Basque and Galician — pick them from the language menu. - The picker now shows the real regional flags: England, Catalonia, the Basque Country and Galicia, plus Português (Brasil) and Português (Portugal). - Long translations no longer clip the menus: wider language menu, aligned flags, one-column language grid on phones, and a wider "More" menu. - Devanagari, CJK and Thai labels are no longer letter-spaced, and the settings language grid now shows flags instead of file paths. 🗺 One world, no repeated continents - Zooming out stops where the single world covers the map — no grey bands and no duplicated continents. - You can still drag horizontally across the Pacific to Hawaii and the Pacific islands; the map wraps at the date line, and vertical panning stops at the poles. --- 🗺 The map is authoritative again - Spots and shops on the map now come only from the SkateSpots community relay, so everyone sees the same pins — and it fixes the empty map some of you hit. - A missing spot was restored to the community relay. 📲 Pass SkateSpots on - On Android, the About page now has a "Share SkateSpots" card: show a QR, use the share sheet, or write the install link to an NFC tag. 🔑 A clearer way in - Sign-in now leads with three plain choices — browser extension, signer app, or sign in with your phone — plus a quiet secret-key option. - On desktop the welcome sign-in appears once per session for logged-out visitors (dismissible). 🛡 Security & stability - Updated core libraries (router, validation, Nostr client) and cleared the known app-facing vulnerabilities; the dependency scanner now runs in the scheduled job too. --- 🔑 A clearer way in - Sign-in now leads with three clear choices — browser extension, signer app (bunker/Amber), or scan a code to sign in with your phone — plus a quiet "Secret Key" option. - On desktop, a welcome sign-in card appears once for logged-out visitors (you can dismiss it). 🛡 Dependency security - Updated Vite, Vitest, unhead and yaml and pinned TypeScript; the OSV scan now reports far fewer known issues (remaining ones are upstream major versions or have no fix). 📄 License - The Zapstore listing now shows the real licence: AGPL-3.0-only (was "custom"). --- 🔧 Amber signing fix - Fixed messages (and other long encrypted data) occasionally failing to open when signed with Amber — the signer can compress large results and the app now reads them correctly every time. - Clearer wording if Amber doesn't respond (it no longer suggests Amber isn't installed). --- 💬 Crew chat, simplified and faster - The crew Chat always uses standard end-to-end encryption now — no more silent transport switching. (Coordinator/MLS chat lives in the crew's Private chat.) - Messages you send appear instantly; the app no longer re-decrypts your whole inbox as you move around, and it remembers decrypted messages on your device, so reopening the app is quick. Far fewer signer prompts. 🔐 Private crew chat - Admins can now Invite members straight from the private chat. 🌍 Languages - All 20 languages are complete again (recent screens were falling back to English). --- 💬 Crew chat fixes - Messages you send now appear straight away (they could seem to vanish before). - Moving between Messages and a crew no longer re-decrypts your whole inbox, so the Amber app stops flashing and things feel faster. You're asked to approve each tap once per message, not over and over. --- 🩹 Crew chat sends with Amber - Sending to a crew no longer fails with "Amber didn't respond". The approvals now come one at a time instead of all at once, so each one lands. (A 2-person crew still needs a few approvals — that's the encrypted-message cost.) For fewer taps, the crew's Private chat needs about one approval per message. --- 🧹 Fewer signer pop-ups - Navigating around no longer re-decrypts your messages over and over, so the Amber app stops flashing as you move between screens. New messages are pulled in with a Refresh button on Messages. 💬 Crews in Messages - Your crews now show up in the Messages tab, with a one-tap link straight into each crew's private chat. 🧭 Clearer crew chat - The crew's "Encrypted chat" card no longer contradicts itself: it shows Chat (always on) and Private chat (MLS) side by side with their real state, and takes you straight to the private chat. - Joining now confirms ("Request sent…"), and admins are told how to add members. --- 🧹 Fewer onboarding pop-ups - The "get started" card on the map now shows only for genuinely new accounts — it no longer appears for returning skaters. - "Save your login" no longer comes back every session once you've saved your key during signup, and the browser's save-password prompt is less likely to appear. --- 🆕 Private crew chat, end to end (MLS) - Crews now get a real encrypted group chat: RFC 9420 MLS through our own self-hosted coordinator. Open a crew → "Private chat". Founders create it and approve join requests; members tap "Ask to join". Roughly a second to join. - Send photos, copy the group link to open the same chat in Cordn or Staircase, and your messages stay between members. The coordinator routes ciphertext and metadata only — it never sees what you write. 🔒 Our infrastructure, not someone else's - The community relay and photo/media storage now run on our own servers, so your spots, crews and photos no longer depend on a third party. Same data, faster and more independent. 🛒 Marketplace: close the deal in-app - Accept an offer and pay right there (NWC / WebLN / Cashu), with the invoice amount verified so you can't be overcharged. - Escrow now uses the mint the seller advertises, and confirmation is safer. 🛡 Trust you can steer - Mute an account and it disappears everywhere (NIP-51 list). - "Alerts" flags accounts you follow that trusted people reported. - Choose your trust provider in Settings → Trust, and every badge says who decided. 🗺 Map & weather - Search now suggests spots and places as you type. - Spots show a 6-day forecast with a colour legend, sunrise/sunset, and a manual refresh. 🧵 New in The Lab - Clothing Designer joins the craft roles. 🛠 Fixes & polish - Long menus scroll properly, and the language picker is searchable. - Spot cards are tappable across the whole card again. - Deleted spots no longer flash back from cache after a refresh. - Lighter on first load (CJK fonts download only if you pick that language). --- 🌍 Ten new languages - Simplified Chinese, Traditional Chinese, Ukrainian, Turkish, Vietnamese, Indonesian, Swedish, Czech, Romanian and Greek are now selectable — full coverage, not partial. (And North/South Korean stay separate, as before.) - Locales lazy-load, so picking a language only downloads that language. 💸 A proper support page - New /donate — three honest rails: ⚡ Lightning, 🕵️ private on-chain (silent payments) and ⛓ Angor. Each with a clear purpose, so you pick what fits you. - The Supporters wall now thanks backers with amounts, tiers and on-chain proof. 🛹 Fixes - Top Shops shows real skateshops again (the community relay is shared, so other apps' shops no longer leak in). - The Monday newsletter reminder no longer covers the map on phones. - New comments appear immediately, and event tickets verify properly at the door. 🔧 Under the hood - A full bug + UI/UX audit pass: safer payments, stricter verification, fewer mobile layout rough edges. --- 📍 The map, cleaner - Fixed the search bar sitting on top of the map's zoom buttons. - The "Offline — showing saved spots" banner now appears only when your device is actually offline (not just when one relay is slow), and you can dismiss it. - The "you are here" dot shows your own profile picture. ✅ Spots are verified by real skaters - Community confidence now counts what other skaters actually do here: photos, status reports, comments, reactions, zaps, saves, links from crews and Lab pros. Cheap signals count for less, a zap or a crew link counts for a lot. - The spot page explains itself ("2 photos · 1 crew · 3 comments") and nudges you to help confirm a new spot. 🪪 More than one handle - Crews, shops and your profile can each carry up to 5 NIP-05 handles, each with a live verified check. 🔐 Private things stay private - Stash backups can now be password-protected (with a strength meter) — the exported file is no longer plain text. - Marketplace payments verify the invoice amount; private messages verify the sender's signature. ✨ Smaller fixes - Crew form tidied into groups (Advanced tucked away), with a "Check" button for a custom chat coordinator and "Sasquatch · Pro" naming. - Stash and the marketplace listing form now fit narrow phone screens — the header, item rows and condition buttons no longer overlap. - The Lab's "Offer" menu is now a tidy, scrollable list (small colour chips instead of a wall of coloured buttons), with "Get Rider Card" pinned at the bottom. - Marketplace reputation no longer shows a stuck "Loading…". --- v1.5.10 🧭 Directions, rebuilt for a phone - Search a new destination right in the app: skate spots, skate shops and Bitcoin merchants (no Google/Apple Maps handoff). - The map is much bigger and the vehicle picker moved below it. - Following is smoother — it re-centres only when you actually move, so GPS jitter no longer twitches the map. 🪙 Mints, with the info that matters - Tap a mint for community rating, reliability, uptime, location and a liveness audit — plus copy/open/terms. Ratings come from the community MintRadar data. 🤝 Haggling: counter-offers + barter - Offers are now a real back-and-forth: accept, decline, withdraw, or counter with a new amount — either side, any number of rounds. - Swapping instead of buying? Offer an item ("my 8.25 deck") instead of, or alongside, sats. Barter counts for reputation exactly like a sale. - New Trades tab in the notification bell, plus notifications for every step: new offer, counter, accepted, declined, and confirm-a-trade requests. ✨ Smaller fixes - Crews: one tidy type control (no more horizontally-scrolling chips). - Spot sheet: single close button. - Map controls float over the map so the map fills the screen. --- v1.5.9 🗣️ Navigation you can actually follow - Directions now talks: a prompt at 150 m and again at 40 m before each turn, plus "You've arrived". It's your phone's own voice — offline, no account, nothing sent anywhere. - The screen stays awake while you're following, so guidance doesn't die mid-route. - The map gets bigger when you hit Start, and the step list steps aside. Mute anytime with the speaker button. 🗺️ A bigger map on the home screen - The map controls now float over the map instead of taking a bar above it, so the map fills the screen — especially on a phone. --- v1.5.8 🛰️ Pick your own group-chat coordinator - New Settings -> Coordinator: point SkateSpots at a Cordn coordinator you choose, see whether it's up, copy or scan its link, and share it on your profile so people can add it in one tap. 📱 Run one — even on a phone - A coordinator can live on an old phone, a Raspberry Pi, or any small box you leave on. We hand you the doorway (the Cordn app, or a one-line Docker command), and your crew can route its encrypted chat through it. Crew founders get a "Use my coordinator" button. 👤 Edit Profile got a face - See how you actually look — banner, avatar, handle, bio and badges — before you save, plus a short "finish your profile" list instead of guesswork. 🔎 Coordinators are discoverable - If someone runs their own coordinator, their profile now shows it with an Add button instead of a bare link. --- v1.5.7 ⏰ Event reminders - RSVP "going" or "interested" to an event and your phone nudges you an hour before it starts — even when SkateSpots is closed. It's an alarm the device holds, not a server, so nothing leaves your phone. - Turn it on in Settings -> Notifications (Android app). --- v1.5.6 🛹 The map is quicker off the mark - Pins no longer rebuild themselves several times while the map loads, and they stream in instead of freezing the screen in a busy city. Same map, less waiting. 🔔 Notifications (opt-in) - Turn them on in Settings -> Notifications and your phone can buzz for DMs, crew invites and join requests, zaps, replies and mentions, and new newsletter drops. - Privacy first: nothing new is sent anywhere, and direct-message alerts never unlock your messages — so an Amber user is never asked to approve one just to be told a message arrived. - Honest limits: alerts come from the device while the app is running. A fully closed app can't be reached without a push server, which SkateSpots doesn't run — we'd rather say that than pretend otherwise. 🏷️ Badges on your profile - A free name@skate-spots.org handle now shows the SkateSpots badge, and you can list your own badges (Cordn, Cashu, NWC, Amber, BTCMap…) as clickable chips. 📍 "Closest spot to me" - Ask the Sasquatch where to skate and it can sort by what's nearest — worked out on your device, without sending your location anywhere. ⚡ Keep the map free - The Supporters page now has a one-tap way to chip in (zap publicly, or pay quietly), if you want to. --- v1.5.5 🗺️ The map works offline now - The basemap you've already looked at is cached on your device, so the map still draws when the signal drops at the park — no more blank grid. 🖼️ A dead image host no longer leaves a blank spot - Photos upload to two hosts, and if one goes down the app quietly loads the copy from the other. Same for avatars and gear pics. 💬 Past conversations actually show up now - Messages reads your real DM inbox relays, so older threads appear instead of the "No messages yet" screen. And if something genuinely can't be decrypted, the app says so rather than pretending your inbox is empty. ✅ Free `name@skate-spots.org` - Pick a handle when you sign up — free, optional, changeable any time — and it shows a verified badge on your profile. --- v1.5.4 🧹 Keeping the map real - Every new spot now needs at least one photo — the cheapest defence against test entries and off-topic pins ("test of secret island airport"). - Spots only say "Community verified" when another skater has contributed (a photo or a status report). Until then they are labelled "Unverified" instead of looking endorsed. - The weather score is now labelled "Conditions · weather only". It was never a verdict on whether a place is a real spot. - One-tap "Not a skate spot" for off-topic pins (test entries, airports, malls, private land), plus an admin review queue that surfaces them for a human. - The queue also weighs mapper trust, whether any skater has reported on the spot, and whether anyone has added a community photo — and a review can now **Confirm** a spot as well as hide it (a staff-vouched spot gets a badge). - Moderation is **reversible**: Hide and Confirm can both be undone, returning the spot to neutral without hiding or vouching for it. - **Reports now reach a human**: the review queue surfaces reported spots at the very top, above the automated signals — so "not a skate spot" actually lands. - **Adding a spot warns you if one already exists** within 60 m, and links you straight to it instead of letting you create a duplicate. - **If a moderator hides or vouches for your spot, you're told** — right there on the spot page (your own spots stay visible to you either way). - **A photo is now strongly recommended, not required.** No picture on hand right now? Publish anyway — the spot just stays marked Unverified until one lands. - **Empty map? It now says so and offers to fix it**: "No spots mapped yet — be the first to map your park", with a one-tap Add spot. - The admin review queue now covers **shops, events, tours, gear, crews and Lab profiles** too, not just spots — and has a **report inbox** (every report, with the reported item resolved, not just whatever's already flagged) plus **bulk undo** for clearing old verdicts. 🛍 App Shop — a new section (empty on purpose, with free printables) - Free to print, no sats needed: a 55 × 86 mm "DO YOU EVEN SKATE BRO?" sticker and an A3 poster, both print-ready vector files with a working QR. - Merch is coming, and it'll be paid in sats: Lightning or Cashu, your choice. No cards, no accounts, no processor skimming the drop. - To be clear: we hold no stock and nothing is for sale yet. No pre-orders, no countdown timers, no fake scarcity — the teasers are labelled "not for sale yet" and there are no prices anywhere. ✉️ Direct messages actually arrive now - Your DM inbox relays were being forgotten every time the app loaded, so messages were sent to your normal relays instead of the ones the other person actually reads — which is why DMs looked like they never arrived. Your DM relays, local relays and relay blocklist now persist properly. - Sending and loading DMs no longer stall or break because of one dead or login-only relay in your list; they now run in parallel. 🧭 Directions look and feel like a navigation screen - A much bigger map, with a metric scale bar, and the plan at a glance: distance, time, arrival, step count and the average speed the route assumes. - The map stays put while the details scroll, and Start/Stop is pinned at the bottom where your thumb already is. 📰 Newsletter reader - Issue intros render as proper italics instead of showing literal underscores. --- v1.5.3 🧭 Real navigation, not just a route preview - Travel modes finally give genuinely different answers: walking 13 min, biking 5, driving 2 on the same trip. Before, every mode showed the same number. - Route steps — the actual turns and street names. Tap a step to jump to it on the map, and use "Whole route" to zoom back out. - Tap Start and it follows you: your dot moves, the current step highlights, and it shows the next turn plus how far is left. (Still no voice guidance.) - Arrival time ("arrive ~08:10 PM"), and it remembers the mode you picked last. - Going somewhere first? "From → Choose on map" sets your start point instead of routing from where you're standing. - Lose signal mid-route and it keeps showing your last route, clearly marked as saved, instead of going blank. - Skating gets its own honest estimate ("~6 min cruise on a board") next to the walking time, and moto is labelled as using driving roads. 🔔 Amber stays out of the way - Amber now only opens for real signed actions: log in / sign up, messages, your Stash, marketplace trades, invites, publishing. Browsing and moving between sections no longer trigger a signer prompt — the app's encrypted cross-device data stays local-only on Amber instead of decrypting on every screen. --- v1.5.2 🛒 Marketplace, levelled up - Every listing lives in one hub now: Browse, Selling (your own listings with one-tap Mark sold), your Trades, and Reputation. - Rate a trade 1–10 skateboard decks when you confirm it. Ratings show on both profiles with an honest average — and every confirmation is with a real person, so two accounts can't pump each other's rep. 🧭 Directions actually work now - Fixed the route map never drawing (you'd get an empty dialog and "no route"). Routes now show your position, the spot, and the line between them. - Opens instantly from your last known location; "Near Me" sorts by distance. 📱 Nav fixes - The desktop "More" menu no longer vanishes when you pin Marketplace. - Marketplace is now in the phone menu (☰) — pin it to the bottom bar too. 🪙 Mints loads in the app again - The mints list was showing a JSON error on phones; it's fixed. 📰 Newsletter - Fixed a bug that pegged your CPU on the newsletter page. - Issues and subscriptions now publish to the community relay so everyone sees the drops. ✨ Smoother everywhere - Amber only pops for things that need a signature — no more prompts just for reading your notifications. - Logo no longer crowds the nav. --- v1.5.1 🦧 Sasquatch — the AI guide, levelled up - Ask real questions and get answers streamed as they're written. - Sasquatch Pro unlocks AI answers plus personal actions (drafting posts & listings, your Stash/Crews in chat). Pay with Lightning — from 7 days. - Free, always: trick & term lookups, and finding spots, events, crews, shops, tours and gear straight from the relays. - Your Pro balance shows right in the guide. 🚇 Directions that stay in the app - Route to any spot by public transport, bike, moto or car — drawn on our own map, no bouncing out to Google or Apple Maps. Pick a mode, see the line. 🧑🎨 New in The Lab: Barbers & Hairstylists - Cuts, fades, beard trims and colour — shop chair or mobile. Find a fresh trim on the scene. ✨ Smoother everywhere - The app shell no longer rebuilds on every screen, so the Sasquatch chat and your scroll position survive navigation. - Directions opens instantly now (it draws from your last known location first). - The signer only pops for things that need it — log in, messages, your Stash, the marketplace and publishing. No more prompts just from moving between tabs. - Mints is now in the phone nav; tidier tab labels. --- v1.4.5 🔄 Cross-device sync - Your read state (notifications, messages, crew chat, newsletter) and app preferences now sync across devices via encrypted NIP-78 app data. 🔒 Security hardening - Amber signatures are verified, and trust scores verify event signatures before they're used. - Cashu wallet seed is stored in the native Keychain/Keystore with a mandatory first-time backup. - The agent (CVM) server only serves signature-verified events. 🗺️ Map & spots - Crisp map pins with spot-type and shelter glyphs, plus smoother loading. - New "Shelter" (weather protection) field. - Better spot dedupe across geohash/city and name variants. - Faster cold-start: query persistence, optimistic geolocation, skeleton pins. 📅 Tours & events - Tour countdown badges, session times on scheduled local tours, and calendar export. Polished Create Tour flow. 🐿️ Sasquatch - Faster answers via a local fast-path, honest spot counts, deduped results, and no more empty/typo dead-ends. 🎨 Polish & accessibility - Lighter onboarding, shared empty states, improved contrast, a skip-to-content link, and live-region announcements. - Relay list UI polish with live connection indicators. - Mobile fix: detail-page grids no longer overflow horizontally on narrow screens. --- v1.3.3 📡 NEW — Local Relay (Citrine) · Android Run a private Nostr relay right on your phone with the free Citrine app, then flip it on in Settings → Relays. When it's connected you get: - Instant reads — the map, spots, crews and messages load from your device - Works offline — browse (and queue posts) at a spot with no signal - On-device backup — a durable local copy of your own events It's opt-in, Android-only, and your Stash and messages stay end-to-end encrypted exactly as before — the local relay only speeds things up. 🛹 Reliability & polish across the app - Events/Tours: month calendar view with a list⇄calendar toggle - Notifications: RSVP/update alerts now open the event, not the sender - Map: fixed trusted-first sorting and stash card borders - Crews: fixed roster edits clobbering each other on rapid changes - Lab/Market/Stash: always show the newest revision of a profile - Wallet: clear warning (with the exact sats at risk) before removing a mint - Spot claims: cleaner ownership history - Newsletter: recurring issue titles no longer overwrite older issues - Messages: group chats no longer leak into your 1:1 conversations --- v1.2.14 🔒 Security hardening (payments & trust signals) - Auto-pay now verifies every Lightning invoice's amount before paying (zaps, crew zaps, listing fee). A server can no longer return an inflated invoice to overcharge your wallet. - Pro access is granted only by a verifiable, provider-issued zap receipt (plus platform owners). Self-signed receipts no longer grant Pro. - "Verified payment" badges on featured listings now require a provider-issued zap receipt — self-published receipts can't fake verification. - Crew funding goals tally only real invoice-backed zaps, so totals can't be inflated with fake zap receipts. Plus the delete diagnostics from 1.2.13 to pinpoint the signing/publish step. --- v1.2.10 🛠️ Fixes a startup crash (black screen) introduced in the previous build and keeps the Amber signing fix: signing now opens Amber the same reliable way login does, so delete / accept invite / zap complete instead of hanging. After updating, log OUT and log back IN once. --- v1.2.8 🛠️ Amber finally pops up — signing works (the real fix) The big one. On some Android setups (notably GrapheneOS), tapping delete, accepting a crew invite, sending a zap, or editing your profile would spin forever and Amber never appeared. Root cause: the app's browser layer was silently dropping the request that opens Amber, so the approval screen never launched. We added a native hand-off so signing requests now open Amber directly — exactly like login already does. Now every signing/encryption action launches Amber, you approve, and the action completes. If Amber genuinely doesn't respond you get a clear message in seconds instead of an endless spinner. IMPORTANT: after updating, log OUT and log back IN once. Then delete, accept invite, zap, and profile edits will just work. 🔔 Notification bell "Mark read" actually clears the badge Marking notifications read now clears the count for crew items too, while your pending invites and requests stay visible in the Crews tab until you act on them. 🧹 Housekeeping Behind-the-scenes reliability fixes across the signing and notification flows.